# Wago 750-652 Modbus Brink KWL



## lullnix (21 Oktober 2022)

Hallo zusammen,

möchte die Werte einer Brink KWL (Flair 400) über den Modbus mit einer Wago 750-652 auslesen und steuern.
Wago 750-8100 + e!Cockpit (alles aktuelle Version).
Ich nutze das Demoprogramm ModbusSerialMaster aus der Bibliothek WagoAppPlcModbus. Mit dem Funktionsblock FbMbMasterSerial.

Die Wago 750-652 ist auf Werkseinstellungen zurückgesetzt und ich habe die Einstellungen der KWL entsprechend gesetzt.
Die KWL hat die Modbus-Adresse 20.

Verkabelt ist die Wago 750-652 mit der KWL nach der Wago Anleitung der 750-652 auf Seite 48.

PROGRAM ModbusSerialMaster
VAR
     mySerialMaster  : FbMbMasterSerial := ( xConnect   := FALSE,
                                            udiBaudrate := 9600, 
                                            usiDataBits := 8,
                                            eParity     := WagoTypesCom.eTTYParity.None,
                                            eStopBits   := WagoTypesCom.eTTYStopBits.One,
                                            eHandshake  := WagoTypesCom.eTTYHandshake.None,
                                            ePhysical   := WagoTypesCom.eTTYPhysicalLayer.RS485_HalfDuplex,
                                            eFrameType  := eMbFrameType.RTU,
                                            tTimeOut    := T#500MS
                                          );

    //--- Identification Object for use of FC43 (in case the slave support it) ------
    myBaseIdentification    :   FbIdentifyBaseObject; // only needed for FC43
    //-------------------------------------------------------------------------------
    utQuery         : typMbQuery := (   bUnitId         := 20,       // Slaveaddress
                                        bFunctionCode   := 16#04,  // read input registers
                                        IIdentifyObject := myBaseIdentification, // only needed for FC43
                                        uiReadAddress   := 0,       // Startaddress
                                        uiReadQuantity  := 10,      // Quantity of wanted registers
                                        uiWriteAddress  := 0,       // not needed for FC4
                                        uiWriteQuantity := 0,       // not needed for FC4
                                        awWriteData     := [124(0)] // not needed for FC4
                                    );

    xTxTrigger      : BOOL;             (* Set this variable once for start a job.
                                           This variable will be automaticly reset by the master
                                           if the job is done.
                                        *)

    utResponse      : typMbResponse;    (* After the job is done you can find at this structure
                                           the result.
                                        *)

    tonDelay        : TON := (PT := T#20MS); // This is the silence time between two requests
    myData            : ARRAY [0..124] OF WORD;
    strDescription    : ARRAY [0..100] OF STRING;
    i : INT;
END_VAR

//--- delay between two requests ----------------------
tonDelay( IN := (NOT tonDelay.Q) AND (NOT xTxTrigger));
xTxTrigger S= tonDelay.Q; // trigger the next request

//--- call cyclic the master --------------
mySerialMaster( I_Port      := RS485,        // my serial port
                utQuery     := utQuery,
                xTrigger    := xTxTrigger,
                utResponse  := utResponse
                  );

mySerialMaster.xConnect :=     GVL.b_xConnect;

IF mySerialMaster.oStatus.sDescription <> 'OK' THEN
    strDescription_ := mySerialMaster.oStatus.sDescription;
    i:=i+1;
END_IF
IF i = 100 THEN 
  i:=0;
END_IF

Ich schreibe die letzten 100 Fehler in die Variable strDescription
Ich erhalte folgende Fehler:
- Error while transmission -> transporlayer can not transmit
- Error time out

In einem anderen Beitrag habe ich gelesen, dass das zeitgleiche setzen der xConnect auf true Probleme machen soll.
Zum testen setze ich xConnect manuell über einen Button auf der Visualisierung.

Hat jemand eine Idee und könnte helfen?

Gruß_


----------



## Oberchefe (21 Oktober 2022)

X12 gesteckt oder nicht? Abschlusswiderstände verschaltet oder nicht?

In meiner Anleitung von der 750-652 finde ich auf Seite 48 was ganz anderes, oder anders gesagt, ist es zu viel verlangt einen Screenshot vom relevanten Teil einzustellen (damit nicht jeder, der helfen will, zuerst die passende Version vom Handbuch laden muss) oder noch besser eine Skizze (gerne auch auf Papier gemalt und abfotografiert)? Alternativ wenigstens zu verlinken. Baudrate Werkseinstellung wäre laut Installationsanleitung Flair 19200 und nicht 9600. Modbus Handbuch habe ich auf die Schnelle nicht gefunden.


----------



## lullnix (22 Oktober 2022)

Hallo Oberchefe,

danke für Deine schnelle Rückmeldung. Sorry, dass ich vergessen habe noch Infos hinzuzufügen.

Hier die Kabelbelegung (auch im Anhang - ich hoffe ich habe dies richtig verstanden/umgesetzt)

Brink Flair 400 Anschluss X15 (ohne Plus Platine)Wago 750-652 (Belegung im Anhang)Pin 1     RS485 Ground3 bzw. 7Pin 2     RS485 A6 gebrückt nach 5Pin 3     RS485 B2 gebrückt nach 1
Abschlusswiderstand Wago 750-650 zw. 1 und 5
Brink X12 geschlossen
Brink X121 & 122 offen
Siehe Foto im Anhang

Die Kommunikationseinstellungen an der KWL sind wie folgt:
Bus-Verbingung: Modbus
Slave-Adresse: 20
Baudrate: 9600 (habe ich von 19200 heruntergesetzt)
Partität: keine (geändert von gerade)

Anleitung für die Brink Modbus Installation findest Du ebenfalls im Anhang.

...und schon mal vielen Dank für Deine Unterstützung.


----------



## Oberchefe (22 Oktober 2022)

an der Wago muss 1 mit 2 gebrückt werden und 5 mit 6.


----------



## lullnix (22 Oktober 2022)

sorry mist - Tippfehler 

2 ist auf 1 gebrückt
5 ist auf 6 gebrückt
4 und 8 sind nicht belegt


----------



## Tobsucht (24 Oktober 2022)

Hallo,

der Fehler "_Error while transmission -> transporlayer can not transmit" hat nichts mit der RS485 Beschaltung zu tun.
Das ist ein Problem mit den internen Bibliotheken:
e-cockpit-modbus-master-rtu-mit-750-652-funktioniert-nicht
wetterstation-eltako-ms-an-das-ecockpit-anbinden_

Grüße


----------



## lullnix (27 Oktober 2022)

Hallo,

danke für den Hinweis. Ich habe geklärt, ob die Brink KWL OK ist. Mit einem Modbus 2 USB Adapter und qModMaster lässt sind die KWL steuern.

Folgende Versionen der Bibliotheken nutze ich:

WagoSysModule_75x_65x Version 1.9.5.6
WagoTypesCom Version 1.6.2
WagoAppPlcModbus Version 1.1.3.5
Muss die WagoTypesCom im Paket WagoSysModule_75x_65x austauschen?

Gruß


----------



## lullnix (28 Oktober 2022)

Hallo,

ich habe die Bibliotheken wie folgt getauscht.

WagoTypesCom Version 1.6.2 getauscht gegen die Version 1.6.1.3
WagoSysModule_75x_65x Version 1.9.5.6  getauscht gegen die Version 1.9.5.2
leider ohne Erfolg.
Darum habe ich die Daten mal mitgeschnitten.

Die 750-652 sendet:  DD 5F 7B FD DD 0C (keine Ahnung was das sein soll)

Mittschnitt des RS438 USB Adapters:
TX:  14 04 0F C2 00 01 91 E7​RX: 14 04 02 04 92 37 9E​HEX: 04 92 => DEC: 1170 wäre der gewünschte Wert.​​Hat jemand eine Idee, warum die 750-652 nicht den richtigen "Befehl" sendet?

Gruß


----------



## Oberchefe (29 Oktober 2022)

> Die 750-652 sendet:  DD 5F 7B FD DD 0C (keine Ahnung was das sein soll)


woher weißt du, dass die Wago das sendet? Das wäre völlig unsinning


Jetzt habe ich nur nicht verstanden, was der USB-Adapter mitschneidet, die Kommunikation zwischen der Wago und dem Ding oder was anderes?



> TX:  14 04 0F C2 00 01 91 E7


Slaveadresse 20, FunctionCode 4, Adresse 4034, Länge 1, sieht erst mal gut aus


> RX: 14 04 02 04 92 37 9E
> HEX: 04 92 => DEC: 1170 wäre der gewünschte Wert.


Antwort von Slaveadresse 20, FunctionCode 4, 2 Bytes Date, Wert 1170, sieht ebenfalls gut aus.


----------



## PN/DP (29 Oktober 2022)

Hast Du mal testweise an einem Teilnehmer die RS485-Drähte A und B getauscht? Z.B. am Brink an Pin 2 und 3 vertauschen.


----------



## lullnix (29 Oktober 2022)

PN/DP schrieb:


> Hast Du mal testweise an einem Teilnehmer die RS485-Drähte A und B getauscht? Z.B. am Brink an Pin 2 und 3 vertauscht.


Ja, gemacht. Kein Unterschied. Leitung A und B werden ja so am USB Adapter betrieben und da funktioniert es.


----------



## lullnix (29 Oktober 2022)

Die Idee des Mitschneidens mit dem USB Adapter kam von Wago. Ich habe einfach die A & B Leitungen zum USB Adapter weiter geführt und sehe einen Empfang am USB Adapter, wenn die Wago sendet. DD 5F 7B FD DD 0C sehe ich im Programm HTerm immer dann, wenn ich den xTrigger aufrufe. Oder messe ich mit dieser Methode dort Mist?


----------



## Plan_B (29 Oktober 2022)

Gestrichen,
Wenn ich lesen könnte, wär ich im Vorteil.
Parität: laut snippet none, laut ba even


----------



## Oberchefe (29 Oktober 2022)

Also wenn du die 4034 lesen willst, warum hast du die dann nicht konfiguriert?



> utQuery         : typMbQuery := (   bUnitId         := 20,       // Slaveaddress
> bFunctionCode   := 16#04,  // read input registers
> IIdentifyObject := myBaseIdentification, // only needed for FC43
> uiReadAddress   := 0,       // Startaddress
> ...



da hätte ich dann erwartet:


> utQuery         : typMbQuery := (   bUnitId         := 20,       // Slaveaddress
> bFunctionCode   := 16#04,  // read input registers
> IIdentifyObject := myBaseIdentification, // only needed for FC43
> uiReadAddress   := 4034,       // Startaddress
> ...


----------



## lullnix (5 November 2022)

Hallo zusammen,

so, läuft, nach dem Tausch der Bibliotheken deuten die hohen Werten DD 5F 7B FD DD 0C darauf hin, dass eine Vertauschung von A & B vorliegt.
A & B (was pos. und was neg. ist, ist wohl nicht genau definiert) an der Wago Klemme sind anscheinend anders als beim USB Adapter.
Vielen Dank noch mal für die Unterstützung und die Hinweise.

Allerding stellt sich gleich die nächste Frage. Die Rückwerte erhalte ich immer als Word (somit dezimal). Gibt es eine Möglichkeit diese als HEX Wert zu wandeln?


----------



## Plan_B (5 November 2022)

lullnix schrieb:


> ibt es eine Möglichkeit diese als HEX Wert zu wandeln?


Das ist ja wohl nur eine Frage der Darstellung, nicht des Werts an sich.


----------



## lullnix (5 November 2022)

Ich erhalte die Seriennummer in 3 Registern zurück als folgende Werte

DEC               HEX
utResponse.awData[0]  17169    ->   4311
utResponse.awData[1]    2081    ->     821
utResponse.awData[2]  17155    ->   4303

Die Hex Werte als String zusammengesetzt würde dann die richtige Ser. Nummer geben.

Den Wert 17169 habe ich wie folgt umgerechnet:

Byte_to_Hexstring(WORD_TO_BYTE(SHR(utResponse.awData[0],8)))
dann erhalte ich die 43
wie komme ich ans untere Byte? 

oder gibt es eine andere Möglichkeit die Darstellung zu ändern?


----------



## Thruser (5 November 2022)

lullnix schrieb:


> Byte_to_Hexstring(WORD_TO_BYTE(SHR(utResponse.awData[0],8)))
> dann erhalte ich die 43
> wie komme ich ans untere Byte?


Überleg einmal warum Du da die SHR Funktion verwendest.

Zu der anderen Frage: Die hast Du falsch formuliert
Ich möchte wie Werte als String im Hex Format anzeigen, wie mache ich das? 

Wenn Du das nur in der Oberfläche während Du Online bist anders dargestellt haben möchtest kann man unter Ansicht oder mit rechter maustaste die Darstellung ändern.

Was ich nicht ganz verstehe, kannst Du jetzt mit der Steuerung die Werte auslesen oder nicht? Da Du noch davon sprichst: DD 5F 7B FD DD 0C 

Gruß


----------



## Oberchefe (5 November 2022)

> wie komme ich ans untere Byte?





> Byte_to_Hexstring(WORD_TO_BYTE(utResponse.awData[0] AND 16#FF))


----------



## lullnix (5 November 2022)

Danke.

mache jetzt die "Umrechnung" wie folgt:

utResponse.awData[0] = 17169
utResponse.awData[1] = 2081
utResponse.awData[2] = 17155

str_SerialNo    := Concat6(Byte_to_Hexstring(WORD_TO_BYTE(SHR(utResponse.awData[0],8))),
                                       Byte_to_Hexstring(WORD_TO_BYTE(utResponse.awData[0])),
                                       WORD_TO_STRING(SHR(utResponse.awData[1],8)),  // da Ergebnis 8 nicht 08 sein muss
                                       Byte_to_Hexstring(WORD_TO_BYTE(utResponse.awData[1])),
                                       Byte_to_Hexstring(WORD_TO_BYTE(SHR(utResponse.awData[2],8))),
                                       Byte_to_Hexstring(WORD_TO_BYTE(utResponse.awData[2])));[/ICODE]

damit erhalte ich die richtige Seriennummer: 43118214303 

die 11 und 03 aus Register 0 und 2 erhalte ich auch ohne AND 16#FF

oder mache ich einen Denkfehler?


----------



## Tobsucht (7 November 2022)

Die CODESYS Funktion WORD_TO_BYTE schneidet schon das obere Byte. Daher hat das zusätzliche AND 16#FF keinen weiteren Effekt.

Da fehlt doch noch eine 0 in der Seriennummer: 4311*0*8214303

Du benutzt mit CONCAT6 schon die WagoAppString. Da würde ich mir das ganze Schieben und Wandeln sparen und gleich mit FORMAT arbeiten:


```
str_SerialNo    := Format3(
    sFormat        := '%04x%04x%04x',
    p1            := ADR(utResponse.awData[0]),
    p2            := ADR(utResponse.awData[1]),
    p3            := ADR(utResponse.awData[2]));
```


----------



## lullnix (7 November 2022)

Hallo, ja, dass mit der NULL habe ich schon bemerkt und geändert. Aber danke für den Tipp mit Format - probiere ich gleich aus.


----------



## lullnix (9 November 2022)

Hallo zusammen,

im Register 4110 erhalte ich die Uhrzeit getrennt nach Lo und Hi Byte.
mit Concat3(BYTE_TO_STRING(WORD_TO_BYTE(myData4110[0])), ':' ,BYTE_TO_STRING(WORD_TO_BYTE(SHR(myData4110[0],8)))); *)
kriege ich die richtige Uhrzeit zusammengebaut allerdings mit dem Schönheitsfehler, dass einzifferig Zahlen nicht mit einer führenden Null dargestellt werden. Ihr kennt doch sicher einen Trick dies zu korrigieren.


----------



## PN/DP (9 November 2022)

Ich kenne die Wago nicht und weiß nicht, ob es da für die Vornull vielleicht eine spezielle Funktion gibt, doch der Standard-Trick ist, eine Zeichenfolge zu erzeugen die garantiert 2 oder 3 Zeichen lang ist, und davon die letzten 2 Zeichen zu nehmen.
Versuche mal
`Concat3( RIGHT(BYTE_TO_STRING( WORD_TO_BYTE(myData4110[0]) + 100), 2), ':', RIGHT(BYTE_TO_STRING( WORD_TO_BYTE(SHR(myData4110[0], 8)) + 100), 2) );`

PS: grrr, zu viel verschachtelt, zu viele Klammern ... 

Harald


----------



## lullnix (9 November 2022)

danke - funktioniert - vielleicht kennt noch jemand einen anderen Weg


----------



## Tobsucht (9 November 2022)

WagoAppString.Format macht das auch.


----------



## lullnix (10 November 2022)

Ich hatte es mit WagoAppString.Format versucht, aber nicht hinbekommen.


----------



## Tobsucht (10 November 2022)

lullnix schrieb:


> Ich hatte es mit WagoAppString.Format versucht, aber nicht hinbekommen.


Dann hast Du dir die Dokumentation nicht angesehen.
Dein Vorhaben wird genau dort gezeigt. Nur mit drei statt zwei Stellen.

sFormat = '%02i' gibt den Dezimalwert immer mit zwei Stellen aus.


----------



## Thruser (10 November 2022)

Wegen des Pointerzugriffs der Format Funktion müssen High- Und Lowbyte aber wahrscheinlich in Temp Variablen kopiert werden.


----------



## PN/DP (10 November 2022)

lullnix schrieb:


> im Register 4110 erhalte ich die Uhrzeit getrennt nach Lo und Hi Byte.
> mit (...) kriege ich die richtige Uhrzeit zusammengebaut allerdings mit dem Schönheitsfehler (...)


Gibt es bei der Wago eine Konvertierfunktion TOD_TO_STRING? (z.B. TIME_OF_DAY zu '12:34:56' )
Da wäre es vermutlich effizienter, aus den 2 Bytes mit den Stunden und Minuten einen TOD (TIME_OF_DAY) zu berechnen und in STRING '12:34:56' zu wandeln und davon die ersten/linken 5 Zeichen zu nehmen. Etwa so:

```
todUhrzeit := (loByte * 60 + hiByte) * 60000;
strUhrzeit := LEFT(TOD_TO_STRING(todUhrzeit), 5);
```
oder über TIME

```
timUhrzeit := (loByte * 60 + hiByte) * 60000;
strUhrzeit := LEFT(TOD_TO_STRING(TIME_TO_TOD(timUhrzeit)), 5);
```

Harald


----------

