NEWS
16 bit signed Float einlesen über den Node-red Modbus
-
@JXA:Mit dem geposteten Sketch komme ich aktuell nicht wirklich weiter….
Habe nochmal die beiden Register[272] für die Temperatur ausgelesen und über Modbus Response angezeigt.
Ausgabe: 32771,16806 diese 32bit float Zahl sollte einer Temperatur von 20,8xx°C entsprechen `
Wenn man die beiden Werte aus den Modbusregistern richtig einliest und als Dezimalzahl umrechnet, dann kommen dabei genau 20.831 raus.Ergebnis für die Reihenfolge 32771, 16806: -0.531
Ergebnis für die Reihenfolge 16806, 32771: 20.831
Garf
-
Hallo "Graf" vielen Dank für deine Hilfe!
Das auslesen der Register über node red funktioniert also "sauber",
das Problem liegt also in der "Funktion" um die Werte Dezimal anzeigen zu können.
Könntest Du die Funktion im Sample Code anpassen um die Sache besser zu verstehen?
Nochmals vielen Dank an "Starter" dafür!!
[{"id":"6f92b84.0ef3ac8","type":"modbus-read","z":"7d4de8d.1542118","name":"X320_Read","topic":"","showStatusActivities":false,"showErrors":false,"unitid":"","dataType":"HoldingRegister","adr":"272","quantity":"2","rate":"1","rateUnit":"s","delayOnStart":false,"startDelayTime":"","server":"741a094c.1340b8","useIOFile":false,"ioFile":"","useIOForPayload":false,"x":330,"y":260,"wires":[[],["3de8b140.13ce2e","cca0874c.f3d76"]]},{"id":"3de8b140.13ce2e","type":"function","z":"7d4de8d.1542118","name":" 32bit","func":"msg.payload=msg.payload.buffer.readFloatLE(0,1,2,3);\nreturn msg;\n","outputs":1,"noerr":0,"x":510,"y":400,"wires":[["f6427835.8241b"]]},{"id":"f6427835.8241b","type":"debug","z":"7d4de8d.1542118","name":"","active":true,"console":"false","complete":"false","x":690,"y":540,"wires":[]},{"id":"cca0874c.f3d76","type":"modbus-response","z":"7d4de8d.1542118","name":"","registerShowMax":20,"x":600,"y":260,"wires":[]},{"id":"741a094c.1340b8","type":"modbus-client","z":"","name":"X320","clienttype":"tcp","bufferCommands":true,"stateLogEnabled":false,"tcpHost":"192.168.0.48","tcpPort":"502","tcpType":"DEFAULT","serialPort":"/dev/ttyUSB","serialType":"RTU-BUFFERD","serialBaudrate":"9600","serialDatabits":"8","serialStopbits":"1","serialParity":"none","serialConnectionDelay":"100","unit_id":"1","commandDelay":"1","clientTimeout":"1000","reconnectTimeout":"2000"}]
-
@JXA:Das auslesen der Register über node red funktioniert also "sauber",
das Problem liegt also in der "Funktion" um die Werte Dezimal anzeigen zu können.
Könntest Du die Funktion im Sample Code anpassen um die Sache besser zu verstehen?
Nochmals vielen Dank an "Starter" dafür!! `
Ich kopiere mir keine Flows mit IP-Adressen die es in meinem Netzwerk nicht gibt in meine laufenden Flows. Dies führt nur zu Problemen. Bitte poste doch einfach mal ein paar Screenshots vom Inhalt des Function Node und die Bufferwerte.
Soviel ich aus dem Flow herauslesen kann, liest Du zwei Modbusregister in vier Buffer ein.
dataType":"HoldingRegister","adr":"272","quantity":"2"
"name":" 32bit","func":"msg.payload=msg.payload.buffer.readFloatLE(0,1,2,3);\nreturn msg
Was steht denn in den Buffern 2 und 3?
Ich kann es zwar nicht testen, aber wenn in den Buffern 0 und 1 die Werte 32771, 16806 stehen, dann müsttest Du nur die Reihenfolge des Einlesens ändern:
msg.payload.buffer.readFloatLE(1,0)
Dann sollte der gewünschte Wert richtig angezeigt werden. Ich kann dies leider nicht im wirklichen Wirkbetrieb testen, es sollte aber eigentlich so funktionieren.
Garf
-
Hallo "Graf"
vielen Dank für deine Antwort!
Zur bisherigen Funktion:
""name":" 32bit","func":"msg.payload=msg.payload.buffer.readFloatLE(0,1,2,3);\nreturn msg"
Der Gedanke die 16 bit je Register a 2x8Bit einzulesen…
Also Register 272=(0,1) 273=( 2,3)
Dank deiner Rechnung ist nun klar das dies nicht erforderlich ist!
Ich habe die Funktion nun geändert:
msg.payload.buffer.readFloatLE(1,0)
Was zum exakt gleichen Ergebnis führt!
Die Werte der Register werden im Screenshot im Modbus Response angezeigt.
Ist die Funktion korrekt von mir übernommen? Habe ich einen Fehler gemacht?
-
Hi JXA,
da muss ich meine Aussage von vorhin wohl doch etwas revidieren. Deine Einstellungen im Function-Node waren absolut richtig. Ich hatte einfach vergessen, dass die Javafunktion ja mit den Buffer 8-bit Werten rechnet. Das heißt das Modbusregister 1 und 2 (je 16bit) werden in je zwei Hexzahlen zerlegt und dann als Dezimalzahl umgerechnet.
Ich habe eben mal verucht die 8-bit Werte von der Reihenfolge 0,1,2,3 in 3,2,0,1 zu ändern. Dies funktioniert aber leider nicht.
Somit haben wir jetzt zwar eine schöne Javafunktion die uns die Rechenarbeit abnimmt, aber keine Möglichkeit zur Verfügung stellt die Modbusregister von hinten nach vorne einzulesen und umzurechnen. Da müssen wir uns wohl noch etwas einfallen lassen. Ich habe vor einigen Wochen selbst ein Funktion-Node programmiert, welches die Einträge in den Modbusregistern einliest und wieder als Dezimalzahl ausgibt. Ich lese dafür allerdings die Datawerte in msg.payload als Arraywerte ein und kann da auch frei bestimmen in welcher Reihenfolge die Werte eingelesen und zurückgerechnet werden. Damit war es mir dann auch möglich deine geposteten Werte in beiden Varianten einmal zu rechnen.
Garf
-
Hallo Graf,
super, dann haben wir jetzt das Grundproblem geklärt und einen soliden Status!
Der aktuelle Sketch sollte ja nur zum testen dienen.
Ich möchte natürlich über Modbus mehrere Register auslesen und dann anzeigen.
Somit ist das speichern der Modbuswerte in einem Array unausweichlich.
Kannst du mir eine Sample code senden mit deinen selbst programmierten Funktions -Node?
Modbus->Array->Funktion->Ausgabe
Danke!
JXA
-
@JXA:Kannst du mir eine Sample code senden mit deinen selbst programmierten Funktions -Node? `
Wenn wir keine andere Lösung finden, dann schicke ich dir das selbst programmierte Funktion-Node zu. Im Moment befindet es sich aber noch in einer Rohfassunge und enthält viele Dinge die man in der praktischen Umrechnung nicht mehr braucht. Um Programmierfehler frühzeitig erkennen zu können, musste ich diese allerdings einbauen. Ich habe an dem Node nicht mehr weitergearbeitet, weil es für die Umrechnung ja bereits diese tolle Javascriptfunktion gibt. Wir müssen mal schauen, ob es da nicht auch schon eine Lösung für dein Problem gibt. Ich lese mich da gleich noch einmal ein.Garf
-
Ich glaube da schon etwas gefunden zu haben.
https://github.com/biancode/node-red-co … endianness
Mit der swap Funktion werden tatsächlich die Bufferwerte getauscht.
Lt. Response stehen als Werte im Buffer 3f 99 99 9a und nach dem swap 99 3f 9a 99. Mir ist nur noch nicht klar was buffer.swap16() macht und ob es die richtige Funktion für dein Problem ist. Da muss man wohl noch mal weiter nachlesen.
Ich bin mal optimistisch, damit könnten wir es irgendwie hinbekommen. Wenn Du magst, kannst Du ja schon mal ein Versuch starten.
-
Hallo Graf,
danke für die Info.
Ich habe den "Buffer Swap" getestet.
Er führt aktuell nicht zum gewünschten Ergebnis…
Habe ich etwas vergessen??
5860_swap.png -
Bei mir scheint es zu funktionieren. Du solltest nur das Debug-Node eingeschaltet lassen, welches uns die Meldungen zu dem Function swap-Node zeigt.
Bitte den Inhalt des swap-Nodes posten.
Ich habe folgende Eintragungen vorgenommen:
msg.payload.buffer.swap16(); msg.payload = msg.payload.buffer.readFloatBE(0,1,2,3); return msg;
-
Habe die Änderung vorgenommen…
5860_swap2.png
5860_swap_function.png -
Erstaunlich, dass es funktioniert, Normalerweise hättest Du das BE durch LE ersetzen müssen. Bisher jedenfalls hast Du immer Littel Endian ausgelesen.
Hier mal die Grundlagen dazu: https://de.wikipedia.org/wiki/Byte-Reihenfolge
Lt. Bedienungsanleitung von deinem X-320 lässt sich die Byte-Reihenfolge einstellen:
` > Big Endian
32-bit data is treated as two individual 16-bit words using IEEE 754 floating point format. Floating
point format is used for sensor, pulse counter, analog, and frequency data as well as for setting
output pulse duration.
If the checkbox is set, the X-320
will use big-endian architecture, and the most significant 16-bit
word (big end) is sent first. If the box is cleared, then the X-320
will use little-endian architecture,
and the least significant word (little end) is sent first. The default setting for this box is
unchecked,
use little-endian.
For example, in little-endian format, a 32-bit floating point number represented by '1234 ABCD' is
sent as 'ABCD 1234'. `
Um Big Endian auslesen zu können verwendest Du die Funktion msg.payload.buffer.readFloatBE(0,1,2,3) und für Littel Endian die Funktion msg.payload.buffer.readFloatLE(0,1,2,3).
Nicht, dass wir uns hier ständig im Kreis drehen. Vielleicht im X-320 Big Endian einstellen und dann mal schauen was in den Modbusregistern 1 und 2 steht. Es könnte dir das Auslesen evtl. vereinfachen.
-
Hallo Graf,
danke für den Hinweis!
Hatte ich mit keinem Gedanken mehr daran gedacht…
Und jetzt funktioniert es!!!!
Danke für DEINE (Eure) Hilfe!
5860_working.png -
Hier noch die Funktion…...
5860_swap_working.png -
das ist ja Wahnsinn,
was ihr hier zu dem Thema abliefert, ich bin begeistert, nun versuche ich mich
damit auch zu befassen, bin jedoch wirklich auf diesem Gebiet ein Noob
Ich komme schon gar nicht so weit wie ihr…
wenn ich die 32bit function von euch übernehme also:
msg.payload.buffer.readFloatLE(0,1.2,3)
erhalte ich folgende fehlermeldung:
TypeError: Cannot read property 'readFloatLE' of undefined
ist das eine zusätzliche Lib die ich übersehen habe, oder warum nimmt er meinem
Code nicht an?
Verwende einen Raspi mit Node Red drauf.
Vielen Dank
Pitu61
-
msg.payload.buffer.readFloatLE(0,1.2,3) `
du hast ein Punkt zwischen 1.2 stehen es muss (0,1,2,3) sein und nicht vergessen die Funktion unten anzuknÜpfen damit du an die Buffer kommst.
Ober wird kein Buffer ausgegeben.
MfG
Jean
-
Ober wird kein Buffer ausgegeben. `
Donnerwetter, gute erkannt. Ist mir gar nicht so direkt aufgeallen.Ich habe mich vielmehr gefragt was will er überhaupt wo und in welchem Format auslesen. Integer- oder Flioatwert, Big Endian oder Littel Endian usw.
Aber vielleicht ist es ja schon genau dieser kleine Tippfehler gewesen.
Aber schön, dass du hier wieder etwas gepostet hast, ich hatte deine Wortmeldungen in den letzten Tagen schon vermisst.
-
Ich bin am Hausbauen, und die Handwerker haben diese Woche wieder angefangen zu arbeiten, da kann ich nicht immer online sein.
Ich habe noch eine Methode gefunden.
return [{ payload: msg.payload.buffer.readFloatBE(0,4)},
{ payload: msg.payload.buffer.readFloatBE(0,4) }];
Habe mal den Modbussimulator hergenommen
https://sourceforge.net/projects/modrssim/
Die Wert habe ich aus dem Screenshot Buffer 0002 41a2
und in die Kolonne +0 41a2 und in der Kolonne +1 0002 in den Simulator eingegeben,
dann kommt genau der Wert 20,25….. heraus
Die Klammer ()wird anders ausgewertet bei den Floats wenn ich richtg liege.
(0,4) 0 ist wo ich anfange zu lesen und 4 die Anzahl
lese ich z.b 3Stück 32 bit Floats ein und ich will das das 3te 32 bit Float haben so schreibe ich (8,4)
wenn ich nur ein Float habe kann ich die Klammer sogar leer lassen.
gebe ich in der Kolonne +0 0002 und in der Kolonne +1 41a2 in den Simulator kommt -2.6157436202396862e-18
Was komisch ist das es egal ist ob ich LE oder BE angebe die Werte sind immer gleich.
Ist es ein Fehler im Simulator?
Man müsste testen ob das obengenannte Beispiel an dem x320 funktioniert.
Es ist alles so schlecht dokumentiert so dass es nur mit try und error geht, ich hasse das.
MfG
Jean
-
Guten Abend!
Ich habe noch 2 Fragen
zum Modbus Read
Kann man mit einer FC3 Abfrage auch Register abfragen die nicht zusammenhängen?
z.B 272-278,528-530…... oder muss man jeden Block einzeln abfragen...
Zur Datenanzeige.
Wie kann ich die Anzahl der angezeigten Stellen einstellen?
5860_feuchtigkeit.png
5860_readout.png -
Ja kann man, die Werte sollten jedoch nicht zu weit auseinanderliegen weil man sonst sehr grosse Arrays hat.
bis 50 dürfte kein Problem sein.
Es gibt Modbus Hardware wo ein Limit gesetzt ist, ab einen gewissen Anzahl werden falsche Werte ausgegeben, so steht es jedenfalls in der Anleitung von Klaus ( Authos der Modbus Software) und das sagt er auch in seinem Youtube Video.
https://www.youtube.com/watch?v=YIqb02D3Ps4
Man muss nur die richtige Array oder Buffer Nummer angeben.
MfG
Jean