SDM72DM Modbus RTU / RS485 Daten auslesen Python

#7642018
Lesenswert?

Hallo zusammen,

ich habe einen Stromzähler (SDM72DM) gekauft, um die aktuelle importierte und exportierte Leistung auslesen zu können. Diese Daten möchte ich dann auswerten und bei zu viel Exportierter Leistung (PV-Anlage) einen Verbraucher automatisch hinzuschalten, um meinen Eigenverbrauch zu erhöhen. Ich hätte dabei an eine Ansteuerung einer Wallbox (GoE-Charger) per MQTT API gedacht...

Soweit so gut.. jedoch scheitert es gerade an dem Versuch die Daten des Stromzählers per RS485 auszulesen. Ich konnte die Daten bereits mit Dem Programm "Modbus Poll" , und einem USB-->RS485 Adapter am PC anzeigen lassen. Damit kann ich aber die daten nicht weiterverarbeiten.

Ich möchte den Zähler daher mit einem Python Programm auslesen.

Dieses Programm hätte ich gebastelt, jedoch bekomme ich als Ausgabe nur den Wert "0":

1
from pymodbus.client import ModbusSerialClient
2
from pymodbus.payload import BinaryPayloadDecoder
3
from pymodbus.constants import Endian
4
client = ModbusSerialClient(port= "COM7", timout = 2, baudrate= 9600, bytesize=8, parity= 'N', stopbits=1)
5
client.connect()
6

7

8
rr = client.read_input_registers(address=0x0000, count=2, slave=1)
9
print (rr)
10
client.close()

Zum Testen möchte ich hier das Input Register 3001 auslesen. Deshalb "adress= 0x0000", "count=2" da laut Datenblatt zweit 16 bit Register für einen Parameter benutzt werden. "slave=1", da ich die Adresse des Zählers auf 1 eingestellt ist.

Kann mir da jemand helfen, was ich falsch mache? Ein verdacht wäre, dass das Format "Float" Probleme verursacht.

Angehängte Dateien:
#7642029
Lesenswert?

Falls du tatsächlich zwei 16bit Werte bekommst, also eine float Wert aufgesplittet, dann hilft:

1
#!/python3
2
from struct import pack,unpack
3

4
registers_16bit = (1, 1) # angenommene Werte
5
final_float_value = unpack("f", pack('HH', *registers_16bit))
6
print(final_float_value)

Reihenfolge der 16bit Werte sind noch wichtig.

#7642072
Lesenswert?

Danke für die Antwort ;)

ich habe dein Ratschlag befolgt, und ich denke das ist schonmal der richtige weg, ich bekomme natürlich als Ergebnis wieder nur eine "0" heraus, da ich ja gar keine Daten vom Bus Teilnehmer bekomme. Ich denke dass beim Auslesen des Registers irgendetwas schief läuft :(

1
from pymodbus.client import ModbusSerialClient
2
from struct import pack, unpack
3
import pymodbus
4
client = ModbusSerialClient(port= "COM7", timout = 2, baudrate= 9600, bytesize=8, parity= 'N', stopbits=1)
5
client.connect()
6

7
rr = client.read_input_registers(address=0x0000, count=2, slave=1)
8

9

10
registers_16bit =(rr.registers[0],rr.registers[1])
11
final_float_value = unpack("f", pack('HH', *registers_16bit))
12
print(rr)
13
print(rr.bits)
14
print(rr.registers)
15
print(final_float_value)
16
client.close()

als Antwort bekomme ich:

1
ReadInputRegistersResponse (2)
2
[]
3
[0, 0]
4
(0.0,)
5
PS C:\Users\mathi>
#7642162
Lesenswert?

Bietet die verwendete Python-Library auch die Möglichkeit, die Rohdaten, die über den Bus transportiert werden, anzuzeigen (als Hexdump)?

Falls ja, poste mal das Anfragetelegramm und die Antwort.

Zeig' auch mal das, was Modbus Poll anzeigt - nutzt das RTU oder ASCII?

"Display > Communication" sollte so etwas anzeigen:

https://www.modbustools.com/images/mbpoll-communication-traffic.png

#7642225
Lesenswert?

Frank K. schrieb:

Der Modbus-Standard schreibt Even Parity als Default vor. Schau mal, ob die Einstellungen für den UART stimmen.

ich hab den kleinen Bruder von dem Stromzähler, den SDM230, an einem ESP32 Modbus RTU->TCP Gateway hängen, läuft bei mir mit 9600 8N1.

Aber: Das kann man am Zähler durch ewig lange Morsecode-Klickorgien sehr frei konfigurieren... Also: Am Gerät nachschauen, wie's tatsächlich eingestellt ist.

Angehängte Dateien:
#7642272
Lesenswert?

Εrnst B. schrieb:

Nachtrag: Gerade mal im Debug-Modus das Read-Commando wie vom TE geplant geschickt, Antwort 0x4366b925, als Float 230.723

Danke für die Zahlen.Passt.

1
#!/usr/bin/python3
2
# -*- coding: UTF-8 -*-
3
# vim:fileencoding=UTF-8:ts=4
4

5
from struct import pack,unpack
6
# 0x4366b925 ,  230.723
7

8
registers_16bit = (0xb925,0x4366)
9
final_float_value = unpack("f", pack('HH', *registers_16bit))
10
print(*final_float_value)
11

12
>>> 230.7232208251953

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren