![]() |
Raspberry-Pi-Projekte: Infrarot-FernsteuerungProf. Jürgen Plate |
Ob Fernseher oder LED-Leiste - so ziemlich jedes Gerät verfügt heute über eine Infrarot-Fernbedienung. Das soll der Raspberry Pi keine Ausnahme bilden. Dabei kann er sowohl als Sender, wie auch als Empfänger arbeiten. Eine gebräuchliche Fernbedienung ist dabei relativ komplex: Zur Übertragung der einzelnen Befehle einer Fernbedienung wird eine Trägerfrequenz von 30 bis 40 kHz mit der Steuerinformation moduliert. Im Empfängersystem erfolgt dann die Demodulation. Das bedeutet schaltungstechnisch Filter, Verstärker, Demodulator usw. Eine insgesamt recht anspruchsvolle Aufgabe, die wir zum Glück der Industrie überlassen können. Es kommen nämlich integrierte Empfangsmodule zum Einsatz. Diese modernen Schaltkreise sind weit entfernt vom simplen Phototransistor, sie enthalten vielmehr eine Fotodiode mit integriertem Verstärker, der nicht nur durch entsprechende Filter an die verschiedenen Trägerfrequenzen angepasst ist, sondern auch seine Verstärkung abhängig von der einfallenden Signalamplitude automatisch regelt. Das folgende Bild zeigt die Blockschaltung des Bausteins.
Die Module bieten hohe Störsicherheit, benötigen nur 3,3 - 5 Volt Versorgungsspannung und haben ein logikkompatibles Ausgangssignal. Sie sind für die üblichen Frequenzen von 30, 33, 36, 38, 40 und 56 kHz erhältlich. Das erste dieser Module, das auf den Markt kam, war das SFH506 von Siemens. Es gibt diese Module inzwischen von verschiedenen Herstellern, wobei die Unterschiede nicht allzu groß sind. Man muss lediglich auf die Pinbelegung und auf die Basis-Trägerfrequenz achten. Das folgende Bild zeigt unterschiedliche Bauformen.
Achten Sie besonders auf die Pin-Zuordnung des verwendeten Empfänger-ICs (ggf. das Datenblatt zu Rate ziehen) und auf die Arbeitsfrequenz. Das Raspberry-System arbeitet mit 38 kHz.
Die Liste der Bezeichungen im Bild ist nur beispielhaft, es gibt noch zahlreiche andere ICs. Gut geeignet ist z. B. der TSOP4838, der sogar bei Amazon erhältlich ist. Beim Empfänger bewegen wir uns also auf sicherem, d. h. digitalem Niveau. Er kann direkt mit einem GPIO-Pin des Raspberry Pi verbunden werden. Das Empfängermodul selbst wird über einen Elektrolytkondensator stromversorgungsmäßig vom Rest der Schaltung entkoppelt. Siehe Schaltung weiter unten. Das Sendesignal wird vom Rechner erzeugt, hier werden nur eine Infrarot-LED und ein Treibertransistor benötigt. Um die Arbeitsweise der Sernderdiode zu überprüfen, eignet sich eine Digitalkamera oder das Smartphone. Derern Sensor hat einen weiteren Arbeitsbereich als das menschliche Auge und man kann das Aufleuchten der LED auf der Mattscheibe als Lichtpunkt erkennen.
Welche IR-Fernbedienung verwendet wird, spielt keine Rolle. Man kann sich iregend eine Universal-Fernbedienung besorgen. Allerdings sollte zum Testen keine Fernbedienung von vorhandenen Geräten gewählt werden, da sonst diese Geräte angesprochen werden. Wie später gezeigt wird, kann man jede Fernbedienung anlernen.
Keine Angst, die Software für Senden und Empfang müssen Sie nicht selbst schreiben. Es gibt bereits seit längerer Zeit ein Programmpaket für Linux, das uns die Arbeit abnimmt und sich "LIRC" nennt. "LIRC" ist ein Acronym für "Linux Infrared Remote Control". Es handelt sich dabei um ein Programmpaket für Linux, mit dessen Hilfe man Befehle von IR-Fernbedienungen zur Steuerung beliebiger Programme einsetzen kann. Nötig ist dafür lediglich ein Infrarot-Empfänger. Um die Signale von Fernbedienungen korrekt zu decodieren, benötigt man eine Konfigurationsdatei, die auf die jeweilige Fernbedienung abgestimmt ist. Man kann diese entweder selbst erstellen, indem man eine Fernbedienung "anlernt" oder man lädt eine passende Datei aus dem Internet herunter.
Der Infrarot-Empfänger hat drei Pins: Vcc, GND und Daten. Der VCC-Pin wird an 3,3 V des Raspberry Pi angeschlosse, GND an GND vom Pi und den Datenpin an einen freien GPIO-Port. Der Infrarot-Sender wird über einen weiteren GPIO-Port angesteuert und benötigt daneben auch einen GND-Anschluss und Vcc, wobei hier der 5-V-Anschluss verwendet wird. Parallel zum Digitalausgang des IR-Sensors und zur IR-Sende-LED ist jeweils noch eine kleine LED angeordnet. Diese LEDs erlauben die Kontrolle von Sendung und Empfang unabhängig von der Software. Für den Anschluss des IR-Empfängers ist der Anschluss fünfpolig ausgeführt, so dass sich die meisten ICs direkt einlöten lasssen - entweder rechtsbündig oder linksbündig.
Im Prinzip kann man IR-Empfänger und -Sender an beliebige Pins der GPIO-Stiftleiste des Raspberry Pi anschließen. Man sollte aber Pins vermeiden, die auch für andere Aufgaben wie I2C, SPI, PWM, UART etc. vorgesehen sind. Um den Anschluss möglichst kompakt zu gestalten, habe ich GPIO 23 und GPIO 24 (Pins 16 und 18) gewählt. Denn gleich neben Pin 18 kann auf Pin 17 die Versorgung mit 3,3 V abgegriffen werden und auch GND ist daneben auf den Pins 14 oder 20. Lediglich die Versorgung mit 5 V muss von Pin 4 aus erfolgen. Es gilt demnach:
Signal | GPIO (BMC) | GPIO-Pin |
---|---|---|
+5 V | - | 2 oder 4 |
+3,3 V | - | 17 |
GND | - | 14 oder 20 |
Empfang | 23 | 16 |
Senden | 24 | 18 |
Wichtig ist, daß die IR-Diode eine Wellenlänge von 900 bis 1100 nm hat, da dort die IR-Empfänger am empfindlichsten sind. Manche extrem starke IR-LEDs arbeiten oft im langwelligeren Bereich um 750 bis 780 nm, was für eine Fernbedienung nichts bringt. Diese LEDs sind eher für "Beleuchtungszwecke" gedacht. Als Sendediode eignen sich unter anderem HSDL-4230 OS-5038F (50 mA, 30°), LTE 5208A (100 mA, 40°), LTE 4208A (100 mA, 20°), SFH 4544 (100 mA, 10°), TSAL 6200 (100 mA, 17°), SFH4501 (100 mA, 14°), SFH4502 (100 mA, 32°) oder SFH4503 (100 mA, 8°). In der Schaltung wird die LED mit 5 V versorgt. Der Widerstand von 47 Ohm begrenzt den Strom auf ca. 80 mA.
Um die Signale des Infrarot-Empfängers im Raspberry Pi zu interpretieren und eigene Befehle über die Infrarot-LED senden zu können, verwenden Sie am Besten das Paket"Linux Infrared Remote Control" (LIRC). Im Paket ist alles enthalten, was man dafür benötigt. Weiterführende Informationen zu LIRC findet man auf der LIRC-Homepage. Das Paket befindet sich glücklicherweise in den Repositories, so dass die Installation recht einfach abläuft. Sinnvoller Weise installiert man die Python-Tools gleich mit dazu:
sudo apt-get -y install lirc python-lircNun sind einige Konfigurationen vorzumehmen. Zunächst teilt man den System mir, welcher Treiber für LIRC eingesetzt werden soll und welche GPIO-Pins verwendet werden. Bei der aktuellen Version von Raspbian reicht ein Eintrag in der Datei /boor/config.txt:
sudo echo 'dtoverlay=lirc-rpi,gpio_in_pin=23,gpio_out_pin=24' >> /boot/config.txtAchten Sie darauf, dass wirklich zwei Größerzeichen (>>) da stehen, sonst überschreiben Sie die Datei.
Bei älteren Versionen des Betriebssystems sind noch Einträge in der Datei /etc/modules notwendig (aber versuchen Sie erst, ob es nicht ohne geht). Auch hier wieder auf die zwei Größerzeichen (>>) achten:
sudo echo 'lirc_dev' >> /etc/modules sudo echo 'lirc_rpi gpio_in_pin=23 gpio_out_pin=24' >> /etc/modules
Nun werden die Konfigurationsdateien von LIRC angepasst. Zunächst nur die Datei /etc/lirc/hardware.conf. Die Änderungen sind farbig hervorgehoben. Danach kann schon mal getestet werden.
# /etc/lirc/hardware.conf # # Arguments which will be used when launching lircd 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=""Wenn Sie die oben beschriebenen Schritte nicht von Hand ausführen wollen, können Sie auch das unten in der Linkliste aufgeführte Installationsscript verwenden, das sich einfach mit dem folgenden Kommando ausführen läßt:
sudo bash setup_lirc.shNun muss der Raspberry Pi einmal booten, damit die ganzen Einstellungen wirksam werden.
Nach dem Reboot kann man zuerst einmal nachsehen, ob der Treiber geladen wurde. Die Ausgabe bei Ihnen muss nicht identisch sein, aber doch recht ähnlich aussehen (einige Zeilen wurden gekürzt):
$ dmesg | grep lirc [ 3.250820] lirc_dev: IR Remote Control driver registered, major 244 [ 3.258400] lirc_rpi: module is from the staging directory, ... [ 4.238316] lirc_rpi: auto-detected active low receiver on GPIO pin 23 [ 4.242044] lirc_rpi lirc_rpi: lirc_dev: driver lirc_rpi registered at minor = 0 [ 4.242085] lirc_rpi: driver registered! [ 10.812634] input: lircd as /devices/virtual/input/input0Dann kann man nachsehen, ob die Gerätedateien (Devces) eingerichtet wurden:
$ ls -l /dev/li* crw-rw---- 1 root video 244, 0 Sep 6 2034 /dev/lirc0 lrwxrwxrwx 1 root root 21 Sep 6 2034 /dev/lircd -> ../var/run/lirc/lircdOb die Kernelmodule geladen wurden, zeigt das Kommando lsmod. Im folgenden Output habe ich nur die Zeilen der lirc-Module aufgeführt:
$ lsmod Module Size Used by ... lirc_rpi 6422 3 ... lirc_dev 8110 1 lirc_rpi ...
$ sudo service lirc stop $ mode2 -d /dev/lirc0 space 2521608 pulse 9064 space 4421 pulse 653 space 474 pulse 655 space 474 pulse 654 space 475 pulse 653 space 476 pulse 658 space 471 pulse 652 space 477 pulse 653 ... ^CDie Codes werden also erkannt und damit ist die Hardware- und Treiberebene schon einmal in Ordnung. Falls keine Codes zu sehen sind oder Fehlermeldungen auftauchen, ist entweder der Empfänger nicht richtig angeschlossen oder er wurde nicht erkannt (Reboot vergessen?). Es kann auch sein, dass Sie eine Fernbedienung erwischt haben, die nicht auf 38 kHz sendet oder es sich gar eine Funkfernbedienung handelt. Hat allerdings alles bis hier funktioniert kann man den Test mit [STRG]+[C] abbrechen und den Daemon wieder starten:
$ sudo service lirc startExistiert bereits die Definition einer Fernbedienung, kann man auch die Funktionalität auf höherer Ebene testen (Näheres zur Definition von Fernbedienungen siehe unten beim Sendertest und dann beim Kapitel über das "Anlernen" einer Fernbedieung). Dazu startet man das Programm irw. Dies Programm decodiert die Infrarot-Befehle und liefert die Tasten als Klartext entsprechend der Definition. Zum Beispiel:
$ irw 0000000000000003 00 KEY_LEFT Keyes 0000000000000004 00 KEY_RIGHT Keyes 0000000000000001 00 KEY_UP Keyes 0000000000000002 00 KEY_DOWN Keyes 0000000000000005 00 KEY_OK Keyes 0000000000000006 00 KEY_0 Keyes ... ^CMit diesem Programm kann man auch testen, ob das "Anlernen" einer Fernbedienung korrekt funktioniert hat.
Nach der Installation ist die Datei lircd.conf mit den Tastendefinitionen der Fernbedienungen noch leer. Sie können nun entweder bestehende Konfigurationsdateien nutzen, sofern es welche für Ihre Fernbedienung gibt, oder eigene Tastendefinitionen aufgenommen werden. Den Inhalt der Datei kann man mit dem Kommando cat /etc/lirc/lircd.conf ansehen.
In dem Remote Projekt auf Sourceforce sind viele Fernbedienungen bereits erfasst. Außerdem liefert LIRC eigene Dateien mit:
$ ls /usr/share/lirc/remotes/ acer avermedia dvico kanam_accent pcmak sasem adaptec awlibusb ea65 knc_one philips sigma_designs adstech bestbuy ericsson kworld pinnacle_systems silitek animax caraca generic leadtek pixelview streamzap apple chronos hauppauge life-view provideo technisat asus cph03x hercules logitech README tekram atiusb creative imon mceusb remotec vlsystem aureal devinput iodata packard_bell samsung x10Ausgehend von einer vorhandenen Definition kann man den Sender testen. Ich habe eine Mini-Fernbedienung mit Zehnertastatur und fünf Steuertasten angelernt. Die Definition heisst "Keyes", weil das auf der Tastatur stand. Jetzt kommt der Trick: Das Sendesignal der IR-Diode wird vom Empfänger aufgenommen und vom RasPi angezeigt. Dabei müssen Sender und Empfänger nicht direkt aufeinander ausgerichtet sein, es genügt, wenn das ausgesendete Signal irgendwo genügend stark reflektiert wird. Für den Test wird das Programm irw im Hintergrund gestartet (der Output kommt aber nach wie vor auf der Standardausgabe raus). Dann kann man mittels irsend IR-Befehle aussenden, die dann von irw angezeigt werden. Wer will, kann natürlich auch irw und irsend in zwei verschiedenen Shell-Fenstern starten:
$ irw & # im Hintergrund laufen lassen [1] 3997 $ irsend SEND_ONCE keyes KEY_OK $ 0000000000000005 00 KEY_OK Keyes irsend SEND_ONCE keyes KEY_LEFT $ 0000000000000003 00 KEY_LEFT Keyes irsend SEND_ONCE keyes KEY_RIGHT $ 0000000000000004 00 KEY_RIGHT Keyes irsend SEND_ONCE keyes KEY_OK $ 0000000000000005 00 KEY_OK Keyes kill 3997 [1]+ Beendet irwDie Ausgabe von irw enthält am Ende den Namen der Taste (z. B. "KEY_LEFT") und den Namen der Fernbedienung, im Beispiel oben "Keyes". Der Name der Fernbedienung muss auch bei irsend angegeben werden. Auf dieses Programm wird später noch genauer eingegangen. Die Programme irw und irsend kommunizieren übrigens über einen UNIX Domain Socket mit dem Server. Der Standardport ist 8765. Die Information über den Socket holen sich die Programme aus der Datei /var/run/lirc/lircd.
Klappt die Kommunikation nicht wie oben, kann man mittels Digitalkamera oder Smartphone überprüfen, ob die IR-Sendediode überhaupt aufleuchtet. Falls nicht, müssen Sie Ihre Hardwae überprüfen. Möglicherweise belegt auch ein anderes Programm den GPIO-Port.
Zum Testen diverser Dinge kann man den LIRC-Daemon auch stoppen und im Vordergrund starten (also nicht als Daemon). Dies geschieht mit dem Kommando:
lircd --nodaemon --device /dev/lirc0 --driver default
Wie schon erwähnt, müssen Sie entweder eine vorhandene LIRC-Konfigurationsdatei für Ihre Fernbedienung finden oder mit Ihrem IR-Empfänger eine neue LIRC-Konfigurationsdatei erstellen. Der anzulernenden Fernbedienung sowie deren Tasten wird jeweils eine Bezeichnung zugewiesen. Im folgenden Beispiel nenne ich die Fernbedienung "Keyes" (der Name steht auf der Fernbedienung). Die Bezeichnungen der einzelnen Tasten sind seitens LIRC vorgegeben und Sie suchen sich aus dem Pool der vorgegebenen Bezeichnung eine möglichst passende für jede Taste aus.
Zum Anlernen der Fernbedieung dient das Tool irrecord. Vom Programm werden Sie aufgefordert, die Tasten zu benennen und dann auf der Fernbedieung die entsprechende Taste zu drücken. irrecord speichert dann den Tastencode unter dem angegebenen Namen. Welche Tastenbezeichungen standardmäßig verfügbar sind, erfahren Sie durch den Aufruf irrecord --list-namespace. Sie können aber auch freie Bezeichnungen wählen. Folgend Kommandos müssen Sie ausführen, um eine neue Konfigurationsdatei zu erzeugen. Die Datei nenne ich mal "Keyes.conf":
# Stoppen des lirc-Daemon, um /dev/lirc0 freizugeben $ sudo service lirc stop # Erstellen einer neuen Fernsteuerungskonfigurationsdatei irrecord -d /dev/lirc0 Keyes.conf # urspruengliche lircd.conf-Datei sichern sudo mv /etc/lirc/lircd.conf /etc/lirc/lircd.conf.orig # neue Konfigurationsdatei an die vorhandene anhängen sudo cat Keyes.conf >> /etc/lirc/lircd.conf # lirc-Daemin wieder starten $ sudo service lirc startStatt des cat-Kommandos können Sie die keyes.conf auch per Editor am Ende der Datei /etc/lirc/lircd.conf anfügen und dabei auch gleich unnötige Kommentarzeilen löschen. Nachdem Sie eine neue Konfigurationsdatei erstellt und an /etc/lirc/lircd.conf angehängt haben, können Sie Senden und Empfang wie oben beschrieben testen.
Hinweis: Gibt es in Zeile 1 der Datei /etc/lirc/lircd.conf der Eintrag "#UNCONFIGURED", muss dieser gelöscht werden. Der Eintrag wird bei der Erstinstallation erstellt. Ist er vorhanden erfolgt die Fehlermeldung "Reconfigure LIRC or manually replace /etc/lirc/lircd.conf to enable.", um den Benutzer darauf hinzuweisen.
Die beiden zum Testen verwendeten Fernbedienungen
Nun beginnt der Lernprozess. Die in den folgenden Schritten generierte Konfigurationsdatei für eine Fernbedienung wird zunächst im Heimatverzeichnis des Users (in der Regel /home/pi/) und dem Dateinamen Keyes.conf gespeichert. Sollte beim Anlernprozess etwas schief gehen, kann diese Datei wieder gelöscht und der Prozess von vorne begonnen werden. Das Programm führt den Benutzer durch den Prozess der Aufnahme. Die Liste der Keycodes hilft bei der korrekt Zuordnung.
Das Ganze dauert etwas länger, aber zum Schluss hat man eine Datei, in der alle Tasten der Fernbedienung enthalten sind. Um diese Datei verfügbar zu machen, müssen wir sie (nach dem Anpassen der Angaben im Kopf) in die bestehende Datei /etc/lirc/lircd.conf übertrage. Nur beim ersten Mal muss man die mitgelieferte /etc/lirc/lircd.conf wirklich überschreiben, weitere Konfigurationen für zusätzliche Fernbedienungen fügt man hinten an die Datei an. Das geht mit einem der beiden folgenden Kommandos:
sudo cat Keyes.conf >> /etc/lirc/lircd.confoder
cat Keyes.conf | sudo tee -a /etc/lirc/lircd.confDann können Sie das Anlernen starten:
$ irrecord -d /dev/lirc0 Keyes.conf irrecord - application for recording IR-codes for usage with lirc Copyright (C) 1998,1999 Christoph Bartelmus(lirc@bartelmus.de) This program will record the signals from your remote control and create a config file for lircd. A proper config file for lircd is maybe the most vital part of this package, so you should invest some time to create a working config file. Although I put a good deal of effort in this program it is often not possible to automatically recognize all features of a remote control. Often short-comings of the receiver hardware make it nearly impossible. If you have problems to create a config file READ THE DOCUMENTATION of this package, especially section "Adding new remote controls" for how to get help. If there already is a remote control of the same brand available at http://www.lirc.org/remotes/ you might also want to try using such a remote as a template. The config files already contain all parameters of the protocol used by remotes of a certain brand and knowing these parameters makes the job of this program much easier. There are also template files for the most common protocols available in the remotes/generic/ directory of the source distribution of this package. You can use a template files by providing the path of the file as command line parameter. Please send the finished config files to <lirc@bartelmus.de> so that I can make them available to others. Don't forget to put all information that you can get about the remote control in the header of the file. Press RETURN to continue. Now start pressing buttons on your remote control. It is very important that you press many different buttons and hold them down for approximately one second. Each button should generate at least one dot but in no case more than ten dots of output. Don't stop pressing buttons until two lines of dots (2x80) have been generated. Press RETURN now to start recording. ................................................................................ Found gap: 95848 Please keep on pressing buttons like described above. ................................................................................ Space/pulse encoded remote control found. Signal length is 71. Found possible header: 9083 4402 Found trail pulse: 663 Found repeat code: 9078 2142 Found repeat gap: 95902 Signals are space encoded. Signal length is 34 Now enter the names for the buttons. Please enter the name for the next button (press <ENTER> to finish recording) KEY_UP Now hold down button "KEY_UP". Something went wrong. Please try again. (9 retries left) Something went wrong. Please try again. (8 retries left) Something went wrong. Please try again. (7 retries left) Something went wrong. Please try again. (6 retries left) Something went wrong. Please try again. (5 retries left) Something went wrong. Please try again. (4 retries left) Something went wrong. Please try again. (3 retries left) Something went wrong. Please try again. (2 retries left) Something went wrong. Please try again. (1 retries left) Something went wrong. Try using the -f option.Da ging wohl etwas schief! Auch für Fernbedienungen gibt es verschiedene Formen der Datencodierung. Das Programm kennt die gebräuchlichsten Codes wie z. B. RC5. Meine Fernbedienung aus dem fernen Osten verwendet wohl einen etwas exotischen Code. Aber auch den bekommt man angelernt. Den Tipp hat irrecord ja schon in der letzen Zeile gegeben: "Try using the -f option". Genau das wird nun gemacht. Vorher müssen Sie die erstellte Datei mit dem Tastendefinitionen aber wieder löschen (den langen Vorspann habe ich nicht noch einmal aufgelistet und das Protokoll nach einigen Tasten gekürzt):
pi@bienenhaus ~/lirc $ irrecord -f -d /dev/lirc0 Keyes.conf irrecord - application for recording IR-codes for usage with lirc Copyright (C) 1998,1999 Christoph Bartelmus(lirc@bartelmus.de) ... Press RETURN now to start recording. ................................................................................ Found const length: 107816 Please keep on pressing buttons like described above. Creating config file in raw mode. Now enter the names for the buttons. Please enter the name for the next button (press <ENTER> to finish recording) KEY_UP Now hold down button "KEY_UP". Got it. Signal length is 67 Please enter the name for the next button (press <ENTER> to finish recording) KEY_DOWN Now hold down button "KEY_DOWN". Got it. Signal length is 67 Please enter the name for the next button (press <ENTER> to finish recording) KEY_RIGHT Now hold down button "KEY_RIGHT". Got it. Signal length is 67 Please enter the name for the next button (press <ENTER> to finish recording) KEY_LEFT Now hold down button "KEY_LEFT". Got it. Signal length is 67 Please enter the name for the next button (press <ENTER> to finish recording) KEY_OK Now hold down button "KEY_OK". Got it. Signal length is 67 Please enter the name for the next button (press <ENTER> to finish recording) KEY_NUMERIC_POUND Now hold down button "KEY_NUMERIC_POUND". Got it. Signal length is 67 Please enter the name for the next button (press <ENTER> to finish recording) KEY_NUMERIC_STAR Now hold down button "KEY_NUMERIC_STAR". Got it. Signal length is 67 Please enter the name for the next button (press <ENTER> to finish recording) KEY_0 Now hold down button "KEY_0". Got it. Signal length is 67 Please enter the name for the next button (press <ENTER> to finish recording) KEY_1 Now hold down button "KEY_1". Got it. Signal length is 67 Please enter the name for the next button (press <ENTER> to finish recording) KEY_2 Now hold down button "KEY_2". Got it. Signal length is 67 ... Please enter the name for the next button (press <ENTER> to finish recording)Die Datei mit den Codes hat dann folgendes Aussehen. Auch hier habe ich nach einigen Tasten gekürzt. Kommentarzeilen beginnen mit einem Doppelkreuz (#). Diese kann man mit einem Editor entfernen, bevor man die Datei an die /etc/lirc/lircd.conf anhängt (einmal der Kommentar sollte reichen). Dann kann man noch die Zeile "name" ändern, wenn man den Dateinamen nicht passend gewählt hat (so wie ich). Der Name wird nämlich beim Tastenempfang ausgegeben, denn er identifiziert die Fernbedieung. Auch beim Senden (siehe unten) muss man ihn angeben. Ich habe vor dem Speichern "Keyes.conf" in Keyes" geändert.:
# Please make this file available to others # by sending it to <lirc@bartelmus.de> # # this config file was automatically generated # using lirc-0.9.0-pre1(default) on Sat Nov 25 09:51:47 2017 # # contributed by # # brand: Keyes.conf # model no. of remote control: # devices being controlled by this remote: # begin remote name Keyes.conf flags RAW_CODES|CONST_LENGTH eps 30 aeps 100 gap 107816 begin raw_codes name KEY_UP 9112 4372 706 453 675 454 675 459 670 455 677 452 677 452 676 454 675 454 677 1528 708 1534 700 1530 706 1530 703 1532 704 1531 706 1534 702 1529 706 454 675 1531 706 1529 705 459 673 452 674 455 677 1530 704 454 675 1531 705 454 675 459 672 1529 706 1530 706 1529 704 455 676 1530 706 name KEY_DOWN 9102 4381 677 483 639 495 664 460 665 465 668 462 664 464 639 490 640 490 639 1566 670 1570 660 1571 662 1573 666 1568 660 1581 660 1571 661 1574 662 1574 662 496 631 1580 631 522 608 1598 638 521 632 498 633 495 634 496 632 1578 658 496 632 1573 664 496 637 1568 636 1598 666 1571 661 name KEY_RIGHT 9031 4452 624 505 624 505 626 503 625 504 625 504 622 506 626 503 626 503 624 1610 625 1610 626 1609 625 1611 624 1608 626 1609 626 1608 627 1609 627 1607 627 1607 627 504 651 477 650 479 626 502 635 1599 627 503 627 501 627 503 650 1583 654 1580 631 1604 626 1609 631 498 628 1606 654 ...Bei einer Fernbedienung für ein LED-Band mussten keine Raw-Werte erfasst werden, in solchen Fällen ist die Defintion wesentlich kompakter:
begin remote name Ledband bits 16 flags SPACE_ENC|CONST_LENGTH eps 30 aeps 100 header 8892 4443 one 593 1643 zero 593 521 ptrail 578 repeat 8900 2195 pre_data_bits 16 pre_data 0xFF gap 107877 toggle_bit_mask 0x0 begin codes KEY_BRIGHTNESSUP 0xA05F KEY_BRIGHTNESSDOWN 0x20DF KEY_POWER2 0x609F KEY_POWER 0xE01F KEY_RED 0x906F KEY_YELLOW 0x8877 KEY_GREEN 0x10EF KEY_BLUE 0x50AF KEY_0 0xD02F KEY_1 0xB04F KEY_2 0x30CF KEY_3 0x708F KEY_4 0xA857 KEY_5 0x28D7 KEY_6 0x6897 KEY_7 0x9867 KEY_8 0x18E7 KEY_9 0x58A7 KEY_PROG1 0xF00F KEY_PROG2 0xE817 KEY_PROG3 0xD827 KEY_PROG4 0xC837 end codes end remoteNachdem die Konfiguration an die /etc/lirc/lircd.conf angefügt und der LIRC-Daemon wieder gestartet wurde, kann man die Fernbedienung mit dem Programm irw testen:
$ irw 0000000000000003 00 KEY_LEFT Keyes 0000000000000001 00 KEY_UP Keyes 0000000000000004 00 KEY_RIGHT Keyes 0000000000000002 00 KEY_DOWN Keyes 0000000000000005 00 KEY_OK Keyes 0000000000000006 00 KEY_0 Keyes 0000000000000006 00 KEY_0 Keyes 000000000000000d 00 KEY_7 Keyes ^C
Um Programme per Fernbedienung zu beeinflussen gibt es zwei Möglichkeiten: Das mitgelieferte Tool irexec und ein Python-Programm mit der zugehörigen Library. Für das Programm irexec wie für Python wird eine wie folgt gestaltete Konfigurationsdatei benötigt. In dieser Datei können auch mehrere Aktionen für Fernbedienungstasten und sogar für mehrere Fernbedienungen festgelegt werden. Dazu muss für jede Taste ein Block "begin" ... "end" erstellt werden. Die Konfigurationsdatei kann entweder im Heimatverzeichnes des Benutzers liegen (sie heisst dann ".lircrc" oder sie wird global für alle im LIRC-Verzeichnis als /etc/lirc/lircrc abgelegt. Im Folgenden werden nur die nötigsten Optionen der Konfiguration besprochen. Für weitergehende Informationen und spezielle Tricks müssen Sie die Homepage von LIRC aufsuchen.
Option | Beschreibung |
---|---|
prog | gibt den Namen des Programms an, dem der in config angegebene Configstring als Parameter übergeben wird. |
remote, button | gibt die Fernbedienung und die Taste der Fernbedienung an, die eine Aktion auslöst. Tastensequenzen können festgelegt werden, indem mehr als eine Remote-/Tastenzeichenfolge angegeben wird (nicht in der gleichen Zeile, sondern mit separaten Remote-/Tasten-Token in separaten Zeilen). Das Zeichen '*' kann als Jokerzeichen für die Fernbedienung oder die Taste verwendet werden. Der Standardwert für remote ist '*'. Der Remote-Name muss immer vor der entsprechenden Taste angegeben werden. Bei Verwendung von Tastenfolgen gilt eine gegebene Fernbedienung für alle folgenden Tasten, bis Sie eine andere Fernbedienung angeben. |
repeat | teilt dem Programm mit, was geschehen soll, wenn eine Taste wiederholt wird. Ein Wert von 0 weist das Programm an, Tastenwiederholung zu ignorieren. Jeder andere positive Wert 'n' weist das Programm an, die Konfigurationszeichenfolge jedes 'n'-te Mal an die entsprechende Anwendung zu übergeben, wenn die Taste wiederholt wird. Der Standardwert für repeat ist 0. |
delay | weist das Programm an, die angegebene Anzahl von Tastenwiederholungen zu ignorieren, bevor die Konfigurationsanweisung repeat von oben verwendet wird. Dies dient dazu, doppelte Trigger von Ereignissen zu verhindern, wenn eine schnelle Wiederholungsrate verwendet wird. Ein Wert von 0 (Defaultwert) deaktiviert die Verzögerungsfunktion. Wenn der repeat-Wert 0 ist, aber delay gesetzt ist, wird ein einzelnes Ereignis erzeugt, das nach Ablauf der Verzögerungsperiode erzeugt wird. |
ignore_first_events | ignoriert beim ersten Mal die angegebene Anzahl an Ereignissen. Die Funktion ähnelt repeat, aber ohne ein Ereignis, bevor die Verzögerungszeit beginnt. Dies ermöglicht es, die Reaktion bei langen Tastendrücken zu definieren. Sollte nicht zusammen mit delay gesetzt werden. |
config |
ist die Parameterfolge (Zeichenkette), die immer dann an die entsprechende Anwendung
übergeben wird, wenn die angegebene Tastenfolge von lircd empfangen wird. Wenn Sie
mehr als eine Konfigurationszeichenfolge angeben, werden die Konfigurationszeichenfolgen
abwechselnd an die Anwendungen übergeben. Mit dieser Funktion können Sie zum Beispiel
Toggle-Buttons implementieren. Sie können nicht druckbare Zeichen an Anwendungen mit allen Standard-C-Escape-Sequenzen übergeben (am häufigsten sind: \n = Zeilenvorschub, \r = Wagenrücklauf, \t = tab, \e = escape, \nnn = ASCII-Code in oktaler Darstellung, \xnn = ASCII-Code in hexadezimaler Darstellung, \\ = Backslash). |
Wenn beim Einsatz der Datei die Fehlermeldung "lirc.IntiError: unable to load default conifg [...]" auftritt, hat die Datei vermutlich einen Formatierungsfehler, etwa ein vergessenes "end".
Die Konfigurationsdatei besteht, wie gesagt aus lauter "begin" ... "end"-Blöcken für die einzelnen Tasten. Der Aufbau eines Blocks ist:
begin remote = <Name der Fernbedienung> prog = irexec button = <Name der Taste> config = <Auszuführende Aktion = externes Programm> repeat = <Anzahl Wiederholungen (0)> endDas könnte zum Beispiel für die Beispiel-Fernbedieung folgendermaßen aussehen:
begin remote = Keyes prog = irexec button = KEY_OK config = echo "You pressed OK" repeat = 0 end begin remote = Keyes prog = irexec button = KEY_UP config = echo "You pressed UP" repeat = 0 end begin remote = Keyes prog = irexec button = KEY_DOWN config = echo "You pressed DOWN" repeat = 0 end ...Solche Blöcke werden nun für einige weitere Tasten eingerichtet. Dann kann man versuchsweise das Programm irexec auf der Kommandozeile starten:
$ irexec You pressed OK You pressed LEFT You pressed DOWN You pressed OK You pressed RIGHT You pressed UP You pressed DOWN You pressed OK ^CMan kann irexec mit der Option -n auch sagen, auf welchen Programmnamen einer Konfiguration es hören soll. Es wird noch der folgende, weitere Block zur Konfiguration hinzugefügt:
begin remote = Keyes prog = foobar button = KEY_OK config = echo "You pressed foobar-OK" repeat = 0 endMit dem Kommando irexec -n foobar wird nun nur noch die eine OK-Taste erkannt und gemeldet:
$ irexec -n foobar You pressed foobar-OK ^CNicht zuletzt kann irexec auch als Daemon-Prozess im Hintergrund laufen. Dann kann man das nicht mehr mit den einfachen echo-Kommandos testen, weil der Daemon nicht auf die Konsole schreibt. Sie könnten es aber beispielsweise mit echo "..." > /home/pi/ip.log (also Umleitung der Ausgabe) ausprobieren. Der Start von irexec als Daemon kann auch in einem Startscript oder in der Datei etc/rc.local erfolgen. Wichtig ist in diesem Fall auch den Pfad zur Konfigurationsadatei anzugeben. Die Kommandozeile lautet dann:
irexec --daemon /etc/lirc/lircrcUnter config können beliebige Kommandos stehen, z. B. zur Steuerung eines Mediaplayers oder des oben erwähnten LED-Bandes.
Nun sind die einzelnen Tasten richtig konfiguriert und den Tasten können Aktionen zugewiesen werden. Das geht nicht nur mit dem oben gezeigten Tool, sondern auch mit Python. Die Einbindung in Python ist auch recht einfach, denn für Python gibt es eine eigene LIRC-Bibliothek, die ja anfangs schon gleich mit installiert wurde.
Für die Anwendungen mit Pyton habe ich die Definitionen in der Datei /etc/lirc/lircrc erweitert, indem ich die vohandenen Zeilen kopiert und dann bearbeitet habe:
begin prog = monty button = KEY_UP config = UP repeat = 0 end begin prog = monty button = KEY_DOWN config = DOWN repeat = 0 end begin prog = monty button = KEY_RIGHT config = RIGHT repeat = 0 end begin prog = monty button = KEY_LEFT config = LEFT repeat = 0 end begin prog = monty button = KEY_OK config = OK repeat = 0 end begin prog = monty button = KEY_NUMERIC_POUND config = FIN repeat = 0 end
Der Python-Code ist recht einfach. Es muss nur die Bibliothek eingebunden und eine Verbindung zum LIRC-Daemon hergestellt werden. Das erreicht man mit den Zeilen:
import lirc sock = lirc.init("monty")Der Name in der Klammer der Init-Methode ("monty") muss der gleiche sein, wie in der Datei /etc/lirc/lircrc. Mit der Methode lirc.nextcode() wird auf den nächsten Tastendruck der Fernbedienung gewartet. Es wird der Name der Taste zurückgegeben. Wird eine Taste gedrückt, die nicht in der /etc/lirc/lircrc aufgeführt ist, gibt lirc.nextcode() einen leeren String zurück. Das folgende Programm wartet in einer Schleife auf eine Fernbedienungstaste und gibt deren Wert aus. Wird die [#]-Taste gedrückt, beendet sich das Programm.
#!/usr/bin/env python import lirc sock = lirc.init("monty") while True: code = lirc.nextcode() print code if "FIN" in code: quit()Die Ausgabe sieht dann z. B. folgendermaßen aus. Nach "OK" wirde die "1" gedrückt, was einen leeren String zur Folge hatte:
$ python test1.py [u'DOWN'] [u'UP'] [u'LEFT'] [u'RIGHT'] [u'OK'] [] [u'OK'] [u'FIN']Wie man sieht, ist das Ergebnis immer eine Liste. Mittels len(code) kann man auch feststellen, ob ein gültiger Tastenwert emfangen wurde.
Will man für das Python-Programm eine andere (z. B. eigene) Konfigurationsdatei verwenden, kann man das bei der Initialisierung machen, indem man den Dateinamen angibt und dann die Datei lädt:
#!/usr/bin/env python import lirc sock = lirc.init("monty", "lircrc") lirc.load_config_file("/home/pi/lirc/lircrc") while True: code = lirc.nextcode() print code if "FIN" in code: quit()Normalerweise ist es programmiertechnisch nicht ratsam, auf externe Tastedrücke bis in alle Ewigkeit zu warten, sondern das Programm kann sinnvolle Dinge erledigen, während keine Taste betätigt wurde. Für solche Fälle kann man lirc.nextcode im "non blocking mode" betreiben. Beim Aufruf von lirc.nextcode wird sofort ein Wert zurückgegeben, der dann meist leer ist. Das kann man im Programm leicht abprüfen. Im Beispiel wird 0.2 Sekunden geschlafen, wenn keine Taste gedrückt wurde:
#!/usr/bin/env python import lirc, time sock = lirc.init("monty", blocking=False) while True: code = lirc.nextcode() if len(code) > 0: print code else: time.sleep(0.2) if "FIN" in code: quit()Das Blocking kann man auch im laufenden Programm ein- und ausschalten:
lirc.set_blocking(True, sock) lirc.set_blocking(False, sock)
Natürlich gibt es auch eine Bibliothek für die C-Programmierer. Diese muss man extra installieren, was mit folgenden Kommando erledigt wird:
sudo apt-get install liblircclient-devIm Quelltext des C-Programms müssen dann die C-Headerdateien mittels #include <lirc/lirc_client.h> eingebunden werden. Beim Compilieren ist dann die LIRC-Library einzubinden. Angenommen, das Programm steht in der Datei t5.c, würde der Compiler mit folgenden Kommando aufgerufen:
gcc -Wall -o t5 t5.c -llirc_clientDie Programmierung selbst ist ähnlich wie bei Python. Nach der Verbindungsaufnahme zum LIRC-Daemon liefert die Funktion lirc_nextcode() den nächsten Tastencode. Bei C wird nicht-blockiernd gelesen, sodass die Funktion den Wert NULL im Parameter zurückgibt, wenn kein Fernbedienungsbefehl vorliegt. Der Returnvalue der Funktion ist normalerweise 0, nur im Fehlerfall ungleich 0.
Vor- und Nachspann sind bei C etwas aufwendiger, aber isgesamt ist die Programmierung genauso einfach wie bei Python. Für genauere Informationen sei auf die Dokumentantion zu lirc_client.h verwiesen. Das folgende Beispielprogramm zeigt die Anwendung der Bibliothek:
#include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <lirc/lirc_client.h> /* compile with: gcc -Wall -o t5 t5.c -llirc_client */ int main(int argc, char *argv[]) { struct lirc_config *config; char *code; int FIN = 0; /* LIRC initialisieren */ if(lirc_init("lirc",1) == -1) { perror("Kann lirc nicht initialisieren"); exit(EXIT_FAILURE); } /* Default-LIRC-config von /etc/lirc/lircd.conf einlesen */ if(lirc_readconfig(NULL,&config,NULL) != 0) { perror("Kann lirc config nicht einlesen"); lirc_deinit(); exit(EXIT_FAILURE); } /* Taste der Fernbedienung einlesen */ while(FIN == 0) { /* Rueckgabewert von lirc_nextcode bei Fehler != 0 */ FIN = lirc_nextcode(&code); /* 500 ms warten */ usleep(500000); /* code == NULL -- keine Taste betaetigt, keine Aktion */ if(code != NULL) { /* code auswerten */ if(strstr (code,"KEY_1")) { printf("KEY_1\n"); } else if(strstr (code,"KEY_2")) { printf("KEY_2\n"); } else if(strstr (code,"KEY_3")) { printf("KEY_3\n"); } else if(strstr (code,"KEY_OK")) { printf("KEY_OK -- Bye\n"); FIN = 1; } } /* Pointer code bei jedem Durchlauf freigeben */ free(code); } /* config-Datenstruktur freigeben */ lirc_freeconfig(config); /* Verbindung zum LIRC-Daemon beenden */ lirc_deinit(); exit(EXIT_SUCCESS); }
Den Kommandozelen-Befehl für das Senden habe Sie ja schon oben beim Test kennen gelernt. Hier wird er etwas genauer erläutert. Die allgemeine Syntax des Kommandos lautet
irsend [options] <Direktive> <Fernbedienung> <Tastencode< ...Eine Liste aller in der Datei /etc/lirc/lircd.conf konfigurierten Tastencodes einer Fernbedienung erhält man mit folgendem Kommando:
$ irsend LIST "" "" irsend: Keyes $ irsend LIST Keyes "" irsend: 0000000000000001 KEY_UP irsend: 0000000000000002 KEY_DOWN irsend: 0000000000000003 KEY_LEFT irsend: 0000000000000004 KEY_RIGHT irsend: 0000000000000005 KEY_OK irsend: 0000000000000006 KEY_0 irsend: 0000000000000007 KEY_1 irsend: 0000000000000008 KEY_2 irsend: 0000000000000009 KEY_3 irsend: 000000000000000a KEY_4 irsend: 000000000000000b KEY_5 irsend: 000000000000000c KEY_6 irsend: 000000000000000d KEY_7 irsend: 000000000000000e KEY_8 irsend: 000000000000000f KEY_9 irsend: 0000000000000010 KEY_NUMERIC_STAR irsend: 0000000000000011 KEY_NUMERIC_POUNDDas Senden geht dann ganz einfach, z. B.:
$ irsend SEND_ONCE Keyes KEY_OK $ irsend SEND_ONCE Keyes KEY_1 $ irsend SEND_ONCE Keyes KEY_NUMERIC_POUNDWenn der LIRC-Daemon nicht läuft oder die Zugriffsrechte nicht stimmen, beendet sich irsend mit einer der folgenden Fehlermeldungen:
irsend: could not connect to socket irsend: Connection refused irsend: Permission deniedObwohl man bei irsend auch mehrere Tastencodes auf einmal senden könnte, sollte man nach jeder gesendeten Taste etwas warten, weil meist die empfangenden Geräte nicht so fix mit der Auswertung und Reaktion sind. Neben SEND_ONCE gibt es noch weitere Direktiven:
Direktive | Bedeutung |
---|---|
SEND_ONCE | sende CODE einmal |
SEND_START | starte andauerndes Senden von CODE |
SEND_STOP | stop andauerndes Senden von CODE |
LIST | liste mögliche Tastencodes (s. oben) |
Bei den Optionen kann man mittels "-d" das Device angeben (z. B.: irsend -d /dev/lirc0 ...); "-v" liefert die Versionsnummer und mit "--count=n" kann das Kommando automatisch n-mal wiederholt werden - es wird also n+1 mal gesendet.
Für das Senden von Infrarot-Signalen benötigen Sie bei Python keine Bibliothek, sondern Sie können einfach loslegen. Dazu nutzen Sie die Möglichkeit, aus einem Python-Script heraus Kommandozeilenbefehle abzusetzen, die das Programm irsend aufrufen. Dazu kann man sich eine kleine Funktion schreiben:
def irsend(directive, remote, code): import subprocess rtn = subprocess.call(["/usr/bin/irsend", directive, remote, code]) # rtn == 0 bedeutet "OK", rtn != bedeutet "Fehler" return rtnEin Testprogramm dazu definiert eine Liste mit fünf Tastennamen und wählt dann per Zufallsfunktion eine der Tasten aus, die dann gesendet wird.
#!/usr/bin/env python import time, random def irsend(directive, remote, code): import subprocess rtn = subprocess.call(["/usr/bin/irsend", directive, remote, code]) # rtn == 0 bedeutet "OK", rtn != bedeutet "Fehler" return rtn tasten = ['KEY_OK', 'KEY_LEFT', 'KEY_RIGHT', 'KEY_UP', 'KEY_DOWN'] while True: taste = tasten[random.randint(0,len(tasten)-1)] res = irsend("SEND_ONCE", "Keyes", taste) print taste, res time.sleep (1)
Das Senden mit einem C-Programm funktioniert genauso, man kann dazu die system()-Funktion verwenden, in der dann das irsend-Kommando steht. Zum "Zusammenbauen" des Befehlsstrings nimmt man am besten die Funktion sprintf(), mit der man die einzelnen Strings passen formatiert zu einen Gesamtstring vereinen kann. Genau das geschieht in der Funktion irsend im folgenden Programm. Zuvor wird genügend Speicher für den Kommandostring reseviert. Der Speicher wird nach dem Absetzen des Kommandos wieder freigegeben.
#include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> /* * Senden eines IR-Codes (code), directive und remote * wie beim Kommando 'irsend' */ int irsend(char *directive, char *remote, char *code) { char sendcmd[] = "/usr/bin/irsend"; char *command; int len, ret; /* Speicherbedarf fuer das Kommmando berechnen, Speicher belegen */ len = strlen(directive) + strlen(remote) + strlen(code) + strlen(sendcmd) + 10; command = malloc(len); /* Kommando string erzeugen und Kommando ausfuehren */ sprintf(command,"%s %s %s %s", sendcmd, directive, remote, code); ret = system(command); usleep(500000); /* Speicher wieder freigeben */ free(command); return(ret); } int main(int argc, char *argv[]) { irsend("SEND_ONCE", "Keyes", "KEY_OK"); exit(EXIT_SUCCESS); }
Mit den oben beschriebenen Möglichkeiten für Senden und Empfangen von Infrarot-Codes und deren weiterverarbeitung auf Kommandoebene oder in Python-Programmen steht der Kommunikation mit Fernbedienungen und IR-gesteuerten Geräten nichts mehr im Wege. Wenn es um wenige Nachrichten geht, könnten sogar zwei Raspberry-Pi-Boards Infos per LIRC austauschen.