ich schreibe gerade an einem Modul für das Abfragen eines Fronius Smart Meters per Modbus RTU (ID = 3).
Das Smart Meter hängt am gleichen Bus wie die EVSE DIN (ID = 1), die gesamte Buslänge sind ca. 30 cm und der Bus ist korrekt terminiert.
Wie in diesem Thread http://openwb.de/forum/viewtopic.php?f= ... 90605#p191 beschrieben, habe ich mir die EVSE DIN durch die Lese-Abfragen des Smart Meters "zerschossen" und konnte sie nur durch ein erneutes Flashen der Firmware wieder zum Leben erwecken.
Nachdem wieder alles so funktioniert hatte wie es sollte, habe ich das Modul für das Smart Meter wieder reaktiviert und siehe da: der Fehler tritt erneut auf.
Je nachdem, welche Register des Smart Meters ich abfrage, geht die EVSE DIN in einen anderen Zustand und ist nicht mehr nutzbar:
- Register 4096/4097 und 4098/4099 (Spannung L1 und L2, die ersten beiden Einträge im Tuple "values") -> kein Problem, alles funktioniert über einen längeren Zeitraum.
- Sobald das Register 4100/4101 (Spannung L3, dritter Eintrag im Tuple "values") hinzukommt -> EVSE DIN blinkt noch normal (grüne LED) aber reagiert nicht mehr, auch der neue EVSE Modbus Test auf der Statusseite schlägt fehl.
- Wenn ich die Register für die Ströme, Leistung und Energie hinzunehme (4102 - 4109, 4116/4117, 4124/4125, die restlichen Einträge im Tuple "values"), dann hört das Blinken der grünen LED auf und die EVSE DIN schaltet das Relais ein.
Besonders der letzte Punkt (also das Freigeben des Schützes durch lesende Abfragen per Modbus) macht mir etwas Bauchschmerzen.
Vom Gefühl her würde ich sagen, dass ich durch lesende Abfragen in bestimmten Registern (hier 4100 und aufwärts) ungewollt im Speicher des PICs herumschreibe. Selbst bei einem unbeabsichtigten Mapping von Registeradressen in bestimmte Bereiche des Speichers kann ich mir das aber nicht wirklich erklären, da ich ja lese, und das auch von einem Gerät mit einer anderen ID.
Kann dazu jemand von Euch etwas sagen?
@aiole: Du hast Doch Kontakt zu dem Entwickler... kannst Du ihn vielleicht dazu mal befragen?
Ich füge die "main.sh" und die eigentliche "readfsm63a3.py" meines Moduls mal unten ein (ein Dateianhang von einfachen *.py, *.sh, *.txt-Dateien funktioniert nicht), in der Hoffnung, dass jemand mal urüberschaut und evtl. noch einen Fehler findet.
Problematisch ist, dass sich das ganze ohne das angeschlossene Smart Meter nicht nachstellen lässt... wenn ich das nämlich vom Bus abziehe (und die Anfragen des Moduls an das Smart Meter somit ins Leere laufen), dann funktioniert EVSE DIN weiterhin (zum Nachstellen des Fehlers werden also die Antworten vom Smart Meter benötigt).
Viele Grüße,
Michael
main.sh
Code: Alles auswählen
#!/bin/bash
. /var/www/html/openWB/openwb.conf
### The following variables need to be added to "openwb.conf":
# fsm63a3modbusllsource=/dev/ttyUSB0
# fsm63a3modbusllid=3
### Furthermore the follwoing value in "openwb.conf" has to be set manually:
# ladeleistungmodul=fsm63a3modbusll
ramdiskpath="/var/www/html/openWB/ramdisk"
sudo python /var/www/html/openWB/modules/fsm63a3modbusll/readfsm63a3.py $fsm63a3modbusllsource $fsm63a3modbusllid $ramdiskpath
Code: Alles auswählen
#!/usr/bin/python
import sys
from pymodbus.client.sync import ModbusSerialClient
from pymodbus.payload import BinaryPayloadDecoder
from pymodbus.constants import Endian
# Set debug to "1" to enable debugging messages
debug = 0
# Check the given arguments
if debug == 1:
print(str(sys.argv))
# Modbus RTU port and id of the Fronius Smart Meter 63A-3
mb_port = str(sys.argv[1])
mb_id = int(sys.argv[2])
# Path to the ramdisk
ramdiskpath = str(sys.argv[3])
# Definition of the values that will be requested
# +-------------------------------- Internal variable name (also used as ramdisk file name)
# | +-------------------- Modbus Address
# | | +------------- Multiplier to calculate the correct unit for openWB
# | | | +------- Precision (digits after the decimal separator)
# | | | | +-- Description
# | | | | |
values = (('llv1', 4096, 0.001, 2, 'Voltage AC Phase 1 [0.001 * V]'),
('llv2', 4098, 0.001, 2, 'Voltage AC Phase 2 [0.001 * V]'),
('llv3', 4100, 0.001, 2, 'Voltage AC Phase 3 [0.001 * V]'),
('lla1', 4102, 0.001, 2, 'Current AC Phase 1 [0.001 * A]'),
('lla2', 4104, 0.001, 2, 'Current AC Phase 2 [0.001 * A]'),
('lla3', 4106, 0.001, 2, 'Current AC Phase 3 [0.001 * A]'),
('llaktuell', 4116, 10.0, 0, 'Power Real P Sum [0.01 * kW]'),
('llkwh', 4124, 0.01, 2, 'Energy Real WAC Sum Produced [0.01 * kWh]'))
### The following value addresses have to be verified:
# ('wl1', 4140, 0.001, 2, 'Power Real P Phase 1'),
# ('wl2', 4142, 0.001, 2, 'Power Real P Phase 2'),
# ('wl3', 4144, 0.001, 2, 'Power Real P Phase 3'),
# ('llpf1', ????, 0.001, 2, 'Power Factor Phase 1'),
# ('llpf2', ????, 0.001, 2, 'Power Factor Phase 2'),
# ('llpf3', ????, 0.001, 2, 'Power Factor Phase 3'),
client = ModbusSerialClient(method = "rtu", port=mb_port, baudrate=9600,
stopbits=1, bytesize=8, timeout=1)
#client.connect()
for value in values:
result = client.read_holding_registers(value[1], 2, unit=mb_id)
if result.isError():
if debug == 1:
print('Could not read register {} ({})'.format(value[1], value[4]))
decoded_value_str = '0'
else:
decoder = BinaryPayloadDecoder.fromRegisters(result.registers,
byteorder=Endian.Big,
wordorder=Endian.Big)
decoded_value_raw = decoder.decode_32bit_uint()
decoded_value = decoded_value_raw*value[2]
decoded_value_str = '{:.{prec}f}'.format(decoded_value, prec=value[3])
if debug == 1:
print('{}: {} ({})'.format(value[0], decoded_value_str, value[4]))
f = open(ramdiskpath + '/' + value[0], 'w')
f.write(decoded_value_str)
f.close()
#client.close()