Python exemplarisch
deutsch     english

SERIELLER PORT, GPS

 

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:

gps4

 

 

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:

gps5

Serial:

gps6

Wählen Sie No bei bei login shell:

gps7

 

 

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
(für Raspberry Pi 3)

console [ttyAMA0] enabled
(für ältere Raspberry Pi)

finden, ist die Konsole nicht deaktiviert (siehe oben, wie man sie deaktivieren kann).

 

 

Kommunikation unter der Verwendung eines USB-Seriell-Adapters

 

Wie bereits erwähnt, werden die meisten Adapter-Modelle in der aktuellen Version des Jessie-Betriebssystem unterstützt. Nachdem Sie den Adapter angeschlossen haben, können Sie prüfen, ob er tatsächlich erkannt wird. Tippen Sie in einer Shell

dmesg | grep tty

so sollten Sie eine Zeile finden, die ähnlich lautet wie

pl2303 converter now attached to ttyUSB0

Notieren Sie den Namen der seriellen Schnittstelle (hier ttyUSB0), weil Sie ihn in Ihren Programmen benötigen.

gps8

 

 

RS232 Pegelwandler für den seriellen GPIO-Port

 

Wenn Sie am GPIO externe RS232-konforme Geräte anschliessen möchten, müssen Sie einen TTL-zu-RS232-Pegelconverter einsetzen, da die Spannung am GPIO-Port (0/3.3 V), nicht mit den RS232-Pegeln übereinstimmt. Die Converter sind meist mit dem IC MAX3232 bestückt. (Suchen Sie auf eBay unter "RS232 Serial Port to TTL-Converter-Module MAX3232".) Verbinden Sie die 4 Pins wie rechts gezeigt.

gps10
(Rote Pfeile zeigen die Datenflussrichtung)


Der weibliche DB9-Stecker hat die folgende Pin-Belegung:

gps12

hand1

Schliessen Sie nie ein externes RS232-Gerät direkt am GPIO an, da die hohen Spannungspegel den Raspberry Pi beschädigen können. Wenn Sie ein serielles Gerät über einen TTL-Pegelconverter anschliessen, stellen Sie sicher, dass dieser die 3.3V Spannungsversorgung (Pin # 1) (und nicht 5 V) verwendet.

Es gibt auch serielle Devices/Adapter, die mit TTL-Pegeln arbeiten. Falls Sie ein solches Gerät am GPIO anschliessen, so müssen Sie sicherstellen, dass dieses mit 3.3V betrieben ist, da die Standardpegel von TTL mit 0V/5V den Raspberry Pi beschädigen können.

 

 

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:
Für diese Demonstration simulieren wir das Messgerät mit einem Computer, der über einen USB-zu-RS232-Adapter angeschlossen ist und auf dem ein Terminal-Emulator (z.B. PuTTY) läuft. Beim Raspberry Pi verwenden wir den GPIO mit einem Pegelwandler. Die männlichen und weiblichen Pins stimmen bei den beiden DB9-Stecker normalerweise überein.

gps13

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
Programmcode markieren (Ctrl+C copy, Ctrl+V einfügen)

Bemerkungen:
Um einen Messzyklus zu simulieren, sendet der Raspberry Pi als Controller ein Synchronzeichen "A" zum Gerät, um sozusagen eine Messung auszulösen. Dann sammelt er ankommende Zeichen in der blockierenden Funktion readline(), bis ein <CR> erhält.

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
Highlight program code (Ctrl+C kopieren, Ctrl+V einfügen)

Bemerkungen:
Zum Austesten der seriellen Kommunikation mit einem Messgerät ist es zweckmässig, auf dem Raspberry Pi einen Terminal-Emulator zu starten und die Kommunikationssequenz von Hand statt mit einem Programm durchzuführen. Dazu verwendet man oft eine VNC-Session. Wie oben erwähnt, installiert man PuTTY in der Linux-Shell mit der Kommandozeile:

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.

serial1

 

 

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:
Ein GPS-Module am Raspberry Pi anschliessen und die aktuellen Daten in der Konsole anzeigen.

Das Cirocomm Board wird direkt am 40-poligen GPIO eingesteckt. Es ist vielseitig und enthält neben dem GPS-Modul auch eine Echtzeituhr mit Batterie-Backup und einen 3-Achsen-Digitalkompass mit I2C Kommunikation. Es ist bei verschiedenen Distributoren erhältlich (siehe günstige Angebote auch auf eBay).
gps15

Das Anschliessen des Microstack Moduls ist sehr einfach. Sie verwenden 3 Kabel, wie im Bild gezeigt wird. Wenn sich das Modul im Freien befindet, brauchen Sie keine externe Antenne. Um das Modul zu testen, können Sie das PuTTY Terminal unter VNC verwenden (Baudrate: 9600 baud). Beachten Sie, dass der Port-Name für den Raspberry Pi 3 unterschiedlich ist und Sie den Parameter core_freq setzen müssen (wie oben erläutert).

Verwenden Sie nie die 5V-Spannungsversorgung!

gps14

Für den Anschluss des Grove-GPS Moduls, das mit dem SIMCOM SIM28 Chip bestückt ist, benötigen Sie ebenfalls nur 3 Leitungen. Um das Modul zu testen, können Sie das PuTTY Terminal unter VNC verwenden (Baudrate: 9600 baud). Beachten Sie, dass der Port-Name für den Raspberry Pi 3 unterschiedlich ist und Sie den Parameter core_freq setzen müssen (wie oben erläutert).

Verwenden Sie nie die 5V-Spannungsversorgung!

gps15

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,
Programmcode markieren (Ctrl+C kopieren, Ctrl+V einfügen)

Bemerkungen:
Das NMEA-Protokoll ist etwas gewöhnungsbedürftig. Alle NMEA-Nachrichten beginnen mit dem Zeichen $ und jedes Datenfeld wird durch ein Komma getrennt. Die aktuelle geographische Länge und Breite kann aus der $GPGGA Zeile extrahiert werden, die 14 Felder enthält.

Beispiel:

$GPGGA,181908.00,3404.7041778,N,07044.3966270,W,4,13,1.00,495.144,M,29.200,M,0.10,0000*40

GP kennzeichnet eine GPS Position (GL würde GLONASS bezeichnen).
181908.00 ist die aktuelle Zeit: UTC Zeit in Stunden, Minuten und Sekunden.
3404.7041778 ist die geografische Breite im Format DDMM.MMMMM. Nachkommastellen sind variabel.
N ist die nördliche Breite.
07044.3966270 ist die geografische Länge im Format DDDMM.MMMMM. Nachkommastellen sind variabel.
W ist die westliche geografische Länge.
4 ist der Qualitätsindikator:
0 = keine GPS Daten
1 = Nichtkorrekte Koordinaten
2 = Teilweise richtige Koordinaten(z.B., WAAS, DGPS)
4 = RTK Fix Koordinaten (zentimetergenau)
5 = RTK Float (dezimetergenau).
13 bezeichnet die Anzahl der Satelliten, die für die Koordinatenbestimmung verwendet wurden.
1.0 bezeichnet HDOP (horizontal dilution of precision).
495.144 ist die Höhe der Antene.
M bezeichnet die Einheiten der Höhe (Meter oder Fuss)
29.200 bezeichnet die Geoid-Korrektur (man subtrahiert diese von der Höhe der Antenne um die tatsächliche Höhe über dem Erde-Ellipsoid (HAE) zu erhalten).
M bezeichnet die Einheiten der Geoid-Korrektur.
1.0 bezeichnet das Alter der Korrektur (falls vorhanden).
0000 bezeichnet die ID der Erstellstation(falls vorhanden).
*40 ist die Prüfsumme.


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)
Programmcode markieren (Ctrl+C kopieren, Ctrl+V einfügen)

Bemerkungen:
Zum Parsen der NMEA-Messages können Sie auch ein Python-Modul von hier herunterladen.

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:

gps16