Auslesen von Int32-Werten per Modbus

JPO

Level-2
Beiträge
55
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo zusammen

Ich stehe vor einem Problem und hoffe, dass mir jemand weiterhelfen kann. Ich arbeite mit einer Wago 750-8212 und möchte per Modbus einen Frequenzumformer auslesen. Laut der Modbus-Liste des Geräts muss ich bestimmte Werte, wie z.B. die Leistung, als Int32 auslesen.

Allerdings bin ich mir unsicher, wie ich dies korrekt umsetzen kann. Gibt es eine spezielle Vorgehensweise oder einen Code-Schnipsel, den ich verwenden kann, um Int32-Werte korrekt auszulesen?

Vielen Dank im Voraus für eure Unterstützung!
 
Modbus RTU oder TCP? Auf der Codesysseite gibt es für beide Szenarien ein Projekt.
Da bei modbus immer Byte für Byte ausgelesen oder geschrieben wird, muss du es noch umwandeln in dein Zielformat.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Modbus RTU oder TCP? Auf der Codesysseite gibt es für beide Szenarien ein Projekt.
Da bei modbus immer Byte für Byte ausgelesen oder geschrieben wird, muss du es noch umwandeln in dein Zielformat.
Es geht um Modbus RTU. Ich habe jetzt versucht zwei Register auszulesen und diese dann umgewandelt. Ich kann jetzt einen Wert auslesen, aber bin mir nicht sicher ob dies so richtig ist.
 
Wenn ich eine neue Bibliothek schreibe, dann nehme ich mir einen Wert heraus der für mich eindeutig ist und prüfe diesen, wie z.B Spannung pro Phase, dann stimmt in der Regel mein neuer Baustein.
 
Hi,

int32 -> DINT , das hast Du ja schon erkannt. Auch das Du da zwei Register auslesen und die dann zusammenfügen mußt. Letzteres kannst Du über Union, Pointer und auch OR, mit Bitshift) machen. Für Pointer und Union hier einfach mal nach Modbus und Real suchen, das wird öfter mal nachgefragt und ist ähnlich von der Lösung.

Probleme ergeben sich meistens mit der Reihenfolge was Hi und Lo Word ist. Da muß man mal rumspielen oder mit vorhandenen Werten vergleichen. Gelegentlich müssen auch noch Hi und Lo Byte in den Words der Register getauscht werden.

Dafür kann man gut diese Seite hier nehmen, einfach die Werte in Hexdarstellung unter Codesys anzeigen lassen und dann auf der Seite eingeben, dann sollte man schnell die richtige Reihenfolge festlegen können.

Mal mit OR
Code:
diWert := DWORD_TO_DINT(shl(WORD_TO_DWORD(wHiWert),16) OR WORD_TO_DWORD(wLoWert))

Gruß
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Modbus RTU oder TCP? Auf der Codesysseite gibt es für beide Szenarien ein Projekt.
Da bei modbus immer Byte für Byte ausgelesen oder geschrieben wird, muss du es noch umwandeln in dein Zielformat.
Du meinst wohl eher Word für Word, denn die Register sind 16 Bit groß.
Worauf man beim Zusammensetzen noch achten muss ist, dass das mit den Indianern (Little, Big) passt.
 
Da bei modbus immer Byte für Byte ausgelesen oder geschrieben wird, muss du es noch umwandeln in dein Zielformat.
Bei Modbus werden Werte nicht "Byte für Byte" ausgelesen, sondern Register für Register (ein Register ist ein 16 Bit Word). Werte größer als 16 Bit liegen üblicherweise in direkt hintereinander liegenden Registern, üblicherweise zuerst das höherwertige Word und im nächsten Register das niederwertige Word, kann aber auch anders herum liegen.

Allerdings bin ich mir unsicher, wie ich dies korrekt umsetzen kann. Gibt es eine spezielle Vorgehensweise oder einen Code-Schnipsel, den ich verwenden kann, um Int32-Werte korrekt auszulesen?
Kann das Auslesen der Register und in Variablen speichern bei Wago einfach projektiert werden, oder musst du die Register mit einem Baustein (FB?) auslesen? Welchen Baustein verwendest du?

Beim selbst programmierten Auslesen so vorgehen:
- 2 Register lesen
- H-Word und L-Word zu DWord zusammensetzen
- die Bitfolge im DWord 1:1 in eine DINT-Variable speichern, ohne dass dabei ein Bit verändert wird (also ohne konvertieren!). Das ist in Codesys allerdings ein kleines Problemchen, weil da DWORD = UDINT gleichgesetzt wird.

Wenn die beiden Words schon in der richtigen Reihenfolge direkt hintereinander im Empfangspuffer liegen, kann man die mit memcpy oder mit einem Pointer direkt in ein DINT umspeichern:
Code:
pDint : POINTER TO DINT;

pDint := ADR(Empfangspuffer); //Pointer auf Adresse des ersten gelesenen Registers (H-Word) setzen
myDInt := pDInt^; //die 4 Bytes in eine DINT-Variable umkopieren

Wenn die beiden Words nicht in der richtigen Reihenfolge im Empfangspuffer liegen, dann kann man die Words im DWord tauschen mit ROL(myDWord, 16). Oder man setzt die beiden Words ganz allgemein so zusammen: myDWord := SHL(WORD_TO_DWORD(HWord), 16) OR LWord; Das DWord muss dann noch wie oben erwähnt in die DInt-Variable gespeichert werden.

Bei Codesys 3 kann man das Umspeichern der 2 Words in einen Int32 (DINT) bequem mit UNION machen. Kann die Wago das auch?
 
Zuletzt bearbeitet:
Du meinst wohl eher Word für Word, denn die Register sind 16 Bit groß.
Worauf man beim Zusammensetzen noch achten muss ist, dass das mit den Indianern (Little, Big) passt.
Bei Modbus werden Werte nicht "Byte für Byte" ausgelesen, sondern Register für Register (ein Register ist ein 16 Bit Word). Werte größer als 16 Bit liegen üblicherweise in aufeinanderliegenden Registern, üblicherweise zuerst das höherwertige Word und im nächsten Register das niederwertige Word, kann aber auch anders herum liegen.


Kann das Auslesen der Register und in Variablen speichern bei Wago einfach projektiert werden, oder musst du die Register mit einem Baustein (FB?) auslesen? Welchen Baustein verwendest du?

Beim selbst programmierten Auslesen so vorgehen:
- 2 Register lesen
- H-Word und L-Word zu DWord zusammensetzen
- die Bitfolge im DWord 1:1 in eine DINT-Variable speichern, ohne dass dabei ein Bit verändert wird (also ohne konvertieren!). Das ist in Codesys allerdings ein kleines Problemchen, weil da DWORD = UDINT gleichgesetzt wird.

Wenn die beiden Words schon in der richtigen Reihenfolge direkt hintereinander im Empfangspuffer liegen, kann man die mit memcpy oder mit einem Pointer direkt in ein DINT umspeichern:
Code:
pDint : POINTER TO DINT;

pDint := ADR(Empfangspuffer); //Pointer auf Adresse des ersten gelesenen Registers (H-Word) setzen
myDInt := pDInt^; //die 4 Bytes in eine DINT-Variable umkopieren

Wenn die beiden Words nicht in der richtigen Reihenfolge im Empfangspuffer liegen, dann kann man die Words im DWord tauschen mit ROL(myDWord, 16). Oder man setzt die beiden Words ganz allgemein so zusammen: myDWord := SHL(WORD_TO_DWORD(HWord), 16) OR LWord; Das DWord muss dann noch wie oben erwähnt in die DInt-Variable gespeichert werden.

Bei Codesys 3 kann man das Umspeichern der 2 Words in einen Int32 (DINT) bequem mit UNION machen. Kann die Wago das auch?

Register sind 16 Bit groß, das steht außer Frage.
Ich gebe z.B. die Slave Adresse an, den Funktionscode, die Startadresse und wie viele n Bytes ich haben möchte oder gibt es andere Möglichkeiten ein Register auszulesen?
 
Register sind 16 Bit groß, das steht außer Frage.
Ich gebe z.B. die Slave Adresse an, den Funktionscode, die Startadresse und wie viele n Bytes ich haben möchte
Zum Lesen von Registern gibt man nicht an wieviele Bytes, sondern wieviele Register. n Register ergeben 2n Bytes Antwort-Daten.
 
Hallo zusammen.
Ich habe ein ähnliches Problem. Ich verwende S7-1200 in KOP.
Hat mir da jemand ein Beispiel in KOP?

Voraussetzungen:​

  • Modbus-Register: Du hast zwei Modbus-Register, die du auslesen möchtest (z. B. Reg1 und Reg2), beide sind 16-Bit-Werte (Worte).
  • Ziel: Du möchtest diese beiden Register zu einem 32-Bit-Wert kombinieren und als Fließkommazahl (REAL) darstellen.


    Danke für eure Hilfe im Voraus!
 
Ich habe ein ähnliches Problem. Ich verwende S7-1200 in KOP.
Hallo
Deine S7-1200 kann nicht mit Codesys programmiert werden. Deine Frage passt daher nicht so richtig hierher...

Du kannst aber in TIA in dein KOP-Programm ein SCL-Netzwerk einfügen und die Programmzeile von Beitrag #5 sinngemäß in SCL umgeformt einfügen.
Code:
diWert := DWORD_TO_DINT(shl(WORD_TO_DWORD(wHiWert),16) OR WORD_TO_DWORD(wLoWert))
Schreibweise in TIA SCL und nach REAL:
Code:
#rWert := DWORD_TO_REAL(SHL(IN := WORD_TO_DWORD(#wHiWert), N := 16) OR WORD_TO_DWORD(#wLoWert));

Oder du schaltest in KOP eine SHL- und eine OR-Box hintereinander. Oder für eine Lösung mit Slice-Zugriff (.%W1 und .%W0) zwei MOVE-Boxen und eine CONV-Box.

Bis wann brauchst du die Lösung der Hausaufgabe? ;)
 
Zuletzt bearbeitet:
Zurück
Oben