Nachdem unser Roboter bereits Fahren und einer Linie zu folgen gelernt hat, wollen wir ihn nun auch noch fernsteuern lassen. Dafür werden wir zunächst eine Infrarot Fernbedienung nutzen und später evtl. noch zusätzlich einen Xbox 360 Controller. Neben dem Steuern der Fahrfähigkeit sollen sich auch die Modi (Linie folgen, Autopilot, etc.) einstellen lassen.
In diesem Teil der Raspberry Pi Roboter Tutorials programmieren wir den IR Empfänger und legen die Befehle zum Fernsteuern an. Im Video dazu ist die Fernsteuerung zusätzlich gezeigt.
Zubehör
Neben den vorherigen Bauteilen brauchen wir für dieses Tutorial noch einen IR Fernbedienung und Infrarot Diode (hier als Kit verfügbar). Meist sind die Jumper Kabel schon dabei und die Diode kann direkt angeschlossen werden. Solltest du die Dioden einzeln kaufen (oder noch verfügbar haben), wirf bitte einen Blick ins Datenblatt, um bei der nachfolgenden Verkabelung auf Nummer sicher zu gehen.
Die IR Diode mit Fernbedienung kannst du im übrigen auch zur generellen Fernsteuerung deines Raspberry Pi’s verwenden, sei es in einem Multimediasystem wie KODI oder einfach nur um Skripte zu starten.
Anschluss des IR Empfängers
Der Anschluss des Infrarot Empfängers am Raspberry Pi ist sehr einfach, da das Modul lediglich drei Pins hat. Solltest du einen Empfänger inkl. PCB verwenden (siehe oben), so werden die Anschlüsse benannt sein. Ansonsten müsstest du im Datenblatt nach der richtigen Belegung schauen, da diese ggf. abweichen kann.
Im Prinzip wird der VCC Pin an einen freien 5V Pin des Raspberry Pi’s angeschlossen, der GND Pin an Masse / GND vom Pi und der mit IN / DATA beschriftete Pin kommt an GPIO 26.
Vorbereitung
Für die Nutzung des Infrarot Empfängers brauchen wir das Programm Lirc. Die Installation und Einstellung von Lirc habe ich bereits in einem vorherigen Tutorial gezeigt. Ich gehe davon aus, dass dieses umgesetzt wurde, da wir im folgenden ein eingerichtetes Lirc brauchen. Im unteren Abschnitt (Infrarot Raspberry Pi Universalfernbedienung – Programme starten) geht es um das Erstellen der lircrc Datei. Um den Roboter zu steuern und die Befehle später in unserem Skript zu erkennen, müssen wir eine solche Datei erstellen.
Sobald du also Lirc installiert und getestet hast, erstellen wir im Ordner, worin sich die restlichen Roboter Skripte befindet, diese Datei:
cd robot/ sudo nano lircrc
Folgender Inhalt wird in die Datei geschrieben. Du kannst natürlich auch eine andere Belegung wählen, diese habe ich genommen:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
begin button = KEY_1 prog = robot_ir config = LEFT_FORWARD end begin button = KEY_2 prog = robot_ir config = FORWARD end begin button = KEY_3 prog = robot_ir config = RIGHT_FORWARD end begin button = KEY_4 prog = robot_ir config = LEFT end begin button = KEY_5 prog = robot_ir config = STOP end begin button = KEY_6 prog = robot_ir config = RIGHT end begin button = KEY_7 prog = robot_ir config = LEFT_BACKWARD end begin button = KEY_8 prog = robot_ir config = BACKWARD end begin button = KEY_9 prog = robot_ir config = RIGHT_BACKWARD end begin button = KEY_PAUSE prog = robot_ir config = LINE_FOLLOW_ON end |
Gleich werden wir auf die Codes der Fernbedienung warten. Dazu wird die Zeichenkette unter „config“ dem Programm übergeben. Du kannst hier später auch noch weitere Tasten belegen, um bspw. später noch andere Aktionen aufrufbar zu machen. In meinem Fall wird mit der Play/Pause Taste der Modus zum Folgen einer Linie gestartet.
Um Lirc gleich auch per Python nutzen zu können, installieren wir anschließend noch eine entsprechende Bibliothek:
sudo apt-get install python-lirc
Solltest du Python 3 nutzen, so lautet das Paket python3-lirc
.
Code zum Infrarot Signale empfangen
Wir erweitern unsere zuvor erstellte Roboter Klasse. Dazu erstellen wir die Funktion IRControl()
nach Ende der Funktion lineFollowModeOn(self)
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
def IRControl(self): sockid = lirc.init("robot_ir", "lircrc") dist_per_leypress = 30.0 #cm while True: #self.motor.stop() code = lirc.nextcode()[0] print(code) if code == "FORWARD": self.motor.forward() time.sleep(dist_per_leypress / self.motor.DIST_PER_SEC) self.motor.stop() elif code == "LEFT_FORWARD": # 30 degree turn left, then stop self.motor.forwardRight() time.sleep(self.motor.SEC_PER_TURN / 360.0 * 30.0) self.motor.stop() elif code == "RIGHT_FORWARD": # 30 degree turn right, then stop self.motor.forwardLeft() time.sleep(self.motor.SEC_PER_TURN / 360.0 * 30.0) self.motor.stop() elif code == "LEFT": self.motor.forwardRight() time.sleep(self.motor.SEC_PER_TURN / 360.0 * 90.0) self.motor.stop() elif code == "RIGHT": self.motor.forwardLeft() time.sleep(self.motor.SEC_PER_TURN / 360.0 * 90.0) self.motor.stop() elif code == "BACKWARD": self.motor.backward() time.sleep(dist_per_leypress / self.motor.DIST_PER_SEC) self.motor.stop() elif code == "LEFT_BACKWARD": # 30 degree turn left back, then stop self.motor.backwardRight() time.sleep(self.motor.SEC_PER_TURN / 360.0 * 30.0) self.motor.stop() elif code == "RIGHT_BACKWARD": # 30 degree turn right back, then stop self.motor.backwardLeft() time.sleep(self.motor.SEC_PER_TURN / 360.0 * 30.0) self.motor.stop() elif code == "STOP": self.motor.stop() elif code == "LINE_FOLLOW_ON": self.lineFollowModeOn() |
Den kompletten (bisherigen) Code kannst du außerdem hier ansehen. Gespeichert wird im Nano Editor wie immer mit STRG+O und geschlossen mit STRG+X.
Hintergrundprozess zum Steuern des Roboters
Nun wollen wir das ganze auf Funktionalität testen. Dazu haben wir zwei Möglichkeiten. Die einfachere ist, dass wir lediglich den folgenden Python Code in der Konsole eingeben (nach sudo python
). Die andere Variante ist ein Skript mit dem entsprechenden Code zu erstellen und dieses nach dem Booten im Hintergrund zu starten. Das ist z.B. vor allem auf Raspberry Pi Zero wichtig, falls man keinen WLAN Adapter angeschlossen hat. Tipp: Sofern du auch ein „großes“ Raspberry Pi 3/2B hast, kannst du den Code erst über SSH oder FTP auf den Pi spielen und anschließend nur noch die Micro SD Karte in den Zero stecken.
Der Code für die Test-Datei ist recht simpel (sudo nano test.py
):
1 2 3 4 5 6 7 8 9 10 11 12 |
from robot import Robot import time try: r=Robot() r.IRControl() #r.lineFollowModeOn() #while True: # time.sleep(0.1) except: r.motor.stop() |
Entweder starten wir die Datei nun einfach (sudo python test.py
) oder wir lassen sie bei einem Neustart automatisch öffnen.
Dazu nutzen wir am einfachsten crontab:
crontab -e
Ans Ende schrieben wir nun folgende Zeile:
@reboot ~/robot/test.py
Die Datei wird ab jetzt beim Neustart aufgerufen und du kannst den Raspberry Pi Roboter per Infrarot Fernbedienung fernsteuern.
Im nächsten Tutorial werden wir dem Roboter einen „Autopiloten“ verpassen, sodass dieser sich automatisch dorthin bewegt, wo kein Gegenstand im Weg ist. In Teil 6 der Reihe ist außerdem noch eine Steuerung per Xbox 360 Controller gezeigt.
34 Kommentare
Hallo,
wenn ich mir z.B.
„Icstation HX1838 IR Infrared Receiver Remote Control Kit for Arduino Raspberry Pi“ bestellen will, kriege ich immer die Anzeige:
This item does not ship to Garding, Germany.
Wo bestellt Ihr denn das ganze Zubehör? Das Problem hatte ich schon drei mal.
Für einen Tip… Danke.
Beste Grüße
Hans
Schau mal hier, die liefern alle.
Danke Felix,
die habe ich wieder nicht gefunden, merke ich mir aber jetzt.
So langsam trudeln alle Zubehörteile ein.
Hallo,
bei ersten Test’s ist er mir fast vom Tisch gefallen, auf dem Fussboden lief er gut bis er sich in den Kabeln verheddert hat, es sind noch Bildschirm, Maus, Hdmi und Strom angeschlossen).
Jetzt bin ich bis „Teil 3, per Infrarot Fernbedienung steuern“ gekommen,
mir ist nicht klar was ich wie anschliessen soll, den Receiving Head (das kleine Ding mit drei Beinen) oder das Remote Modul (das ist doch PCB?), oder Beides?
Diese Teile sind inzwischen angekommen:
IR Remote Control(not contain battery).
HX1838 remote module.
1838 Universal Receiving Head.
3Pin 20cm Dupont cable.
Danke für Hilfe.
Gruß
Hans
Hi Hans,
das PCB hat einen Steckplatz für den dreibeinigen IR Receiver. Auf der anderen Seite sind 3 Pins, welche per Jumper Kabel an den Pi angeschlossen werden. Hier wird das auch genauer erklärt: Raspberry Pi: Per IR Remote Befehle ausführen
Hallo Felix,
(alles) klar, denn mach‘ ich ‚mal weiter.
Danke!
Hallo Felix,
Bin jetzt bei Teil 3.
Wenn ich „pi@pibernd:~/robot $ sudo python test.py“ starte und z.B. Taste „Vorwaerts“ druecke, faehrt er ein Stueck zeigt im Terminal „FORWARD“ an und springt gleich wieder zurueck zu „pi@pibernd:~/robot $ “
Haste du eine Idee?
Gruss Bernd
Hallo Bernd,
klingt als ob die Funktion irgendwo beendet wird. Kannst du mal nach jedem 2. oder 3. Befehl eine print setzen, um zu schauen, was das letzte ist, was ausgeführt wird?
Sorry, aber da musst du mir sagen in welcher Datei ich dass machen soll.
Bin noch am lernen. Im terminal sieht es so aus.
pi@pibernd:~/robot $ sudo python test.py
BACKWARD
pi@pibernd:~/robot $ sudo python test.py
FORWARD
pi@pibernd:~/robot $ sudo python test.py
RIGHT
pi@pibernd:~/robot $
Hallo Felix,
meine crontab macht noch nicht was sie soll, wie in Raspberry Pi Robot IR Control (Teil 3) beschrieben.
Führe ich die Datei test.py direkt aus, läuft der Kleine schon einigermaßen, ist aber durch die angeschlossenen Kabel noch eingeschrenkt.
Nach einem Neustart werden die Tastenbewegungen der Fernbedienung lediglich im Terminal angezeigt (siehe unten).
Wo kann ich den Fehler suchen?
Danke für Hilfe!
pi@raspberrypi:~ $ crontab -l
# For example, you can run a backup of all your user accounts
# at 5 a.m every week with:
# 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/
#
# For more information see the manual pages of crontab(5) and cron(8)
#
# m h dom mon dow command
@reboot ~/RaspberryPi-Robot/test.py
pi@raspberrypi:~ $
grep cron /var/log/syslog
Jan 21 18:00:44 raspberrypi cron[419]: (CRON) INFO (pidfile fd = 3)
Jan 21 18:00:44 raspberrypi cron[419]: (CRON) INFO (Running @reboot jobs)
pi@raspberrypi:~ $ 000111222333
Hat dein Skript entsprechende Rechte? Hast du Header definiert? Außerdem solltest du den Pfad absolut angeben:
Hallo Felix,
Erstmal ein sehr großes Kompliment für diese Seite. Mit gefällt sie sehr gut vor allem weil auf Deutsch. Alle Themen sehr gut beschrieben und mann versteht alle Tutorials sehr gut.
Ich würde gerne einen Roboter bauen zum Rasen mähen, das Problem ist die Begrenzung der Mähfläche . Ich finde keine Info was das für ein Draht sein muss, welches Signal da drauf muss und wie der Roboter das Signal empfängt. Für Paar Tipps oder Anregungen wäre ich sehr dankbar.
Ein Tutorial wäre der Hammer.
Hi Wladi,
was meinst du mit Draht und Signal? Ein User hat mir neulich geschrieben, dass er ein solches Projekt vorhat und es gerne hier teilen will. Ich weiß aber nicht, wann dies der Fall ist.
LG, Felix
Danke für die schnelle Antwort. Schau mal bitte hier
rasenmaeher-im-test.de/rasenroboter-im-test/
Auch für Mähroboter mit modernen Sensor- und Navigationssystemen gilt nach wie vor: Ohne Begrenzungsdraht läuft nichts. Den Draht, dessen Enden entweder an die Ladestation oder an eine weitere Stromquelle angeschlossen werden, verlegt man entlang der Rasenkante. Wer möchte, kann diesen auch in die Erde eingraben, am besten bis zu zwanzig Zentimeter tief. Der Begrenzungsdraht erzeugt ein elektrisches Feld, das den Arbeitsbereich des Roboters festlegt.
Gruß Wladi
Ich muss gestehen, darüber habe ich mir noch keine Gedanken gemacht. Ich denke, da wird ein Spannungsgedektor verbaut sein. Im Selbstbau könnte im freien aber auch GPS eine Alternative sein. Hilft dir dieser Beitrag weiter?
Dank deinem Link bin ich weiter gekommen, das Prinzip hab ich nun verstanden.
Hier gibts ein Selbstbau Projekt http://www.tomanja.de/robitobi/history.htm
Hallo
Bei mir schliesst sich die Datei sofort wieder, sobald ich sie ausfuehre.
Was koennte da das Problem sein.
Vielen Dank schon im Voraus.
Da tritt ein Fehler auf, der das Programm beendet. Lass dir am besten mal alles innherlab des try-Blocks ausgeben.
Hey Felix und Mitstreiter,
auch hier habe ich Probleme. Das Einrichten von LIRC hat geklappt dank anderer Tutorials im Netz (neuere Version). Ich kann auch die Fernbedienung programmieren, aber wenn ich mit „irw“ testen will, dann passiert nichts. Im Terminal bin ich zwar im laufenden Programm, aber es gibt keine Ausgabe und ich beende wieder mit STRG+C.
Wenn ich dann trotzdem weitermache wie im Tutorial beschrieben und die test.py ausführe, dann kommt gleich wieder der prompt im Terminal, das Skript wird also sofort beendet.
An anderer Stelle hast du geschrieben, man solle sich alles innerhalb des try-Blocks ausgeben lassen, aber wie geht das?
Danke schonmal und Grüße
Florian
Im except Block kannst du die Exception ausgeben (mit print).
Ich kenne mich mit Python nicht aus und kann mit den Befehlen wenig anfangen, auch wenn ich das mit dem „except“ schon gesehen hatte. Irgendwie habe ich mal versucht, etwas ausgeben zu lassen, und das hier kam dabei heraus:
File „test.py“, line 6, in
r.IRControl()
File „/home/pi/Pi3D2/robot.py“, line 15, in IRControl
sockid = lirc.init(„robot_ir“, „lircrc“)
NameError: global name ‚lirc‘ is not defined
import lirc
hast du aber? Übernimm ggf. das komplette Skript (Link oben)Ich hatte die Skripte aus den Tutorials 1:1 in nano kopiert. import lirc hatte in robot.py und test.py gefehlt, das habe ich einfach mal in beiden eingefügt.
Wenn ich jetzt test.py ausführe, kommt die Fehlermeldung:
ImportError: No module named lirc
Probeweise habe ich statt „lirc“ auch „lircd“ ausprobiert, aber immer noch der Fehler.
Unabhängig davon funktioniert ja auch der Test über den Befehl „irw“ nicht, da gibt es keine Reaktion auf die Fernbedienung. Merkwürdige Sache.
Ich vermute, dass python-lirc nicht installiert ist.
Stimmt, das Paket gibt es unter Raspbian Stretch nicht mehr im Repository, ich habe es manuell von github installiert.
Das Problem bleibt aber, dass aus irgendeinem Grund LIRC nicht richtig funktioniert. Wenn ich im ersten Schritt die Fernbedienung teste, kommen reihenweise „pulse“/“space“-Ausgaben und programmieren kann ich die Tasten auch, aber danach bei „irw“ passiert einfach nichts.
Ich habe die Lösung gefunden! Das Problem ist die neue Version von LIRC, die eine 32-bit *.conf erstellt, obwohl eine 16-bit benötigt wird. Beim Googlen habe ich ein Forum gefunden, wo ein User ein ähnliches Problem hatte.
Die Lösung ist es, die erzeugte lircd.conf manuell anzupassen. Dazu zuerst LIRC stoppen, dann mit nano die .conf wie folgt ändern:
bits 32 ändern in: bits 16
Folgendes hinzufügen:
pre_data_bits 16
pre_data 0xFF (war bei mir so; das ist der Wert, der unten bei den Codes immer zuerst steht, in meinem Fall war das 0x00FF, wird hier verkürzt zu 0xFF)
Nun noch die Codes anpassen. Überall werden die ersten 4 Zeichen nach dem 0x entfernt, also wird zB aus 0x00FF807F einfach 0x807F. Außerdem müssen alle Codes in der zweiten Spalte gelöscht werden. Diese sind alle identisch.
Danach LIRC wieder starten und nach einem Test mit irw müssten jetzt die Tasten erkannt werden.
Hallo,
tolle Seite und tolles Roboterprojekt. Ich habe nur eine Frage: Ich nutze ein L298N Mikrokontroller und keine Line Follow Module, der übrige Aufbau ist der selbe wie im Tutorial. Es funktionieren auch alle Komponenten ABER der Roboter führt über die Fernbedienungseingabe nur den einen (gerade gedrückten) Befehl aus. Eine weitere Eingabe auf der Fernbedienung ist nur nach erneutem starten des Pythonskriptes möglich. Gibt es dafür eine Erklärung (Bin ein totaler Anfänger!!!!)
Das Problem bei IR ist, dass das Signal nicht dauerhaft gesendet wird. Ich würde für eine bessere Steuerung den Xbox Controller empfehlen.
Hallo,
ich hänge nun seit Stunden an dem selben Problem und komme einfach nicht weiter.
Ich habe meine Fernbedienung (selbe wie im Beispiel) in lirc eingerichtet und die Tasten eingelernt. So weit ist die Funktion nun auch gegeben. Danach habe ich den Code wie beschrieben erweitert und die lircrc Datei in Python im entsprechenden Ordner erstellt. Die Bibliothek für Python 3 habe ich auch installiert. Wenn ich nun aber den Test Code starte und Tasten auf der Fernbedienung drücke, erscheinen nur die Zahlen in der gestartetet Datei. Zum Beispiel Nr. 1 bei Taste 1, Nr. 2 bei Nummer 2 etc. Der Roboter bewegt sich kein Stück. Ich habe alles wie im Beispiel gemacht nur das ich bei der IR Diode nicht diese kleine Platine habe, welche ja wahrscheinlich nur zum senden ist und ich habe bei irexec nichts eingegeben, aber hierfür ist doch der Python Lircrc Code wenn ich das richtig verstehe.
Ich hoffe du kannst mir bei meinem Problem weiter helfen.
Gruß Paul
Hallo,
ich habe die Steuerung per Fernbedienung soweit fertig und es funktioniert auch alles, nur der Eintrag in die Crontab macht mir etwas Probleme.
Starte ich die test.sh manuell also in der Console, erscheint im syslog der Eintrag
raspberrypi lircd-0.9.0-pre1[718]: accepted new client on /var/run/lirc/lircd
und ich kann den Roboter mit der FB steuern. Stoppe ich das Sript erscheint folgende Meldung
lircd-0.9.0-pre1[718]: removed client
was auch durchaus Sinn ergibt.
Start ich dagegen das script mit der Crontab passiert anscheinend gar nichts. Um den Fehler zu lokalisieren lasse ich test.py minütlich starten
(* * * * * python /home/pi/RaspberryPi-Robot/test.py)
im syslog erscheint folgender Eintag
raspberrypi cron[444]: (pi) RELOAD (crontabs/pi)
raspberrypi CRON[2876]: (pi) CMD (python /home/pi/RaspberryPi-Robot/test.py)
15:22:01 raspberrypi lircd-0.9.0-pre1[718]: accepted new client on /var/run/lirc/lircd
15:22:01 raspberrypi lircd-0.9.0-pre1[718]: removed client
also scheint das Script gestartet zu werden, aber es wird sofort wieder beendet.
Hat jemand eine Idee warum das so sein könnte?
Gruß Tom
sorry, das script heißt natürlich test.py
Suche jemanden der mir dies alles zusammen fassen kann und in eine Präsentation sowie Hausarbeit packt
we are to opfers we want help for our wreally dupf scool projekt danks
i am dup to plasue help ))()=//&)(&523&U&()/