TIA MB Client dynamisch aufrufen

--alex--

Level-2
Beiträge
92
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Leute,

habe die folgende Aufgabenstellung.
Ich muss über Modbus-TCP ca. 50 Werte abfragen, welche von den Modbus-Adressen leider komplett verstreut sind.
Die Modbus-TCP Abfrage funktioniert jetzt einmal mit einem Wert.
Jetzt möchte ich die Parameter dynamisch aus einem DB auslesen und die gelesenen Werte in einen eigenen DB schreiben.

Dazu habe ich mir folgenden Ansatz überlegt.
Ich lege im DB ein Array [0..xx] of Datentyp_xx an.
Das sieht dann folgendermaßen aus:


Modubus_Abfrage[1]
-Modbus-Adresse (Int) 6722
-Länge (Int) 10
-Ziel-DB (Int) 100
-Adresse im Ziel-DB (Int) 2

Modubus_Abfrage[2]
-Modbus-Adresse (Int) 7822
-Länge (Int) 1
-Ziel-DB (Int) 100
-Adresse im Ziel-DB (Int) 22




Für den MB_Client möchte ich jetzt daraus die folgenden Parameter für zB. Modbus_Abfrage[1] generieren:

MB_DATA_ADDR = 6722
MB_DATA_LEN = 10
MB_DATA_PTR = DB100.DBX2.0


Mein Problem ist aktuell wie ich den Zeiger für den Datenpuffer aus 2 Int-Werten generieren kann
und in eine Variable setze, die ich dann an den MB_Client übergeben kann.


Hoffe ich konnte mein Problem halbwegs verständlich darstellen.

Gibt es eventuell einen viel eleganteren Ansatz um so etwas umzusetzen?


Danke für eure Unterstützung
 
Code:
i:= HierZeigerVariable

ModbusParameter1:= ModbusConnection[i].ModbusParameter1
...
ModbusParameter9:= ModbusConnection[i].ModbusParameter9

Meinst du so etwas?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich habe es so gemacht. geht halt nur mit nicht Optimiertem DB
(Bei einer Nibe Wärmepumpe da sind die Adressen auch sehr verstreut)

Code:
            #vPokePeek := true;
            #l := DINT_TO_UINT(#vLen - 1);
            FOR #n := 0 TO #l DO
                POKE(area := 16#84,
                     dbNumber := #Konfig[#Block].Datenbaustein,
                     byteOffset := #Konfig[#Block].Offset + #n,
                     value := #Buffer[#n],
                     ENO => ENO);
                IF ENO = 0 THEN
                    #vPokePeek := False;
                END_IF;
            END_FOR;
            #Konfig[#Block].PokePeekOk := #vPokePeek;
 
Habe es letztendlich so gelöst:

Code:
LAR1  P##device1_mb_Any_read
    L     B#16#10
    T B [ AR1 , P#0.0 ]
    L     B#16#2
    T B [ AR1 , P#1.0 ]
    L     Modubus_Abfrage[x].Laenge
    T W [ AR1 , P#2.0 ]
    L     Modubus_Abfrage[x].Ziel-DB
    T W [ AR1 , P#4.0 ]
    L     Modubus_Abfrage[x].Adresse im Ziel-DB
    SLD   3
    L     P#DBX0.0
    +D
    T D [ AR1 , P#6.0 ]

Danke für eure Hinweise.

Hätte noch eine Frage:
Aktuell läuft der Request jede Sekunde mit einem neuen Parameter.
Kann man das Geschwindigkeitsmässig "optimieren"?

Ich hatte eine Abfrage nach einer positiven DONE Flanke eingebaut, aber das wollte die SPS nicht so richtig.


Danke Alex
 
Habe es letztendlich so gelöst:
Wenn man verschiedene weit auseinanderliegende Register lesen/schreiben muss, dann löst man sowas üblicherweise mit einer Jobliste, wo die Lese/Schreib-Auftragsparameter fix und fertig eingetragen sind, und aus der die Parameter zwischen den Aufträgen in die Modbus-Aufrufparameter umkopiert werden. Das kann man schön symbolisch gestalten und muss nicht kryptisch in AWL ANY-Pointer zusammenbasteln.
Forumsuche: modbus job

Hinweis: in Modbus ist es schneller, wenn man bei nahe zusammenliegenden Registern diese in einem Block (inklusive dazwischen liegender unbenötigter Register) liest, als wenn man nur die benötigten Register in einzelnen Aufträgen liest.

Aktuell läuft der Request jede Sekunde mit einem neuen Parameter.
Kann man das Geschwindigkeitsmässig "optimieren"?
Ja. Das Lesen in eine Schrittkette packen (und am Ende bzw. Anfang die Auftragsparameter umkopieren) und wenn die SK fertig ist, dann wiederholen (ggf. mit dem nächsten Leseauftrag).
 
Zurück
Oben