Den Raspberry Pi mit der Infrarot-Fernbedienung fernsteuern

Mein Projekt Always-On-Display, zuletzt erweitert durch einen BMP280 Barometer / Thermometer soll jetzt endlich eine Fernsteuerung bekommen, um die Screens durchzuschalten. Der erste Screen ist schon lange voll und ein zweiter, der mir den Webserver-Status anzeigt, ist auch schon fertig.

Für den Webserver-Status habe ich mir ein Windows-Programm für den Server gebaut, dass über WMI (Windows Management Instrumentation) die für mich interessanten Werte wie freies RAM, freier Plattenplatz, derzeitiger Netwerk-Traffic, CPU-Auslastung etc. ausliest und Textdateien im HTTP-Serververzeichnis schreibt. Der Raspi holt sich dann die Textdateien via HTTP vom Server und zeigt die Werte auf dem LCD an. So habe ich immer die Auslastung von meinem Webserver im Blick.

Auf den Teil der Informationsbeschaffung via Web will ich nicht groß eingehen. Trotzdem hier ein entsprechender Code-Schnippsel, wie man auf HTTP-Resourcen zugreift: import urllib # für HTTP-Abfragen ... # RAM frei r = urllib.urlopen ("http://mein-server.de/ram-free.txt").read() r=r.replace("\r\n","") r=r.replace(",",".") lcdMsg (1,0,"RAM: "+r)

Der 1838T Infrarot-Empfänger


Heute soll es um ein neues Bauteil gehen: den 1838T-IR-Empfangs-Chip. Der sieht aus wie eine dunkle LED mit einem Blechgehäuse, auf dessen Vorderseite sich ein X aus sich zwei kreuzenden Blechstreifen bildet. Das "38" im Namen wird wohl für die Trägerfrequenz von 38 kHz stehen.


Den 1838T gibt es auch als kleines Modul, wie rechts abgebildet. Meist befindet sich darauf einfach nur eine simple LED, die leuchtet, wenn IR-Signale empfangen werden.

Vorsicht! Die Anschlüsse am Header müssen nicht der Reihenfolge an der LED entsprechen. Bei mir waren es nämlich von oben nach unten, Header-Anschlüsse nach links: GND, VCC, OUT. Auch fehlte bei mir jegliche Beschriftung. Da hilft nur Durchmessen mit dem Durchgangsprüfer, welcher LED-Pin zu welchem Header-Pin passt.




Schaut man das Datenblatt zum 1838T genauer an, bemerkt man, dass sich im Blechgehäuse außer der eigentlichen LED auch noch ein paar Kondensatoren und Widerstände befinden.

Dadurch lässt sich der 1838er direkt an 3.3V oder 5V betreiben.

Die sonstigen technischen Daten sind:
Ein weiterer Blick ins Datenblatt gibt Aufschluss darüber, wie die Signale von der LED empfangen und weitergereicht werden.

Die Bits werden auf einer Trägerfrequenz von 38 kHz transportiert. Die Bits sind durch Highs und Lows definiert.



Das Prinzip

Mein erster Gedanke war: jeder der Knöpfe auf der Fernbedienung sendet einen unterschiedlichen Bitcode aus. Dann muss ich nur 38000 mal pro Sekunde den Input-Pin (bei mir BCM 22) abfragen und erhalte so ein Bitmuster, dass ich nur samt Tastenbezeichnung speichern muss. Das Bitmuster vergleiche ich beim nächsten Eingang wieder und kann so sagen, welche Taste gedrückt wurde.

Ich habe einfach einmal alle Bits per Schleife ausgeben lassen, die auf meinem GPIO-Input-Port aufliefen: ... 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ... In dem Wust von Einsen, was ja der Normalzustand ist, da der 1838T die Leitung per Pullup auf High zieht, gibt es einen Burst, bei dem sich Nullen und Einsen abwechseln.

Mit dem Code def waitForIRSignal(secs): # secs Sekunden auf IR-Fernbedienungseingabe warten zeros=0 ones=0 burst = "" for i in range(0,38000*secs): st=GPIO.input(pinIR) # normalzustand high if st == 0: zeros += 1 if st ==1: ones += 1 if zeros == 20: ones=0 # Einsen vor dem Burst weg if zeros > 20: # es tut sich was burst = burst + str(st) sleep (1/38000.) if zeros > 20 and ones > 50: #1. Nullerblock weg pos=burst.find("1") burst=burst[pos:len(burst)-1] #1. folgender Einserblock weg pos=burst.find("0") burst=burst[pos-1:len(burst)-1] print burst return burst return "" hatte ich erwartet, immer das gleiche Ergebnis beim Druck auf die selben Taste zu bekommen. Das Ergebnis aber war: Taste 1 10001110 00011 10001111 00001 10000111 00001 11000011 10000110000 10000111 00001 10000111 00001 11000011 10000 11100011 110001 10001110 00011 10001111 00011 10000111 00011 11000111 000 10000110 00011 10000111 00011 10000011 00001 11000011 10000111000 10000111 00001 10000111 00001 11000111 10001 11000011 10000011000 10000111 00011 10000111 00011 11000111 00001 11000111 100 10001111 00011 11000111 10001 11100011 10000 111000 10001110 00011 10001111 00011 11000111 00001 11000011 1000 10001110 00011 10000111 00011 11000111 00001 11000011 10000 10001110 00011 10000111 00001 10000111 00001 11000011 00001110000 Taste 2 10000111 00011 11000111 00001 11000011 10000 11100011 10000 10000111 00011 10000111 00011 11000111 00001 11000011 10000 10000111 00011 10000111 00001 11000011 10001 11100011 1100 10000111 00011 10000111 00001 11000111 10000 11100011 10000 10001111 00011 11000111 00001 11000011 10000 11100001 1100 10001110 00011 10000111 00001 11000011 10000 11100001 1100001 10000111 00001 11000011 10000 11000011 10000 11100001 110000111000 10000111 00001 11000011 10000 11100001 11000 01110000 11110000 10000111 00011 11000111 00001 11000011 10000 11100001 110000 10001111 00011 11000011 10000 11100001 11000 01110000 1 Der Raspi mit Python ist dann wohl nicht schnell oder genau genug, um 38.000 Ereignisse pro Sekunde zu überwachen. Hinzu kommt eine marginale Abweichung, weil die High-Signale länger als die Low-Signale sind. Bevor ich jetzt ewig mit dem Timings herumprobiere und dann doch zu dem Schluss komme, das Python dafür zu lahm ist, habe ich mich nach einer anderen Lösung umgeschaut.

LIRC

Mit LIRC (Linux Infrared Remote Control) bin ich fündig geworden. LIRC ist ein Paket, um unter Linux IR-LED zum Senden und Empfangen anzusteuern.

Zuerst aber muss der entsprechende Treiber in der Kommandozeile installiert werden: sudo apt-get install lirc liblircclient-dev Nach einer kleinen Weile ist der Raspi damit fertig und wir sollte die /etc/modules editieren, damit der Treiber auch nach einem Reboot zur Verfügung steht: sudo nano /etc/modules lirc_dev lirc_rpi gpio_in_pin=22 Dabei geben wir den BCM-GPIO-Port an, an dem die OUT-Leitung des IR-Sensors hängt - bei mir BCM 22. Außerdem sollten wir noch die Boot-Config ergänzen: sudo nano /boot/config.txt # Uncomment this to enable the lirc-rpi module dtoverlay=lirc-rpi,gpio_in_pin=22 Als weitere Datei benötigt es /etc/lirc/hardware.conf, die wir wie folgt anlegen: sudo nano /etc/lirc/hardware.conf # /etc/lirc/hardware.conf # # Arguments which will be used when launching lircd #LIRCD_ARGS="--uinput --driver=default --device=/dev/lirc0" LIRCD_ARGS="--uinput" # Don't start lircmd even if there seems to be a good config file # START_LIRCMD=false # Don't start irexec, even if a good config file seems to exist. # START_IREXEC=false # Try to load appropriate kernel modules LOAD_MODULES=true # Run "lircd --driver=help" for a list of supported drivers. DRIVER="default" # usually /dev/lirc0 is the correct setting for systems using udev DEVICE="/dev/lirc0" MODULES="lirc_rpi" # Default configuration files for your hardware if any LIRCD_CONF="" LIRCMD_CONF="" Zeit für einen Reboot: sudo reboot Danach können wir unser neues Device lirc einmal testen. Geben wir einfach mal alles in Hex aus, was dort aufläuft, was der Fall sein sollte, sobald wie eine Taste drücken: pi@raspberrypi:~ $ xxd /dev/lirc0 00000000: 1a1a 2a00 af23 0001 6d11 0000 6f02 0001 ..*..#..m...o... 00000010: 0302 0000 3f02 0001 2d02 0000 5502 0001 ....?...-...U... 00000020: 2902 0000 4702 0001 1b02 0000 7502 0001 )...G.......u... 00000030: fe01 0000 5c03 0001 0e01 0000 5c02 0001 ....\.......\... 00000040: 1902 0000 7902 0001 f201 0000 c002 0001 ....y........... 00000050: 0806 0000 4b02 0001 6e06 0000 3702 0001 ....K...n...7... 00000060: 9006 0000 dc02 0001 e305 0000 4d02 0001 ............M... 00000070: 7506 0000 4b02 0001 6e06 0000 3502 0001 u...K...n...5... 00000080: 9306 0000 8402 0001 3a06 0000 3302 0001 ........:...3... 00000090: 4b02 0000 b502 0001 a201 0000 5302 0001 K...........S... 000000a0: 7506 0000 5a02 0001 6306 0000 3202 0001 u...Z...c...2... 000000b0: 8902 0000 0602 0001 1702 0000 6c02 0001 ............l... 000000c0: 0402 0000 8d02 0001 dd01 0000 5202 0001 ............R... 000000d0: 7706 0000 4b02 0001 6b06 0000 5202 0001 w...K...k...R... 000000e0: 2002 0000 cf02 0001 9d01 0000 5002 0001 ...........P... 000000f0: 7806 0000 2d02 0001 8706 0000 3702 0001 x...-.......7... 00000100: 9306 0000 8802 0001 3306 0000 4e02 0001 ........3...N... Genaueres zeigt das mitgelieferte Tool mode2 an: pi@raspberrypi:~ $ mode2 --driver default --device /dev/lirc0 Using driver default on device /dev/lirc0 Trying device: /dev/lirc0 Using device: /dev/lirc0 space 16777215 pulse 351 space 637305 pulse 8993 space 4540 pulse 539 space 600 pulse 533 space 590 pulse 536 space 590 pulse 540 space 595 pulse 600 space 535 pulse 535 space 603 pulse 663 space 458 pulse 645 space 490 pulse 698 space 1539 Funktioniert es nicht auf Anhieb, müssen wir erst den Service stoppen, der das LIRC-Device exklusiv benutzt: sudo /etc/init.d/lircd stop Hier werden die Signallängen ausgegeben. Drückt man hier allerdings mehrmals die gleiche Taste, führt das noch nicht zum exakt gleichen Ergebnis. Es scheint wohl doch ein wenig komplexer zu sein.

Dank der LIRC-Entwickler muss ich das Rad aber nicht noch einmal neu erfinden. Es gibt sogar ein nettes kleines Tool, das die Tasten einer Fernbedienung für mich aufnimmt und in eine Config-Datei packt: irrecord --disable-namespace -d /dev/lirc0 ~/lircd.conf Mit diesem Tool kann man eine Konfigurationsdatei erstellen, in der die Codes für Tasten gespeichert werden. Man muss dazu jeweils den Namen* der Taste eingeben und diese dann eine Weile lang gedrückt halten, bis das Tool die Taste erkannt hat. pi@raspberrypi:~ $ irrecord --list-namespace |more KEY_0 KEY_1 KEY_102ND KEY_10CHANNELSDOWN KEY_10CHANNELSUP KEY_2 KEY_3 KEY_4 KEY_5 KEY_6 KEY_7 KEY_8 KEY_9 KEY_A KEY_AB KEY_ADDRESSBOOK KEY_AGAIN KEY_ALS_TOGGLE KEY_ALTERASE KEY_ANGLE KEY_APOSTROPHE KEY_APPSELECT KEY_ARCHIVE KEY_ATTENDANT_OFF KEY_ATTENDANT_ON KEY_ATTENDANT_TOGGLE KEY_AUDIO KEY_AUX KEY_B KEY_BACK KEY_BACKSLASH KEY_BACKSPACE KEY_BASSBOOST KEY_BATTERY KEY_BLUE KEY_BLUETOOTH KEY_BOOKMARKS KEY_BREAK KEY_BRIGHTNESSDOWN KEY_BRIGHTNESSUP KEY_BRIGHTNESS_AUTO KEY_BRIGHTNESS_CYCLE KEY_BRIGHTNESS_MAX KEY_BRIGHTNESS_MIN ... Für die Fernbedienung carmp3 entsteht dann ein solches File:
pi@raspberrypi:~ $ cat carmp3.lircd.conf # ... begin remote name carmp3 bits 64 eps 30 aeps 100 one 0 0 zero 0 0 pre_data_bits 64 pre_data 0x0 gap 187 toggle_bit_mask 0x0 frequency 38000 begin codes KEY_0 0x11EA0000010001D4 KEY_1 0x11E40000010001B8 KEY_2 0x11D400000100020E KEY_3 0x11DF0000010001D3 KEY_4 0x11E10000010001F2 KEY_5 0x11BC00000100020F KEY_6 0x02960000010001D3 KEY_7 0x121A0000010001E0 KEY_8 0x09220000010001D9 KEY_9 0x1199000001000211 KEY_A 0x11E200000100020F KEY_B 0x119000000100022C KEY_VOLUMEDOWN 0x11A900000100020A KEY_VOLUMEUP 0x08F90000010001D3 KEY_E 0x11DB0000010001C0 KEY_PREVIOUS 0x1184000001000268 KEY_NEXT 0x1146000001000252 KEY_PLAY 0x1181000001000251 KEY_CHANNELDOWN 0x112B000001000273 KEY_C 0x117A000001000264 KEY_CHANNELUP 0x11A7000001000248 end codes end remote Sollte man Fehler in der Art Now hold down button "KEY_0". Something went wrong: Cannot decode data Please try again. (23 retries left) bekommen, dann muss man irrecord im Force-Raw-Mode ausführen: irrecord -f -d /dev/lirc0 ~/lircd.conf Dies führt zu einem anderen Konfigurationsfile: # ... begin remote name carmp3 flags RAW_CODES|CONST_LENGTH eps 30 aeps 100 gap 107736 begin raw_codes name KEY_0 9388 4123 849 279 886 235 818 322 592 540 1950 313 848 282 727 403 756 1481 794 1444 617 1619 756 1480 645 1591 757 1489 530 1697 537 1700 536 594 700 1536 537 1708 530 594 700 1536 536 596 536 593 539 593 598 1638 652 480 537 593 727 1509 538 593 537 1701 751 1484 545 1692 538 name KEY_1 9373 4153 4292 191 5494 1281 887 1374 944 1292 960 1275 929 1307 988 1249 923 1321 918 1310 2031 181 1009 1276 956 1281 4303 168 953 1336 962 1274 3198 1301 877 1359 1016 1221 905 1330 925 name KEY_2 9357 4192 1979 269 858 273 895 203 891 274 814 294 880 275 850 282 819 1417 780 1456 824 1412 777 1468 785 1442 774 1463 793 1443 773 1463 823 308 782 349 769 361 808 1429 782 1453 812 319 788 344 780 352 775 1460 815 1422 751 1485 783 347 783 349 787 1449 808 1429 747 1488 809 name KEY_3 9306 4215 2000 238 2011 205 920 269 893 204 3204 1328 834 1404 925 1309 893 1344 893 1345 897 1339 887 1349 832 1404 913 160 986 1307 871 1365 936 1300 902 1336 2086 1283 864 264 865 1373 880 233 909 207 3232 1298 867 209 917 1373 888 name KEY_4 9397 4142 4267 250 907 176 954 183 3237 1313 990 1244 900 1337 893 1344 872 1375 884 1343 890 1344 923 1314 4305 1325 5429 1333 993 1245 907 1327 2071 1297 959 1278 856 1379 896 1340 937 name KEY_5 9335 4199 1992 267 7795 1230 936 1299 855 1384 1031 1204 964 1271 938 1299 938 1307 961 1268 900 179 2149 1270 908 1327 966 1270 4335 1294 960 1276 4353 1279 936 1300 959 1288 916 name KEY_6 9394 1876 937 name KEY_7 9298 1945 900 name KEY_8 9423 4128 873 224 8908 1272 934 1300 968 1268 937 1275 950 1321 929 1295 968 1268 914 1323 2027 1351 886 194 2045 1361 2099 1270 2076 1293 2146 1221 895 1341 2068 1309 2086 1271 906 name KEY_9 9397 4137 896 190 914 258 897 194 939 189 951 171 951 195 939 187 2067 1347 866 1370 925 1320 856 1371 890 1348 885 1350 918 1318 848 1390 831 299 916 1320 861 270 863 1375 2025 214 896 1363 883 227 878 1381 857 271 824 1414 874 253 893 1348 848 1390 823 308 816 1419 875 name KEY_VOLUMEDOWN 9371 4165 857 273 789 342 727 404 753 378 789 320 829 326 813 318 703 430 730 1505 785 1452 758 1486 780 1450 730 1505 760 1476 731 1506 849 1387 729 1508 702 1535 788 1448 679 430 790 364 822 310 874 246 793 346 756 376 729 402 789 321 901 1355 575 1663 887 1350 728 1507 875 1362 749 name KEY_VOLUMEUP 9397 4148 2020 182 4347 174 3230 1326 905 1332 916 1321 935 1301 908 1339 977 1250 937 1301 904 1333 904 1332 2054 1315 2064 1305 5447 1315 2046 1323 2070 1298 1036 1203 934 1302 1001 name KEY_E 9383 4154 824 305 874 252 869 267 894 205 904 259 892 208 926 201 2034 1370 888 1350 909 1336 816 1412 863 1375 889 1347 862 1374 939 1298 891 1345 1993 267 863 1377 2014 231 877 270 890 216 896 261 871 1368 889 1347 866 265 893 1344 922 1314 927 1310 892 1344 874 name KEY_PREVIOUS 9368 4163 3146 223 2055 201 4343 1315 893 1344 893 1352 885 1343 883 1353 920 1316 916 1320 900 1337 853 278 1988 1379 3121 271 869 1369 2094 1274 889 1347 2019 1357 902 1325 951 1286 2001 1365 975 name KEY_NEXT 9395 4150 9966 1311 929 1307 988 1249 939 1298 937 1300 1051 1186 903 1333 928 1308 7852 1173 2078 1300 1014 1212 934 1304 1019 1216 954 1292 1009 1219 899 184 1023 1263 910 name KEY_PLAY 9363 4145 4299 184 3179 247 2056 1321 964 1277 991 1242 930 1307 893 1343 935 1313 947 1279 953 1284 953 1284 893 1343 2030 206 2025 214 1008 1280 3165 177 919 1370 949 1288 932 1305 1083 1153 2069 1278 939 name KEY_CHANNELDOWN 9380 4140 2035 165 5461 252 2085 1288 904 1333 907 1330 929 1308 935 1311 860 1368 908 1329 933 1304 931 1306 2066 1302 3160 196 951 1326 897 192 2078 1332 2073 1296 901 1335 951 1286 2065 1304 937 name KEY_C 9412 4123 7703 158 2126 1310 919 1309 1015 1222 899 1338 893 1345 905 1333 936 1300 963 1274 2043 1326 902 1334 2028 196 2080 1327 2029 1349 3121 1372 900 1337 951 1285 912 168 1014 1276 875 name KEY_CHANNELUP 9447 4094 3165 178 4320 249 2067 1309 960 1275 967 1270 880 1358 967 1270 974 1272 982 1246 939 1297 971 1266 933 1305 943 1294 4303 1329 5469 1293 957 1281 898 1340 2108 1258 960 end raw_codes end remote Jetzt kopieren wir diese Config-Datei noch ins LIRC-Verzeichnis: sudo cp carmp3.lircd.conf /etc/lirc/lircd.conf Danach müssen wir den Treiber neu starten, damit er die neuen Konfigurationsdateien lädt: sudo /etc/init.d/lircd restart Weil ich schon festgestellt habe, wie schön empfindlich meine Empfangs-LED ist, habe ich die Hoffung, dass das Senden auch so gut geht (sonst nimmt man halt zwei oder drei parallele LEDs) und mir kommt schon eine Idee für die ultimative Universal-Fernbedienung und wie ich mit dem Tool alle Codes einlese, speichere und bei Bedarf wieder absenden kann. Und mich nicht mehr ärgern muss über Fernbedienungen, die man ganz exakt auf den IR-Empfänger im TV ausrichten muss, weil da jemand meinte, aus Designgründen eine monolithische Oberfläche in schwarzer Klavierlack-Optik schaffen zu müssen und dabei den IR-Empfangspegel auf 10% drosselte. Aber das wird ein anderes Projekt. (Spätere Anmerkung: Oder bleibt ein Traum, denn so einfach ist das mit LIRC auch nicht, wie wir im weiteren Verlauf sehen werden.)

Nun können wir die Fernbedienung mit dem Tool irw testen: pi@raspberrypi:~ $ irw 0000000000000007 00 KEY_6 carmp3 0000000000000007 01 KEY_6 carmp3 0000000000000007 02 KEY_6 carmp3 0000000000000007 00 KEY_6 carmp3 0000000000000007 01 KEY_6 carmp3 0000000000000007 02 KEY_6 carmp3 0000000000000007 03 KEY_6 carmp3 0000000000000007 04 KEY_6 carmp3 0000000000000007 00 KEY_6 carmp3 0000000000000007 01 KEY_6 carmp3 0000000000000007 02 KEY_6 carmp3 0000000000000007 03 KEY_6 carmp3 0000000000000007 04 KEY_6 carmp3 0000000000000007 00 KEY_6 carmp3 0000000000000007 00 KEY_6 carmp3 0000000000000007 00 KEY_6 carmp3 0000000000000007 01 KEY_6 carmp3 0000000000000007 02 KEY_6 carmp3 0000000000000007 03 KEY_6 carmp3 0000000000000007 04 KEY_6 carmp3 0000000000000007 00 KEY_6 carmp3 0000000000000007 01 KEY_6 carmp3 0000000000000007 02 KEY_6 carmp3 0000000000000007 03 KEY_6 carmp3 0000000000000007 04 KEY_6 carmp3 0000000000000007 05 KEY_6 carmp3 Dummerweise kommt bei jeder gedrückten Taste KEY_6 heraus. Das ist nicht richtig. Schaue ich in die Konfigurationsdatei, sehe ich, dass KEY_6 nur 3 Zahlen hat. Da passt wohl fälschlicherweise das meiste zu und LIRC sortiert das falsch ein. Jetzt muss ich wohl so lange mit Abstand und Winkel zum Empfänger herumprobieren, bis nicht nur Blödsinn, sondern die unterschiedlichen Tasten herauskommen. Was für ein Spaß (NICHT!).

Ich versuche mich, auf KEY_6 und KEY_7 zu beschränken. pi@raspberrypi:~ $ cat test2.lircd.conf begin remote name test2 flags RAW_CODES|CONST_LENGTH eps 30 aeps 100 gap 107719 begin raw_codes name KEY_6 9383 4146 4294 167 5584 1235 947 1289 927 1309 1006 1228 912 1324 876 1359 942 1294 938 1307 2027 1330 2069 1298 877 1359 2097 1269 2066 1300 2041 1325 3286 1212 2062 1303 899 name KEY_7 9474 4062 2023 165 6594 193 957 1338 937 1299 1023 1211 934 1311 925 1301 907 1330 873 1361 909 1327 901 178 996 1292 885 222 2032 245 2106 1270 884 240 910 1331 868 202 939 1359 873 1361 913 1332 898 1330 2122 1243 967 end raw_codes end remote Mit den beiden neuen Einträge für KEY_6 und KEY_7 überschreibe ich die alten in der carmp3.lircd.conf und kopiere sie erneut. Nach einem Restart des Service versuche ich mein Glück mit irw erneut. Jetzt wird gar nichts mehr erkannt.

Ich versuche testweise statt in 20cm Entfernung auf die IR-LED zu zielen, gerade vor mich auf den Monitor zu zielen, also fast 90° an der IR-LED vorbei. Die kleine Normal-Leucht-LED auf dem IR-LED-Modul blinkt. Es wird also etwas empfangen. Mit irremote erstelle ich eine weitere Config-Datei nur für die Tasten 1 bis 3 und starte wieder irw. Halte ich die Fernbedienung exakt wie vorher, so kann LIRC die Tasten 1, 2 und 3 auseinanderhalten und zeigt sie richtig an.

pi@raspberrypi:~ $ sudo cp test3.lircd.conf /etc/lirc/lircd.conf pi@raspberrypi:~ $ sudo /etc/init.d/lircd restart [ ok ] Restarting lircd (via systemctl): lircd.service. pi@raspberrypi:~ $ irw 0000000000000001 00 KEY_1 test3 0000000000000002 00 KEY_2 test3 0000000000000003 00 KEY_3 test3 0000000000000001 00 KEY_1 test3 0000000000000002 00 KEY_2 test3 0000000000000003 00 KEY_3 test3 0000000000000001 00 KEY_1 test3 0000000000000002 00 KEY_2 test3 0000000000000003 00 KEY_3 test3 0000000000000001 00 KEY_1 test3 0000000000000002 00 KEY_2 test3 0000000000000003 00 KEY_3 test3 0000000000000001 00 KEY_1 test3 0000000000000001 00 KEY_1 test3 0000000000000002 00 KEY_2 test3 0000000000000003 00 KEY_3 test3 0000000000000001 00 KEY_1 test3 0000000000000002 00 KEY_2 test3 0000000000000003 00 KEY_3 test3 0000000000000001 00 KEY_1 test3 0000000000000002 00 KEY_2 test3 0000000000000003 00 KEY_3 test3 0000000000000001 00 KEY_1 test3 0000000000000002 00 KEY_2 test3 0000000000000003 00 KEY_3 test3 0000000000000001 00 KEY_1 test3 Halte ich die Fernbedienung direkt auf die Empfang-LED aus 20 cm Abstand, wird gar nichts erkannt. Aus 3 m Entfernung an die Decke in Richtung LED gehalten funktioniert die Erkennung wieder und aus 3 m direkt auf die LED wieder nicht.

Ein ziemlicher Krampf. Man muss durch Trial und Error den richtigen Winkel und den richtigen Abstand zum programmieren finden, damit die Fernbedienung in möglichst vielen Situationen funktioniert. Und dazwischen immer wieder das config-File erstellen, kopieren und den Service restarten. Das braucht Geduld.

Mit der "Fernbedienung in einem cm Abstand vor den Sensor halten"-Methode - so wie man programmierbare Fernbedienungen anlernt, habe ich übrigens hier sehr schlechte Ergebnisse erzielt.

Die besten Ergebnisse habe ich erzielt, indem ich mit der Fernbedienung an die weiße Zimmerdecke ziele und die IR-LED nur die reflektierten Strahlen einfängt. Evtl. ist die Signalstärke ja zu hoch und ein Blatt Papier oder ein halbdurchsichtiges Stück Plastik würde für Dämpfung und besseren Empfang sorgen, auch wenn das auf den ersten Blick etwas paradox erscheint !?

Manchmal hakt es auch mit dem Treiber, das irw rein gar nichts ausgibt. Dann hilft zum Troubleshooting folgendes:

1. Stoppen des Background-Services: sudo /etc/init.d/lircd stop 2. Starten des Services im Vordergrund: sudo lircd --nodaemon -H default -d /dev/lirc0 3. Eine zweite Putty-Sitzung aufmachen und dort irw starten und die Ausgabe von evtl. Fehlermeldungen im 1. Fenster beobachten. Diese können sehr aufschlussreich sein, wo es hapert und man kann so leichter einer Fehlkonfiguration auf die Schliche kommen.

Den Raspi generell über irexec fernsteuern

Das mitgelieferte Programm irexec kann man über die Kommandozeile starten. Es wartet dann auf Signale von der Fernbedienung. Was irexec dann beim Empfang machen soll, ist in der Datei /etc/lirc/lircrc definiert, dessen Aufbau fast selbsterklärend ist: pi@raspberrypi:~ $ cat /etc/lirc/lircrc begin prog = irexec button = KEY_1 config = htop repeat = 0 end prog = irexec zeigt an, dass dieser Eintrag für das Programm irexec ist. Falls nun KEY_1 gedrückt wird, wird der Befehl htop (also die Prozessanzeige) ausgeführt. Wird die Taste gehalten, soll der Befehl nur einmal ausgeführt werden (repeat = 0).

So einfach kann man den Raspberry per Fernbedienung steuern und z. B. Kodi unter 1, Retropie unter 2 etc. ausführen. Beim Hochfahren mitgestartet spart man sich so die Tastatur zur Eingabe der Befehle auf der Kommandozeile.

Dies nur nebenbei, denn eigentlich wollen wir ja in Python auf die Fernbedienung zugreifen.

Zugriff im Python-Programm

Die nächste zu überwindene Hürde ist: wie können wir auf das LIRC-Device via Python zugreifen? Dahin ist es kein weiter Weg mehr. Zuerst brauchen wir das LIRC-Paket für Python, dass wir wie folgt installieren: sudo apt-get install python-lirc Als zweites benötigen wir noch eine eigene lircrc für unser Monitor-Programm: pi@raspberrypi:~ $ cat monitor.lircrc begin prog = monitor button = KEY_0 config = 0 repeat = 0 end begin prog = monitor button = KEY_1 config = 1 repeat = 0 end begin prog = monitor button = KEY_2 config = 2 repeat = 0 end begin prog = monitor button = KEY_3 config = 3 repeat = 0 end ... Da kommt für alle Tasten, die wir brauchen, ein Eintrag hinein, wobei das was hinter config steht, später an unseren Python-Code zurückgegeben wird. In Python gibt es dann nur sehr wenige Befehle: import lirc # für IR-Fernsbedienung socket = lirc.init("monitor", config_filename="/home/pi/monitor.lircrc", blocking=False) # Verbindung zu LIRC herstellen am Beginn des Programms. Und jedesmal, wenn wir einen Fernbedienungscode abfragen wollen, etwas in der Richtung def waitForIRSignal(secs): # secs Sekunden auf IR-Fernbedienungseingabe warten for i in range(0,secs*50): code=lirc.nextcode() if len(code) > 0: print code[0] return code[0] sleep (.02) return "" Wichtig hierbei der Befehl lirc.nextcode(), der den nächsten aufgelaufenen IR-Code vom LIRC-Treiber holt. Das ist auch schon alles, was man braucht.

Zwischen den Aktualisierungen des LCD warte ich immer eine (Zeit-Screen) bis einige Sekunden (Webserver-Screen, weil der jeweils ein halbes Dutzend HTTP-Abfragen absetzt), in der bisher nichts getan worden ist. Jetzt frage ich in dieser Wartezeit ab, ob eine Fernbedienungstaste gedrückt worden ist und schalte dementsprechend auf den gedrückten Screen (1-9), auf den nächsten (+ von der FB) oder den vorherigen (- von der FB).

Natürlich könnte ich noch weitere Befehle vom Raspi ausführen lassen wie etwa mit einem 433 MHz-Modul die Steckdose mit dem Licht einschalten.

Das Ergebnis