Neues Modul für Geräte mit Modbus Schnittstelle über RS232 bzw. RS485

Begonnen von StefanStrobel, 12 Juli 2014, 14:50:22

Vorheriges Thema - Nächstes Thema

StefanStrobel

Hallo Denis,

Dein Timeout scheint ein anderes Problem zu sein. Das gesendete Modbus-Frame sieht für mich korrekt aus, aber dein Gerät antwortet nicht.

Bekommst Du denn eine Fehleranzeige bei der Übertragung des Schreib-Befehls auf den LEDs Deines Geräts?
Hast Du eine Möglichkeit die Kommunikation der mitgelieferten Software mitzulesen? (evt. kannst Du da sehen wo der Unterschied liegt)

Gruss
   Stefan

Roger

Hallo Stefan,
so nun hatte ich endlich zeit zum Testen. Senden ist etwas besser, aber noch nicht gut  :(
Hier das Log:
2015.02.09 20:12:15 5: HA_SDM630M_1: Set: found option Demand_Period__minutes in setHash, setVal = 60
2015.02.09 20:12:15 5: HA_Modbus_1: Add frame to queue: 01100002000204084b, force send
2015.02.09 20:12:15 5: HA_SDM630M_1: _Send: creating new queue
2015.02.09 20:12:15 5: HA_Modbus_1: handle send queue, force
2015.02.09 20:12:15 4: HA_Modbus_1: handle queue sends frame: 01100002000204084b (fcode 16 to 1)
2015.02.09 20:12:15 5: SW: 01100002000204084b
2015.02.09 20:12:15 5: HA_SDM630M_1: ReadAnswer called and remaining timeout is 1.99783301353455 requested reading is Demand_Period__minutes
2015.02.09 20:12:17 3: HA_SDM630M_1: Timeout2 in ReadAnswer for Demand_Period__minutes
2015.02.09 20:12:17 1: Perfmon: possible freeze starting at 20:12:16, delay is 1.451
2015.02.09 20:12:17 4: HA_Modbus_1: timeout waiting for 16 from 1, Request was 01100002000204084b, last Buffer: 01030442700000ef90

Byte-Count 04 wird nun eingetragen, aber irgendwie scheinen die Daten zu fehlen:
Field Name Example Hex-OK   Hex-Modul
Slave Address        01      01
Function             10      10
Start Address High   00      00
Start Address Low    02      02
Number of Reg. High  00      00
Number of Reg. Low   02      02
Byte Count           04      04
Data, Hi-Reg,Hi-Byte 42
Data, Hi-Reg,LowByte 70
Data, LowReg,Hi-Byte 00
Data, LowReg,LowByte 00
Error Check Low      67      08
Error Check High     D5      4B

Was kann ich tun?
Roger
Zotac, BBB, RPIs mit 10*FHEM
2*HM-LAN, 2*JeeLink, 2*RS485, SignalESP
HomeMatic, PCA301 Komponenten, ModBus: Stromzähler, Fronius WR, Shelly

StefanStrobel

Hallo Roger,

Du kannst für Dein Holding Register den unpack-Code in ParseInfo angeben.
Dann wird der Wert auch ins Frame gepackt.
Der defUnpack Key als Default wird im Modul noch nicht verwendet - Sorry, soweit war ich noch nicht.
Siehe Funktion ModbusLD_Send im Basis-Modul.

Gruß
     Stefan

Roger

Hallo Stefan,
mit unpack-Code in ParseInfo geht das Schreiben  :)
2015.02.10 18:13:58 5: HA_SDM630M_1: Set: found option Demand_Period__minutes in setHash, setVal = 60
2015.02.10 18:13:58 5: HA_Modbus_1: Add frame to queue: 011000020002044270000067d5, force send
2015.02.10 18:13:58 5: HA_SDM630M_1: _Send: creating new queue
2015.02.10 18:13:58 5: HA_Modbus_1: handle send queue, force
2015.02.10 18:13:58 4: HA_Modbus_1: handle queue sends frame: 011000020002044270000067d5 (fcode 16 to 1)
2015.02.10 18:13:58 5: SW: 011000020002044270000067d5
2015.02.10 18:13:58 5: HA_SDM630M_1: ReadAnswer called and remaining timeout is 1.99634289741516 requested reading is Demand_Period__minutes
2015.02.10 18:13:58 5: SetSilent ReadAnswer got: 01
2015.02.10 18:13:58 5: SetSilent ReadAnswer got: 0110
2015.02.10 18:13:58 5: SetSilent ReadAnswer got: 011000
2015.02.10 18:13:58 5: SetSilent ReadAnswer got: 01100002
2015.02.10 18:13:58 5: SetSilent ReadAnswer got: 011000020002
2015.02.10 18:13:58 5: HA_Modbus_1: ParseFrames got: 011000020002
2015.02.10 18:13:58 4: HA_Modbus_1: ParseFrames: fcode 16 from 1, data 0002 calc crc = 56449, read = 512 -> mismatch! expect 16 from 1 for module HA_SDM630M_1
2015.02.10 18:13:58 5: HA_Modbus_1: ParseFrames got wrong crc and returns (maybe data is still incomplete)
2015.02.10 18:13:58 5: SetSilent ReadAnswer got: 011000020002e008
2015.02.10 18:13:58 5: HA_Modbus_1: ParseFrames got: 011000020002e008
2015.02.10 18:13:58 4: HA_Modbus_1: ParseFrames: fcode 16 from 1, data 00020002 calc crc = 2272, read = 2272 expect 16 from 1 for module HA_SDM630M_1
2015.02.10 18:13:58 5: HA_Modbus_1: reply to fcode 16 arrived, 2 registers written
2015.02.10 18:13:58 5: HA_SDM630M_1: ReadAnswer done
2015.02.10 18:13:58 5: HA_SDM630M_1: Set: sending read after write
2015.02.10 18:13:58 5: HA_Modbus_1: Add frame to queue: 01030002000265cb, force send
2015.02.10 18:13:58 5: HA_SDM630M_1: _Send: creating new queue
2015.02.10 18:13:58 5: HA_Modbus_1: handle send queue, force
2015.02.10 18:13:58 5: HA_Modbus_1: HandleSendQueue sendDelay for device HA_SDM630M_1 not over, sleep 0.0541110038757324 forced
2015.02.10 18:13:58 5: HA_Modbus_1: HandleSendQueue commDelay for device HA_SDM630M_1 not over, sleep 0.0939970016479492 forced
2015.02.10 18:13:58 4: HA_Modbus_1: handle queue sends frame: 01030002000265cb (fcode 3 to 1)
2015.02.10 18:13:58 5: SW: 01030002000265cb
2015.02.10 18:13:58 5: HA_SDM630M_1: ReadAnswer called and remaining timeout is 1.99457097053528 requested reading is Demand_Period__minutes
2015.02.10 18:13:58 5: SetSilent ReadAnswer got: 01
2015.02.10 18:13:58 5: SetSilent ReadAnswer got: 0103
2015.02.10 18:13:58 5: SetSilent ReadAnswer got: 010304
2015.02.10 18:13:58 5: SetSilent ReadAnswer got: 01030442
2015.02.10 18:13:58 5: SetSilent ReadAnswer got: 0103044270
2015.02.10 18:13:58 5: HA_Modbus_1: ParseFrames got: 0103044270
2015.02.10 18:13:58 4: HA_Modbus_1: ParseFrames: fcode 3 from 1, data 04 calc crc = 13089, read = 28738 -> mismatch! expect 3 from 1 for module HA_SDM630M_1
2015.02.10 18:13:58 5: HA_Modbus_1: ParseFrames got wrong crc and returns (maybe data is still incomplete)
2015.02.10 18:13:58 5: SetSilent ReadAnswer got: 010304427000
2015.02.10 18:13:58 5: HA_Modbus_1: ParseFrames got: 010304427000
2015.02.10 18:13:58 4: HA_Modbus_1: ParseFrames: fcode 3 from 1, data 0442 calc crc = 10611, read = 112 -> mismatch! expect 3 from 1 for module HA_SDM630M_1
2015.02.10 18:13:58 5: HA_Modbus_1: ParseFrames got wrong crc and returns (maybe data is still incomplete)
2015.02.10 18:13:58 5: SetSilent ReadAnswer got: 01030442700000ef
2015.02.10 18:13:58 5: HA_Modbus_1: ParseFrames got: 01030442700000ef
2015.02.10 18:13:58 4: HA_Modbus_1: ParseFrames: fcode 3 from 1, data 04427000 calc crc = 11969, read = 61184 -> mismatch! expect 3 from 1 for module HA_SDM630M_1
2015.02.10 18:13:58 5: HA_Modbus_1: ParseFrames got wrong crc and returns (maybe data is still incomplete)
2015.02.10 18:13:58 5: SetSilent ReadAnswer got: 01030442700000ef90
2015.02.10 18:13:58 5: HA_Modbus_1: ParseFrames got: 01030442700000ef90
2015.02.10 18:13:58 4: HA_Modbus_1: ParseFrames: fcode 3 from 1, data 0442700000 calc crc = 37103, read = 37103 expect 3 from 1 for module HA_SDM630M_1
2015.02.10 18:13:58 5: HA_SDM630M_1: ParseRegs called with 42700000 and start 002
2015.02.10 18:13:58 4: HA_SDM630M_1: ParseRegs assign Demand_Period__minutes with 60
2015.02.10 18:13:58 5: HA_SDM630M_1: Set: ? not found, return list Demand_Period__minutes Modbus_Speed__baud System_Password Modbus_Parity_Stop Modbus_Node_adr
2015.02.10 18:13:58 5: HA_Modbus_1: reply to fCode 3 parsed, 1 readings
2015.02.10 18:13:58 5: HA_SDM630M_1: ReadAnswer done

Das Ende sieht mit Set: ? not found, return list Demand_Period__minutes Modbus_Speed__baud System_Password Modbus_Parity_Stop Modbus_Node_adr noch etwas merkwürdig aus, aber das Schreiben selbst scheint wohl geklappt zu haben.


Dafür habe ich einen anderen Fehler entdeckt  :(
Seit der Einführung von combine zum Lesen von mehreren Registern mit einem Read-Kommando, werden nicht mehr alle Register mit defaultpoll=>1 zyklisch gelesen. Ich hatte den Wert auf 10 stehen und es fehlten ca. 30% der Werte.
Seit ich es wieder auf 1 gezetzt habe, werden wieder alle Register abgefragt.
Wie kann ich das näher untersuchen/loggen?

@Denis: Hast Du auch ein solches Verhalten? Ich habe derzeit 51 Register, welche ich zyklisch einlese.

Roger
Zotac, BBB, RPIs mit 10*FHEM
2*HM-LAN, 2*JeeLink, 2*RS485, SignalESP
HomeMatic, PCA301 Komponenten, ModBus: Stromzähler, Fronius WR, Shelly

StefanStrobel

Hallo Roger,

schick doch mal einen Log-Auszug, in dem man das getupdate sieht. Da sollte erkennbar sein, welche Register in einem gemeinsamen Lesebefehl zusammengefasst werden, wie die Anfrage aussieht und wie Dein Gerät antwortet.
Die Debug-Meldung mit dem set ? ist übrigens völlig normal.

Gruss / Thanx
   Stefan

golem

Hallo Roger,
Ich werde morgen mal nachschauen. Das update von mehreren Readings funktioniert aber ich habe im Moment keine mit defaultpoll =1 drin.
Gruß Denis
Pi - Max-Lan - 8x max Ht -3x Max WT - Max Fk -modbus umg103- 2x Arduino mit Firmata Ethernet- ws300 - 433Mhz Sender Empfänger - 7x 1wire ds1820

golem

Hallo,

ich habe mal getestet und alle werte auf defaultpoll=> 1 gesetzt. Keine Probleme.

Hier mal ein Logauszug wenn ich versuche einen Wert zu schreiben.

2015.02.11 08:12:10 5: umg103: Set found option Delete_Work in setHash created from parseInfo data
2015.02.11 08:12:10 5: umg103: checking Value 1 against Min 0
2015.02.11 08:12:10 5: umg103: checking Value 1 against Max 1
2015.02.11 08:12:10 5: umg103: converted Value 1 to 1 using expr $val
2015.02.11 08:12:10 5: ModbusRT485: Add frame to queue: 0106000901ded8, force send
2015.02.11 08:12:10 5: umg103: _Send: creating new queue
2015.02.11 08:12:10 5: ModbusRT485: handle send queue, force
2015.02.11 08:12:10 4: ModbusRT485: handle queue sends frame: 0106000901ded8 (fcode 6 to 1)
2015.02.11 08:12:10 5: SW: 0106000901ded8
2015.02.11 08:12:10 5: umg103: ReadAnswer called and remaining timeout is 1.99001908302307 requested reading is Delete_Work
2015.02.11 08:12:12 3: umg103: Timeout2 in ReadAnswer for Delete_Work
2015.02.11 08:12:13 4: ModbusRT485: timeout waiting for 6 from 1, Request was 0106000901ded8, last Buffer: 01030442e766ab3463
2015.02.11 08:12:20 5: umg103: GetUpdate called


und der Passende Eintrag aus praseInfo


   "h9"=>  { unpack => "c", # 9 Lösche_Arbeit 0 1 CHAR 0
name => "del_wh",
                                        #defaultpoll => 1,
showget => 1,
expr => '$val',
                                        setexpr => '$val',
len => 1,
reading => "Delete_Work",
                                        set => 1,
                                        setmin => 0,
setmax => 1},   


Gruß Denis
Pi - Max-Lan - 8x max Ht -3x Max WT - Max Fk -modbus umg103- 2x Arduino mit Firmata Ethernet- ws300 - 433Mhz Sender Empfänger - 7x 1wire ds1820

StefanStrobel

#37
Hallo Roger und Denis,

anbei eine neue Version. Jetzt sollte der defUnpack key im deviceInfo Hash auch bei schreibenden Zugriffen verwendet werden. Zudem wird für jedes Reading nicht nur ein poll- Attribut angeboten sondern auch ein optionales pollDelay- Attribut. Das kann man auf einen höheren Wert als das normale Poll-Intervall setzen. Wenn dann nach einem Poll-Intervall die GetUpdate Routine aufegrufen wird, prüft die für jedes zu pollende Reading, ob ein individueller Delay per Attribut spezifiziert wurde und falls ja, ob schon genügend Zeit verstrichen ist. Sonst wird das entsprechende Reading in diesem Update-Zyklus übersprungen.
Im Log wird das bei verbose 5 entsprechend ausgegeben.

Beispiel:

define PWP ModbusSET 5 60            # normaler Update-Zyklus 1 Minute
attr PWP pollDelay-Temp_Soll 300    # dieses Reading nur alle 5 Minuten abfragen


Gruss
   Stefan

edit: removed old versions

Roger

Hallo Stefan,
habe neue Version getestet --> schreiben geht jetzt auch ohne explizite Angabe von unpack  ;D


Allerding habe ich die Thematik, das mit combine=10 nur 22 readings gelesen werden.
Bei combine=1, kommen alle 51 readings
Logs und meine Device.pm habe ich angehängt. Bestimmt siehst Du was.


Die Lösung mit dem
Zitatattr PWP pollDelay-Temp_Soll 300
gefällt mir nicht so  :(
Ich würde eine Lösung im Device-Modul bevorzugen, anstatt das der Anwender als einzige Lösung 50 attrib-Zeilen einfügen muss.
Eher schwebt mir folgendes vor: Im Device Modul lege ich fest, ob das Register bei jedem Zyklus, jeden zweiten usm. ausgelesen wird. Der Anwender kann ev. mit attr einzelne Werte übersteuern.
Vielleicht kannst Du Dir hier noch was überlegen  :-\

Roger
Zotac, BBB, RPIs mit 10*FHEM
2*HM-LAN, 2*JeeLink, 2*RS485, SignalESP
HomeMatic, PCA301 Komponenten, ModBus: Stromzähler, Fronius WR, Shelly

StefanStrobel

Hallo Roger,

wenn man ins Log schaut, sieht man recht schnell woran das mit den fehlenden Readings liegt:


2015.02.12 20:49:09 5: HA_SDM630M_1: ParseRegs called with 434f1f11000000004561d765 and start 082
2015.02.12 20:49:09 5: HA_SDM630M_1: doing sprintf with format %.3f kAh value is 207.121353149414
2015.02.12 20:49:09 5: HA_SDM630M_1: result is 207.121 kAh
2015.02.12 20:49:09 4: HA_SDM630M_1: ParseRegs assign Charge__kAh with 207.121 kAh
2015.02.12 20:49:09 5: HA_SDM630M_1: moving to next register value, skip 2 to 84
2015.02.12 20:49:09 5: HA_SDM630M_1: ParseRegs: no parseInfo for i84
2015.02.12 20:49:09 5: HA_SDM630M_1: moving to next register value, skip 2 to 86
2015.02.12 20:49:09 5: HA_SDM630M_1: ParseRegs: no parseInfo for i86


Bei einem Read für mehrere Register bekommt die ParseRegs Funktion den gelesenen String und die Adresse des ersten Registers. Nach dem Verarbeiten des ersten Registers erhöht die ParseRegs Funktion die Adresse und sucht nach der passenden Definition im parseInfo hash. Nach der Startadresse 82 und einem Wert, der über zwei Register geht, kommt 84. Für das Input-Register mit Adresse 84 findet die Routine jedoch keinen Key mit "i84", da in Deinem Hash "i084" als Key verwendet wird.

Die einfachste Lösung wäre wenn Du die führenden Nullen entfernst.

Für die unterschiedlichen Lese-Intervalle kann ich Dir noch einen weiteren Key im parseInfo bauen, in dem Du eine Vorgabe je Register hinterlegen kannst. Dem Benutzer würde ich aber auf jeden Fall per Attribut ermöglichen, die Intervalle zu ändern.

Gruss
   Stefan

StefanStrobel

#40
Hallo,

hier nochmal eine erweiterte Version.
Es gibt jetzt in der parseInfo noch einen weiteren Key defaultpolldelay, mit dem Ihr einen Default für pollDelay im Modul setzen könnt. Der Benutzer kann das dann per Attribut überschreiben wenn er möchte.

Gruss
   Stefan

Edit: removed old versions

Roger

Hallo Stefan,
habe alle führenden Nullen entfernt --> es wir auch bei combine=40 alles eingelesen  :)

Auch das mit dem defaultpolldelay geht, auch wenn ich es nicht schön finde  :(
(hier hätte ich eher es was wie: in jedem Durchlauf, nur in jedem zweiten - anstatt feste Zeiten. Ich weiß ja nicht, mit welcher Zykluszeit andere Anwender das Modul laufen lassen und auch ich möchte die Zykluszeit beim Aufruf mit einem einzigen Parameter verändern und Beeinflussung aller Abfragen haben :))


Nun habe ich noch ein paar Fragen zur Schönheit in parseInfo:

9.: Warum gibt es showget und warum muss man es bei jedem Register angeben? Ich denke ein get sollte doch bei jedem Register gehen, oder? Eventuell als Standard zu deviceInfo

10.: Kann ein Standard für defaultpoll nicht auch in  deviceInfo möglich sein? Alle meine i-Register sollen zyklisch ausgelesen werden, von den h-Registern keines.

11.: Einige h-Register möchte ich beim Start einmalig auslesen. Kannst Du so etwas noch einbauen?


So das wars erst mal. Vielen Dank für Deine Hilfe und die bisherigen Korrekturen/Erweiterungen  :D
Roger

Zotac, BBB, RPIs mit 10*FHEM
2*HM-LAN, 2*JeeLink, 2*RS485, SignalESP
HomeMatic, PCA301 Komponenten, ModBus: Stromzähler, Fronius WR, Shelly

golem

Hallo Stefan,

für Rogers Vorschlag aus Punkt 11 bin ich auch.

Zum testen der neuen Version komme ich erst nächste Woche.

Gruß Denis
Pi - Max-Lan - 8x max Ht -3x Max WT - Max Fk -modbus umg103- 2x Arduino mit Firmata Ethernet- ws300 - 433Mhz Sender Empfänger - 7x 1wire ds1820

StefanStrobel

Hallo,

Das mit dem einmaligen Lesen kann ich Euch noch einbauen, ebenso ein defaultpoll in der DeviceInfo.
Was die Gets angeht, so wird per Default jeder Wert als Get implementiert. Nur in Fhemweb wird er nicht notwendigerweise angezeit (siehe Rückgabe auf get ?).
Ich schau mal wie ich nächste Woche Zeit finde noch ein paar Zusatzfeatures einzubauen.

Gruss
   Stefan

golem

Hallo Stefan,

super, dann  kann ich ja mal alle Sinnvollen Werte die das Gerät liefert mit einbauen.

Hast du auch vor eine Unterstützung für Modbus Tcp mit einzubauen?

Grus Denis
Pi - Max-Lan - 8x max Ht -3x Max WT - Max Fk -modbus umg103- 2x Arduino mit Firmata Ethernet- ws300 - 433Mhz Sender Empfänger - 7x 1wire ds1820