Bardzo łatwo można zbudować układ do sterowania STM32F4Discovery za pomocą pilota telewizyjnego (TV Remote). Na początek trochę teorii.
Najbardziej powszechne są dwa rodzaje nadajników i odbiorników podczerwieni: 36kHz i 38kHz. Częstotliwości te są używane do modulowania impulsów danych. Odbiornik 36kHz nie będzie reagował na piloty 38kHz i na odwrót. Pilot wysyła impulsy, które po odebraniu przez odbiornik można zamienić na kod przycisku naciśniętego na pilocie. Sposób w jaki są zakodowane impulsy danych (liczba impulsów i ich szerokości), to protokół transmisyjny. Piloty mogą mieć różne protokoły transmisji (zależy od firmy). Najbardziej powszechnym jest chyba protokół RC5, wymyślony przez Philipsa. Więcej o tym można poczytać tutaj: TR Remote Control Theory
Ja akurat zakupiłem (w ciemno bo nie wiedziałem jakie mam piloty) odbiornik podczerwieni na 36kHz: TSOP31236, ale jest podobny na 38kHz: TSOP31238. Zresztą chyba i inne się nadadzą tylko trzeba w notach katalogowych popatrzeć jak je podłączyć. Ja mój podłączyłem tak jak na obrazku poniżej (kondensator i rezystor do testów można sobie darować):
Teraz kot. Konstruujemy klasę, która podłączona pod nóżkę odbiornika będzie informowała (EventHandler) o odebranych danych. Interesuje nas stan (1 lub 0) oraz czas trwania każdego impulsu. Obsługujemy każdą zmianę sygnału na pinie odbiornika (InterruptEdgeBoth).
public class IRReceiver : IDisposable
{
public delegate void PulseEventHandler(TimeSpan width, bool state);
public event PulseEventHandler Pulse;
private readonly InterruptPort _receiverPort;
private long _lastTick = DateTime.Now.Ticks;
public IRReceiver(Cpu.Pin pin)
{
_receiverPort = new InterruptPort(pin, false,
Port.ResistorMode.PullUp,
Port.InterruptMode.InterruptEdgeBoth);
_receiverPort.OnInterrupt += PortInterrupt;
}
public void Dispose()
{
_receiverPort.Dispose();
}
private void PortInterrupt(uint port, uint state, DateTime time)
{
long current = time.Ticks;
TimeSpan pulseWidth = TimeSpan.FromTicks(current - _lastTick);
_lastTick = current;
//Debug.Print("pulse " + pulseWidth.TotalMicroseconds()+ "us " + state);
if (Pulse != null)
Pulse(pulseWidth, state == 1);
}
}
Teraz program, który będzie reagował na impulsy z IRReceiver. Na razie bez rozpoznawania protokołu transmisyjnego i dekodowania impulsów. Będziemy włączać i wyłączać diody na płytce STM32F4Discovery dowolnym klawiszem na pilocie. Nie możemy jednak reagować na każdy impuls, bo w ramce transmisyjnej może ich być kilka czy kilkanaście i diody będą miały losowy stan. Robimy więc opóźnienie, tak aby reagować na pierwszy impuls, a na kolejny dopiero po 500 milisekundach.
public class Program
{
private const int DelayBetweenCommands = 500; //ms
public static void Main()
{
var leds = new[]
{
new OutputPort(Stm32F4Discovery.LedPins.Green, true),
new OutputPort(Stm32F4Discovery.LedPins.Orange, true),
new OutputPort(Stm32F4Discovery.LedPins.Red, true),
new OutputPort(Stm32F4Discovery.LedPins.Blue, true)
};
var receiver = new IRReceiver(Stm32F4Discovery.FreePins.PB5);
DateTime nextCommand = DateTime.MinValue;
receiver.Pulse += (width, state) =>
{
DateTime now = DateTime.Now;
if (now < nextCommand)
return;
nextCommand = now.AddMilliseconds(DelayBetweenCommands);
Toggle(leds);
};
Thread.Sleep(Timeout.Infinite);
}
private static void Toggle(OutputPort[] leds)
{
bool state = !leds[0].Read();
foreach (OutputPort led in leds)
led.Write(state);
}
}
Piloty w dłoń i celujemy w odbiornik. Naciskamy dowolne klawisze. U mnie w domu na trzy piloty dwa były 36kHz, a jeden prawdopodobnie 38kHz. Pełny kot: DemoIRReceiver


Brak komentarzy:
Prześlij komentarz