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:
- Versorgungsspannung: 2.7 ... 5.5V (abs. max. -0.3 ... 6.5V)
- Stromaufnahme: 0.6 ... 1 mA (typ. 0.8 mA)
- Empfangsempfindlichkeit: 20+ Meter (typ. 23 m)
- Empfangswinkel: &plusminus; 60°
- Trägerfrequenz: 38 kHz
- Pulsweite low: 500-700 µs (typ. 600 µs)
- Pulsweite high: 540-740 µs (typ. 640 µs)
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.