Forum: Mikrocontroller und Digitale Elektronik Alpha-Bus zu RS232 Adapter (1 bidirektionale Datenleitung)


von Simon S. (simschmid)



Lesenswert?

Liebe Community

Ich experimentiere hier mit einer Gorba LCD Anzeige (Fahrzielazeige in 
einem Bus) herum. Diese wird per Alpha-Bus angesteuert.

Was ich weiss, ist dass die Datenleitung bidirektional ist und mit 19200 
Baud, 8N2 angesteuert wird. Ich kann auch schon erste Erfolge mit einem 
Python Script erzielen.

Nun die Krux: Die Datenleitung ist idle auf 24V. Ich habe mir nun einen 
Schaltung zusammengebastelt, die via Optokoppler und Transistor die 5V 
vom FTDI Chip an die 24V der Anzeige anpasst. Das funktioniert soweit. 
Um die Antwort der Anzeige zu empfangen habe ich das Signal via 
Optokoppler an die 5V angeglichen. Achtung, es ist ein Gebastel 
funktioniert soweit für erste Kommunikation.

Nun das Problem: Sende ich auf TX, so kommt das gleich im RX wieder an 
(da ja die Anzeige nur eine Datenleitung hat). Ich muss also beim Senden 
das TX Signal auf der RX Leitung unterdrücken.

Ich dachte, ich könne dies mit einem 7400 NAND erledigen (den habe ich 
rumliegend und verwende diesen bereits im RX Pfad um das Signal nach dem 
Optokoppler zu invertieren). Doch der 7400 erzeugt auch ein Delay, somit 
geht das nicht. Ich weiss, 7400 ist keine schlaue Wahl.

Was gäbe es hier für einfachere Lösungen?
Ev. Kann ich dies auch softwaremöäsig lösen, doch dafür sind meine 
Python Kenntnisse wohl zu mager. Und die Telegramme der Kommunikation 
sind unterschiedlich lange und haben als Start- und Stopbyte jeweils 
0x7E.

: Bearbeitet durch User
von Flip B. (frickelfreak)


Lesenswert?

das lokale echo von der datenleitung ist eigentlich sogar zu bevorzugen, 
einfach vor jeder erwarteten antwort den rx fifo flushen und ggf später 
die integrität der selbst gesendeten signale prüfen. eine 
empfangsunterdrückung klappt dann ggf mit höherer kabelkapazität nicht 
mehr richtig bzw unterdrückt auch korrekte signale.

von Mario M. (thelonging)


Lesenswert?

Man könnte ja über die Steuersignale des FTDI vor Sendebeginn den 
zweiten Eingang des 7400 auf low ziehen und nach dem Stopbit letzten 
Zeichens wieder auf high legen.

von Schorsch X. (bastelschorsch)


Lesenswert?

Du kannst doch die Antwort entsprechend in deinem Programm einfach 
"verschlucken" ? Du weisst ja, was du gesendet hast. Überspring diesen 
Teil der Antwort.

: Bearbeitet durch User
von Hmmm (Gast)


Lesenswert?

Simon S. schrieb:
> Ev. Kann ich dies auch softwaremöäsig lösen, doch dafür sind meine
> Python Kenntnisse wohl zu mager.

Einfach nach jedem gesendeten Paket die gleiche Anzahl Bytes empfangen.

Tritt dabei ein Timeout auf oder weichen die Daten ab, wirfst Du eine 
Fehlermeldung aus, dass etwas mit dem Bus nicht stimmt.

von Simon S. (simschmid)


Lesenswert?

Danke für die bisherigen Antworten, dieses Forum ist einfach so toll. 
Auch wenn ich mich nur alle Schaltjahre hierbewege, die werstschätzende 
Unterstützung und Lösungsideen aus der Community kommen sofort. 
Herzliche Dank.

Fürs erste möchte ich die Idee von Schorsch X. weiterverfolgen.

Schorsch X. schrieb:
> Du kannst doch die Antwort entsprechend in deinem Programm einfach
> "verschlucken" ? Du weisst ja, was du gesendet hast. Überspring diesen
> Teil der Antwort.

Da ich wirklich Python Beginner bin, stelle ich hier mal meinen Code 
ein. Wie könnte ich das anpassen, dass bei der Antwort, die gesendeten 
Pakete "verschluckt" werden?
1
import serial
2
import time
3
4
ser = serial.Serial('/dev/cu.usbserial-A400C24C',
5
    baudrate=19200,
6
    parity=serial.PARITY_NONE,
7
    stopbits=serial.STOPBITS_TWO,
8
    bytesize=serial.EIGHTBITS,
9
    timeout=0
10
    )
11
12
tx_1 = [0x7E, 0x81, 0x7D, 0x5E, 0x7E]
13
tx_2 = [0x7E, 0x91, 0x04, 0x02, 0x68, 0x7E] 
14
15
# Initialisierung senden
16
print ("Sende Initialisierung " + ''.join(format(x, '02x') for x in tx_1))
17
ser.write(serial.to_bytes(tx_1))
18
19
print ("\nWarte auf Antwort ...")
20
time.sleep(0.007)
21
ser.flushInput()
22
23
while 1:
24
    # Bytes einlesen
25
    hexData= ser.read(50).hex()
26
    #Auf Antwort warten
27
    if (hexData):
28
        print("Empfange: " + hexData)
29
30
        if (hexData == "7e817d5e7e7e014c4d01563135ac7e"):
31
            print ("    rx_1")
32
            print ("    Sende Antwort " + ''.join(format(x, '02x') for x in tx_2))
33
            ser.write(serial.to_bytes(tx_2))
34
        else:
35
            print ("    Daten unbekannt")
36
37
        print ("\nWarte auf Antwort ...")
38
39
ser.close()

Obiger COde funktionert so weit. Unschön daran ist, dass ich den String
1
"hexData == "7e817d5e7e7e014c4d01563135ac7e"
 manuell generiert habe.
Die Variable tx_1 würde "7e817d5e7e" enthalten. Wie müsste ich das 
anpassen, damit dies von hexData "subtrahiert" wird?

: Bearbeitet durch User
von Simon S. (simschmid)


Lesenswert?

Flip B. schrieb:
> das lokale echo von der datenleitung ist eigentlich sogar zu bevorzugen,
> einfach vor jeder erwarteten antwort den rx fifo flushen und ggf später
> die integrität der selbst gesendeten signale prüfen. eine
> empfangsunterdrückung klappt dann ggf mit höherer kabelkapazität nicht
> mehr richtig bzw unterdrückt auch korrekte signale.

Kannst du mir beim Code oben helfen, wie ich diese umsetzen könnte? Das 
mit dem ser.flushInput() direkt nach dem Senden habe ich bereits 
probiert. Das hat leider nichts genützt.

von Simon S. (simschmid)


Lesenswert?

Hurrah, ich konnte den Code wie von euch empfohlen anpassen. Dabei kann 
ich mit dem Python Befehl "replace()" die gesendeten Bytes von den 
Empfangenen abziehen:
1
# Bytes einlesen
2
hexData = ser.read(100).hex()
3
# Antwort bereinigen
4
rxData = hexData.replace(''.join(format(x, '02x') for x in txData), "", 1)

Nun kann ich auch die Anzeige ansteuern mit den Befehlen, die ich 
gesnifft habe. Ich mache mich nun daran, die Bytes den einzelnen Pixeln 
der Anzeige zuzuordnen.

Nun muss ich aber erst mal herausfinden, wie die Checksumme berechnet 
wird. Was ich soweit sehe:

Startbyte und Endbyte sind jeweils "0x7E". Kann mir jemand anhand der 
Daten helfen, wie die Checksumme berechnet wird?

Hier ein paar Telegramme:
1
tx_301 = [0x7E,0x82,0x7D,0x5D,0x7E]
2
tx_302 = [0x7E,0x83,0x7C,0x7E]
3
tx_303 = [0x7E,0x84,0x7B,0x7E]
4
tx_304 = [0x7E,0x85,0x7A,0x7E]
5
tx_305 = [0x7E,0x86,0x79,0x7E]
6
tx_306 = [0x7E,0x87,0x78,0x7E]
7
tx_307 = [0x7E,0x88,0x77,0x7E]
8
tx_308 = [0x7E,0x89,0x76,0x7E]
9
tx_309 = [0x7E,0x8A,0x75,0x7E]
10
tx_310 = [0x7E,0x8B,0x74,0x7E]
11
tx_311 = [0x7E,0x8C,0x73,0x7E]
12
tx_312 = [0x7E,0x8D,0x72,0x7E]
13
tx_313 = [0x7E,0x8E,0x7D,0x5E,0x7E,0x00,0x00]
14
tx_314 = [0x7E,0x81,0x7D,0x5E,0x7E]
15
row_24 = [0x7E,0xA1,0x24,0x90,0x00,0x00,0x00,0x00,0x00,0x90,0x00,0x00,0x00,0x00,0x00,0x90,0x00,0x00,0x00,0x00,0x00,0x90,0x00,0x00,0x00,0x00,0x00,0x90,0x00,0x00,0x00,0x00,0x00,0xEA,0x7E]
16
row_23 = [0x7E,0xA1,0x23,0x90,0x00,0x00,0x00,0x00,0x00,0x90,0x00,0x00,0x00,0x00,0x00,0x90,0x00,0x00,0x00,0x00,0x00,0x90,0x00,0x00,0x00,0x00,0x00,0x90,0x00,0x00,0x00,0x00,0x00,0xED,0x7E]
17
row_22 = [0x7E,0xA1,0x22,0x90,0x00,0x00,0x00,0x00,0x00,0x90,0x00,0x00,0x00,0x00,0x00,0x90,0x00,0x00,0x00,0x00,0x00,0x90,0x00,0x00,0x00,0x00,0x00,0x90,0x00,0x00,0x00,0x00,0x00,0xEC,0x7E]

von Simon S. (simschmid)


Lesenswert?

Die Checksumme ist gefunden: Es ist XORen der einzelnen Bytes (ohne 
Startbyte) und dann von 0xFF abziehen. In Python habe ich das mit 
folgender Funktion lösen können:
1
def checksum(data):
2
    xorval = 0
3
    for el in data:
4
        xorval ^= el
5
    return 255 - xorval

Die Bitmaps können nun verändert werden. Nächste Hürde wird nun sein, 
die Pixel eines Bildes den Pixeln auf der Anzeige zuordnen zu können. 
Dies wird spannend, da in zwei Halbbildern übertragen wird.

: Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.