Seite 1 von 2

HEX Länge ermitteln

Verfasst: Samstag 10. Januar 2026, 20:32
von kiaralle
Hi,
hätte mal wieder eine Frage.
Folgenden Hex hätte ich im Angebot

b'@B\x00\x01,\xc8\xe7'

Ich weiß, das sich das Ding aus 4 Segmente (Hex-Werte) zusammen setzt.
Nun erhalte ich wenn etwas nicht funktioniet statt diesem langen HEX nur einen kurzen.

b'@B\x0c

0c is der Fehlercode, mit dem ich was anfangen kann.

Wie kann ich die Länge des Hex ermitteln.


Code: Alles auswählen

sick_string = "FF 42"


def status(sick_string):    
    
    data = bytearray.fromhex(sick_string)
    data.append(ChecksumXor8.calc(data))
  
        
    ser.reset_input_buffer() 
    ser.reset_output_buffer()
    time.sleep(0.01)  #give the serial port sometime to receive the data

    ser.write(data)
    time.sleep(0.01)
    response = ser.read(7)
    print(response)
    

    if  .....wenn der Hex zu kurz kommt ....:
        fehlermeldung=''.join(format(byte, '02x') for byte in response[2:3])
        fehlerspeicher = sick_error.srm_errors(fehlermeldung)        
        data = 0
    else:
        fehlerspeicher = ""
        data = int.from_bytes(response[2:6],'big',signed=False)
    
    return data, fehlerspeicher
 
test = status(sick_string)
print(test[0])
print(test[1])

Gruß Ralf

Re: HEX Länge ermitteln

Verfasst: Samstag 10. Januar 2026, 20:48
von sparrow
XY-Problem.

Prüfe nicht auf die Länge. Prüfe auf den Inhalt.
Wenn du weißt, dass b'@B\x0c' einen Fehler bedeutet, dann prüfe exakt darauf, nicht auf die Länge.
Vielleicht kommt es zu dem Umstand, dass b'@Baa' zurück kommt. und dann möchtest du das wissen und nicht so tun, als wäre das der Fehlercode.

Re: HEX Länge ermitteln

Verfasst: Samstag 10. Januar 2026, 21:46
von kiaralle
b'@B\x0c' kann aber auch teil der Daten = Positionszahl sein.

b'@B\x0c\x01,\xc8\xe7' ... Zahl
b'@B\x0c ... Error

Re: HEX Länge ermitteln

Verfasst: Samstag 10. Januar 2026, 22:23
von kiaralle
ich zerlege

int.from_bytes(response[2:6],'big',signed=False)

und prüfe vorab ob
int.from_bytes(response[3:4],'big',signed=False)
etwas enthält.
wenn nicht, ist der Datensatz kürzer.

Re: HEX Länge ermitteln

Verfasst: Samstag 10. Januar 2026, 23:02
von Sirius3
Wie ist denn die Spezifikation des Protokolls? Das muß ja irgendwo genau erklärt sein, was welches Byte bedeutet. Es muß ja irgendwie klar sein, was ein gültiger Datensatz ist und was ein Fehler. Anscheinend fängt ja beides mit `40 42` an, was etwas ungewöhnlich wäre, wenn danach nur noch Nutzdaten kommen.
Zusätzlich solltest Du auch die Prüfsumme prüfen, dafür ist sie ja da.
Ohne Dokumentation kann man also hier nur raten, was Du eigentlich brauchst.

Zur Funktion an sich: alles was eine Funktion braucht, muß sie über ihre Argumente bekommen. `ser` kommt aber aus dem Nichts. Eine Funktion sollte einen eindeutigen Rückgabewert haben und bei Fehler eine Exception werfen.

Code: Alles auswählen

SICK_STRING = b"\xFF\x42"

def query_status(serial_interface, sick_string):    
    data = bytearray.fromhex(sick_string)
    data.append(ChecksumXor8.calc(data))
    serial_interface.reset_input_buffer() 
    serial_interface.reset_output_buffer()
    time.sleep(0.01)
    serial_interface.write(data)

    # give the serial port sometime to receive the data
    time.sleep(0.01)
    response = serial_interface.read(7)
    print(response)
    if response[:2] == b"\x40\x42" or ChecksumXor8.calc(response) != 0:
        raise ValueError("Wrong data received")
    if  is_error(response):
        error_code = f"{response[2]:02x}"
        raise ValueError(sick_error.srm_errors(error_code))        
    result = int.from_bytes(response[2:6], "big", signed=False)
    return result
 
print(query_status(serial_interface, SICK_STRING))

Re: HEX Länge ermitteln

Verfasst: Sonntag 11. Januar 2026, 08:17
von kiaralle
Ich werde falsch verstanden. Ist aber nicht so schlimm.


Ich sende den sick_string an das Gerät.

sick_string = "Rs485-Adresse + Befehl "

Erhalten werde ich wenn alles iO. ist

response = "Rs485-Adresse + Befehl + 4Bit Position+ Checksum "

Erhalten werde ich wenn nicht alles iO. ist

response = "Rs485-Adresse + Befehl + 1Bit Fehlermeldung + Checksum "

Wobei das 7. Bit das Errorbit sein soll. Ich jedoch noch nie festgestellt habe, das dies gesetzt ist.
Ich erhalte immer b' '.
Wahrscheinlich muss ich mich darauf konzentrieren. Denn wenn das gesetzt wäre, hätte ich ja meine Fehlererkennung.

Dokumentation: https://www.audin.fr/pdf/documentation ... ERFACE.pdf

Re: HEX Länge ermitteln

Verfasst: Sonntag 11. Januar 2026, 10:29
von __blackjack__
@kiaralle: Wenn das Fehlerbit nicht gesetzt ist, vermute ich dass gar kein Fehler vorliegt, sondern Du ein Timeout beim `Serial`-Objekt gesetzt hast, das zu klein ist, und Du einfach nicht die komplette Nachricht empfängst.

Re: HEX Länge ermitteln

Verfasst: Sonntag 11. Januar 2026, 12:05
von Sirius3
Wenn man die Dokumentation liest, wird klar, dass es sehr auf das richtige Timing ankommt. Abb. 21 zeigt ein Beispiel.
Nach dem Senden deines Commands wird eine einstellbare Zeit gewartet, bis der Empfänger versteht, dass das Command fertig ist. Dann braucht es bis einige ms bis die Antwort erzeut wurde und dann werden Bytes gelesen, bis wieder der Timeout eintrifft.

Sieht also so aus:

Code: Alles auswählen

READ_POSITION_COMMAND = 0x42
READ_POSITION_ANSWER_TIME = 10 / 1000

def read_position(serial_interface, address):
    data = bytearray([address, READ_POSITION_COMMAND])
    data.append(ChecksumXor8.calc(data))
    serial_interface.reset_input_buffer() 
    serial_interface.reset_output_buffer()
    time.sleep(0.01)
    serial_interface.write(data)
    start_time = time.monotonic()
    while True:
        response = serial_interface.read()
        if response:
            break
        if time.monotonic() - start_time > READ_POSITION_ANSWER_TIME:
            raise TimeOutError()
    print(response)
    if ChecksumXor8.calc(response) != 0:
        raise ValueError("Checksum failed")
    command = response[1]
    if  command & 0x80:
        raise ValueError(sick_error.srm_errors())        
    result = int.from_bytes(response[2:6], "big", signed=False)
    return result
Achte bei Deinen Beträgen auf präzise Ausdrucksweise: Wenn Du von 4 Bit sprichst meinst Du eigentlich 4 Bytes. Und wenn Du von Hex redest, meinst Du eigentlich auf Bytes.

Re: HEX Länge ermitteln

Verfasst: Sonntag 11. Januar 2026, 14:41
von kiaralle
Hier noch mal mein kompletter Test - Code.
Das eigentliche Programm funktioniert soweit, nur eben meine Fehlerbehandlung nicht.
Deshalb hier meine Bastelstunde.

Ich rufe den Befehl Hex=42 auf. Es wird korrekt die Position ausgegeben.
Fehler wird keiner erkannt, er wird in meiner sick_error.py korrekt übersetzt.

response = b'@B\x00\x00M\x8e\xc1'
Position, data = 19854
Fehlermeldung = 00 - der Geber hat keinen Fehler erkannt

00 weil im Fehlerfall keine Daten, response[2:6], gesendet werden, sondern nur ein Datenpaket response[2:3]
Er liest hier also die "00" obwohl diese 00 zur Position gehören. Es ist also keine Fehlermeldung.
Bei anderen Positionen, generiert er mir dann Fehlermeldungen. ZB. bei "0c"
Datenpaket response[0:2] ist immer Adresse, Befehl.
import serial, time
from crccheck.checksum import ChecksumXor8
import sick_error
#import csv, os
#import binascii

# initialization and open the port
ser = serial.Serial()
ser.port = "/dev/ttyUSB0"
#ser.port = "COM7"
ser.baudrate = 9600
ser.bytesize = serial.EIGHTBITS #number of bits per bytes
ser.parity = serial.PARITY_EVEN #set parity check: no parity
ser.stopbits = serial.STOPBITS_ONE #number of stop bits
ser.timeout = 0.1 #block read
ser.xonxoff = False #disable software flow control
ser.rtscts = False #disable hardware (RTS/CTS) flow control
ser.dsrdtr = False #disable hardware (DSR/DTR) flow control

ser.open()


#SRM50
sinus_cosinus_perioden= 1024
absolut_erfassbaren_umdrehungen = 4096
gesamtschrittzahl = 134217728


sick_string = "FF 42"


def status(sick_string):

data = bytearray.fromhex(sick_string)
data.append(ChecksumXor8.calc(data))


ser.reset_input_buffer()
ser.reset_output_buffer()
time.sleep(0.01) #give the serial port sometime to receive the data

ser.write(data)
time.sleep(0.01)
response = ser.read(7)

print(response)

data = int.from_bytes(response[2:6],'big',signed=False)
print(data)

fehlermeldung=''.join(format(byte, '02x') for byte in response[2:3])
fehlerspeicher = sick_error.srm_errors(fehlermeldung)
print(fehlerspeicher)

print(response[7:])

status(sick_string)



Fehler provozieren:

Wir ändern den sick_string von sick_string = "FF 42" zu sick_string = "FF 42 55"
Der Befehl enthällt nun einen zusätzlichen Hex, der im Protokoll so nicht vorgesehen ist.
Wir erhalten folgende Ausgabe:

response = b'@P\x0c\x1c'
data = 3100.... ist nun nur wirres Zeug, da hier die Fehlermeldung und die Checksum verbastelt werden.
Fehlermeldung 0c - Anzahl der übertragenen Daten ist falsch... Das ist schon mal korrekt.

x1c wird die Chechsum sein.

Soweit alles klar? Ihr könnt mir folgen? :-) Hab ich einen Denkfehler?

Bei allen was ich mache, bleibt print(response[7:]) immer b' '
Das sollte doch mein Fehlerbit sein. Richtig?

Was sagt Sick dazu?
Fehlerbehandlung
Fehlermeldung
• Befehle die nicht bearbeitet werden können (Protokollfehler, Befehlsargumente oder interne Fehler des MFB)
führen zum Abbruch der Befehlsbearbeitung und das MFB antwortet mit einem Fehlerprotokoll
(s. Command 50h)
Warnmeldung
• Während der Befehlsausführung wird der Betriebszustand des MFB überwacht (z. B. Temperatur, Sender-
strom). Werden hierbei kritische Parameter festgestellt die jedoch auf den aktuell bearbeiteten Befehl ohne
direkte Auswirkung sind, so generiert das MFB bei gesetztem Errorbit, das erwartete Antwortprotokoll.
• Das Fehlerbit wird mit dem Auslesen des Fehlercodes (Command 50h) oder durch einen MFB-Reset (Command
53h) gelöscht.
• Treten mehrere Fehler gleichzeitig auf, so werden vom MFB bis zu 4 Fehlercodes zwischengespeichert die mit
dem Command 50h nacheinander ausgelesen werden können.
Das Fehlerbit bleibt hierbei solange gesetzt, bis alle Fehlercodes ausgelesen sind.
• Werden hierbei kritische Parameter festgestellt die jedoch auf den aktuell bearbeiteten Befehl ohne direkte Aus-
wirkung sind, so generiert das MFB bei gesetztem Errorbit das erwartete Antwortprotokoll.

Gruß Ralf

Re: HEX Länge ermitteln

Verfasst: Sonntag 11. Januar 2026, 15:02
von kiaralle
Beispiel für falsche Fehlererkennung.

Der Befehl wird korrekt ausgeführt-
x07 steht für einen Teil der Position und wird hier als Fehler gedeutet.

b'@B\x07\xff\xb1\x8f\xc4'
134197647
07 - Geberreset durch Programmüberwachung aufgetreten
Errorbit ist b''

Re: HEX Länge ermitteln

Verfasst: Sonntag 11. Januar 2026, 15:06
von kiaralle
Wenn ich das so mache, also Bit 7 abrufe, erhalte ich im Fehlerfall 28, sonnst unterschiedliche Zahlen :roll:

Code: Alles auswählen

errorbit =response[-1]
print(errorbit)

Re: HEX Länge ermitteln

Verfasst: Sonntag 11. Januar 2026, 15:15
von sparrow
Kannst du bitte noch einmal Sirius3s Beitrag lesen?
Du verwechselst Bits und Bytes. Kennst du den Unterschied?

Code: Alles auswählen

b'@P\x0c\x1c'
sind 4 BYTES. Ist dir das bewusst?
Du abeitest da auf den BYTES und versuchst auf das 7. BYTE oder das letzte BYTE zuzugreifen. Das hat nichts mit einem BIT zu tun.
Wenn also ein errorBIT gesetzt ist, bist du auf dem falschen Weg.

Re: HEX Länge ermitteln

Verfasst: Sonntag 11. Januar 2026, 15:23
von kiaralle
sparrow hat geschrieben: Sonntag 11. Januar 2026, 15:15 Kannst du bitte noch einmal Sirius3s Beitrag lesen?
Du verwechselst Bits und Bytes. Kennst du den Unterschied?

Code: Alles auswählen

b'@P\x0c\x1c'
sind 4 BYTES. Ist dir das bewusst?
Du abeitest da auf den BYTES und versuchst auf das 7. BYTE oder das letzte BYTE zuzugreifen. Das hat nichts mit einem BIT zu tun.
Wenn also ein errorBIT gesetzt ist, bist du auf dem falschen Weg.
Jetzt kommt es mir auch langsam. Bin halt nur ein Schrauber :-)
Kannst du mich in die richtige Richtung schieben?

Re: HEX Länge ermitteln

Verfasst: Sonntag 11. Januar 2026, 15:34
von sparrow
Ich glaube, da liegt ein grundsätzlicher Interpretationsfehler vorliegt.
In der Dokumentation steht folgendes:
https://www.audin.fr/pdf/documentations/sick/codeurs/HIPERFACE.pdf hat geschrieben:• Befehle die nicht bearbeitet werden können (Protokollfehler, Befehlsargumente oder interne Fehler des MFB)
führen zum Abbruch der Befehlsbearbeitung und das MFB antwortet mit einem Fehlerprotokoll
(s. Command 50h)
Da steht nichts von einem Fehlerbit.
Und wenn wir uns deine Antwort anschauen, anschauen, dann macht das ja auch Sinn. Denn die ist:

Code: Alles auswählen

'\x40\x50\x0c\x1c'
das zweite Byte ist also 50h und damit exakt wie beschrieben der Indikator dafür, dass ein _Fehler_ aufgetreten ist.

Was du da mit einem ErrorBIT gelesen hat, betrifft ein Flag in den korrekt gegeben Antworten, dass ein potentielles Problem auf dem Gerät vorliegt (auch bekannt als Warnung [Warnung != Fehler]) und dass du die abfragen sollst.
Das musst du dann separat tun. Und das Flag ist das gesetzte 8. Bit im Command-Byte.

Re: HEX Länge ermitteln

Verfasst: Sonntag 11. Januar 2026, 15:41
von kiaralle
'\x40\x50\x0c\x1c'

Hab ich wo stehen?

Ich bekomme im Fehlerfall nur b'@P\x0c\x1c'

Re: HEX Länge ermitteln

Verfasst: Sonntag 11. Januar 2026, 15:46
von kiaralle
Ich lese also 1Byte bestehend aus 8 bit aus. Richtig?

Re: HEX Länge ermitteln

Verfasst: Sonntag 11. Januar 2026, 15:50
von sparrow
Und damit ist diese Aussage auch falsch:
kiaralle hat geschrieben: Sonntag 11. Januar 2026, 14:41 response = b'@B\x00\x00M\x8e\xc1'
Position, data = 19854
Fehlermeldung = 00 - der Geber hat keinen Fehler erkannt
Deine Response hier ist:

Code: Alles auswählen

40 42 00 00 4d 8e c1
Das 3. Byte ist 00h und sagt gar nichts über einen Fehler aus.
Du weiß, dass kein Fehler vorliegt, weil das 2. Byte nicht 50h ist.

Re: HEX Länge ermitteln

Verfasst: Sonntag 11. Januar 2026, 15:52
von sparrow
kiaralle hat geschrieben: Sonntag 11. Januar 2026, 15:41 '\x40\x50\x0c\x1c'

Hab ich wo stehen?

Ich bekomme im Fehlerfall nur b'@P\x0c\x1c'
Weißt du was HEX ist? Also Hexadezimaldarstellung?
Falls nicht, musst du dir das jetzt anlesen. Denn darauf basiert deine Dokumentation.

Code: Alles auswählen

>>> b'@P' == b'\x40\x50'
True
>>> b'@P\x0c\x1c'.hex()
'40500c1c'

Re: HEX Länge ermitteln

Verfasst: Sonntag 11. Januar 2026, 15:58
von grubenfox
kiaralle hat geschrieben: Sonntag 11. Januar 2026, 08:17 Wobei das 7. Bit das Errorbit sein soll.
Dokumentation: https://www.audin.fr/pdf/documentation ... ERFACE.pdf
Laut Abb. 19 der Doku soll das achte Bit das Errorbit sein.
und darunter...
Fehlerbehandlung
Fehlermeldung
• Befehle die nicht bearbeitet werden können (Protokollfehler, Befehlsargumente oder interne Fehler des MFB)
führen zum Abbruch der Befehlsbearbeitung und das MFB antwortet mit einem Fehlerprotokoll
(s. Command 50h)
Warnmeldung
• Während der Befehlsausführung wird der Betriebszustand des MFB überwacht (z. B. Temperatur, Sender-
strom). Werden hierbei kritische Parameter festgestellt die jedoch auf den aktuell bearbeiteten Befehl ohne
direkte Auswirkung sind, so generiert das MFB bei gesetztem Errorbit, das erwartete Antwortprotokoll.
• Das Fehlerbit wird mit dem Auslesen des Fehlercodes (Command 50h) oder durch einen MFB-Reset (Command
53h) gelöscht.
• Treten mehrere Fehler gleichzeitig auf, so werden vom MFB bis zu 4 Fehlercodes zwischengespeichert die mit
dem Command 50h nacheinander ausgelesen werden können.
Das Fehlerbit bleibt hierbei solange gesetzt, bis alle Fehlercodes ausgelesen sind.
• Werden hierbei kritische Parameter festgestellt die jedoch auf den aktuell bearbeiteten Befehl ohne direkte Aus-
wirkung sind, so generiert das MFB bei gesetztem Errorbit das erwartete Antwortprotokoll.

Ein adressiertes MFB antwortet auf eine fehlerfrei bearbeitete Befehlssequenz stets mit der Wiederholung
von ADDRESS und COMMAND, gefolgt von den angeforderten Daten und der CHECKSUM.
Also die Warnmeldung ist mir einigermaßen klar: wenn in dem empfangenen Byte welches das 6bit lange COMMAND enthält (also wohl das Zweite Byte der Nachricht) das Errorbit gesetzt ist [hinten dran nach dem COMMAND mit gesetztem Fehlerbit kommen die angeforderten Daten] , dann liegen da bis zu 4 Fehlercodes rum die man einzeln mit Command 50h abrufen kann. Die Antwort mit dem letzten Fehlercode hat dann kein gesetztes 8. (Fehler-) Bit mehr.

Wie bei einer richtigen Fehlermeldung nun dieses "Fehlerprotokoll" aussieht, ist mir eher weniger klar. Der Begriff wird auch nicht weiter erläutert. Möglicherweise kommt da als Antwort sofort das zurück, was man bei Warnungen erst mit Command 50h abfragen müsste. Da wäre beim Fehler dann das empfangene Command gleich 50h und damit ungleich dem gesendeten Command. Mit oder ohne gesetztem Fehlerbit, je nach dem ob da dann nur ein einziger oder mehrere Fehlercodes rum liegen.

Re: HEX Länge ermitteln

Verfasst: Sonntag 11. Januar 2026, 16:05
von kiaralle
Das ist doch das, was ich vom Geber zurück bekomme.
Laut Beschreibung "Pos.abfragen" Befehl 42

40 42 00 00 4d 8e c1

40 = Geräteadresse
42 = Befehl, Position abfragen
00+00+46+8e = Position = int.from_bytes(response[2:6],'big',signed=False)
c1 sollte, ist Checksum

Im Fehlerfall sollte ich doch soetwas bekommen

40 42 0c

Oder nicht?

Bei der Abfrage vom Fehlerspeicher das wäre dann 40 50 kann ich nacheinander die vier Fehlerspeicher abrufen.
Nur ist da auch nie was drinnen :-)