Python exemplarisch |
Alle Programme können von hier heruntergeladen werden. |
Was ist RS-232C Protokoll? |
Obwohl für den Datenaustausch zwischen einem Computer und Peripheriegeräten meist Bluetooth, Ethernet oder USB-Schnittstellen und bei Mikrocontroller-Systemen I2C, SPI und 1-Wire verwendet werden, ist die Kommunikation über die serielle Schnittstelle (RS-232C) immer noch beliebt. Traditionsgemäss wird die serielle Schnittstelle oft zur Kommunikation mit Messeinrichtungen (Voltmeter, Oszilloskopen, usw.) verwendet, aber auch, um mit Modems, Roboter, oder Mikroprozessor-Systemen zu kommunizieren (z.B. Programmdownload auf den Arduino). Moderne Computer haben keine seriellen Ports mehr, jedoch kann dieses Problem leicht mit einem billigen USB-Seriell-Adapter gelöst werden. Die Struktur der übertragenen Daten ist einfach. Die Datenbytes werden über eine einzige Leitung sequentiell übertragen. Der Datentransfer beginnt mit einem Startbit, durch welches dem Empfänger die Datenübertragung angekündigt wird. Dann folgen die Daten mit 5, 6, 7 oder (normalerweise) 8 Bits. Um eine Fehlerkorrektur zu erleichtern, kann ein Paritätsbit folgen, das angibt, ob die Anzahl gesetzter Bits ungerade oder eine gerade ist. Das Paritybit kann aber auch fehlen. Der Transfer wird mit einem oder zwei Stopp-Bits abgeschlossen. Die Sende- und Empfangsgeräte sind ausserhalb der Datenübertragung nicht miteinander synchronisiert, das heisst, die Datenübertragung kann zu jedem beliebigen Zeitpunkt beginnen (asynchrones Protokoll). Es ist jedoch notwendig, dass die Zeitdauer für das Senden eines einzelnen Bits für beide Geräte übereinstimmt. Diese wird durch die Baudrate (in Baud, Bits/s) angegeben, und hat meist einen der standardisierten Werte 300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200 Baud. Darüber hinaus können beide Geräte mit einem Handshake (Flusskontrolle) bestätigen, dass sie für die Datenübertragung bereit sind. Man unterscheidet zwischen Hardware- oder Software-Handshake, je nachdem ob für das Handshake spezifische Handshake-Leitungen verwendet werden oder ob spezielle ASCII-Zeichen (XON / XOFF) im Datenstrom eingebettet sind. Eine typische RS232-Portkonfiguration umfasst daher: Baudrate, Anzahl Datenbits (5, 6, 7, 8), Anzahl Stopp-Bits (1 oder 2), Parität (keine, ungerade oder gerade), Handshake (kein, Hardware oder Software). Beispiel: Der Spannungsverlauf während der Übertragung des Buchstaben 'B', mit der Konfiguration: 7 Datenbits / keine Parität / 1 Stoppbit sieht wie folgt aus: |
Serielle Ports auf dem Raspberry Pi |
Es gibt zwei Möglichkeiten eine serielle Schnittstelle am Raspberry Pi einzurichten: Entweder über den GPIO-Stecker oder mit einem externen USB-Seriell-Adapter. Da das Raspbian Betriebssystem die gängigsten USB-to-Serial Adapter (z. B. den U232-P9) unterstützt, ist es empfehlenswert, externe RS232-Geräte über USB anzuschliessen. (USB-to-Serial Adapter finden Sie auf eBay oder in Computershops.) Es gibt aber auch Zusatzgeräte, die man direkt am GPIO-Stecker aufsteckt und welche die serielle Kommunikation über das GPIO verwenden. Dazu gehören die meisten GPS- und GSM-Geräte, die speziell für den Raspberry Pi entwickelt wurden. In diesem Fall werden für den RS232-Datentransfer die GPIO Pins #8 und #10 (UART-TXD0 bzw. UART-RXD0) verwendet. Standardmässig wird der serielle GPIO-Port für ein externes RS232-Terminal (bzw. einen Terminal-Emulator) als Linux-Shell verwendet. Dies ist eine interessante Alternative, um mit dem Raspberry Pi zu arbeiten und erinnert etwas an die "guten alten Zeiten", als Terminals (und Fernschreiber) die üblichen Ein-/Ausgabegeräte für Minicomputer und Mainframes waren. Heute gibt es zwar keine dedizierten Terminal mehr, dafür aber virtuelle Terminals (Terminal-Emulatoren) für alle gängigen Plattformen. Eines der beliebtesten Programme ist PuTTY, das mit folgender Kommandozeile auch auf dem Raspberry Pi installiert werden kann: sudo apt-get install putty Nach der Installation gibt es eine Startikone im Menü unter Internet. Wenn Sie den GPIO-Port für die serielle Kommunikation mit anderen Geräten verwenden wollen, müssen Sie allerdings die Linux-Konsole in der Raspi-Konfiguration wie folgt deaktivieren: Verwenden Sie eine angeschlossene Tastatur / Bildschirm oder eine VNC-Verbindung und geben Sie in der Konsole: sudo raspi-config. Wählen Sie Advanced Options: Serial: Wählen Sie No bei bei login shell: |
Serielle Schnittstelle des GPIO mit dem Raspberry Pi 3 |
Die serielle Kommunikation funktioniert leider mit der aktuellen Version des Jessie-Betriebssystem für den Raspberry Pi 3 anders als mit den Vorgängermodellen. Erstens wir der Name ttyAMA0, der bisher für die serielle Kommunikation mit dem GPIO reserviert war, neu durch den Bluetooth-Treiber beschlagnahmt. Der serielle GPIO-Port heisst neu ttyS0. Zweitens und ärgerlicher ist die Tatsache, dass die serielle Schnittstelle aufgrund der höheren CPU-Core-Taktfrequenz des Raspberry Pi 3 nicht mehr funktioniert. Damit die Baudraten stimmen, müssen Sie die Taktfrequenz anpassen. Dazu gehen Sie wie folgt vor: Öffnen Sie als sudo in einer Konsole mit dem Nano-Editor die Datei /boot/config.txt: sudo nano /boot/config.txt und fügen Sie die folgende Zeile ein: core_freq=250 Booten Sie neu: sudo reboot Um in Ihren Programmen (oder mit PuTTY) auf die serielle Schnittstelle zuzugreifen, müssen Sie also auf dem Raspberry Pi 3 den Portnamen ttyS0 anstelle von ttyAMA0 verwenden. Alles andere sollte wie mit den älteren Modellen funktionieren. (Es ist unklar, ob die verringerte Taktfrequenz das allgemeine Verhalten des Raspberry Pi beeinträchtigt. Wenn Sie aber die serielle Schnittstelle nicht mehr verwenden, so kommentieren Sie die eingefügte Zeile in config.txt aus.) Informationen über die Namen aller seriellen Ports erhalten Sie mit dem Befehl: dmesg | grep tty Wenn Sie die Zeile console [ttyS0] enabled console [ttyAMA0] enabled finden, ist die Konsole nicht deaktiviert (siehe oben, wie man sie deaktivieren kann). |
Kommunikation unter der Verwendung eines USB-Seriell-Adapters |
|
RS232 Pegelwandler für den seriellen GPIO-Port |
|
Experiment 1: Anschluss eines Gerätes über RS232 simulieren |
Der Raspberry Pi wird oft als Controller für Messgeräte oder Sensoren eingesetzt, die über eine serielle Schnittstelle kommunizieren. Ziel: Programm:[►] # Serial1.py import serial import time port = "/dev/ttyAMA0" # Raspberry Pi 2 #port = "/dev/ttyS0" # Raspberry Pi 3 def readLine(port): s = "" while True: ch = port.read() s += ch if ch == '\r': return s ser = serial.Serial(port, baudrate = 1200) print "starting" while True: time.sleep(1) print "sending synch" ser.write("A") rcv = readLine(ser) print "received:", rcv Bemerkungen: Um zu vermeiden, dass die Hauptschleife blockiert, werden jede Sekunde Daten abgefragt und die Anzahl der empfangenen Zeichen im Eingangspuffer überprüft. Mit read(nbChars) erhält man die Zeichen. Programm:[►] # Serial2.py import serial import time port = "/dev/ttyAMA0" # Raspberry Pi 2 #port = "/dev/ttyS0" # Raspberry Pi 3 ser = serial.Serial(port, baudrate = 1200) print "starting" while True: time.sleep(1) ser.write("A") nbChars = ser.inWaiting() if nbChars > 0: data = ser.read(nbChars) print data Bemerkungen: sudo apt-get install putty Nachher öffnet man das Programm durch Klicken auf die Ikone im Menu | Internet. Im Dialog unter Basic options aktiviert man Serial und wählt im Textfeld /dev/ttyS0 für den Raspberry Pi 3 oder /dev/ttyAMA0 für ältere Versionen. |
Experiment 2: GPS-Modul verwenden und aktuelle GPS-Daten anzeigen |
Kommerzielle GPS-Module sind typische Geräte, die das serielle Protokoll zur Datenübertragung verwenden. Die meisten von ihnen benötigen keine spezielle Installation. Sobald sie eingeschaltet werden, senden sie GPS-Daten zeilenweise als ASCII-Zeichen in einem speziellen Format, genannt NMEA Messages. Die Informationen können in einem Python-Programm mit der Funktion readline() als String empfangen und dann analysiert werden. Die Baudrate beträgt normalerweise 9600 Baud, der Wert sollte aber aus dem Datenblatt des GPS-Moduls entnommen werden. Zu Testzwecken können die Daten auch mit einem Terminal-Emulator (z.B. PuTTY) auf dem Raspberry Pi angezeigt werden. Ziel:
Programm:[►] # Serial3.py import serial port = "/dev/ttyAMA0" # Raspberry Pi 2 #port = "/dev/ttyS0" # Raspberry Pi 3 ser = serial.Serial(port, baudrate = 9600, timeout = 0.5) while True: data = ser.readline() print "Data:--", data, Bemerkungen: Beispiel: $GPGGA,181908.00,3404.7041778,N,07044.3966270,W,4,13,1.00,495.144,M,29.200,M,0.10,0000*40GP kennzeichnet eine GPS Position (GL würde GLONASS bezeichnen).
Programm:[►] # Serial4.py import serial port = "/dev/ttyAMA0" # Raspberry Pi 2 #port = "/dev/ttyS0" # Raspberry Pi 3 def parseGPS(data): # print "raw: ", data[:-1] if data.find('GGA') > 0: s = data.split(",") if s[6] == '0': print "no satellite data available" return time = s[1][0:2] + ":" + s[1][2:4] + ":" + s[1][4:6] lat = decode(s[2]) dirLat = s[3] lon = decode(s[4]) dirLon = s[5] alt = s[9] + " m" sat = s[7] print "Time(UTC): %s-- Latitude: %s(%s)-- Longitude:%s(%s)\ -- Altitute:%s--(%s satellites)" %(time, lat, dirLat, lon, dirLon, alt, sat) def decode(coord): # DDDMM.MMMMM -> DD deg MM.MMMMM min v = coord.split(".") head = v[0] tail = v[1] deg = head[0:-2] min = head[-2:] return deg + " deg " + min + "." + tail + " min" ser = serial.Serial(port, baudrate = 9600, timeout = 0.5) while True: data = ser.readline() parseGPS(data) Bemerkungen: Es ist interessant und lehrreich, die Prinzipien des GPS zu studieren. Das Grundprinzip ist einfach: Der GPS-Empfänger bestimmt die Entfernungen zu mindestens 3 GPS-Satelliten und berechnet daraus die geographische Position mit Triangulation: |