Vor ein paar Wochen hatte ich ein Olimex ESP8266-EVB bestellt und bin am Wochenende endlich mal tatsächlich dazu gekommen, damit herumzuspielen. Als erste Fingerübung habe ich IRMP darauf zum Laufen gebracht. Siehe die beiden Anlagen. 1.patch sind die Diffs zu der aktuellen SVN-Version von IRMP, user_main.c ist das Hauptprogramm. Ein Gag am Rande: die sich im Beispieloutput als SAMSG32 meldende Fernbedienung taucht in der kürzlichen Umfrage nicht auf. Das liegt daran, daß die mit "LG" beschriftete Fernbedienung eines Blu-Ray-Players normalerweise zwar in dieser Zunge spricht, aber auf NECisch umschaltet, wenn man einen rechts oben mit "TV" beschrifteten Block benutzt. Noch schlimmer ist eine originale Philips-Fernbedienung einer alten Stereoanlage, die schaltet ihre Tasten zwischen verschiedenen Codes um (Adresse und Commando) und ggfs. auch ganz ab, je nachdem, welches Gerät man einschaltet. Für den Benutzer soll das konsistent aussehen: Lautstärke ist Lautstärke und das Radio kann man nicht zurückspulen. :-)
:
Bearbeitet durch User
Wolfgang S. schrieb: > Ein Gag am Rande: die sich im Beispieloutput als SAMSG32 meldende > Fernbedienung taucht in der kürzlichen Umfrage nicht auf. Ich hab's nicht aufgeführt, weil Gerät und Fernbedienung ohne IRMP funktionieren, aber auf meinem IR-Spion sehe ich das Protokoll. Ich hatte mal eine Fernbedienung mit abweichendem Protokoll bei der On/Off-Taste. Damit rechnet man ja erstmal nicht.
Wolfgang S. schrieb: > Als erste Fingerübung habe ich IRMP darauf zum Laufen gebracht. Klasse. Ich werde Deine Änderungen gern in IRMP einbauen. Planst Du auch noch eine Portierung von IRSND? ;-) > Das liegt > daran, daß die mit "LG" beschriftete Fernbedienung eines Blu-Ray-Players > normalerweise zwar in dieser Zunge spricht, aber auf NECisch umschaltet, > wenn man einen rechts oben mit "TV" beschrifteten Block benutzt. Ja, sowas ist mir auch schon mal untergekommen. Ist aber selten.
Frank M. schrieb: > Wolfgang S. schrieb: >> Als erste Fingerübung habe ich IRMP darauf zum Laufen gebracht. > > Klasse. Ich werde Deine Änderungen gern in IRMP einbauen. Wie ich gerade sehe, hast Du schon. Das ging aber flott. :). > Planst Du auch noch eine Portierung von IRSND? ;-) Im Moment brauche ich das zwar nicht, da es aber keine besonderen neuen Anforderungen stellt, erledige ich das bei Gelegenheit nebenher.
Ein kurzer Bericht zum aktuellen Stand. Das Basteln mit dem ESP8266 gestaltet sich zäher als erwartet, hauptsächlich aufgrund der etwas unübersichtlichen Gemengelage aus unterschiedlichen SDK nebst eher dürftiger Dokumentation. Angefangen habe ich mit dem esp_iot_sdk_v1.4.1_pre5_15_10_27.zip Ziel ist zunächst mal eine kleine Anwendung, die auf bequeme Weise die von IRMP verstandenen Tastendrücke auf einem geeigneten Gerät per Browser oder App anzeigen kann. Code bereitstellen möchte ich noch nicht, da der ganze Aufbau noch zu sehr mit der heißen Nadel gestrickt ist, aber schon mal ein paar Zwischenergebnisse diskutieren. Das aktuelle Demoprogramm realisiert einen Accesspoint, der mit der festen SSID irmp432, via WPA2 und einer festen Passphrase einen DHCP- und einen Webserver auf der Adresse 192.168.4.1 realisiert und auf jeglichen http-Request mit einer Standard-HTML-Seite antwortet, wie sie in den ersten beiden Bildern gezeigt wird, einmal auf einem Android-Handy, dann im Firefox. Zu diesem Zweck habe ich ein Espressif-Beispiel gnadenlos abgespeckt. Gezeigt werden in umgekehrter chronologischer Reihenfolge die letzten maximal vierzig von IRMP erkannten Tastendrücke, die zu diesem Zweck in einem Ringpuffer aufgehoben werden. Bei jedem Webrequest wird der aktuelle Zustand gerendert, wobei der erneute Abruf der Seite mit einem Refresh-Tag getriggert wird, wenn der Browser mitspielt. Primitiv, aber wirksam. Zusätzlich schickt das Programm gleich beim Erkennen eines Tastendrucks eine entsprechende Teile an das UART sowie ein UDP-Paket. Eine entsprechende App (basierend auf dem hier https://play.google.com/store/apps/details?id=de.mystrobl.rechner) horcht auf diese Pakete und zeigt sie ohne zeitliche Verzögerung an, siehe drittes Bild. Falls jemand den aktuellen Stand ausprobieren möchte und weil das Binary nicht sonderlich groß ist, habe ich es ebenfalls hier angehängt. boot_v1.1.bin kann man aus dem SDK nehmen. Geflasht wird das hier wie folgt:
1 | esptool.py --baud=345600 --port=COM9 write_flash 0x00000 boot_v1.1.bin 0x01000 user1.2048.old.3.bin |
SSID wie oben genannt, pw ist 0123456789zwotzeL Abschließend noch zwei WifiAnalyzer-Screenshots. Inzwischen ist der esp_iot_sdk_v1.5.0 herausgekommnen, wie ich gerade gesehen habe. Nächstes Wochenende. :-)
Statt den im Vorposting gezeigten Entwurf weiter zu polieren, habe ich mich darauf beschränkt, diesen i.W. unverändert mit dem IOT-SDK 1.5.0 zu übersetzen, dies zusammen mit einem älteren Android-Tablet als kabelloses Kontrolldisplay für IR-Codes zu verwenden und erst mal eine andere Idee zu verfolgen, nämlich IRMP in die unter dem Namen NodeMCU bekannte Lua-Adaption (https://en.wikipedia.org/wiki/NodeMCU) einzubauen. Trotz einiger überraschender Hürden (s.w.u.) war das insgesamt weniger Aufwand als erwartet. http://nodemcu.com/index_en.html vermittelt zunächst den Eindruck einer Hardwareplattform. Tatsächlich ist aber die auf GitHub gehostete Firmware https://github.com/nodemcu/nodemcu-firmware problemlos mit dem ESP-Open-SDK https://github.com/pfalcon/esp-open-sdk übersetzbar und läuft dann anstandslos auch auf dem Olimex-Board (https://www.olimex.com/Products/IoT/ESP8266-EVB/open-source-hardware). So weit, so gut. Dann fangen die Probleme aber an. In der mit dem unveränderten Espressif-SDK realisierten IRMP-Adaption hatte ich den sog. Hardware-Timer aus der driver_lib verwendet, um Timer-Interrupts zuverlässig alle 67 µS (bei 15 kHz) realisieren zu können. Dummerweise fehlt aber NmiTimSetFunc(func) im esp-open-sdk in ets_sys.h und das aus gutem Grunde, denn ein dafür wiederum benötigtes externes Symbol fehlt in einer der nur als Object-Module verfügbaren Library, die im open-sdk verwendet wird. Selbst der auf Minimum 100 µs beschränkte Softwaretimer ist nicht verfügbar. Damit fehlt die wesentliche Grundlage für den Betrieb der IRMP-ISR. Es gibt aber einen Ausweg. Es läßt sich nämlich vergleichsweise einfach ein Interrupt an die steigende, fallende oder an beide Flanken eines Pegelwechsels an einem Pin binden. Der genaue Zeitpunkt steht über einen API-Call µs-genau oder über inline-Assembly sogar taktgenau zur Verfügung:
1 | #define STORE_CYCLES(r) do { \
|
2 | __asm__ __volatile__("rsr %0, CCOUNT \n\t" : "=a" (r)); \
|
3 | } while (0);
|
Zwar besagt das nichts über die zeitliche Genauigkeit des Interrupts selber, in der Praxis ist es aber offenbar hinreichend präzise für IRMP. Zusammen mit einem kleinen Ringpuffer läßt sich so ganz einfach eine Pulse-Train mitschreiben. Jedoch ist dies nicht das, was IRMP erwartet. Da IRMP allerdings völlig egal ist, wann und wie irmp_ISR() aufgerufen wird, lassen sich die Aufrufe ohne weiteres vor dem Aufruf von irmp_get_data nachholen. Ein positiver Nebeneffekt dieses Verfahrens besteht darin, daß der IR-Empfang nebenläufig und gepuffert erfolgt. Der Beispieloutput im Anhang zeigt z.B. das Dekodieren von 29 IRMP-Telegrammen am Klump aus bereits gepufferten IR-Daten. Modul irmp mit den drei Funktionen init, get_data und close. ---------- Funktionen ---------- irmp.init(int queuesize) -> 0 (no memory) oder 1 (ok) queuesize: Gesamtzahl von Pulsen und Lücken, die gepuffert werden. Wie viele pro Tastendruck verwendet werden, hängt vom Protokoll ab. irmp.get_data() -> protokollname(string) adress(int) command(int) flag(int) oder 0 (nichts) oder -1 (keine queue, closed) irmp.close() -> Queue wieder freigeben. Für das Herumprobieren damit war ESPlorer (http://esp8266.ru/esplorer/) nützlich. Lua, das ich mir erst bei der Gelegenheit oberflächlich angeeignet habe, hat ein etwas ungewöhnliches Features, das mit der Implementation von mehrfachen Rückgabewerten von Funktionen zu tun hat: http://www.lua.org/pil/5.1.html und das einige Verrenkungen erfordert, wenn man dergl. Listen tatsächlich verwenden möchte. Zwar ist es ziemlich einfach und elegant, mehrere Werte, auch unterschiedlich viele, von einem C-Programm aus abzuliefern - man kippt sie einfach nacheinander auf dem Stack ab - so einfach das aber ist, so umständlich ist es dann wieder in Lua, mit diesen etwas anzufangen. Leider hat eine der dafür benötigten Funktionen ("unpack") zwischen 5.1 und 5.3 ihren Namen bzw. Ort gewechselt (von globalem Namensraum zu Attribut von "tables"). Die einzige simple, auch mit variabel langen Rückgabelisten zurechtkommende Verfahrensweise, ein direkt auf einen Funktionsaufruf angewandter Table Constructor http://www.lua.org/pil/3.6.html funktioniert in der vorliegenden NodeMCU-Version nicht, es kommen nur zwei von vier oder mehr Rückgabewerten an. Zum Glück gibt es einen Workaround, das Einsammeln der Rückgabewerte läßt sich nachbilden: http://www.lua.org/pil/5.2.html. Dies erklärt die Funktion collect in dem nachfolgenden Schnipsel.
1 | require "irmp" |
2 | function collect(...) |
3 | return arg |
4 | end |
5 | function irmpg() |
6 | local r |
7 | repeat |
8 | r=collect(irmp.get_data()) |
9 | if #r>2 then print(string.format("%s(%d): addr=%04x cmd=%04x f=0x%02x ",unpack(r))) |
10 | else break end |
11 | until #r==1 |
12 | end |
13 | print (irmp.init(1000)) |
Wenn dieses Schnipsel ausgeführt wurde, können nachfolgend alle zwischenzeitlich aufgelaufenen Tastendrücke mit einem einfachen Aufruf von irmpg() dekodiert und über das UART angezeigt werden. Siehe Beispieloutput. Es wäre schön, wenn IRMP statt per Polling wahlweise auch per Pulse-Train mit Input versorgt werden könnte. Wenn ich mich erinnere, hattte Frank vor einer Weile mal angedeutet, über so etwas nachdenken zu wollen.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.