IR-Remote-Transmitter via PIO (Programmable IO) in Python auf dem PI
Pico
Auf dem PI Pico gibt es ein (mir) neues Konzept von programmierbaren
IOs.
Damit kann man gemäß der Beispiele in der Doku SPI, I2C, WS2812 und
sonstige
BitBang-Schnittstellen nachbilden.
Einen IR-Remote-Transmitter, der auf einem Träger von 38KHz das
NEC-Format
ausgibt, habe ich als Testobjekt mit Python erstellt.
Der Transmitter arbeitet völlig unabhängig vom Rest des Controllers und
wird
über eine Fifo mit den zu sendenden Datenframes versorgt.
Der Pico hat zwei PIO-Blöcke mit jeweils 4 Statemaschines, die jeweils
auf
einen gemeinsamen Speicherbereich von 32 Worten zugreifen.
Benutzt habe ich eine der Statemaschine, um den 38KHz Takt für die
IR-LED zu
erzeugen.
Die 2.Statemaschine moduliert die Ausgabe der 1.Statmeaschine
entsprechend
des NEC-Protokolls.
Dazu wird ein IRQ zur Synchronisation zwischen den beiden Statemaschines
genutzt.
Um die Ausgabe zu kontrollieren, habe ich in Python ein Skript
geschrieben,
das zum Testen des Timings an der 2.Statemaschine per Pin-Interrupt
lauscht und
die Pulszeiten zunächst unabhängig von konkreten Protokollen
aufzeichnet.
(Zum Debuggen wird parallel zum IRQ ein Pin geschaltet, an dem die
Pulse-Pause
Zeiten aufgezeichnet werden können).
Eine Variante des Skriptes decodiert das Signal als NEC-Protokoll, kann
also
im praktischen Einsatz mit dem Ausgang eines TSOP gefüttert werden und
als
IR-Receiver dienen.
Sender und Empfänger laufen unabhängig nebeneinander auf dem Pico.
Schickt man einen Frame (32Bits) an die TX-Fifo des Transmitters, dann
werden
diese im Hintergrund versandt und die Bitzeiten können vom Receiver
protokolliert
werden.
Das sieht dann so aus (die Bitzeiten sind jeweils um 20us verlängert,
weil zum
Debuggen ein zusätzlicher Pin geschaltet wird (was zusätzliche 20us
kostet.):
1 | Bit -1 - 0 Pulse: 8016 - 1 Pause: 4540 - Sum: 12556
|
2 | Bit 0 - 0 Pulse: 575 - 1 Pause: 583 - Sum: 1158
|
3 | Bit 1 - 0 Pulse: 583 - 1 Pause: 574 - Sum: 1157
|
4 | Bit 2 - 0 Pulse: 583 - 1 Pause: 578 - Sum: 1161
|
5 | ---
|
6 | Bit 27 - 0 Pulse: 584 - 1 Pause: 570 - Sum: 1154
|
7 | Bit 28 - 0 Pulse: 588 - 1 Pause: 1694 - Sum: 2282
|
8 | Bit 29 - 0 Pulse: 584 - 1 Pause: 1701 - Sum: 2285
|
9 | Bit 30 - 0 Pulse: 577 - 1 Pause: 1703 - Sum: 2280
|
10 | Bit 31 - 0 Pulse: 573 - 1 Pause: 1703 - Sum: 2276
|
11 | Bit 32 - 0 Pulse: 583 - 0 Pause: 0 - Sum: 583
|
Die Sollzeiten des NEC-Protokolls betragen:
Startbit: Pulse 8000us, Pause 4500us
Datenbit: Pulse 560us, Pause 560us / 1690us
Stopbitt: Pulse 560us
Dass die Interrupts in Micropython mit einer Latenz von ca. 30us
auslösen,
das ist mir bekannt. Solange die Latenz weitgehend konstant ist, sollte
das
Messergebnis dadurch nicht relevant verfälscht werden.
Die Python-Skripte für den Transmitter, den Bitzeitenlogger sowie den
Deconder
sind beigefügt (Transmitter und Decoder verwenden das verbreitete
NEC-Protokoll).
Die meisten anderen IR-Protokolle sollten nach dieser Vorlage relativ
leicht
zu implementieren sein.
Im 2.PIO-Block wäre Platz für einen 2.Transmitter ggf.mit anderer
Trägerfrequenz
und anderem Protokoll - ob das allerdings Sinn macht, das ist eine
andere Frage.
Michael S.