TIA Stationsnummernaufruf mittels Poke nur in eine Richtung möglich

Sebastian_97

Level-1
Beiträge
4
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo zusammen,
ich habe folgendes Problem:
Über GEO2LOG lese ich die Hardware ID's von DI und DO Modulen ein. Das geschieht über einen Array [0..255]
Die Nummer dabei entspricht immer der zugehörigen Stationsnummer (Gerätenummer). Im Anschluss lese ich die Ein- und Ausgabeadressen mit RD_ADDR ein.
Das klappt egal, welche Stationsnummern ich vergebe, egal in welcher Reihenfolge.
Nun zum Problem:
In einem Funktionsbaustein spreche ich mit der Funktion Poke über eine for-Schleife die Byteadressen an. Allerdings werden die Byteadressen nur beschrieben, wenn die Stationsnummern in aufsteigender Reihenfolge von der CPU aus nummeriert sind. D.h. sollte die erste Station die Nummer 5 haben und die nachfolgende die 1, so wird bei der ersten Station kein Wert geschrieben. Siehe Bild.
Mir fällt zudem auf dass der Byteoffset zum einen immer um ein Bit niedriger sein muss als die ausgelesene Adresse. Ebenso kann ich Poke nur mit einer rückwärtslaufenden for Schleife anwenden. Bei Peek ist das nicht so.
Gibt es einen Parameter, der die Teilnehmernummer wie im Bild beschrieben im Anwenderprogramm auslesen kann, sodass die Stationsnummern dementsprechend sortiert werden können? Bzw. gäbe es eine alternative zu Poke außer set_io?
Im Bild handelt es sich um eine Ringtopologie, allerdings hab ich das auch schon mit einer Linientopologie probiert und bin auf das gleiche Ergebnis gekommen.
Im Bild würde zwar bei Station 5 die Byteadresse von DI und DO eingelesen werden, allerdings könnten keine Werte über Poke geschrieben werden.
Danke für eure Antworten.
 

Anhänge

  • Screenshot 2021-01-26 120721.jpg
    Screenshot 2021-01-26 120721.jpg
    28,5 KB · Aufrufe: 34
Ich kann Dir nicht wirklich folgen, aber für mich klingt das so, als würdest Du mit jedem Schreib-/Lesevorgang 1 Wort schreiben/lesen.
Dabei würde bei jedem SchreibZugriff auf 1 ByteAdresse das benachbarte Byte gleich mit überschrieben werden, vermutlich mit 0.
Zumindest würde es das unterschiedliche Verhalten zwischen aufwärts und abwärts adressieren und den 'ByteOffset immer um 1 Bit niedriger" erklären.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich kann dir auch nicht folgen.
"Ebenso kann ich Poke nur mit einer rückwärtslaufenden for Schleife anwenden"
hört sich für mich auch irgendwie nach Logik/Programmierproblem an. Der Befehl selber wird wohl kaum Schleifenrichtungsabhängig sein!

Aus Neugier: Was machst Du damit ?
Ich habe inzwischen schon ein paar komische Dinge mit TIA gemacht (das Lachen ist mir dabei aber auch vergangen) , aber PEEK/POKE hatte ich nur nach migrieren und habe es dann geändert/rausgeschmissen.
Ist wirklich ein reiner Notfall-Befehl aus meiner Sicht,
Muss immer alles automatisch in Schleifen irgendwie in einer Standard-DB ?
Ist ein ausgeschriebenes direktes symbolisches Zuweisen nicht mehr möglich ?
Für die Nachvollziehbarkeit (Referenz !) hat das schon Vorteile...



 
Hintergrund ist, dass dem Anwender die Eingabe von Ein- und Ausgabeadresse sowie eingabe der Stationsnummer erspart bleiben soll. Das erspart bei der Projektierung einiges an Zeit.
Und damit kommt meiner Meinung nach eben nur die indirekte Adressierung in Frage. Wenn also zwischen vorhandenen Stationen eine weitere in das Projekt mit migriert wird muss diese lediglich im entsprechenden Subnetz mit eingebunden werden und das Anwenderprogramm läuft mit darauf.
Belehrt mich aber gerne eines Besseren falls das anders gehen sollte:)


Wie oben beschrieben werden die Byteadressen entprechend der aufsteigenden Stationsnummern sortiert. Das heißt beim schreiben (poke) wird die Station mit der niedrigsten nummer genommen und beschrieben. danach die 2. niedrigste usw. Die Reihenfolge der Byteadressen spielt dabei keine Rolle.
Deshalb kann meiner Einschätzung eine Station mit höherwertiger Stationsnummer, welche sich vor einer Station mit niederer Nummer befindet nicht mit den Daten beschrieben werden. Oder verstehe ich da was falsch?
Da TIA standarmäßig die geringste Stationsnummer zur Verfügung stellt, ebenso wie bei der HW-ID ist diese eben nicht immer automatisch fortlaufend.
Jetzt würde mich interessieren ob es entweder einen Baustein gibt, der erkennt welche Station am nächsten der CPU ist (entsprechend der Topologie) damit die Stationsnummern eben entsprechend der Topologie nach angesprochen werden
oder ob es alternative Bausteine für die indirekte Adressierung zu PEEK/POKE bzw. set/get IO.


Ich hoffe das meine Frage jetzt verständlicher ist.


Den Programmcode werde ich nicht posten, da er zum einen recht lange ist und nicht wirklich zum Verständnis beiträgt.


Danke jetzt schon für eure Antworten :)
 
Zuletzt bearbeitet:
Also ich muß schon sagen, ich kann dem Ganzen ebenfalls nicht folgen.
Bin ich zu doof dazu oder kannst/willst du es einfach nicht so erklären, dass wir dummen Kleinprogrammierer das verstehen?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich vermute wie Heinrich, daß der TE da mit POKE in zu großen Speichereinheiten in Speicheradressen schreibt, wo der Compiler nicht warnen kann/tut. Z.B. Words in ein Byte-Array speichern überschreibt das angezielte Byte und das nächsthöhere Byte. Solcher Code "funktioniert" in aufsteigender Reihenfolge, und erst bei absteigender Reihenfolge fällt auf, daß unbeteiligte Variablen mit überschrieben werden.
Wenn er das Schreiben vollsymbolisch mit Array-Zugriffen tun würde, dann würde der Compiler dafür sorgen, daß die Zugriffe passen.
Wenn uns aber kein Programmcode gezeigt wird, dann können wir auch nicht auf den Fehler zeigen...

Harald
 
Anbei mal auszugsweise der relevante Code zum Einlesen der Adressen. Letzter Absatz ist dann die Ausgabe auf die Module.
Ich hoffe die Variablennamen verwirren nicht allzu sehr^^

//Einlesen HW-Kennung DI und DQ Module
//EA Adressen werden in Globalen DB gespeichert (ar_dqbyteaddr/ar_dibteaddr)

FOR #i := 0 TO #ui_maxnumofstations DO

//HW-ID einlesen
FOR #j := 1 TO 2 DO
#geoAddr.STATION := #i;
#geoAddr.SLOT := #j;
#i_retval := GEO2LOG(GEOADDR := #geoAddr, LADDR => #var_hw_any);
#wo_retval := INT_TO_WORD(IN := #i_retval);
#ar_HWID[#j] := #var_hw_any;
END_FOR;

// DQ/DI Einlesen
FOR #j := 1 TO 2 DO
#i_retval := RD_ADDR(LADDR := #ar_HWID[#j],
PIADDR => #ar_dibyteaddr[#i],
PICount => #ar_PICOUNT[#i],
PQADDR => #ar_dqbyteaddr[#i],
PQCount => #ar_PQCOUNT[#i]);
#wo_retval := INT_TO_WORD(IN := #i_retval);
//Schreiben von DI und Anzahl Bytes von Modul in Global DB
IF #ar_dibyteaddr[#i] <> 0 THEN
"Global".ar_dibyteaddr[#i] := #ar_dibyteaddr[#i];
END_IF;

IF #ar_PICOUNT[#i] <> 0 THEN
"Global".ar_di_amountofbytes[#i] := #ar_PICOUNT[#i];
END_IF;

//Schreiben von DQ und Anzahl Bytes von Modul in Global DB
IF #ar_dqbyteaddr[#i] <> 0 THEN
"Global".ar_dqbyteaddr[#i] := #ar_dqbyteaddr[#i];
END_IF;

IF #ar_PQCOUNT[#i] <> 0 THEN
"Global".ar_dq_amountofbytes[#i] := #ar_PQCOUNT[#i];
END_IF;

END_FOR;

END_FOR;

END_REGION


REGION Anzahl an vorhandenen Stationen festlegen und in Array Zwischenlücken entfernen
//Zweite Bedingung bei IF abfrage um bspw. Koppler herauszunehmen (Bei Koppler: Anzahl DQ Bytes=2, Anzahl DI Bytes=1)
#j := 0;
FOR #i := 0 TO #ui_maxnumofstations DO
IF "Global".ar_dibyteaddr[#i] <> 0 AND "Global".ar_dqbyteaddr[#i] <> 0
AND "Global".ar_di_amountofbytes[#i]="Global".ar_dq_amountofbytes[#i] THEN
"Global".ui_numofstations := "Global".ui_numofstations+1;
"Global".ar_dibyteaddr[#j] := "Global".ar_dibyteaddr[#i];
"Global".ar_dibyteaddr[#i] := 0;
"Global".ar_dqbyteaddr[#j] := "Global".ar_dqbyteaddr[#i];
"Global".ar_dqbyteaddr[#i] := 0;
#j += 1;
END_IF;
END_FOR;
END_REGION


//Dieser Code steht in anderem Baustein, aber greift eben auf die oben erstellten Arrays zu.
//Bei Verwendung von Poke ist Byte um eine Stelle versetzt, daher bei byteOffset -1
//numofdq8 entspricht hier der Anzahl an modulen
FOR #i := UDINT_TO_INT(IN := (#ar_dq8byteaddr[#ui_numofdq8-1])) TO UDINT_TO_INT(IN := #ar_dq8byteaddr[0]) DO
POKE(area := 16#82,
dbNumber := 0,
byteOffset := #i - 1,
value := #wo_graydq8 );
END_FOR;




Da stellt sich mir noch die Frage ob es möglich ist statt die Zahl der Bytes auch die Anzahl der Bits von Modulen zu unterscheiden... Wobei dieses Problem schon anderweitig, allerdings etwas aufwendiger gelöst wurde.

Danke für eure Zeit.
Falls ihr sagt nein danke das ist mir zu viel, ist mir eine die Idee gekommen, wie ich die Byteadressen im Array sortieren kann.

Grüße
Sebastian
 
Zuletzt bearbeitet:
Hallo,

ich denke Heinlein lag richtig.

Ich würde mal hier:
Code:
POKE(area := 16#82,
  dbNumber := 0,
  byteOffset := #i - 1,
  value := #wo_graydq8 );

an Stelle des wo_graydq8 würde ich eiine Sint Variable verwenden, dann kannst du vermutlich auch das -1 beim byteoffset weglassen
 
Aus Neugier: Was machst Du damit ?
Ich habe inzwischen schon ein paar komische Dinge mit TIA gemacht (das Lachen ist mir dabei aber auch vergangen) , aber PEEK/POKE hatte ich nur nach migrieren und habe es dann geändert/rausgeschmissen.
+1
PEEK und POKE habe ich auch nur in alte migrierte STEP7 Classic code den ich mir nicht bemüht habe aufzuräumen. Neue Code in TIA mit PEEK/POKE finde ich kritisabel.

Hintergrund ist, dass dem Anwender die Eingabe von Ein- und Ausgabeadresse sowie eingabe der Stationsnummer erspart bleiben soll. Das erspart bei der Projektierung einiges an Zeit.
Und in Anwenderprogramm wie verküpfst du die Code mit die E/A Adressen ? Das ganze hört sich an als ein Art Absolutadressierung. Die Zeit-ersparniss ist nichts wert gegenüber die Wartungsfreundlichkeit von die Code.
 
Die Zeit-ersparniss ist nichts wert gegenüber die Wartungsfreundlichkeit von die Code.
Genau.

Ich weiß auch nicht, wieso neue Programmierer immer denken, ihre paar eingespaarten Arbeitsstunden wären so furchtbar wertvoll...
Da werden einmalig ein paar Stunden gespart, vielleicht auch nicht, und später wird wieder und wieder stundenlang versucht den Code nachzuvollziehen ...
Oder man braucht immer wieder mal Stunden, um eine Problemursache zu finden, während die Produktion steht und vielleicht das Produkt verdirbt, wo eine Stillstandsstunde einige 10.000 EUR kostet.

Und der erzeugte Code braucht dann auch für immer 3 bis 10 mal so lange wie direkter linearer Code, d.h. die Performance leidet auch total - der Kunde soll dann eine 10x so schnelle CPU bezahlen als eigentlich nötig.

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Und der erzeugte Code braucht dann auch für immer 3 bis 10 mal so lange wie direkter linearer Code, d.h. die Performance leidet auch total - der Kunde soll dann eine 10x so schnelle CPU bezahlen als eigentlich nötig.

Ich find da ist eigentlich immernoch Siemens in der Pflicht. Jetzt haben sie überall Symbolik eingeführt, aber wir müssen uns immernoch um Absolutadressen in der Peripherie kümmern.
Wieso kann ich im Programm nicht schreiben
Code:
      "FC_OverVoltageProtection"(Suppressed := #suppressed,                               Overvoltage := [COLOR=#ff0000]RIO-Q47002-BAS~451A2[0], // Direkt das Symbol des RIO und der entsprechenden Karte gefolgt vom Datenpunkt.[/COLOR]
                               Typ => "HW_AS"."04 UV QAK 47.002 Überspannungsableiter Normalnetz");

statt das ich erstmal alles in der Symboltabelle nochmal deklarieren muss und mit UDTs überlagern muss.

Code:
      "FC_OverVoltageProtection"(Suppressed := #suppressed,                               Overvoltage := [COLOR=#ff0000]"Q47002-BAS-451A2".DI[0],[/COLOR]
                               Typ => "HW_AS"."04 UV QAK 47.002 Überspannungsableiter Normalnetz");

Eigentlich sollten die Peripherieadressen obsolet sein, und man sollte einfach und effizient über die Symbole die Koordinaten angeben können.
 
Zurück
Oben