# Codesys 2.3 Modbus TCP + Kostal Wechselrichter



## Gärtner (19 Oktober 2022)

Hi,
ich bin absoluter Modbus Anfänger. Ich habe die letzten 2 Wochen schon einige Tutorials gelesen/angesehn und heute meinen Wago 8202 für die Testumgebung bekommen. Ich habe mit eine TCP Modbus Verbindung zu meinen Kostal Wechselrichtern über die Modbus Master Konfiguration hergestellt. Kommunikation ist erfolgreich.
Ich tue mich jedoch schwer "sinvolle" Daten zu erhalten. Vermutlich ist das für jemand mit Erfahrung trivial.

Hier ein Auszug aus der Modbus Tabelle des Wechselrichters.


> 0xAA 170 Voltage Phase 3 V Float 2 RO 0x03
> 0xAC 172 Total AC active power W Float 2 RO 0x03
> 0xAE 174 Total AC reactive power Var Float 2 RO 0x03


Ich versuche Adresse 172 mit folgenden Einstellungen auszulesen:
Byte Reihenfolge: big endian (B1 B2 B3 B4)
MODBUS-FC: Read holding registers (FC3)
Adresse 10#: 172 16#: ac
Bit-Offset: 0

Ich habe schon alle Variablen Typen probiert. Ich habe bisher keinen sinnvollen Wert erhalten. 
Float ist doch eine Gleitkommazahl? Also -> REAL? Aber Real ist doch 32 Bit? Und wenn ich die Adressierung richtig verstanden habe (172+173= 2 Byte = 16 Bit) wird hier eine 16Bit Zahl geliefert? Welche Variable muss ich nemen?

Oder suche ich den Fehler an einer völlig falschen Stelle?

Im Anhang die Modbus Doku von Kostal.
Danke.


----------



## Oberchefe (19 Oktober 2022)

> 172+173= 2 Byte = 16 Bit



Falsch, 172+172 = 2 Worte = 32 Bit

Welchen Hex-Wert bekommst du zurück?


----------



## Gärtner (19 Oktober 2022)

Ok, danke für die Berichtigung. Wo kann ich den Hex Wert sehen?

Bisher habe ich nur den Wert der Variable "xNewVar" deklariert über den Modbus Konfigurator "angesehen".


----------



## Oberchefe (19 Oktober 2022)

Dann ändere mal den Datentyp der Variable "xNewVar" von REAL nach DWORD. Dann Online einen Rechtsklick darauf, "Hexadezimal"


----------



## Oberchefe (19 Oktober 2022)

und dann noch den am Gerät angezeigten Wert dazu


----------



## Gärtner (19 Oktober 2022)

Danke, werde ich machen sobals es hell ist und ich dazu komme!


----------



## Gärtner (20 Oktober 2022)

So, der einfachheit habe ich nun die die Adresse 158 - 9e genommen. Die sollte die Spannung Phase 1 liefern. Das ist leichter auf Plausibilität zu prüfen.
Der Wert wechselt. Unter anderem:
16#666643C7
16#733343C7


----------



## PN/DP (20 Oktober 2022)

16#666643C7 --> Words tauschen --> 16#43C76666 = REAL 398.799987793 ~ 398.8
16#733343C7 --> Words tauschen --> 16#43C77333 = REAL 398.899993896 ~ 398.9
siehe https://www.h-schmidt.net/FloatConverter/IEEE754de.html


----------



## Gärtner (20 Oktober 2022)

Danke für die Erklärung. Jetzt kann ich mich an die Umsetzung machen.
Die nächste Herausforderung, aber jetzt weiß ich, woran ich arbeiten muss.


----------



## Gärtner (20 Oktober 2022)

Ich benötige schon wieder Hilfe, oder zumindest Hilfe zur Selbsthilfe.
Das vertauschen der Words habe ich nun so gelöst, dass ich einm,al das Word unter 158 und winmal das Word unter 159 abfrage und dann per


> testvariable:=DWORD_OF_WORD(MBCFG_ModbusSlave.xNewVar,MBCFG_ModbusSlave.xNewVar0);


wieder zu einem Dword in der "richtigen" Reihenfolge zusammenführe.
Testvariable liefert dann z.B. 16#43C77333
Das sollte doch soweit richtig sein?!

testvariable3:=DWORD_TO_REAL(testvariable);
liefert dann wieder murks?! Muss ich die Umrechnung von 16#43C77333 in eine Real Zahl "manuell" durchführen?


----------



## Gärtner (20 Oktober 2022)

> testvariable3:=DW_TO_REAL(testvariable);


So sieht das schon besser aus


----------



## Tobsucht (20 Oktober 2022)

DWORD_TO_REAL liefert keinen Murks. Die Funktion wandelt den Ganzahlwert des Doppelworts in eine Gleitkommazahl mit dem gleichen Wert.
Also z.B 1234 zu 1,234E+3. Der Wert wird nicht verändert nur in einem anderen Format dargestellt.

Du musst den Ganzahlwert in den Speicher einer Realvariable bringen.
Das geht über Pointer oder z.B. den Merkerbereich.

dwQuelle : dword := 16#733343C7;
dwZiel AT %MW0 : dword;
rZiel at %MW0: real;
----------------------------------
dwZiel := ROL(dwQuelle,16);
rZiel;


----------



## PN/DP (20 Oktober 2022)

Bei Codesys muß man das Bitmuster des DWORD in eine REAL-Variable speichern, aber so daß das Codesys nicht den REAL-Wert in einen Ganzzahl-Wert konvertiert. Ab Codesys 3 kann man dafür (und für das zusammenbasteln des DWORD aus 2 einzelnen WORD) sehr gut UNIONs verwenden.
Bei Codesys 2.3 braucht man für das umspeichern des DWORD in eine REAL-Variable einen Pointer.
hier: Beispiele für das Umspeichern DWORD in REAL-Variable per Pointer und per UNION

Um die Words eines DWORD zu tauschen, kann man das DWORD um 16 Bit links oder rechts rotieren (ROL, ROR). Man kann auch das DWORD aus 2 Word zusammensetzen. Du könntest aus der OSCAT Lib die Functions DW_TO_REAL und DWORD_OF_WORD verwenden:
`myReal := DW_TO_REAL( DWORD_OF_WORD(W1:=word1, W0:=word0) );`

oder diese Function MB_DW_TO_REAL :

```
FUNCTION MB_DW_TO_REAL : REAL
(* konvertiert ein Modbus-Doppelregister 32 Bit in REAL *)
VAR_INPUT
  dwReg : DWORD;
END_VAR
VAR
  dwVar : DWORD;
  pReal : POINTER TO REAL;
END_VAR

dwVar := ROL(dwReg, 16);  //Words des Doppelregisters tauschen
pReal := ADR(dwVar);      //Pointer auf die DWord-Variable setzen
MB_DW_TO_REAL := pReal^;  //Bitmuster aus der Variable lesen und als REAL-Wert zurückgeben

END_FUNCTION
```

Harald


----------



## Tobsucht (20 Oktober 2022)

Du nimmst ja den Modbus Konfigurator von Wago. Da kannst du dich direkt den Datentyp Real nehmen und die Byte Reihenfolge anpassen.


----------



## Gärtner (20 Oktober 2022)

Hallo,
danke für die ganze Hilfestellung. 
Die Variante von Tobsucht habe ich nachvollziehen können aber nicht probiert. Ich habe es heute Mittag schon so gelöst gehabt, wie Harald es auch vorgeschlagen hat: mit der Oscat Lib. DW_toReal(DW_of_word(...,...);

Also nochmals großes Danke für die Hilfestellung bis hierhin!!

Als ich am frühen Nachmittag in meiner 750-8202 Testumgebung das so weit am laufen hatte, wollte ich diesen Teil in meiner bestehenden Projekt (750-841) integrieren. Die 750-841 soll dann durch die 750-8202 ersetzt werden.
Jedoch bekomme ich folgende Fehlermeldung, nachdem ich die Verbindung im Modbus Konfigurator erstellt habe.





Ich vermute das es ein Problem mit "alten" Bibliotheken in meinem alten Projekt ist (das habe ich 2008 angefangen), kann jedoch den direkten Fehler nicht finden. Wie gehe ich damit vor?


----------



## Oberchefe (20 Oktober 2022)

Die Netzwerkbibliothek scheint zu fehlen.


----------



## Gärtner (20 Oktober 2022)

Tobsucht schrieb:


> Du nimmst ja den Modbus Konfigurator von Wago. Da kannst du dich direkt den Datentyp Real nehmen und die Byte Reihenfolge anpassen.


Die überlegung hbae ich heute auch schon, aber die richtige Reihenfolge stand nicht zur Auswahl. Jetzt gerade geprüft und festgestellt, dass ich im Konfigurator erst DWORD auswählen muss und dann auf Adresse bearbeiten gehen. Dann bekomme ich auch bei der Byte Reihenfolge die vermutlich richtige Variante angeboten! Kann ich aber erst morgen testen, da es nun schon wieder dunkel ist. Sollte dann gehen.

Im Grunde komme ich nun mit allen drei Varianten zurecht. 

Die Hilfe hier ist echt Super!


----------



## Oberchefe (20 Oktober 2022)

SysLibSockets.Lib


----------



## Gärtner (20 Oktober 2022)

Merkwürdig.... war eigentlich vorhanden. Gelöscht und wieder eingefügt und der Fehler ist weg,


----------



## Gärtner (21 Oktober 2022)

So zum Abschluss möchte ich mich nochmals bei allen bedanken.
Wenn man erst mal weiß wie es geht, ist der Aufwand verdammt gering.

Nun noch mal zum letztendlichen Lösung.
Im Codesys Modbus Konfigurator erst den Variablen Typ wählen. Wenn ich DWORD oder REAL wähle und DANN die Adresse eingebe, kannich die Byte Reihenfolge "middle endian (B3 B4 B1 B2)" wählen. Somit habe ich auf Anhieb den richtigen Typ mit dem richtigem Inhalt!

Jetzt werde ich ein wenig mit Modbus rumspielen und die bisher genutzten Netzvariablen durch Modbus ersetzten um einfach sicherer zu werden in der Adressierung(Speicherzuweisung. Bisher habe ich Merker nicht verwenden müssen. Ich hoffe, dass das eine gute Übung ist.

Und mein nächstes Projekt habe ich schon im Kopf, da werde ich wohl bald ein neues Thema aufmachen.

Nochmals DANKE!


----------

