Raspberry Pi Advanced: Unterschied zwischen den Versionen
Tut (Diskussion | Beiträge) |
(→GPIO Serial) |
||
(8 dazwischenliegende Versionen von 2 Benutzern werden nicht angezeigt) | |||
Zeile 50: | Zeile 50: | ||
gpio.pwmWrite (18,n) | gpio.pwmWrite (18,n) | ||
time.sleep (0.01) | time.sleep (0.01) | ||
+ | </pre> | ||
+ | |||
+ | == GPIO Serial == | ||
+ | Man kann über die GPIO-Pins eine serielle Verbindung zu einem PC, Arduino, ... aufbauen um Daten auszutauschen oder Steuerinformationen zu übertragen.<br> | ||
+ | [[File:Raspi3_GPIO_Rxtx.PNG|150px]][https://pinout.xyz/pinout/]<br><br> | ||
+ | Zuerst muss die serielle login shell deaktiviert und die serielle Schnittstelle aktiviert werden. | ||
+ | <pre> sudo raspi-config </pre> | ||
+ | * 5. Interfacing Options | ||
+ | ** P6 Serial<br> | ||
+ | *** Would you like a login shell to be accessible over serial? No<br> | ||
+ | *** Would you like the serial port hardware to be enabled? Yes<br> | ||
+ | <pre> sudo reboot </pre> | ||
+ | Schnittstelle mittels eines '''Terminals''' testen.<br> | ||
+ | Es gibt minicom oder cu und weitere.<br> | ||
+ | |||
+ | Wenn man die beiden pins 8(TX) und 10(RX) miteinander verbindet, kann man die Schnittstelle mit sich selbst testen. | ||
+ | Auf dem Terminal werden die Tastatureingaben als ein lokales Echo wiedergegeben. | ||
+ | <pre>sudo minicom -b 115200 -D /dev/ttyS0 (Verlassen über Strg+a, z, x)</pre> | ||
+ | oder | ||
+ | <pre>cu -l /dev/ttyS0 -s 115200 (Verlassen ~.)</pre> | ||
+ | |||
+ | |||
+ | Da die GPIO-Pins des Raspis mit 3.3V und der PC oder Arduino mit 5V Logic Level funktionieren müssen wir die Level convertieren.<br> | ||
+ | Da ein TX-Signal vom Raspi mit 3.3V im PC immer noch ein High ist brauchen wir hier nichts zu tuen.<br> | ||
+ | Das 5V TX-Signal vom PC zum Raspi würde aber den Pin zerstören. Hier reicht es aber einen Spannungsteiler zwischen zu schalten.<br> | ||
+ | [[File:SerialRaspiArduino.jpg]] | ||
+ | |||
+ | '''PC'''<br> | ||
+ | Hier ein Terminalprogramm wie Terminal von Br@y verwenden. | ||
+ | |||
+ | '''Arduino''' | ||
+ | <pre> | ||
+ | void setup() { | ||
+ | Serial.begin(9600); | ||
+ | } | ||
+ | void loop() { | ||
+ | if(Serial.available()) { | ||
+ | Serial.write(Serial.read()); | ||
+ | } | ||
+ | } | ||
+ | </pre> | ||
+ | Und hier ein etwas komplexerer Kommandoparser:<br> | ||
+ | Die Kommandos sind a und b gefolgt von einem Integer wie z.B. ''a21'' | ||
+ | <pre> | ||
+ | void receive_serial_cmd(void) { | ||
+ | static uint8_t cmd[18]; // command buffer | ||
+ | static uint8_t cmdcount = 0; // position in the buffer of the received byte | ||
+ | uint8_t c; // received byte | ||
+ | while(Serial.available()) { | ||
+ | c = Serial.read(); | ||
+ | if(c > ' ') cmd[cmdcount++] = c; | ||
+ | if((c == 8) && (cmdcount > 0)) cmdcount--; // deals with backspaces, if a person on the other side types | ||
+ | if((c == 0x0d) || (c == 0x0a) || (cmdcount > 16)) { // end of command, gets interpreted now | ||
+ | cmd[cmdcount] = 0; // clear the last byte in cmd buffer | ||
+ | if(cmdcount > 0) { // prevent empty cmd buffer parsing | ||
+ | switch(cmd[0]) { | ||
+ | case 'a': | ||
+ | if((cmdcount > 2) && (cmdcount < 7)) { | ||
+ | int temp = atoi((const char *)&cmd[1]); | ||
+ | Serial.print("a:"); | ||
+ | Serial.println(temp); | ||
+ | } | ||
+ | break; | ||
+ | case 'b': | ||
+ | if((cmdcount > 2) && (cmdcount < 7)) { | ||
+ | int temp = atoi((const char *)&cmd[1]); | ||
+ | Serial.print("b:"); | ||
+ | Serial.println(temp); | ||
+ | } | ||
+ | break; | ||
+ | } | ||
+ | } | ||
+ | cmdcount = 0; | ||
+ | } | ||
+ | } | ||
+ | } | ||
</pre> | </pre> | ||
Zeile 85: | Zeile 161: | ||
Ein Raspberry ist nun im Hackerspace installiert. Er dient zunächst als Samba-Fileaustausch-Server, erreichbar ist er unter der internen IP 192.168.178.122. Es können auch Nutzeraccounts eingerichtet werden für Mitglieder des Hackerspaces, die auch aus dem Internet zu erreichen sind. Der Raspberry ist zum spielen (aber nicht kaputt-spielen!) freigegeben, Nutzer können daher auch recht schnell sudo-Rechte bekommen. Octoprint wurde weitgehend installiert (Phyton-Serial muss vermutlich noch auf 250kBaud gepatcht werden, Autostart für Octoprint fehlt auch noch, Kamera ist auch noch nicht installiert). | Ein Raspberry ist nun im Hackerspace installiert. Er dient zunächst als Samba-Fileaustausch-Server, erreichbar ist er unter der internen IP 192.168.178.122. Es können auch Nutzeraccounts eingerichtet werden für Mitglieder des Hackerspaces, die auch aus dem Internet zu erreichen sind. Der Raspberry ist zum spielen (aber nicht kaputt-spielen!) freigegeben, Nutzer können daher auch recht schnell sudo-Rechte bekommen. Octoprint wurde weitgehend installiert (Phyton-Serial muss vermutlich noch auf 250kBaud gepatcht werden, Autostart für Octoprint fehlt auch noch, Kamera ist auch noch nicht installiert). | ||
− | [[Kategorie:Workshops]] | + | [[Kategorie:Workshops]] [[Kategorie:Raspberry Pi]] |
Aktuelle Version vom 19. Juli 2017, 14:02 Uhr
Hier einige Notizen zu erweiterten Raspberry Themen.
Inhaltsverzeichnis
Filesystem prüfen und reparieren
Geht nur beim Reboot, wird normalerweise nur nach jedem 30sten Neustart gemacht. Erzwingen kann man die Prüfung durch Neustart mit der Option -F:
sudo shutdown -rF now
GPIO Zugriffe
Der Raspberry verfügt über einen IO-Connector, der digitale Ein- und Ausgänge mit 3.3V Pegeln bereitstellt. Bestimmte Pinne können dabei auch als serielle, SPI oder I2C Schnittstelle verwendet werden. Auch PWM-Ausgänge stehen zur Verfügung. Was es beim Raspberry nicht gibt, sind analoge Eingänge.
Für den Zugriff auf die seriellen Schnittstellen können Kerneltreiber verwendet und angesprochen werden, was den Vorteil hat, das dies auch ohne Root-Rechte klappt. Aber auch ohne den Kernel können die GPIO-Pinne und Schnittstellen angesprochen werden - dann muss aber die Anwendung immer als root laufen.
Eine gute Anlaufstelle für den Zugriff auf die IO-Pinne findet sich hier.
WiringPi Library
Ich empfehle die Verwendung der wiringPi library, die nach der Installation auch den Shell-Befehl gpio mitbringt, mit der schon sehr viel gemacht werden kann, auch aus Skripten heraus. Etwas konfus ist, dass diese Library verschiedene Pinnummerierungen unterstützt, hier muss also aufgepasst werden.
Die Installation dieser Library ist hier beschrieben, in Kurzform muss das hier gemacht werden (dazu sollte man sich im Home-Verzeichniss befinden):
sudo apt-get install git-core git clone git://git.drogon.net/wiringPi cd wiringPi git pull origin ./build
Ausprobieren kann man die Lib dann hiermit:
gpio -v gpio readall
WiringPi Library unter Python
Installieren mitsudo apt-get install python-dev python-pip sudo pip install wiringpi2um damit eine LED via PWM an GPIO 18 zu dimmen:
#!/usr/bin/python import wiringpi2 as gpio import time #set up gpio gpio.wiringpiPiSetupGpio () gpio.pinMode (18,2) while True: gpio.pwmWrite (18,0) for n in range (0,1024): gpio.pwmWrite (18,n) time.sleep (0.01)
GPIO Serial
Man kann über die GPIO-Pins eine serielle Verbindung zu einem PC, Arduino, ... aufbauen um Daten auszutauschen oder Steuerinformationen zu übertragen.
[1]
Zuerst muss die serielle login shell deaktiviert und die serielle Schnittstelle aktiviert werden.
sudo raspi-config
- 5. Interfacing Options
- P6 Serial
- Would you like a login shell to be accessible over serial? No
- Would you like the serial port hardware to be enabled? Yes
- Would you like a login shell to be accessible over serial? No
- P6 Serial
sudo reboot
Schnittstelle mittels eines Terminals testen.
Es gibt minicom oder cu und weitere.
Wenn man die beiden pins 8(TX) und 10(RX) miteinander verbindet, kann man die Schnittstelle mit sich selbst testen. Auf dem Terminal werden die Tastatureingaben als ein lokales Echo wiedergegeben.
sudo minicom -b 115200 -D /dev/ttyS0 (Verlassen über Strg+a, z, x)
oder
cu -l /dev/ttyS0 -s 115200 (Verlassen ~.)
Da die GPIO-Pins des Raspis mit 3.3V und der PC oder Arduino mit 5V Logic Level funktionieren müssen wir die Level convertieren.
Da ein TX-Signal vom Raspi mit 3.3V im PC immer noch ein High ist brauchen wir hier nichts zu tuen.
Das 5V TX-Signal vom PC zum Raspi würde aber den Pin zerstören. Hier reicht es aber einen Spannungsteiler zwischen zu schalten.
PC
Hier ein Terminalprogramm wie Terminal von Br@y verwenden.
Arduino
void setup() { Serial.begin(9600); } void loop() { if(Serial.available()) { Serial.write(Serial.read()); } }
Und hier ein etwas komplexerer Kommandoparser:
Die Kommandos sind a und b gefolgt von einem Integer wie z.B. a21
void receive_serial_cmd(void) { static uint8_t cmd[18]; // command buffer static uint8_t cmdcount = 0; // position in the buffer of the received byte uint8_t c; // received byte while(Serial.available()) { c = Serial.read(); if(c > ' ') cmd[cmdcount++] = c; if((c == 8) && (cmdcount > 0)) cmdcount--; // deals with backspaces, if a person on the other side types if((c == 0x0d) || (c == 0x0a) || (cmdcount > 16)) { // end of command, gets interpreted now cmd[cmdcount] = 0; // clear the last byte in cmd buffer if(cmdcount > 0) { // prevent empty cmd buffer parsing switch(cmd[0]) { case 'a': if((cmdcount > 2) && (cmdcount < 7)) { int temp = atoi((const char *)&cmd[1]); Serial.print("a:"); Serial.println(temp); } break; case 'b': if((cmdcount > 2) && (cmdcount < 7)) { int temp = atoi((const char *)&cmd[1]); Serial.print("b:"); Serial.println(temp); } break; } } cmdcount = 0; } } }
Weitere Nutzer einrichten
Weitere Benutzer können persudo adduser NAMEhinzugefügt werden. Soll dieser auch sudo/admin-Rechte bekommen, danach noch das hier hinterher werfen:
sudo adduser NAME adm sudo adduser NAME sudo
Um den Login ohne Passworteingabe zu ermöglichen, muss der Public-Key (generiert z.B. unter Windows mit puttygen via copy'n'paste) in die Datei .ssh/authorized_keys im jeweiligen Home-Verzeichnis hinzugefügt werden.
Streaming mit geringer Latenz von der Raspberry Cam
Vorweg: Es gibt mittlerweile viele Indizien dafür, dass mit einem guten Setup sehr brauchbare Latenzen möglich sind. So wurden kabelgebundene Unterwasserroboter gebaut, die sehr hohe Kameraauflösungen in unter 50ms streamten. Kommt WIFI ins Spiel, so gibt es hier zusätzliche Engpässe und Latenzen bedingt durch den limitierten Datendurchsatz der USB-Schnittstelle (trotz USB 2.0 erscheinen hier eher 10MBit/s realistisch). Der Netzwerkport ist schneller, schiebt man die Daten über weite Strecken durch das Internet wurden aber auch hier Latenzen deutlich unter 100ms erreicht, wie z.B. in der Masterthesis hier: http://www.ti5.tu-harburg.de/staff/meier/master/meier_audio_over_ip_embedded.pdf Man kann aber auch sehr viel falsch machen und hat dann schnell Latenzen im Sekundenbereich, wie es vielen Leuten passiert. Dann ist es hilfrech zu verstehen, an welcher Stelle es genau klemmt.
Learnings:
- Netzwerklatenz spielt eine wichtige Rolle, gerade WLAN-Adapter sind hier gerne Problematisch. Um das zu untersuchen sollte der Raspberry von einem anderen Computer fortlaufend angepingt werden (Option -t unter Windows). Hier sollten dauerhaft Ping-Latenzen von unter 10ms erreicht werden können, wenn das hier schlecht ist, müssen Maßnahmen am WLAN getroffen werden, um eine geringere Latenz zu bekommen.
- Bei WLAN-Sticks ist oft ein Stromsparmodus aktiv, der sehr störend sein kann wenn man geringe Latenzen erreichen will. Auch verhalten sich Sticks je nach Chipsatz verschieden. Den Stromsparmodus kann man bei manchen Sticks wie folgt abschalten:
sudo iwconfig wlan0 power off
. Mitiwconfig wlan0
kann man sehen, ob der Stromsparmodus aktiv ist oder nicht und auch die Verbindungsqualität feststellen. - Da der Raspberry die volle WLAN-Rate eh nicht nutzen kann, ein hin- und herschalten verschiedener WLAN-Geschwindigkeiten sich aber auch negativ auf die Latenz auswirken kann, kann man versuchen das WLAN auf langsamere (aber robustere) Kodierungen festzunageln (b statt g oder n). TODO: Wie?
- Schlecht für die Latenz ist es auch, wenn die Pakete an irgendeiner Stelle fragmentiert werden müssen, um zum Ziel zu gelangen. Damit die Pakete gleich von Anfang an nicht zu groß herausgesendet werden, reduziert man die MTU etwas in der Datei /etc/network/interfaces durch hinzufügen der Zeile
mtu 1464
im Bereich der Einstellungen für WLAN0.
- Bei WLAN-Sticks ist oft ein Stromsparmodus aktiv, der sehr störend sein kann wenn man geringe Latenzen erreichen will. Auch verhalten sich Sticks je nach Chipsatz verschieden. Den Stromsparmodus kann man bei manchen Sticks wie folgt abschalten:
- Bandbreite: Nur der LAN-Port vom Raspberry erreicht halbwegs brauchbare Bandbreite, bereits mit WLAN-Sticks und erst recht über langsame Internetverbindungen ist der Hauptgrund für eine schlechte Latenz dass schlicht die Bandbreite nicht ausreicht. Hier kann man aber meist wenig machen, daher muss man dafür sorgen, dass der Bandbreitenbedarf des Video-Streams gedrosselt wird. Hier ist die Option -q ein wichtiger Hebel, mit dem die Bildqualität zu Gunsten geringerem Bandbreitenbedarf reduziert werden kann.
-
Streaming geht am schnellsten, wenn natürlich möglichst wenig umcodiert wird. Die Raspicam liefert nativ bereits einen H264 codierten Datenstrom. Oft macht es Sinn, diesen umzocodieren, z.B. auf MJPEG, da sich dies recht einfach auch in Browsern darstellen lässt. Für die H264 dekodierung sowie JPG Komprimierung kann der Raspberry aber auf eine gute Hardwarebeschleunigung zurück greifen, so dass z.B. auch Streams mit höheren Auflösungen als 640x480 noch mit hoher Framerate und geringer Prozessorlast umcodiert werden können. Gerade bei schmalbandigen Netzwerkverbindungen, und dazu gehört bereits eine WLAN-Verbindung zum Raspberry, bringt es bezüglich Latenz viel mehr, hier den Bandbreitenbedarf auch auf Kosten von etwas CPU Zeit stark herunterzubrechen, als mit dem zu wenig komprimierten H264 Strom gleich den Kanal zu verstopfen.- Mit mjpg-streamer und einem Phyton Skript geht es flott http://petrkout.com/electronics/low-latency-0-4-s-video-streaming-from-raspberry-pi-mjpeg-streamer-opencv/ - das bringt auch ein Webinterface mit, aber hier musste ich die Qualität herunter stellen, damit auch die Latenz besser wurde (trotz lokalem Netz, wo es klemmt ist mir noch nicht klar):
./mjpg_streamer -o "output_http.so -w ./www" -i "input_raspicam.so -x 640 -y 480 -fps 15 -q 8"
. Die Option -q 8 gibt schon deutlich schlechtere Qualität, aber es läuft dann auch meist sehr gut im Browser. Ausserhalb vom Browser ging weit mehr Rate und Qualität. - Direkt wegschaufeln von H264 über netcat
raspivid -hf -w 1280 -h 1024 -t 999999999 -fps 20 -b 5000000 -o - | nc -l -p 5001
, dann empfangen mitnc\nc.exe 192.168.1.76 5001 | mplayer\mplayer.exe -fps 30 -demuxer h264es -
- Mit mjpg-streamer und einem Phyton Skript geht es flott http://petrkout.com/electronics/low-latency-0-4-s-video-streaming-from-raspberry-pi-mjpeg-streamer-opencv/ - das bringt auch ein Webinterface mit, aber hier musste ich die Qualität herunter stellen, damit auch die Latenz besser wurde (trotz lokalem Netz, wo es klemmt ist mir noch nicht klar):
- Weitere Maßnahmen (noch nicht ausprobiert):
- Empfänger auf hohe fps stellen (ruhig höher als gesendet wird)
- Im Browser auch Größe angeben:
<img alt="" src="http://phobos:8080/?action=stream" width="1280" height="960" />
- Weiterlesen: http://www.raspberrypi.org/forums/viewtopic.php?f=43&t=32605&start=150#p336453 und http://www.raspberrypi.org/forums/viewtopic.php?f=43&t=45793&start=25 und http://blog.tkjelectronics.dk/2013/06/how-to-stream-video-and-audio-from-a-raspberry-pi-with-no-latency/
- Nicht gebrauchte Dienste deaktivieren: http://wiki.linuxaudio.org/wiki/raspberrypi
Hackerspace Raspberry
Ein Raspberry ist nun im Hackerspace installiert. Er dient zunächst als Samba-Fileaustausch-Server, erreichbar ist er unter der internen IP 192.168.178.122. Es können auch Nutzeraccounts eingerichtet werden für Mitglieder des Hackerspaces, die auch aus dem Internet zu erreichen sind. Der Raspberry ist zum spielen (aber nicht kaputt-spielen!) freigegeben, Nutzer können daher auch recht schnell sudo-Rechte bekommen. Octoprint wurde weitgehend installiert (Phyton-Serial muss vermutlich noch auf 250kBaud gepatcht werden, Autostart für Octoprint fehlt auch noch, Kamera ist auch noch nicht installiert).