Serielle Kommunikation mit Python

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
gtrdriver
User
Beiträge: 11
Registriert: Donnerstag 28. Februar 2019, 13:52

Hallo zusammen

ich möchte erstmal ein freundliches "HALLO" in die Runde werfen.
Mein eigentliches Gebiet ist Programmierung auf Windows Basis (Datenbanken Access VB/VB.net) unter Linux habe ich mir bisher immer mit Perl soweit helfen können - jetzt habe ich hier ein kleines Projekt auf Basis eines Respberry PI bei dem ich mit Perl nicht weiter komme und bin daher notgedrungen nun bei Python gelandet.

Es geht um die Ansprache einer Seriellen Schnittstelle (nicht mal Hardware sondern eine emulierte Bluetooth/Serial verbindung). Das klappt soweit auch alles schon ganz prima...

Dabei geht es darum einen OBD II Adapter per RPI abzufragen und die Rückgabewerte dann auszuwerten.
Diese Adapter werden per klassischem AT Kommand Syncron angesprochen.

Also z.B:

wir senden "ATZ" - der Adapter macht nen RESET und sendet "OK"
wir senden "ATL1" - der Adapter aktiviert Linefeed und sendet ein OK zurück
wir senden eine Anfrage an den CANBUS Freeze Frame Daten zu liefern "2105" - wir erhalten z.b:

Code: Alles auswählen

7EA037F2112
7EB037F2112
7EC102D6105FFFFFFFF
7EC2100000000001616
7EE037F2112
7EC22161616161616A4
7EC2326480001501516
7EC2403E800000000C8
7EC2500310000000000
7EC2600000000000000
Da ich in Python wie gesagt vollkommen neu bin habe ich mir aus ein paar Beispielen was zusammengebastelt - das mehr schlecht als recht funktioniert:

Prinzipiell bin isch schon mal begeistert dass die grundlegende Kommunikation mit der Schnittstelle und dem Bluetooth OBD Adapter funktioniert - aber das ist noch eher trial and error als was anderes ...

Hier mal das Machwerk mit dem ich aktuell teste:

Code: Alles auswählen

import serial
import re
import time
import string
import io


ser = serial.Serial("/dev/rfcomm0", timeout=None)
ser.baudrate = 9600
ser.flushInput()
ser.write(b'ATL1\r\n')
time.sleep(5)
ser.write(b'2105\r\n')
ser.flush()
seq = []
while True:
    reading = ser.read()
    seq.append(reading)
    joineddata = ' '.join(str(v) for v in seq).replace(' ', '')
    print joineddata
    err = re.search('ERROR', joineddata)
    if err:
        break

Ziel ist es ein AT Kommando zu senden - den Result auszuwerden - dann das nächste Kommando usw...

BTW: ich weiß dass es für python ein OBD Modul gibt - das beinhaltet aber nur standard PID´s - damit kann ich leider nix anfangen ...

Wäre toll wenn mir jemand einen "schub" in richtung nach vorne versetzten könnte.

cu
GTR
__deets__
User
Beiträge: 14540
Registriert: Mittwoch 14. Oktober 2015, 14:29

Mir ist nicht ganz klar, wohin ich schieben soll. Was geht denn nicht?

Die flushs sind denke ich ueberfluessig.

Das join ist ein bisschen absurd. Du verbindest die eingelesenen Daten bewusst mit einem leerzeichen (' '), um dann eben dieses Leerzeichen rauszufiltern mit replace. Dann verbinde doch einfach direkt mit ''.

Wobei sich auch die Frage stellt, warum *ueberhaupt* der Umweg ueber die Liste gegangen wird. Ein einfaches

joineddata += ser.read()

ersetzt den gesamten Code in den ersten 4 Zeilen.

Edit: 4 Zeilen der Schleife ist gemeint.
Benutzeravatar
__blackjack__
User
Beiträge: 13109
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@gtrdriver: Da das Python 2 ist, macht das sowieso nicht so viel Sinn `str()` auf Zeichenketten aufzurufen. Und die b's bei den b'…'-Zeichenketten sind in Python 2 auch nur Absichtserklärungen ohne irgend eine Wirkung. Vielleicht möchtest Du aber auch lieber Python 3 verwenden. Es macht kaum Sinn neue Projekte noch mit Python 2 anzufangen. Das läuft ende diesen Jahres aus: https://pythonclock.org/

Wenn man von Perl kommt sind reguläre Ausdrücke wahrscheinlich obligatorisch, aber für diesen einfachen Test kann man auch ``if 'ERROR' in joinddata:`` schreiben.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
gtrdriver
User
Beiträge: 11
Registriert: Donnerstag 28. Februar 2019, 13:52

Hallo zusammen

erstmal danke für die Tipps - ich habe das jetzt mal alles rausgeworfen - bin noch bei python2 und arbeite jetzt nur mit "ser.readline()" und "ser:write()"

Aber evtl habe ich irgendwas bei der ganzen Sache falsch verstanden ... - denn obwohl das prinzipiell funktioniert - so funktioniert es nur 3 von 10x und das kann ja nicht sein ...

Mein Grundgedanke ist:

mit "ser.write" die Commandos an den OBD Adapter zu senden und dann sofort in einer Endlos Schliefe ser.readline() laufen zu lassen.

Wie gesagt - das klappt aber nur unzuverlässig ...

Übersehe ich hier irgendwas ? - Ist das ganze so zeitkritisch dass - was weiß ich - der Adapter so schnell auf das Send Kommando antwortet - dass das Read noch nicht geöffnet ist ????

Ich verstehe es nicht ...

Ich hab die Adapter Geschwindigkeit auch schon auf 9600Baud gedrosselt - das ändert aber nichts am Problem ...

CU
GTR

BTW: Ich habe hier noch nen GPS Dongle der auch als Serielles Device arbeitet - dieser "sendet" aber nur daten und ich muss nichts an ihn senden.
Quasi sobald man den Port öffnet fängt er an zu "senden" - habe das auch mal mit beschriebener funkton ".readline" und ner Endlos Schleife gemacht das klappt hier einwandfrei...

BTW2: Gefühlt müsste ich Senden und Empfangen in unterschiedliche Threads packen (keine Ahnung ob das mit pyhton geht) - der REV Thread müsste permanent arbeiten und der SND Thred halt nur das Senden übernehme - aber wenn dem so ist dann habe ich aktuell keinen Plan wie ich das mit python mache
Antworten