Forum: Projekte & Code IR-Remote-Transmitter via PIO (Programmable IO) in Python auf dem PI Pico


von Michael S. (Gast)


Angehängte Dateien:

Lesenswert?

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.

von c-hater (Gast)


Lesenswert?

Michael S. schrieb:

> 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.

Und noch viel mehr. Die Dinger sind rasend schnell, erlauben taktgenaues 
Timing und sie sind halt flexibel programmierbar.

D.h.: man kann genau das damit tun, was Hardware-Caches, Betriebssysteme 
und höhere Programmiersprachen (oder gar Scriptsprachen) normalerweises 
mehr oder weniger stark verhindern.

> Einen IR-Remote-Transmitter, der auf einem Träger von 38KHz das
> NEC-Format
> ausgibt, habe ich als Testobjekt mit Python erstellt.

Schönes Anfängerprojekt (aber naturgemäß deswegen auch noch massiv 
optimierbar).

Richtig spannend wird es aber erst, wenn du auch den Receiver auf einer 
PIO implementierst. Merke: Receiver sind immer der schwierigere und 
zeitkritischere Teil einer Kommunikation. Gerade hierfür würde sich also 
primär so ein PIO anbieten.

> 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.

Das Schicke an den PIOs ist auch, dass man sie zur Laufzeit dynamisch 
umkonfigurieren kann. Code für NEC ist also nicht festgenagelt, wenn 
irgendein andere Code versandt werden muß, wird halt einfach mal schnell 
ein anderes PIO-Programm aktiviert.

von Michael S. (Gast)


Lesenswert?

c-hater schrieb:
> Richtig spannend wird es aber erst, wenn du auch den Receiver auf einer
> PIO implementierst. Merke: Receiver sind immer der schwierigere und
> zeitkritischere Teil einer Kommunikation. Gerade hierfür würde sich also
> primär so ein PIO anbieten.

Den Receiver via PIO zu realisieren, das schien mir im ersten Moment 
eigentlich
kaum möglich. Wäre aber schön.

Nachdem ich auf dem Papier ein Konzept aufgetragen habe, wie man mit den
eingeschränkten Mitteln den Empfang realisieren könnte und wie man 
diesen
Weg in Instruktionen umsetzen könnte, habe ich meine Meinung geändert.

Ich zähle 25 Instruktionen, da bleibt noch etwas Luft bis 32.

Ich will sehen, ob mein Gedanke auch in der Praxis funktioniert.

Michael S.

von ;Michael S. (Gast)


Angehängte Dateien:

Lesenswert?

Passend zum IR-Remote-Transmitter ist hier noch der Receiver 
nachgeliefert.
Auch er läuft im Hintergrund auf einem PIO-Block des PI Pico.

Sobald ein komplettes Frame empfangen ist, wird ein Interrupt ausgelöst, 
so das
der RX-Fifo nicht gepollt werden muss.

Es werden 32 Datenbit (für das NEC-Protokoll) aufgezeichnet, die 
Auswertung und
ggf. Prüfung muss extern erfolgen.

Zur Ausführung des Codes werden 31 pioasm-Instruktionen benötigt, das 
passt also
gerade in den Programmspeicher eines der beide PIO-Blöcke.

Michael S.

von c-hater (Gast)


Lesenswert?

;Michael S. schrieb:

> Zur Ausführung des Codes werden 31 pioasm-Instruktionen benötigt, das
> passt also
> gerade in den Programmspeicher eines der beide PIO-Blöcke.

Naja, damit hast du doch gleich das nächste Ziel für deine 
Auseinandersetzung mit den PIOs: Optimierung.

Da geht noch einiges, sowohl beim Sender als auch beim Empfänger. Ich 
kann's jetzt aus dem Stehgreif nicht garantieren, aber ich bin nahezu 
sicher, dass sich der Code so weit eindampfen läßt, dass zumindest 
Sender und Empfänger in eine PIO passen.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.