# Selbst erstellten Datentyp mit Modbus auslesen



## mnuesser (11 Januar 2022)

Huhu zusammen,

ich habe unter Codesys 2.3 einen eigenen Datentyp erstellt:


```
TYPE RaumstatusBool :
STRUCT
    Licht_An:BOOL;
    Heizung_An:BOOL;
       Fenster_Auf:BOOL;
       Anwesend:BOOL;
       Heizung_Spuelen:BOOL;
       Reserve02:BOOL;
       Reserve03:BOOL;
       Reserve04:BOOL;
       Reserve05:BOOL;
       Reserve06:BOOL;
       Reserve07:BOOL;
       Reserve08:BOOL;
       Reserve09:BOOL;
       Reserve10:BOOL;
       Reserve11:BOOL;
       Reserve12:BOOL;
END_STRUCT
END_TYPE
```

und wollte diesen Datentypen nun an meinen Modbusadressen verwenden:


```
MODB_OG_Stat_Kind2 AT %MD19:RaumstatusBool;
```

Was an sich auch funktioniert, nur wird mir eine der Variablen in der Online Ansicht als gesetzt angezeigt, was sie auch ist,
aber im iobroker verändert sich der value nicht.

Ein weiteres Problem besteht darin, dass mir ein Bit im nächsten Raum gesetzt ist, obwohl es nicht beschrieben wird.

```
MODB_OG_Stat_Kind1 AT %MD20:RaumstatusBool;
```

Wenn ich nun mir die Querverweise von MODB_OG_Stat_Kind1 anzeigen lasse, steht dort dass es beschrieben wird von MODB_OG_Stat_Kind2?
Habe ich da einen Denkfehler bei der Adressierung gemacht?


----------



## s-ga (11 Januar 2022)

Deine Bools werden jeweils als eigene Bytes angesehen. Wenn du Coils verwenden willst solltest du %MX verwenden.

MFG


----------



## Ludewig (11 Januar 2022)

Habe zwar 0 Erfahrung mit Codesys , aber es fällt auf, dass Deine Struktur Wortlänge hat (16 Bit= 2 Byte = 1 Word). Oben steht aber MD und nicht MW??
Mit was kommunizierst Du? Ich muss bei Modbus zwischen Geräten unterschiedlicher Hersteller oft swappen, also die Reihenfolge von Bytess systematisch tauschen.


----------



## mnuesser (11 Januar 2022)

Ja ok, ich habe natürlich noch was rumprobiert und dachte dass ich irgendwas bei den Wortgrenzen vielleicht falsch gemacht habe. Ich habe vorher aber MW mit der passenden Adresse probiert.


----------



## mnuesser (11 Januar 2022)

s-ga schrieb:


> Deine Bools werden jeweils als eigene Bytes angesehen. Wenn du Coils verwenden willst solltest du %MX verwenden.
> 
> MFG


Da sagst du was... Mir ist schon aufgefallen dass das zweite Bit bei mir auf dem ersten Bit des zweiten Bytes ankommt... Da wollte ich auch noch nach schauen... Jetzt weiss ich es... Aber warum betrachtet Codesys jeden Eintrag einer Struktur als Byte?


----------



## Heinileini (11 Januar 2022)

mnuesser schrieb:


> Mir ist schon aufgefallen dass das zweite Bit bei mir auf dem ersten Bit des zweiten Bytes ankommt...


Hinter welcher Formulierung Deiner ProblemBeschreibung versteckt sich diese Beobachtung? Habe ich irgendwie überlesen.


mnuesser schrieb:


> Aber warum betrachtet Codesys jeden Eintrag einer Struktur als Byte?


Woraus schliesst Du das?


----------



## KLM (11 Januar 2022)

Nicht jeder Eintrag der Struktur wird als Byte betrachtet, sondern ein Byte ist die kleinste Einheit im Speicher. Ein ein Bit großes Boolean wird daher als ganzes Byte gespeichert. Diese Begrenzung kommt aus dem physischen Speicherbausteinen und ist manchmal sogar ein Word groß. In e!COCKPIT (CODESYS 3.5) kannst Du eine Struktur aus Bits definieren, aber in CODESYS 2.3 kannst Du das nur umgehen, wenn Du ein Byte in die Struktur aufnimmst und anschließend auf die einzelnen Bits zugreifst,  also z.B. xStatusLicht := bStatus.0; Aber eigentlich hast Du ausreichend Speicher und musst beim Einlesen auf der Gegenseite nur darauf achten, dass Bool als Byte gespeichert ist und sich entsprechend die Modbus-Adresse verschiebt.
Nachtrag: Das Bool wird immer im ersten Bit abgelegt also Byte.0


----------



## Tobsucht (12 Januar 2022)

Hallo Markus,

dass Deine BOOL Variablen aus der Struktur eine Größe von einem Byte haben wurde ja schon gesagt.
Die Struktur MODB_OG_Stat_Kind2 beginnt auf dem Merkerdoppelwort 19, also auf dem Merkerwort 38.

Nun hängt es davon ab, ob du mit IO Broker per Register oder Coil zugreifst.
Ich gehe erstmal von einem Coilzugriff auf.
Somit ergeben sich die folgenden Modbus Adressen:
MODB_OG_Stat_Kind2.Licht_An; Merkerbit MX38.0; Modbusadresse 12896
MODB_OG_Stat_Kind2.Heizung_An; Merkerbit MX38.8; Modbusadresse 12904
MODB_OG_Stat_Kind2.Fenster_Auf; Merkerbit MX39.0; Modbusadresse 12912
MODB_OG_Stat_Kind2.Anwesend; Merkerbit MX39.8; Modbusadresse 12920
MODB_OG_Stat_Kind2.Heizung_Spuelen; Merkerbit MX40.0; Modbusadresse 12928

Über SIZEOF(MODB_OG_Stat_Kind2) erfährst Du, dass die Struktur eine Größe von 16 Byte hat. Somit überschneiden sich die Strukturen MODB_OG_Stat_Kind2 und MODB_OG_Stat_Kind1.

Daher müsstest Du die Adressen der Strukturen anpassen (hier als Merkerwort, macht das rechnen einfacher):
MODB_OG_Stat_Kind2 AT %MW38:RaumstatusBool;
MODB_OG_Stat_Kind1 AT %MW46:RaumstatusBool;

Grüße


----------



## JSEngineering (12 Januar 2022)

Du könntest dann auch, statt einer Struktur anzulegen, die Member Deiner Struktur als globale Constanten anlegen:


```
var_global constant
    Licht_An : INT := 0;
    .
    .
    .
end_var
```

Und Dein MODB_OG_Stat_Kind2 definierst Du wie bereits vorgeschlagen als WORD.
Dann ergibt sich im Programm ein Zugriff, der so aussieht: MODB_OG_Stat_Kind2.Licht_An.
Also sieht eigentlich genau so aus, als wenn Du das als Struktur angelegt hättest. Nur ist halt ein Bitzugriff auf das Wort dank der globalen Konstanten.


----------



## Tobsucht (12 Januar 2022)

JSEngineering schrieb:


> Du könntest dann auch, statt einer Struktur anzulegen, die Member Deiner Struktur als globale Constanten anlegen:
> 
> 
> ```
> ...


Nette Idee, funktioniert nur nicht.
Gibt den Fehler Ganze Zahl oder symbolische Konstante erwartet


----------



## JSEngineering (12 Januar 2022)

Tobsucht schrieb:


> Gibt den Fehler Ganze Zahl oder symbolische Konstante erwartet


OK, gerade ausprobiert: Bei WAGO funktioniert's nicht; bei Bachmann wohl, da machen wir das nämlich täglich.

Aber: Wenn Du in den Optionen und Übersetzungsoptionen angibst "Konstanten ersetzen", dann funktioniert das auch bei WAGO.

Hilfe gibt's im Kapitel "Adressierung von Bits in Variablen".


----------



## mnuesser (12 Januar 2022)

> Hinter welcher Formulierung Deiner ProblemBeschreibung versteckt sich diese Beobachtung? Habe ich irgendwie überlesen.


"Da wollte ich auch noch nach schauen..." Das war der Rest meines Kommentars den du nicht Zitiert hast... Dieses Phänomen war für mich hier erstmal nicht wichtig als ich den Thread erstellt habe, ich dachte da noch, dass es dort keinen Zusammenhang gibt.



> Woraus schliesst Du das?


Aus der Antwort vom User s-ga, Posting #2
Quasi aus der von mir zitierten Antwort


----------



## StructuredTrash (12 Januar 2022)

mnuesser schrieb:


> Aber warum betrachtet Codesys jeden Eintrag einer Struktur als Byte?


Nicht jeden Eintrag einer Struktur, sondern der Datentyp BOOL ist bei Codesys immer ein Byte, von dem nur Bit 0 verwendet wird. Ausnahme sind absolute Adressierungen wie "AT %QX0.5", dort wird tatsächlich nur ein einzelnes Bit adressiert.
Der Grund für diese "Speicherverschwendung" ist die bessere Performance beim Laden, Verknüpfen und Speichern von Bools, weil man sich dabei spart, in den geladenen oder zu speichernden Bytes das gewünschte Bit erst zu isolieren und auf Position 0 zu schieben.


----------



## mnuesser (12 Januar 2022)

KLM schrieb:


> Nicht jeder Eintrag der Struktur wird als Byte betrachtet, sondern ein Byte ist die kleinste Einheit im Speicher. Ein ein Bit großes Boolean wird daher als ganzes Byte gespeichert. Diese Begrenzung kommt aus dem physischen Speicherbausteinen und ist manchmal sogar ein Word groß. In e!COCKPIT (CODESYS 3.5) kannst Du eine Struktur aus Bits definieren, aber in CODESYS 2.3 kannst Du das nur umgehen, wenn Du ein Byte in die Struktur aufnimmst und anschließend auf die einzelnen Bits zugreifst,  also z.B. xStatusLicht := bStatus.0; Aber eigentlich hast Du ausreichend Speicher und musst beim Einlesen auf der Gegenseite nur darauf achten, dass Bool als Byte gespeichert ist und sich entsprechend die Modbus-Adresse verschiebt.
> Nachtrag: Das Bool wird immer im ersten Bit abgelegt also Byte.0


Ja ok, dann ist zumindest schon mal mein Phänomen erklärt, dass das zweite Bit was ich setze auf Byte1.bit0 ankommt.... danke schon mal dafür...
Ich bin mir nur nicht sicher was ich jetzt machen soll. Entweder ich muss mir die Bits jetzt einfach einzeln anlegen als Modbus-Adressen. Hätte den Vorteil von "sprechender Symbolik", d.h. ich weiß wofür dieses Bit wirklich ist. Nachteil ist das händische anlegen. Oder halt alles auf Byte umstellen und dann per Bitzugriff darauf zugreifen wie du beschrieben hast.


----------



## mnuesser (12 Januar 2022)

Tobsucht schrieb:


> Hallo Markus,
> 
> dass Deine BOOL Variablen aus der Struktur eine Größe von einem Byte haben wurde ja schon gesagt.
> Die Struktur MODB_OG_Stat_Kind2 beginnt auf dem Merkerdoppelwort 19, also auf dem Merkerwort 38.
> ...


Sehr ausführliche Antwort, danke dafür...
Mir geht's eher um das Phänomen dass die Bits nicht wie gewollt hintereinander liegen,
bzw. jetzt um die Konsequenz, dass ich eh alles umfummeln muss, da das sich anders verhält wie ich gedacht habe.
Die Adressierung habe ich dank Excel-Tabelle aus dem iobroker Forum schon ganz gut im Griff.


----------



## mnuesser (12 Januar 2022)

StructuredTrash schrieb:


> Nicht jeden Eintrag einer Struktur, sondern der Datentyp BOOL ist bei Codesys immer ein Byte, von dem nur Bit 0 verwendet wird. Ausnahme sind absolute Adressierungen wie "AT %QX0.5", dort wird tatsächlich nur ein einzelnes Bit adressiert.
> Der Grund für diese "Speicherverschwendung" ist die bessere Performance beim Laden, Verknüpfen und Speichern von Bools, weil man sich dabei spart, in den geladenen oder zu speichernden Bytes das gewünschte Bit erst zu isolieren und auf Position 0 zu schieben.


Danke das erklärt es natürlich.

Es widerstrebt mir zwar gerade, aber ich glaube ich werde die Bits einfach händisch anlegen um sie dann zu verschalten.
Im Endeffekt geht's nur um meine Haussteuerung, die ändert sich nicht so gravierend alle Nase lang.
Ist halt einmal Arbeit und gut is.


----------

