TIA TIA V14.1 Modbus/TCP richtig parametrieren

Partyarti777

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

ein Kollege und ich haben für die Schule ein Projekt am laufen. In diesem Projekt müssen wir eine HMI-Software mit WinCC OA auf dem Raspberry Pi zum laufen bringen, die auf eine S7-1500 per Modbus/TCP zugreift und Daten lesen bzw. schreiben kann (Tanksteuerung mit 2 Tanks, Ventilen, Pumpen und Füllständen).

Die HMI-Software greift auf ein Projekt auf der SPS zu, dass wir selber schreiben müssen. Dazu haben wir erstmal eine Verbindung per Modbus mit den Bausteinen von der Siemens Seite hergestellt, die vorprogrammiert und parametriert sind (der Beitrag heißt: "Wie programmieren und parametrieren Sie die Modbus/TCP-Kommunikation zwischen S7-1500 CPU und S7-1200 CPU?").

Von diesem Bausteinen verwenden wir nur den "MB_SERVER" und die dazugehörigen DB´s. Dieser reicht anscheinend um mit der HMI Daten auszulesen und zu schreiben.
Der MB_SERVER-Baustein verwendet ein Holding Register (Array of ...), dass bei uns z.B als Array of Bool festgelegt ist. Die Verbindung ist da und zwei in WinCC OA erstellte Schalter können einen Ausgang von der SPS lesen und schreiben (0/I) (in WinCC OA: Referenz M.1.3.0, read multiple registers, Eingang, Polling). Der Status im MB-SERVER ist auf 7006 - Data is being received.

Es gibt ja verschiedene Funktionscodes in Modbus und wir denken, dass wir das soweit verstanden haben, allerdings verstehen wir dass mit den Adressbereichen nicht und wo man diese parametrieren kann.



Jetzt hab ich ein paar Fragen:

Wo stellt man die Adressbereiche mit den verschiedenen Datentypen ein?
Oder
Wie kriegen wir ein weiteres "Holding Register", indem wir andere Datentypen (Uint, Real) schreiben können? In der vorgefertigten DB ist ein Register in dem Arrays von 0 bis .... erstellt werden können (
holdingRegister[0] ....[1]... usw.) und alle diese Arrays haben dann den gleichen Datentyp wie oben eingestellt (bei uns Bool).

Dann gibt es noch ein Problem mit den Daten in den Arrays. Schalter_1 z.B. wird in das holdingRegister[8] geschrieben und Schalter_2 in das holdingRegister[9]. Ist Schalter_1 auf "1", steht eine "1" im Register. Schaltet man Schalter_2 noch dazu auf "1", wird das Array [8] wieder auf 0 gesetzt und das Array [9] geht auf 1. Genauso ist es andersrum - es können also nicht 2 Arrays gleichzeitig auf "1" sein. Gibt es da eine Möglichkeit das mehrere Arrays auf "high" geschrieben werden können?


Ahnung von dem Ganzem haben wir so gut wie gar nicht und bis Mitte Januar müssten wir von der Schule aus zumindest mehrere Datentypen schreiben bzw. lesen können.
Nach schon etlichen unnötigen Stunden die wir für das Projekt investiert haben, hoffen wir dass uns hier jemand zur Seite stehen kann der sowas in der Art schon einmal gemacht hat.
Jede Hilfe und Verweise auf hilfreiche Seiten nehmen wir gerne an - Gruß :)
 
Zuletzt bearbeitet:
Von diesem Bausteinen verwenden wir nur den "MB_SERVER" und die dazugehörigen DB´s. Dieser reicht anscheinend um mit der HMI Daten auszulesen und zu schreiben. Der MB_SERVER-Baustein verwendet ein Holding Register (Array of ...), dass bei uns z.B als Array of Bool festgelegt ist.
Ich denke hier liegt ein Missverständnis vor.

Ein Register, egal ob Input-, Holding- oder Output-Register, ist im Sinne von ModBus immer* 16Bit (WORD) breit.
Binäre Signale werden bei ModBus als Coils (Input/Output) bezeichnet. Es gibt aber keine Holding-Coils, nur Halteregister die 16Bit breit sind.

Den Datenbereich den ihr beim MB_MASTER an MB_HOLD_REG anlegt definiert, wie der Name schon sagt die Ablage der Halteregister im Server. Nur weil ihr bei diesem Datenbereich ein Array_of_BOOL verwendet beziehen sich die ModBus-Register-Nummern nicht auf BOOL. In eurem Fall würde als ModBus-Halteregister-Register 1 (Adresse 0) die ersten 16 Bits in eurem Array beinhalten.

Es gibt ja verschiedene Funktionscodes in Modbus und wir denken, dass wir das soweit verstanden haben, allerdings verstehen wir dass mit den Adressbereichen nicht und wo man diese parametrieren kann.
Die Function-Codes 3,6,16 bedienen die Halteregister welche über MB_HOLD_REG definiert werden.
Codes 1, 2, 4, 5, und 15 lesen/schreiben direkt das Prozessabbild der Ein/Ausgänge der CPU, hierfür ist also keine Defintion der Speichers mehr nötig. Seht euch dazu Kapitel 13.8 in folgendem Handbuch an. https://support.industry.siemens.com/cs/at/de/view/109741593

Wo stellt man die Adressbereiche mit den verschiedenen Datentypen ein?
Wie kriegen wir ein weiteres "Holding Register", indem wir andere Datentypen (Uint, Real) schreiben können?
Gar nicht. Wie gesagt Register sind 16Bit WORD. Größere Datentypen werden über mehrere Register verteilt (32Bit = 2 Register).
Ich würde folgendermaßen vorgehen. Euer Array stellt ihr auf Array_of_Word um, das ist verständlicher da das der tatsächlichen Datenbreite der Register entspricht. Für Bits könnt ihr ein Register mit 1 oder 0 beschreiben. Integer haben direkt Platz, größere Datentypen teilt ihr entsprechend auf.

Um z.B. einen REAL-Datentypen auf 2 WORD (Register) aufzuteilen (oder umgekehrt) solltet ihr euch mit der SLICE-Funktionalität vertraut machen. https://support.industry.siemens.com/cs/at/de/view/57374718

Dann gibt es noch ein Problem mit den Daten in den Arrays. Schalter_1 z.B. wird in das holdingRegister[8] geschrieben und Schalter_2 in das holdingRegister[9]. Ist Schalter_1 auf "1", steht eine "1" im Register. Schaltet man Schalter_2 noch dazu auf "1", wird das Array [8] wieder auf 0 gesetzt und das Array [9] geht auf 1. Genauso ist es andersrum - es können also nicht 2 Arrays gleichzeitig auf "1" sein. Gibt es da eine Möglichkeit das mehrere Arrays auf "high" geschrieben werden können?
Das ist eben das oben beschriebene Problem. Da ihr auf Halteregister schreibt, schreibt ihr immer 16 Bit. Da die Bits [8] und [9] des Array_of_Bool zum selben WORD gehüren, werden beide durch den Register-Zugriff überschrieben.

Ahnung von dem Ganzem haben wir so gut wie gar nicht...
Habt ihr euch das schon mal durchgelesen? http://www.simplymodbus.ca/FAQ.htm
Wenn ihr schon grundsätzlich Daten via ModBus lesen/schreiben könnt, dann seit ihr nicht mehr weit vom Erfolg weg.... ;)
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Vielen Dank erstmal für die Hilfe, hat uns schon weiter gebracht :)

Die Function-Codes 3,6,16 bedienen die Halteregister welche über MB_HOLD_REG definiert werden.
Codes 1, 2, 4, 5, und 15 lesen/schreiben direkt das Prozessabbild der Ein/Ausgänge der CPU, hierfür ist also keine Defintion der Speichers mehr nötig. Seht euch dazu Kapitel 12.5.2.2 in folgendem Handbuch an. https://support.industry.siemens.com...view/109741593

Das sind wir durchgegangen. Wenn ich richtig verstanden habe, brauchen wir das HoldingRegister z.B. für Bool Datentypen nicht, nur für z.B. Int´s oder größere Daten an sich. Sagen wir ich betätige einen Schalter mit dem FC 05 (Bit schreiben, Ausgang) von WinCC OA, schreibt es dann direkt in einen Ausgang von der SPS rein, z.B. A0.0 ? Leider kommen wir nicht drauf wo oder wie wir einstellen können welcher Ausgang geschrieben werden soll. Wird das mit den Merkern gemacht (%M...)? Entweder haben wir was übersehen, oder es liegt wieder ein Missverständnis vor :cry:

Kann uns da jemand bitte noch eine kleine Hilfestellung geben?
 
Das sind wir durchgegangen. Wenn ich richtig verstanden habe, brauchen wir das HoldingRegister z.B. für Bool Datentypen nicht, nur für z.B. Int´s oder größere Daten an sich.
Nein, es hindert euch niemand daran ein Holding-Register mit 16 einzelnen Bits zu beschreiben. Wenn es sich bei dem Register mit den 16 Einzel-Bits nur um Lese-Zugriff handel ist es leicht.
Bei Schreibzugriff, wenn nur ein Bit im Wort geändert werden soll, muss zuerst das Wort gelesen werden damit man den Zustand der anderen Bits bekommt, dann das Bit angepasst und das Wort danach wieder zurück geschrieben werden. Kann sein dass das WinCC OA automatisch macht, keine Ahnung.

Einfacher wäre es, vor allem bei eurer Anwendung mit nur ein paar Signalen, einfach ein ganzes Word-Register pro Bit zu verwenden.

Sagen wir ich betätige einen Schalter mit dem FC 05 (Bit schreiben, Ausgang) von WinCC OA, schreibt es dann direkt in einen Ausgang von der SPS rein, z.B. A0.0 ?Leider kommen wir nicht drauf wo oder wie wir einstellen können welcher Ausgang geschrieben werden soll.
Welchen Ausgang ihr schreibt hängt davon ab welche Coil-Nummer ihr im Telegramm übergebt.
Siehe dazu Seite 1252 des Handbuchs:
Code:
Modbus-Funktionen    S7-1200
Codes    Funktion    Datenbereich    Adressbereich    Datenbereich            CPU-Adresse
05     Bit schreiben    Ausgang        1 An 8192    Prozessabbild der Ausgänge    A0.0 bis A1023.7
Grundsätzlich würde ich aber abraten die IOs direkt vom HMI zu beschreiben.
Fehler lassen sich schwer diagnostizieren wenn dir jemand direkt in das IO-Abbild schreibt, man Stelle sich vor der externe Client vertut sich mit der Adresse und beschreibt was wo wirklich was dran hängt. https://support.industry.siemens.com/cs/ww/de/view/109748190


Für den reinen Datenaustausch zwischen Systemen sind eigentlich die Holding-Register gedacht.
Wie ich es machen würde habe ich ja schon im ersten Beitrag geschrieben.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
frage

ich bin grad auch an dem Thema dran

ich hätte da noch ein paar Fragen die mir die erfahrenen Benutzer unter euch ggf beantworten können

ich kommuniziere von ner Siemens 1500 mittels MB_CLIENT zu einem Externen Gerät per Modbus TCP
nun sind die Werte dich ich abgreife ziemlich auf den Registeradressen verteilt, was mich dazu verleitete Anfragen aufzuteilen.
ich gehe mit der Siemens über die Profinetschnittstelle raus.
so nun geht aber pro Anfrage bis die entsprechende Antwort kommt ca 2-3 sec. Das bedeutet bei mehreren Anfragen summiert sich das, vor allem wenn mann etwas zyklisch immer wieder abfrägt kann das störend sein.
ist es taktisch sinnvoll das zu staffeln oder ist es besser eine Anfrage über einen grösseren Registerblock zu machen.
und wie ist das dann beim Schreiben da ginge das ja nicht denn da sonst ja der ganze Block geschrieben wird.

Weiters ist es sinnvoll/ nötig die Verbindung bei zyklischen Abfragen zu trennen oder nicht
Momentan öffne ich die Verbindung dann sende ich alle Anfragen nach der reihe raus und beende die Verbindung danach beginne ich von vorne, ich weiss aber nicht ob dies nötig ist
ggf ist der Ansatz auch falsch und richtig wäre pro Anfrage eine Verbindung aufzubauen, ggf könnte man zumindest die zyklischen dann auch schneller kommuniziert haben, wenn mehrere Verbindungen der Lösungsansatz wäre.
ich wählte den Ansatz eine Verbindung und dann der Reihe nach die Anfragen aus, weil ichs nicht besser weiss :)
und es so auch geht , einfach relativ langsam da sequenziell, vor allem bei mehreren.

Noch eine Frage zu den Siemens Spezialisten: ab und zu , meist nach dem laden des Programmes kommt mir beim Status 80A3 was auf Probleme mit der eindeutigen ID hinweist, nach ändern dieser geht auch alles wieder, gibst da nen saubereren Reset oder ist ggf die Lösung "wenn Fehler dann id wechseln " auch nicht so verkehrt.
 
Zuletzt bearbeitet:
Ich bin nicht der Modbus-Experte und arbeite nur hin und wieder damit, aber 2 bis 3 Sekunden pro Telegramm scheinen merkwürdig. Normalerweise sollten eine Anfrage über paar Register deutlich schneller gehen. Dauert das, wenn du zu z.B. einen PC-basierten Modbus-TCP-Server zum Testen nimmst genau so lange? Was ist das für ein Server?

Ich denke nicht dass es sinnvoll ist die Verbindung zwischen den Telegrammen zu trennen. Der Verbindungsaufbau kostet schon seine Zeit.
Wenn du eine Serie von Telegrammen abgearbeitet hast und dann eine weile keine Daten mehr brauchst kann man die Verbindung schon trennen.

Zum Thema ID. Deine CPU legt eine Verbindungsrecource mit einer ID an. Der MB_Client hat diese ID und den Status "Verbindung in der CPU erstellt" in den Instanzdaten gespeichert. Wenn du einspielst und die Instanzdaten zurücksetztst, ohne vorher die Verbindung am MB_Client abzubauen, dann bleibt die Verbindungsrecource in der CPU bestehen. Wenn du den MB_Client dann wieder aufrufst meldet dieser dass die Recource bereits belegt ist. Er weiß ja nicht dass die existierende Verbindungsrecource seine eigene war - könnte ja genauso gut die Verbindung eines Anderen sein und es wurden die IDs falsch eingetippt. Nützlich ist wenn man die Instanzdaten des MB_Client als separaten DB hat, damit man diesen nicht zwingend mit dem Aufrufer-FB mit-initialisieren muss.
 
Server ist ein Frequenzumrichter 100 Mbps Ethernet

den Rest wird ich mal umsetzen und beobachten
die Antwortzeit halte ich auch als eher hoch jedoch ist mir im Moment noch nicht ganz klar wie ich da ansetzen soll.
bezüglich Grösserer Block zum abfragen, kann man da was sagen zb ab welchen unnötig angefragten Daten einzelne schneller sind als ein grosser Block?
und weiters ist mir nicht ganz klar wie das dann beim Schreiben ist da wird ich um einzelne Abfragen wohl nicht herum kommen
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo
Ich habe mit der 1500 zwar keine Erfahrung aber prinzipiell sollte die Abfrage eines einzelnen Registers 50ms (je nach Konfiguration) nicht wesentlich überschreiten.
(Ist bei allen Systemen ähnlich die ich kenne). Wenns schneller gehen soll wäre UDP eventuell eine Lösung.
Bei der Blockgröße kann man maximal 125 Worte übertragen. Ab wann eine Teilung sinnvoll ist kommt auf die genaue Aufteilung an. Aus dem Bauch raus würde ich sagen wenn die Verteilung unter 10% der 125 Worte liegt würde ich teilen. Die Verbindung aber auf keinen Fall trennen.
Zuerst solltest du klären ob der Block auch zusammenhängend gelesen werden kann. Selbst nebeneinander liegende Adressen bedeuten nicht zwangsläufig, dass diese als Block gelesen werden können.
Beim schreiben verhält es sich ähnlich. Hier kann es durchaus sinnvoll sein den kompletten Bereich erst zu lesen, die einzelnen Register zu bearbeiten und anschließend den gesamten Block zurückzuschreiben als z.b. 50 einzelne Register verstreut zu schreiben. Aber auch hier prüfen ob ein schreiben als Block zulässig ist. (am besten mit einen PC Tool)
Holger
 
ah besten Dank der Ansatz beim schreiben hilft mir glaubs
das Hauptproblem ist glaube aber die Reaktionszeit
wenn ich mit der Siemens die Anfrage rauslasse bis der Siemenseigene Baustein mir das Done gibt vergehen locker 2-3s
muss mich da erst schlau machen, bzw suchen wo das Problem liegen könnte
aber somit sollte die TCP Verbindung nicht der Bremser sein
auch die Siemens 1500 Zykluszeit agiert im ms wenn nicht us Bereich
(ich brauche etwa 5 Zyklen) Befehl zusammenstellen , schicken -> warten auf busy -> warten auf busy weg -warten auf done ->Resultat wegspeichern
ggf die Gegenseite muss das mal klären

besten Dank erstmal

Also als Feedback, die hohe Antwortzeit hat anscheinend mit der Gegenseite zu tun die dies einfach nicht schneller kann.
es ist ein Frequenzumformer für einen Motor, der redet intern über Modbus RTU und auf der Schnittstelle modbus TCP gab es einen Bereich für "Schnelle" Adressen darauf ist die Reaktionszeit bei ca 2s
die Restlichen sind auch zu erreichen aber haben Antwortzeiten von 4-5s, ich denke mal das die wegen der Seriellen RTU Kommunikation einfach nicht schneller gehen
meine Erkenntnis daraus ist das die Geschwindigkeiten teils doch zu beachten sind Modbus TCP heißt nicht automatisch schnell.

eine Problematik habe ich aber immer noch, also eigentlich nicht mehr durch das auslagern der Modbusclients in einen eigenen DB hat sich die ID Problematik nicht mehr gezeigt.
Aber dennoch gefällt mir das nicht ganz. wenn der Fehler 80A3 = id schon gebraucht , wie handelt man das sauber einfach ID wechseln ? unsauber darum weil wenn der Fehler kommt krieg ich den Fehler nur weg mit ID umnummerieren mit dem Programmiergerät, sprich im Normalen Betrieb, wenn denn der Fehler kommt geht nichts mehr. und eigentlich gefällt mir der Gedanke nicht das man meine Software umschreiben muss um das wieder zum laufen zu kriegen :), ausser ich mach das Programmtechnisch selber wenn es denn der Richtige Weg ist.
wenn das Leben ein Wunschkonzert wäre, würde mir ein sauber Reset oder so was gefallen, nur weiss ich noch nicht wie.
 
Zuletzt bearbeitet:
Server ist ein Frequenzumrichter 100 Mbps Ethernet

den Rest wird ich mal umsetzen und beobachten
die Antwortzeit halte ich auch als eher hoch jedoch ist mir im Moment noch nicht ganz klar wie ich da ansetzen soll.
bezüglich Grösserer Block zum abfragen, kann man da was sagen zb ab welchen unnötig angefragten Daten einzelne schneller sind als ein grosser Block?
und weiters ist mir nicht ganz klar wie das dann beim Schreiben ist da wird ich um einzelne Abfragen wohl nicht herum kommen


Hallo rKoster,
als Anfänger bei der SPS kommuniziere ich auch einem Frequenzumrichter mit einen S7-300 CPU PN mittels Modbus TCP für einen Projekt an der Uni und hätte gerne wissen wie kann man die werte aus Freque.. Lesen bzw. schreiben? Haben Sie eienen FUP Beispielsprogramm?

ich freue mich auf eine Antwort
Glindayzer
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo rKoster,
als Anfänger bei der SPS kommuniziere ich auch einem Frequenzumrichter mit einen S7-300 CPU PN mittels Modbus TCP für einen Projekt an der Uni und hätte gerne wissen wie kann man die werte aus Freque.. Lesen bzw. schreiben? Haben Sie eienen FUP Beispielsprogramm?

ich freue mich auf eine Antwort
Glindayzer

hi

also welche Register adresse welchen wert in welchem Format hat müsste aus den Unterlagen des Frequenzumrichters hervorgehen

ich programmiere leider nicht in Fup sondern scl
aber erst musst du wissen wo was beim Freqenzumformer steht.
schreiben bzw lesen machst du dann mittels dem Modbusmode FC03(=103) oder FC16(=116) bei multiple Register

Unter der Siemenshilfe mittles Suchbegriff Modbus tcp findest du den Beschrieb zu dem Modbusclient

gruss
Roman
 
Zuletzt bearbeitet:
Hallo Roman,
erstmal danke für die schnelle Antwort nur ich programmiere das ganze mit TIA Portal 14 und ich find eirgendi die Bausteine FC03 bzw. FC16 nicht??

viele Grüße
Glingayzer
 
hi

sorry mein Fehler (FC = Funktionscode)
FC03 bzw. FC16 sind keine Bausteine sondern der Modbus Mode
in der Siemens Hilfe ist der Baustein MB_CLIENT beschrieben

Auswahl des Modus der Modbus-Anfrage (Lesen, Schreiben oder Diagnose) bzw. direkte Auswahl einer Modbus-Funktion

Function CodeActionTable Name
01 (01 hex)ReadDiscrete Output Coils
05 (05 hex)Write singleDiscrete Output Coil
15 (0F hex)Write multipleDiscrete Output Coils
02 (02 hex)ReadDiscrete Input Contacts
04 (04 hex)ReadAnalog Input Registers
03 (03 hex)ReadAnalog Output Holding Registers
06 (06 hex)Write singleAnalog Output Holding Register
16 (10 hex)Write multipleAnalog Output Holding Registers

Gruss Roman
 
Zuletzt bearbeitet:
Zurück
Oben