Modbus RTU Teilnehmer auslesen (minimalmodbus)

Python auf Einplatinencomputer wie Raspberry Pi, Banana Pi / Python für Micro-Controller
Antworten
RobotSox
User
Beiträge: 3
Registriert: Donnerstag 26. Januar 2023, 18:06

Hallo Gemeinde,

ich habe einen Batterieladeregler welchen ich gerne per Modbus-RTU auslesen möchte.
Ich habe dazu vom Hersteller ein Dokument welches die Register beschreibt sowie die Grund Konfiguration.

Leider bekomme ich es einfach nicht hin einen Datensatz zu lesen.

Folgendes habe ich bereits probiert:

Code: Alles auswählen

#!/usr/bin/env python3

import serial
import minimalmodbus
from time import sleep

client1 = minimalmodbus.Instrument('/dev/laderegler', 1, debug=True)  # port name, slave address (in decimal)
client1.serial.baudrate = 9200  # baudrate
client1.serial.bytesize = 8
client1.serial.parity   = serial.PARITY_NONE
client1.serial.stopbits = 1
client1.serial.timeout  = 0.1      # seconds
client1.address         = 1        # this is the slave address number
client1.mode = minimalmodbus.MODE_RTU # rtu or ascii mode
client1.clear_buffers_before_each_transaction = True
#client1.BYTEORDER_BIG_SWAP= 2


#driver_temp = client1.read_float(3018, 4, False, 3)
driver_temp  = client1.read_register(3018, 0, 4) # read 4bytes (32bit)
print("driver temp: ", driver_temp)


client1.close_port_after_each_call = True


Ich bekomme jedoch leider immer folgenden Fehler:

Code: Alles auswählen

 python modbus_min.py
MinimalModbus debug mode. Create serial port /dev/laderegler
MinimalModbus debug mode. Will write to instrument (expecting 7 bytes back): 01 04 0B CA 00 01 13 D0 (8 bytes)
MinimalModbus debug mode. Clearing serial buffers for port /dev/laderegler
MinimalModbus debug mode. No sleep required before write. Time since previous read: 4992932.15 ms, minimum silent period: 4.18 ms.
MinimalModbus debug mode. Response from instrument: 01 04 0B CA 00 01 13 (7 bytes), roundtrip time: 0.0 ms. Timeout for reading: 100.0 ms.

Traceback (most recent call last):
  File "/home/pi/Modbus-RTU/modbus_min.py", line 20, in <module>
    driver_temp  = client1.read_register(3018, 0, 4) # read 4bytes (32bit)
  File "/home/pi/.local/lib/python3.9/site-packages/minimalmodbus.py", line 480, in read_register
    returnvalue = self._generic_command(
  File "/home/pi/.local/lib/python3.9/site-packages/minimalmodbus.py", line 1245, in _generic_command
    payload_from_slave = self._perform_command(functioncode, payload_to_slave)
  File "/home/pi/.local/lib/python3.9/site-packages/minimalmodbus.py", line 1329, in _perform_command
    payload_from_slave = _extract_payload(
  File "/home/pi/.local/lib/python3.9/site-packages/minimalmodbus.py", line 1867, in _extract_payload
    raise InvalidResponseError(text)
minimalmodbus.InvalidResponseError: Checksum error in rtu mode: '\x01\x13' instead of '?\x92' . The response is: '\x01\x04\x0bÊ\x00\x01\x13' (plain response: '\x01\x04\x0bÊ\x00\x01\x13')
Ich kenne mich leider überhaupt nicht mit Modbus aus, kann mich hier jemand unterstützen?
Das Ziel wäre es, den Datensatz 3018 auszulesen.

In der Dokumentation ist folgendes beschrieben:


Bild
Bild
Bild

Kann mir hier bitte jemand weiterhelfen?
Vielen Dank :)
Benutzeravatar
__blackjack__
User
Beiträge: 13079
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Benutzeravatar
__blackjack__
User
Beiträge: 13079
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Das 3018 in dezimal scheint auf jeden Fall schon mal falsch zu sein. In der Dokumentation steht, dass die Adresse hexadezimal ist. In der Tabelle steht ja auch der dezimale Wert dazu:

Code: Alles auswählen

In [1]: 0x3018
Out[1]: 12312
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
RobotSox
User
Beiträge: 3
Registriert: Donnerstag 26. Januar 2023, 18:06

__blackjack__ hat geschrieben: Donnerstag 26. Januar 2023, 20:09 Das 3018 in dezimal scheint auf jeden Fall schon mal falsch zu sein. In der Dokumentation steht, dass die Adresse hexadezimal ist. In der Tabelle steht ja auch der dezimale Wert dazu:

Code: Alles auswählen

In [1]: 0x3018
Out[1]: 12312
Stimmt, hatte auch selber gerade gesehen das ich bei der Baudrate 9200 geschrieben habe statt 9600.

Bekomme jedoch immer noch keinen Wert zurückgeliefert.

Ich verstehe jedoch auch nicht ob ich das mit minimalmodbus als float/long oder register auslesen muss :?
Wie ist denn bei soetwas hier das vorgehen?
juwido
User
Beiträge: 20
Registriert: Donnerstag 15. Dezember 2022, 13:41

Was mir auffällt: "Response from instrument: 01 04 0B CA 00 01 13 (7 bytes)" sieht der debugger. Aber in der Fehlermeldung ist der Wert "CA" übersetzt in "E mit Dach" (erweiterter ASCII-Code)...? Da schlägt anscheinend eine Zeichenauswertung zu, sollte bei Bytes nicht sein.
RobotSox
User
Beiträge: 3
Registriert: Donnerstag 26. Januar 2023, 18:06

Ich habe mich nun noch etwas weiter gespielt, bekomme jedoch nichts brauchbares zusammen...
Mein Code schaut nun wiefolgt aus:

Code: Alles auswählen

#!/usr/bin/env python3

import serial
import minimalmodbus
from time import sleep

client1 = minimalmodbus.Instrument('/dev/laderegler', 1, debug=False)  # port name, slave address (in decimal)
client1.serial.baudrate = 9600  # baudrate
client1.serial.bytesize = 8
client1.serial.parity   = serial.PARITY_NONE
client1.serial.stopbits = 1
client1.serial.timeout  = 0.1      # seconds
client1.address         = 1        # this is the slave address number
client1.mode = minimalmodbus.MODE_RTU # rtu or ascii mode
client1.clear_buffers_before_each_transaction = True


driver_temp = client1.read_long(12312, 4, False, 0)
#driver_temp = client1.read_float(12312, 4, 2, 0)
#driver_temp  = client1.read_register(12312, 0, 4) # read 4bytes (32bit)

#driver_temp = client1.read_register(12342, 1, 4)

print("############")
print("############")
print("driver temp: ", driver_temp)
print("############")
print("############")


client1.close_port_after_each_call = True
Damit bekomme ich jedoch immernoch folgenden Fehler:

Code: Alles auswählen

Traceback (most recent call last):
  File "/home/pi/Modbus-RTU/modbus_min.py", line 18, in <module>
    driver_temp = client1.read_long(12312, 4, False, 0)
  File "/home/pi/.local/lib/python3.9/site-packages/minimalmodbus.py", line 599, in read_long
    self._generic_command(
  File "/home/pi/.local/lib/python3.9/site-packages/minimalmodbus.py", line 1252, in _generic_command
    return _parse_payload(
  File "/home/pi/.local/lib/python3.9/site-packages/minimalmodbus.py", line 1649, in _parse_payload
    _check_response_payload(
  File "/home/pi/.local/lib/python3.9/site-packages/minimalmodbus.py", line 3447, in _check_response_payload
    _check_response_bytecount(payload)
  File "/home/pi/.local/lib/python3.9/site-packages/minimalmodbus.py", line 3576, in _check_response_bytecount
    raise InvalidResponseError(errortext)
minimalmodbus.InvalidResponseError: Wrong given number of bytes in the response: 48, but counted is 3 as data payload length is 4. The data payload is: '0\x18\x00\x02'

Kann mir jemand erklären was ich falsch mache?
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

Die Antwort vom modbus Geraet ist falsch. Warum auch immer, aber die behauptet 48 Bytes zu haben, hat aber nur 3. Die Art, wie du da die Einstellungen vornimmst, sieht sehr falsch aus. Die Argumente gehoeren wenn in den Konstruktor, und den seriellen Port so von hinten durch die Brust ins Auge zu konfigurieren ist auch schraeg. Und das waere auch mein heisser Kandidat fuer die Ursache hier. Wenn der stattdessen mit 19200 liest, kommt da halt sonstewas bei rum. Ich wuerde die minimalmodbus so umschreiben, dass der einfach die gewuenschten 9600 BPS benutzt. Und auch nicht diese absurd niedrigen Timeout setzen. Warum denkst du, der ist notwendig?
Antworten