Forum: Haus & Smart Home SDM72DM Modbus RTU / RS485 Daten auslesen Python


von Mathias (mathias1906)


Angehängte Dateien:

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.

: Bearbeitet durch User
von Norbert (der_norbert)


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.

von Mathias (mathias1906)


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>

von Rüdiger B. (rbruns)


Lesenswert?

Ich benutze FHEM und hier ist eine Perl Modul zum auslesen:
https://github.com/ahermann86/fhemModbusSDM72DM
vielleicht hilft dir das etwas.

von Frank K. (fchk)


Lesenswert?

Mathias schrieb:

> client = ModbusSerialClient(port= "COM7", timout = 2, baudrate= 9600,
> bytesize=8, parity= 'N', stopbits=1)

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

fchk

von Harald K. (kirnbichler)


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

: Bearbeitet durch User
von Εrnst B. (ernst)


Angehängte Dateien:

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.

von Εrnst B. (ernst)


Angehängte Dateien:

Lesenswert?

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

Den Online-Konverter hab ich hier gefunden:
https://gregstoll.dyndns.org/~gregstoll/floattohex/

von Norbert (der_norbert)


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

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.