# ModBus



## mailmir (27 Januar 2017)

Hallo zusammen,

ich nutze Beckhoff-Hardware. Beim aktuellen Projekt haben wir einen CX5120. Hier haben wir einige ModBus-Feldgeräte von Biral und Belimo. Das ist eigentlich auch kein Problem.
Bei meinen bisherigen Projekten habe ich bei der IBS immer wieder festgestellt das bei fehlender Kommunikatio sehr oft die Busleitung das Problem war (falsch angeschlossen usw.)
Gibt es da einen Befehle den alle Modbusteilnehmer, egal von welchem Hersteller beantworten, quasi wie ein PING. Dann könnte ich vorab immer erstmal schauen welche Teilnehmer ich erreiche.

DNAKE schon mal.

Gruß Norbert


----------



## Captain Future (27 Januar 2017)

Ich hab keine Ahnung von Beckhoff obwohl hier immer wieder viele schreiben was für geiles Zeug 
der Kram sein soll.... 

Bitte korrigiere mich wenn ich was falsches schreibe. 
Modbus RTU oder Modbus TCP ? Ist aber auch egal.
Ich denke du hast für die Programmierung TwinCAT und dafür gibt es doch eine Softwarebibliothek Kommunikation
die zB. eine Modbus-RTU-Kommunikation über eine serielle RS232-, RS422- oder RS485-Schnittstelle realisiert.

Diese Bausteine aus der Softwarebibliothek müssen doch eine Fehlerbehandlung haben wenn ein Slave auf ein
Telegramm keine Antwort gibt. Damit hast du doch deinen Ping für jeden Teilnehmer.

Sorry das ich dir hier nicht weiter helfen kann im TIA Portal hätten wir das Problem in 0,5 Sekunden beseitigt.

Gruss

Nachtrag:
oder meist du einen Befehl wie bei Windows "Ausführen" Ping + Adresse zum testen ob ein Teilnehmer da ist ? Das gibt es nicht bei Modbus


----------



## holgermaik (27 Januar 2017)

Modbusfunktion 08 Subfunktion 00 währe so etwas.
Dabei wird dir der Request als Response zurückgesendet.
Das sollten eigentlich alle Geräte können.
Holger


----------



## mailmir (27 Januar 2017)

@Capiain Future



> Nachtrag:





> oder meist du einen Befehl wie bei Windows "Ausführen" Ping + Adresse zum testen ob ein Teilnehmer da ist ? Das gibt es nicht bei Modbus



GENAU so etwas meine ich

@Holger
Ich hab da etwas im Infosys von Beckhoff gefunden. Wenn ich an einen Slave eine Anfrage sende, Muss ich ja immer die Modbus-adresse angeben, 
die Registeradresse und die Anzahl der Register die ich lesen möchte. Diese Infos habe ich im Infosys leider nicht gefunden. Kannst Du mir da auch weiterhelfen?

Ich mach das immer so (arTempDaten usw. nur als Bsp.):



> Master.ReadRegs(
> Quantity:= 9,
> MBAddr:= 0,
> cbLength:= SIZEOF(arTempDaten),
> ...


----------



## holgermaik (28 Januar 2017)

> Diese Infos habe ich im Infosys leider nicht gefunden



Welche Infos hast du nicht gefunden? Ich verstehe deine Frage irgendwie nicht

Schreibe doch auch bitte dazu: 
Welcher Kommunikationsweg TCP/IP oder RTU seriell.?
Wenn RTU mit Klemme KLxxx oder über Schnittstelle vom Controller?


----------



## Captain Future (28 Januar 2017)

holgermaik schrieb:


> Welche Infos hast du nicht gefunden? Ich verstehe deine Frage irgendwie nicht
> 
> Schreibe doch auch bitte dazu:
> Welcher Kommunikationsweg TCP/IP oder RTU seriell.?
> Wenn RTU mit Klemme KLxxx oder über Schnittstelle vom Controller?



Das finde ich auch *etwas mehr Info *kann nicht schaden

 Seine erste Frage war ob es einen Befehl unter Modbus gibt bei Windows "Ausführen" Ping + Adresse
 Ich als *nicht *Beckhoff Fachfrau sage "NEIN" den gibt es nicht.
 Wenn du bei Deiner Inbetriebnahme testen willst ob alle Teilnehmer da sind dann muß du Software wie Modbus Poll benutzen

 Ansonsten muß Du im Programm bei jedem Zugriff auf einen Teilnehmer die Antwort ( respond) auswerten ob Busy, Done oder Error 
 oder wie der Kram bei euch heißt.


----------



## Guga (28 Januar 2017)

Nach dem geposteten Baustein vom Thread-Eröffner dürfte es sich um ein serielle Kommunikation handeln.

Und bei serieller Kommunikation ist es immer etwas mühsam festzustellen ob die Kommunikation geht/nicht geht oder halb geht (duplex versus half duplex). Das ist halt das Problem wenn man allgemeine HW (beliebige serielle Schnittstellen) und viele Möglichkeiten (Modbus ASCII, Modbus RTU oder oder oder) abdecken will/muss. Flexible, kommt aber mit einem Kostenfaktor daher.

Prinzipiell: 
 -Jeder Slave sollte in seiner Doku definieren welche Modbus-Funktion er unterstützt. Es gibt keine zwingend vorgeschriebene Funktion. Eine equivalentes Teil zu einem Ping gibt es nicht da Modbus je nach Slave-Hersteller z.B. sehr sehr sehr dürftig implementiert ist. 
 -Wie schon weiter oben erwähnt musst du schauen ob du im TwinCAT Antworten erhälst über den Busy-Ausgang und den Fehlercode.
 -Wenn du eine Antwort erhälst, diese aber unbrauchbar ist (d.h. es gibt einen ensprechenden Fehlercode) könntest du (aus der Erinnerung heraus) im Baustein auf eine interne Struktur schauen die dir das empfangene Telegramm logisch in die Modbus-Elemente auflöst. Dann sieht man gegebenenfalls wo das Problem ist. Letztendlich ist es aber nur eine etwas detaillierte Info als der Fehlercode.

Guga


----------



## Senator42 (28 Januar 2017)

als ich mit Modbus (RTU, RS485 Halfduplex) nicht weiter kam,
habe ich 2 RS485->RS232 wandler gebaut (2 ICs + 7805).
Die Signale an 2 COM-Ports (RxD) angeschlossen und in Binterm beobachtet.
(USB-RS232 geht auch falls der PC,Laptop keinen COM hat.)


----------



## mailmir (29 Januar 2017)

Hallo zusammen,

sorry, natürlich gebe ich auch mehr Infos

ich nutze immer die KL6041 von Beckhoff und kommuniziere damit per MudBus RTU



> @Holger
> Ich hab da etwas im Infosys von Beckhoff gefunden. Wenn ich an einen Slave eine Anfrage sende, Muss ich ja immer die Modbus-adresse angeben,
> die Registeradresse und die Anzahl der Register die ich lesen möchte. Diese Infos habe ich im Infosys leider nicht gefunden. Kannst Du mir da auch weiterhelfen?



ich habe die Infos, auf welche Register/Adresse ich die Anfrage senden und abfragen muss nicht gefunden, genauso wie die Anzahl der zu schreibenden/lesenden Register.

@Captain Future



> Ansonsten muß Du im Programm bei jedem Zugriff auf einen Teilnehmer die Antwort ( respond) auswerten ob Busy, Done oder Error
> oder wie der Kram bei euch heißt.



Diese Auswertung mach ich sowieso, aber meine Idee war eine einfache Übersicht die unabhängig von den angeschlossenen Geräten ist. (Bsp. 100 Lampen die mir anzeigen ob ein Teilnehmer auf den Adressen 0 - 100 vorhanden ist oder nicht)
Prinzipiell ist mir ja bekannt welcher Teilnehmer welche Adresse hat und so erstelle ich ja auch die Software, aber bei der IBS gibt er bekanntlich viel Fehlerpotential (falsch eingestellte Adressen, falsch angeschlossene Geräte usw.) 

@Guga



> -Wenn du eine Antwort erhälst, diese aber unbrauchbar ist (d.h. es gibt einen ensprechenden Fehlercode) könntest du (aus der Erinnerung heraus) im Baustein auf eine interne Struktur schauen die dir das empfangene Telegramm logisch in die Modbus-Elemente auflöst. Dann sieht man gegebenenfalls wo das Problem ist. Letztendlich ist es aber nur eine etwas detaillierte Info als der Fehlercode.



Prinzipiell würde mir eine Antwort, EGAL welcher Art ja ausreichen. Wenn ich die Antwort auswerte und nur schaue ob diese "No Response" ist dann sollte ich doch eigentlich wissen ob da ein Teilnehmer ist oder nicht. 
Fehlercode = No Response = Kein Teilnehmer bzw. ungültige Einstellungen vom Teilnehmer
Fehlercode xy = Teilnehmer vorhanden


----------



## Oerw (30 Januar 2017)

Hallo, 

wie bereits die Vorgänger geschrieben haben gibt es einen "ping" bei Modbus nicht

Daher einfach ein Functioncode nutzen mit einer beliebigen Adresse und einer kleinen Länge. Ist das Gerät vorhanden und wird die Anfrage nicht unterstützt, wird bei einem erreichbaren Gerät ein Exceptioncode kommen. keine Antwort ist somit nicht erreichbar


----------



## mailmir (5 Februar 2017)

Hallo zusammen,

ich habe die Idee mit dem ModBus-Sucher umgesetzt und es klappt sehr gut. 


```
CASE State_ModBus_Suche OF


0..9:
    byModBusLinie;
    byModBusAdr;


    IF bModBus_Suche THEN
        FOR iAktuell := 0 TO 254 DO
            arModBus[iAktuell] := FALSE;
        END_FOR
        bModBus_Suche_Aktiv := TRUE;
        sTime_LetzteSuche := sZeitStempel;
        State_ModBus_Suche := 10 ;
        byModBusAdr := 1;
    ELSE
        State_ModBus_Suche := 100 ;
    END_IF


10: (* Daten lesen *)


        Master.ReadRegs(
        UnitID:= byModBusAdr,
        Quantity:= 1,
        MBAddr:= iLeseAdresse,
        cbLength:= SIZEOF(wModBus_Suche),
        pMemoryAddr:= ADR(wModBus_Suche),
        Execute:= TRUE,
        Timeout:= T#2s,
        BUSY=> ,
        Error=> ,
        ErrorId=> ,
        cbRead=> );


    IF  (NOT Master.BUSY) OR TimeOut.Q THEN
        Master.ReadRegs(Execute:= FALSE);
        TimeOut(In := FALSE);
        IF Master.Error AND ( Master.ErrorId = MODBUSERROR_NO_RESPONSE) THEN
            arModBus[byModBusAdr] := FALSE;
            State_ModBus_Suche:= State_ModBus_Suche + 1 ;
        ELSE
            arModBus[byModBusAdr] := TRUE;
            State_ModBus_Suche := State_ModBus_Suche + 1 ;
        END_IF
    ELSE
        TimeOut(In := TRUE);
    END_IF


11: (* ModBus-Adresse erhöhen *)


    IF byModBusAdr < 20 THEN
        byModBusAdr := byModBusAdr + 1;
        State_ModBus_Suche := 10 ;
    ELSE
        State_ModBus_Suche := State_ModBus_Suche + 1 ;
    END_IF


12..1000:
    bModBus_Suche := FALSE;
    bModBus_Suche_Aktiv := FALSE;
    State_ModBus_Suche:= 0 ;
    State := State + 1;
END_CASE
```


----------

