TIA gebündelte und automatisierte Flankenauswertung in einem global DB

StefanTSM

Member
Beiträge
9
Punkte Reaktionen
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo liebe SPS ler,

In meinen alten SIEMENS Step7 Classic Projekten haben ich mithilfe eines FCs von einem Doppelwort gleichzeitig durch Invertierung INVD und Bitvergleich UD 32 positive und negative Flanken erzeugt. Das war sehr nützlich, da man im Vergleich zum bit-Befehl PF und NF deutlich Zykluszeit spart und automatisch von allen Boolschen Prozessvariablen die pos u neg Flanken zur Vefügung hat. Die globalen DBs waren in Classic fest absolut adressiert und aufgebaut.
In dem globalen DB gab es 4 structs: X (Bool) , FP_X, FN_X und HM_X (Flanken-Hilfsmerker). Die Variablen i d 4 Structs waren identisch und jedes struct 20 Byte lang.

1667890680173.png


Der o.g. FC hat über seine Bausteinschnittstelle den global DB und die als INT jeweils die Adresse des Doppelwortes im DB abgefragt (zB 4, 24, 44 und 64), worin die 32 Bits standen von denen die Flankenauswertung gemacht werden sollte:

so sah der alte STEP7 FC aus:
//--------------------------------------------------
AUF #DBe_Datenbaustein
//--------------------------------------------------
// Adresse, wo die Flanken gebildet werden sollen
L #Ie_STATUS_Adr
SLW 3
LAR1

// Hilfsmerkeradresse
L #Ie_HM_Adr
SLW 3
LAR2
//--------------------------------------------------
// Bilden der positiven Flanke
L DBD [AR1,P#0.0]
L DBD [AR2,P#0.0]
INVD
UD
T #DWt_FP_Status_Val

// Bilden der negativen Flanke
L DBD [AR2,P#0.0]
L DBD [AR1,P#0.0]
INVD
UD
T #DWt_FN_Status_Val

// aktuellen Status in Hilfsmerker schreiben
L DBD [AR1,P#0.0]
T DBD [AR2,P#0.0]

// schreiben der pos. Flanke in entsprechende Pos in DB
L #Ie_FP_Adr
SLW 3
LAR1
L #DWt_FP_Status_Val
T DBD [AR1,P#0.0]

//schreiben der neg. Flanke in entsprechende Pos in DB
L #Ie_FN_Adr
SLW 3
LAR1
L #DWt_FN_Status_Val
T DBD [AR1,P#0.0]
//--------------------------------------------------

Das Ganze hat uns 2 Jahrzehnte lang wunderbar die Arbeit beim Flankenauswerten erleichtert.
Dann kam TIA mit der dynamischen und symbolischen Adressverwaltung, was ja auch gut ist.

Ich habe es dann mal probiert den FC mit der Bausteinschnittstelle DB_ANY zu erstellen.
In meiner Not habe ich dafür den optimierten Bausteinzugriff abgeschaltet.

1667890340029.png
Da hat der Compiler aber brav gemeckert, da fehlt mir wohl noch die TIA Übung.

Nun meine Frage(n):

1) Wie kann ich das jeweilige Doppelwort im global DB (ohne opt. Speicherzugriff) verpointert übergeben ?

2) Wie kann ich das Problem mit optimierten Bausteinzugriff lösen?
Symbolisch ist schwierig, da ich 32 Boolsche Variablen in meinen Structs habe und anschließend diese 32 Bits als DWORD mit INVD und UD behandeln möchte.
Müsste ich dafür dann von jedem 32 Bit Paket zuerst ein UDT -Paket schnüren?

Ich hoffe, mein Anfrage ist halbwegs nachvollziehbar und Danke schon mal und VGe

Stefan
 

hucki

User des Jahres 2014
Beiträge
6.059
Punkte Reaktionen
1.930
2) Wie kann ich das Problem mit optimierten Bausteinzugriff lösen?
Symbolisch ist schwierig, da ich 32 Boolsche Variablen in meinen Structs habe und anschließend diese 32 Bits als DWORD mit INVD und UD behandeln möchte.
Müsste ich dafür dann von jedem 32 Bit Paket zuerst ein UDT -Paket schnüren?
Ich übergebe die optimierte Struktur direkt ohne irgendwelche Zeiger.

In einem optimierten FB erstelle ich darauf mit AT eine Sicht (Remanenz "Im IDB setzen" als (D)WORD und kann dann damit arbeiten.
In einem FC (da gibt's ja keinen IDB) übertrage ich die Struktur per Serialize und Deserialize in die Temp-Struktur zum Arbeiten und muss sie am Ende dann halt wieder zurück übertragen.
 

circlehook

Well-known member
Beiträge
45
Punkte Reaktionen
9
Zuviel Werbung?
-> Hier kostenlos registrieren
Wäre es eine Möglichkeit, gleiche UDT's für alle deine Structs zu benutzen?
In TIA ist es möglich, die Variablenkommentare unabhängig vom UDT zu definieren.
Dann ist zwar der eigentliche Variablenname nicht mehr aussagekräftig, jedoch kann die Verwendung der Variable dann über den Kommentar identifiziert werden.

Somit könnten deine FC's alle den gleichen UDT als IN/OUT nutzen.
Intern dann wie bereits erwähnt mit Serialize/Deserialize arbeiten.

Was spricht eigentlich gegen die Verwendung von FB's mit internem Speicher für Flankenauswertungen?
 

Heinileini

Well-known member
Beiträge
5.733
Punkte Reaktionen
1.333
Das Ganze hat uns 2 Jahrzehnte lang wunderbar die Arbeit beim Flankenauswerten erleichtert.
Ich verstehe den Aufwand nicht so ganz. Die Pointerei ist doch hoffentlich nicht unverzichtbar?
Die u.g. Variablen dürfen gerne Elemente eines Structs sein oder Elemente eines (oder mehrerer) Arrays bzw. Arrays of struct sein, wenn mehrere DDs in einer Schleife abzuarbeiten sind.
Wie die "eigentlichen" BOOLs in die DatenDoppelworte DD_actual bzw. aus den DatenDoppelworten DD_posEdges bzw. DD_negEdges (und ggfs DD_allEdges) in die "eigentlichen " BOOLs gelangen, habe ich aussen vor gelassen.

PseudoCode, völlig ungetestet:
Code:
L    DD_actual
L    DD_previous  // statisch !
XOD
T    DD_allEdges  // darf Temp sein, falls extern nicht benötigt
TAK
T    DD_previous  // statisch !
UD
T    DD_posEdges
INVD
L    DD_allEdges  // darf Temp sein, falls extern nicht benötigt
UD
T    DD_negEdges
 
Zuletzt bearbeitet:

Onkel Dagobert

Well-known member
Beiträge
5.484
Punkte Reaktionen
1.223
Vielleicht ist es eine Option, die vier DINT jeweils in ein ARRAY zu verpacken, und in SCL in einer Schleife zu verarbeiten? Das wäre dann unabhängig von optimiert/nichtoptimiert und auch abseits von ANY und AWL.
 

Heinileini

Well-known member
Beiträge
5.733
Punkte Reaktionen
1.333
Zuviel Werbung?
-> Hier kostenlos registrieren
Vielleicht ist es eine Option, die vier DINT jeweils in ein ARRAY zu verpacken, und in SCL in einer Schleife zu verarbeiten? Das wäre dann unabhängig von optimiert/nichtoptimiert und auch abseits von ANY und AWL.
Jaaa! Ich habe mich nur nicht getraut, es sooo direkt zu sagen. ;)
Geeignter als 4 DINT fänd ich allerdings 4 DWORD.
Wir wissen eigentlich gar nicht, ob es um nur 4 DWORDs geht.
Wenn die "anderen" 3 lediglich diejenigen für die 2 Ergebnisse (negFlanken + posFlanken) sowie die "FlankenMerker" sind, dann fänd ich ein entsprechendes Struct hilfreicher und erst, wenn mehr als 32 BOOLs auf Flanken getestet werden sollen, käme dann ein Array of struct in Frage.

Code:
FOR ix := ? TO ?? DO
   array[ix].posEdges := array[ix].actual   AND NOT array[ix].previous ;
   array[ix].negEdges := array[ix].previous AND NOT array[ix].actual ;
   array[ix].previous := array[ix].actual ;
END_FOR ;
 
Zuletzt bearbeitet:
OP
S

StefanTSM

Member
Beiträge
9
Punkte Reaktionen
0
Hallo liebe Antworter,

das ist mehr feedback als erwartet, Danke!
Jetzt gehen die Antworten alle ein bisschen in verschiedene Richtungen.
Dazu 2 (philosphische) Kommentare:
1) die einfachste Lösung ist oftmals die Beste, aber
2) ein kompliziertes Problem lässt sich eben nicht beliebig vereinfachen.

Meine kurze Stellungnahme, sofern ich es korrekt verstanden habe:
Hucki, Deine Lösung sieht vielversprechend aus, muss ich ausprobieren.
Heinileini, Schleife aus Kommentar2 kostet zu viel Zykluszeit, weil die Flankenauswertung Bit für Bit erfolgt.
Kommentar1 funktioniert zwar, aber wie die Bits in die DWORD gelangen etc. war ja gerade meine Frage.
Die insgesamt 5 DWORD (oder DINT) = 20 Byte sollen nur bei Bedarf flankenausgwertet werden.
circlehook, UDTs sind gut, aber, wenn sich diese beim Programmieren der Anlage ständig ändern, dann hat man mehr Stress als Gewinn: neu initialisieren, übersetzen etc. Ihr kennt das. Und das mit dem FB internen Speicher ist bei 5000 Bits mit Flanken in 100 DBs etc. nicht mehr handhabbar. In großen Anlagen haben wir ca 5000 Flanken in verschiedenen DBs verwendet.

Zur Veranschaulichung, hier noch mal der Aufruf des alten Flankenauswerter-FCs
1668113123759.png
Der FC schnappt sich das DWORD DBD4 im DB und schreibt von allen 32 Bits die pos Flanken in DBD24 und die neg. in DBD44, DBD64 ist der Hilfsmerker / previous.
Jetzt habe ich die Wahl den FC gezielt nur dort aufzurufen, wo auch 32 Boolesche Variablen (oder weniger) in einem DWORD stehen.

In TIA mit der dynamischen Adressierung habe ich das so leider nicht hinbekommen.

Danke u Grüße

S.
 

Heinileini

Well-known member
Beiträge
5.733
Punkte Reaktionen
1.333
Heinileini, Schleife aus Kommentar2 kostet zu viel Zykluszeit, weil die Flankenauswertung Bit für Bit erfolgt.
Wie kommst Du darauf? Von "Bit für Bit" war nicht die Rede, sondern ...
Symbolisch ist schwierig, da ich 32 Boolsche Variablen in meinen Structs habe und anschließend diese 32 Bits als DWORD mit INVD und UD behandeln möchte.
Was packst Du denn bisher für Bits in Deine DWORDs? Evtl. viel zu viele, nur weil dann das Umschaufeln einfacher geht? Von wie vielen Bits willst Du wirklich die Flanken erkennen?
Kommentar1 funktioniert zwar, aber wie die Bits in die DWORD gelangen etc. war ja gerade meine Frage.
Das hat Dir hucki in #2 beantwortet:
serialize, um bis zu 32 BOOLs in ein DWORD zu packen
bzw. deserialize, um bis zu 32 BOOLs aus einem DWORD zu extrahieren.
Die insgesamt 5 DWORD (oder DINT) = 20 Byte sollen nur bei Bedarf flankenausgwertet werden.
Vergiss nach Möglichkeit "oder DINT".
Ich komme nur auf 4 DWORDs:
1. das DWORD, in das Du bis zu 32 BOOLs gepackt hast,
2. das DWORD, das Du als "FlankenMerker" benötigst.
3. das DWORD, in dem Du die positiven Flanken ablegst und
4. das DWORD, in dem Du die negativen Flanken ablegst.
Nur bei Bedarf willst Du die detektierten Flanken abfragen, nehme ich an. Aber der FC müsste dennoch zyklisch aufgerufen werden und jedes Mal die mindestens 157 SchleifenDurchläufe ausführen (für 5000 BOOLs benötigst Du 157 32-Bit-Pakete).
UDTs sind gut, aber, wenn sich diese beim Programmieren der Anlage ständig ändern, dann hat man mehr Stress als Gewinn: neu initialisieren, übersetzen etc. Ihr kennt das. Und das mit dem FB internen Speicher ist bei 5000 Bits mit Flanken in 100 DBs etc. nicht mehr handhabbar. In großen Anlagen haben wir ca 5000 Flanken in verschiedenen DBs verwendet.
Die UDTs geben doch für mein Verständnis "nur" die Struktur an. Warum müssen sie sich ständig ändern?
Die Zuweisung der einzelnen BOOLs zu den DWORDs würde ich nicht in dem FC realisieren. Der soll nur die aufbereiteten DWORDs nehmen und auf Flanken untersuchen. Das Extrahieren der BOOLs aus den Ergebnis-DWORDs hast Du ja auch nicht als Aufgabe des FC eingeplant?
Nun meine Frage(n):

1) Wie kann ich das jeweilige Doppelwort im global DB (ohne opt. Speicherzugriff) verpointert übergeben ?
Verpointert am besten gar nicht.
2) Wie kann ich das Problem mit optimierten Bausteinzugriff lösen?
Auch hier auf die "Pointerei" verzichten.
Müsste ich dafür dann von jedem 32 Bit Paket zuerst ein UDT -Paket schnüren?
Die genaue Vorgehensweise kann Dir hucki oder sonst wer sicherlich besser eklären.
Ich kann nur sagen: "im Prinzip ja". Du musst etwas ausserhalb des FC tun, das Dir die 32 BOOLs fertig in ein DWORD packt, ehe Du den FC diese Information in den DWORDs abarbeiten lässt.
5000 einzelne BOOLs in 157 DWORDs packen und 10000 Bits an Ergebnissen wieder aus 314 DWORDs in BOOLs umsetzen, ist schon ein ziemlicher Aufwand, zumal die Zuordnung der BOOLs zu den Bits der DWORDs wahrscheinlich recht "unübersichtlich" sein dürfte.
Könnte mir vorstellen, dass hier häufiger mal geändert wird.
 
Zuletzt bearbeitet:
OP
S

StefanTSM

Member
Beiträge
9
Punkte Reaktionen
0
Danke !
Wie kommst Du darauf? Von "Bit für Bit" war nicht die Rede, sondern ...
wenn ich das richtig sehe, wertet die Schleife bitweise aus u wird bei 5 DWORD 160 mal durchlaufen, aber das könnte man auch mit DWORD machen, dann wären es 5 Befehle für 5x32 Bits.
Vergiss nach Möglichkeit "oder DINT".
Ich komme nur auf 4 DWORDs:
OK, ich lasse mal die DINT weg, das ist m M n auch egal, es geht ja nur um einen Platzhalter für 4 Byte, in TIA mit den neuen Datentypen könnte man jetzt sogar ein LWORD mit 64 Bit verwenden, falls die Befehle INVD etc. für LONG existieren, muss ich schauen.
In einem DB habe ich früher immer ein Struct mit 160 Bits (= 5 DWORD) als Status angelegt und X genannt.
Das ganze kopiert und als PF_X und noch mal als NF_X Struct hintendran, + 5 DWORD als Hilfsmerker
Von diesen 5 DWORD sollen jetzt die PF und NF ausgewertet werden.
In dem DB sind insgesamt dann 80 Byte Daten.
Die UDTs geben doch für mein Verständnis "nur" die Struktur an. Warum müssen sie sich ständig ändern?
Die Zuweisung der einzelnen BOOLs zu den DWORDs würde ich nicht in dem FC realisieren. Der soll nur die aufbereiteten DWORDs nehmen und auf Flanken untersuchen. Das Extrahieren der BOOLs aus den Ergebnis-DWORDs hast Du ja auch nicht als Aufgabe des FC eingeplant?
Wenn das UDT nur die 5 DWORD als Platzhalter enthält, ändert es sich natürlich nicht, aber meine 160 Bits ändern sich in der Programmierphase der Anlage immer mal wieder.
Nach aktuellem Stand, dann hätten wir eine Aufgabenteilung:
1) Bits in DWORD umpacken, müsste mit serialize deserialize gehen.
2) DWORD weise Flanken auswerten.
Aber 2 FCs dafür zu verwenden oder Schritt1 außerhalb zu machen, wäre umständlich.

Ich probiers mal ...

Viele Grüße
 

PN/DP

User des Jahres 2011-2013; 2015-2017; 2020-2022
Power-User
Beiträge
19.632
Punkte Reaktionen
5.917
Problem des Fragestellers ist, daß die Bits in den DB als BOOL deklariert sind und er will aber immer 32 BOOL auf einmal als DWORD verarbeiten (weil man vor Jahrzehnten so "deutlich Zykluszeit sparen" konnte, und nicht soviel Code eintippen muß ;) ), d.h. die Bits sollen anders adressiert werden als deklariert, was aber bei "optimiertem" Speicher gar nicht geht (jaja, "... im IDB setzen") und bei DB mit Standard-Zugriff weiß er nicht wie man DB[i].DBD[j] adressiert.

Zum indirekten Lesen/Schreiben von Speicheradressen gibt es die Anweisungen PEEK/POKE

Aber ob umständlicher Code mit PEEK/POKE oder Serialize/Deserialize oder unsichtbares aufwendiges Umkopieren bei der Bausteinparameter-Versorgung immer noch schneller als eine Schleife mit sauberen BOOL-Verknüpfungen ist? :unsure: (Wobei die BOOLs in den DB da als ARRAY deklariert sein müssten (was vermutlich nicht gewollt ist) oder ebenfalls vorher/nachher umkopiert werden müssten). Die Ausführungszeiten der Varianten müsste man mal an aktuellen CPU S7-1x00 messen.

Harald
 
OP
S

StefanTSM

Member
Beiträge
9
Punkte Reaktionen
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Die Ausführungszeiten der Varianten müsste man mal an aktuellen CPU S7-1x00 messen.

Harald Danke für Deine Antwort (insbesondere für die neu formulierte Zusammenfassung der Frage) !

Richtig ist, neue SPSen sind wesentlich leistungsfähiger als alte (wir hatten nur 416er und 417er im Einsatz).
Dafür werden neue Anlagen komplexer und die Datenhaltung umfangreicher.
Das kompensiert sich ein Stück weit. Wie Du sagst, man müsste die Laufzeiten i d Schleife mal ausprobieren.
Du hast Recht: im DB ist UDT und Array ungewollt, weil es eine zusätzliche Zwischenschicht, die NUR für das Handling in TIA benötigt wird.

Im Grunde ist die Aufgabenstellung aber doch simpel:
Fische 5 DWORD aus einem DB, bilde doppelwortweise jeweils 160 pos und neg Flanken und schreibe diese an eine andere parametrierbare Adresse i d selben DB. Das ganze sollte in einem FC von statten gehen, damit mir die Verwaltung von IDBs erspart bleibt. Das ganze am liebsten speicheroptimiert. (aber, vlt ist das von mir der unerfüllbare "wasch mir den Pelz, aber mach mich nicht nass" Wunsch)
Die IDB Verwaltung ist kein Problem, kann man alles machen, aber wenn man bei der Inbetriebnahme zur Laufzeit an der Anlage "schraubt" sind Initialisierungen etc. immer lästig (gewesen). Vielleicht fehlt mir aber auch nur die Eingebung / Programmierexpertise.

Daher super, dass es dieses Forum gibt !

Gruß i d Runde ...
 

PN/DP

User des Jahres 2011-2013; 2015-2017; 2020-2022
Power-User
Beiträge
19.632
Punkte Reaktionen
5.917
In meinen alten SIEMENS Step7 Classic Projekten haben ich mithilfe eines FCs von einem Doppelwort gleichzeitig durch Invertierung INVD und Bitvergleich UD 32 positive und negative Flanken erzeugt. Das war sehr nützlich, da man im Vergleich zum bit-Befehl PF und NF deutlich Zykluszeit spart und automatisch von allen Boolschen Prozessvariablen die pos u neg Flanken zur Vefügung hat.
UD ist kein Bitvergleich sondern eine DWORD-UND-Verknüpfung. Die Flankenbefehle heißen nicht PF und NF sondern FP und FN. Eine Ansammlung von 32 unabhängigen Bits hat nicht den Datentyp DInt sondern DWORD ... Die Struktur ist sehr ungünstig, weil wenn eine Baugruppe/ein DWORD hinzukommt, dann verschieben sich die Adressen im DB und dann müssen alle Aufrufparameter händisch angepasst werden.

Die globalen DBs waren in Classic fest absolut adressiert und aufgebaut.
In dem globalen DB gab es 4 structs (...)
Wie waren denn im STEP7 classic Projekt die Structs deklariert?

Wenn Du gern mit Variablen ohne "sprechendes" Symbol programmierst, dann könntest Du die 32-Bit-Sammlungen in den Structs auch als DWORD deklarieren und im Programm auf die Bits per SLICE zugreifen. Dann könntest Du die DWORDs leicht an den Flanken-FC übergeben und es ginge auch mit "optimierten" DB. Und es ginge auch ganz ohne indirekte Adressierung (besser für die Querverweise).

Beispiel: "GDB_Bedienpult".X.DI_04.%X25 adressiert "GDB_Bedienpult".DBX4.1

Schön ist aber anders...

Wenn Du doch besser die Bits in den Structs im Programm symbolisch ansprechen willst, dann könntest Du einmalig nach der DWORD-Verarbeitung die DWORDs auf einen zweiten Struct umkopieren, wo die Bits als BOOL deklariert sind (z.B. mit SCATTER), und im folgenden Programm auf diese Bit-Kopien symbolisch zugreifen.

Code:
FUNCTION "FC_Flankenauswertung_SCL" : Void
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
//Flankenauswertung DWORD
   VAR_INPUT
      Status : DWord;
   END_VAR
   VAR_OUTPUT
      FP : DWord;
      FN : DWord;
   END_VAR
   VAR_IN_OUT
      HM : DWord;
   END_VAR

BEGIN
  #FP := #Status AND NOT #HM;
  #FN := NOT #Status AND #HM;
  #HM := #Status;
END_FUNCTION
Aufruf
Code:
//Flankenauswertung DWORDs
"FC_Flankenauswertung_SCL"(Status:="DB_EA".X.DI_04,
                           FP=>"DB_EA".PF_X.DI_04,
                           FN=>"DB_EA".NF_X.DI_04,
                           HM:="DB_EA".HM_X.DI_04);

//DWORDs umkopieren auf BOOL-Structs
SCATTER(IN := "DB_EA".X.DI_04, OUT => "DB_EA".X2.DI_04);
SCATTER(IN := "DB_EA".PF_X.DI_04, OUT => "DB_EA".PF_X2.DI_04);
SCATTER(IN := "DB_EA".NF_X.DI_04, OUT => "DB_EA".NF_X2.DI_04);

//symbolische Verwendung der BOOL-Bits
#xTemp := "DB_EA".X2.DI_04.Bit00 AND "DB_EA".PF_X2.DI_04.Bit01;

PS: und noch der Aufbau des DB für das Beispiel
Code:
DATA_BLOCK "DB_EA"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
   VAR
      X : Struct
         DI_04 : DWord;
         DI_08 : DWord;
      END_STRUCT;
      PF_X : Struct
         DI_04 : DWord;
         DI_08 : DWord;
      END_STRUCT;
      NF_X : Struct
         DI_04 : DWord;
         DI_08 : DWord;
      END_STRUCT;
      HM_X : Struct
         DI_04 : DWord;
         DI_08 : DWord;
      END_STRUCT;
      X2 : Struct
         DI_04 : Struct // 32 BOOLs
            Bit24 : Bool;
            Bit25 : Bool;
            ...
            Bit06 : Bool;
            Bit07 : Bool;
         END_STRUCT;
      END_STRUCT;
      PF_X2 : Struct
         DI_04 : Struct // 32 BOOLs
            Bit24 : Bool;
            Bit25 : Bool;
            ...
            Bit06 : Bool;
            Bit07 : Bool;
      END_STRUCT;
      NF_X2 : Struct
         DI_04 : Struct // 32 BOOLs
            Bit24 : Bool;
            Bit25 : Bool;
            ...
            Bit06 : Bool;
            Bit07 : Bool;
      END_STRUCT;
   END_VAR

END_DATA_BLOCK

Harald
 
Zuletzt bearbeitet:

Heinileini

Well-known member
Beiträge
5.733
Punkte Reaktionen
1.333
Im Grunde ist die Aufgabenstellung aber doch simpel:
Fische 5 DWORD aus einem DB, bilde doppelwortweise jeweils 160 pos und neg Flanken und schreibe diese an eine andere parametrierbare Adresse i d selben DB.
Genauso hatte ich Deine Aufgabenstellung ursprünglich verstanden.
Woran ich aber rütteln wolte, war "fische x DWORD aus einem DB ... und schreibe diese an eine andere parametrierbare Adresse in denselben DB".
Warum "fischen" und an "parametrierbarer" Adresse ablegen? Warum nicht in demselben DB ein Array of struct anlegen und damit festlegen, wo die Informationen abgelegt werden?
Warum muss die jeweilige Gruppe von 32 Bit "fischbar" sein und warum die Adressen "parametrierbar".
Sind angeflanschte Bereiche in demselben DB für spätere Erweiterungen vorzusehen, die nicht an einer von vorn herein zugeordneten Stelle liegen dürfen?
Über den Index des Array dann diejenige Gruppe von 32 Bit ansprechen und über die Elemente des Structs adressieren, welchen der DWORDs man gerade ansprechen will, ob EingangsSignale oder "FlankenMerker" oder ErgebnisDWORD der pos. Flanken oder ErbgenisDWORD der neg. Flanken.
 

JesperMP

Well-known member
Beiträge
7.650
Punkte Reaktionen
1.631
Zuviel Werbung?
-> Hier kostenlos registrieren
Dei eigentliche Frage sollte sein, gibt es ein Grund dafür ausser die Zykluzeitersparniss (welches in STEP7 Klassik eine grössere Thema war) dass die besagte Bits in ein globalen DB verlagert werden müssen ?
Heute habe ich nur solchen Bedarf für die HMI Bit-Meldungen und die dafür relevante HMI Quittier Bits.
Alles anders wird intern in die FCs oder FBs programmiert und dies als einzelne Flankenauswertungen pro Bit.
 

Heinileini

Well-known member
Beiträge
5.733
Punkte Reaktionen
1.333
Dei eigentliche Frage sollte sein, gibt es ein Grund dafür ... dass die besagte Bits in ein globalen DB verlagert werden müssen ?
Das ist die Frage, die ich mir und in ...
Was packst Du denn bisher für Bits in Deine DWORDs? Evtl. viel zu viele, nur weil dann das Umschaufeln einfacher geht? Von wie vielen Bits willst Du wirklich die Flanken erkennen?
... gestellt hatte, bestärkt duch die Bemerkung ...
Die insgesamt 5 DWORD (oder DINT) = 20 Byte sollen nur bei Bedarf flankenausgwertet werden.
Ich hatte schon den Verdacht, dass eine gewisse "SammelLeidenschaft" dahintersteckt, den einst eingeschlagenen Weg weiterverfolgen zu wollen.
 
OP
S

StefanTSM

Member
Beiträge
9
Punkte Reaktionen
0
Danke für Eure Beiträge,

ich bin jederzeit bereit, neue (Programmier)wege einzuschlagen.
Allerdings sind 15 Jahre Programmfundus technologisch allein durch den Umstieg von Classic auf TIA nicht auf einen Schlag in Sachen Funktionsumfang veraltet.

Zur Erklärung, warum der globale DB und auf keinen Fall lokal ...

Wenn ich eine Kleinanlage aus der Serienproduktion nehme (zB mit 100 EAs), dann ist idR der komplette Datenumfang vorab genau definiert und ich kann Flanken lokal bilden etc. Dafür kann ich UDTs etc. anlegen, es ändert sich meist nichts mehr oder nur sehr wenig.

Wenn ich allerdings eine Sondermaschine (Loszahl 1) mit 3000 EAs programmiere und bei der Inbetriebnahme das Programm weiter entwickelt wird, ist jede Programmierung einer zusätzlichen Flankenauswertung (insbesondere lokal ... stat Variable anlegen... IDB neu generieren usw.) sehr lästig, wenn man einfach unmittelbar (innerhalb von Sekunden) den FC oder FB downloaden und testen möchte.
Daher werden alle boolschen Prozessvariablen zu einem bestimmten Anlagenteil in einem globalen DB mit 160 Bit (5 DWORD) gespeichert.
Vielleicht sind aber in diesem bestimmten Anlagenteil auch nur 40 Bit davon in Verwendung, in welchem Fall nur 2 DWORDs auf Flanken ausgewertet werden müssen. Die anderen 3 sind dann einfach leer.

Aber nochmal, wenn es eine TIA gerechte Alternative gibt, diese Flexibilität der schnellen Testmöglichkeiten umzusetzen, dann schmeiße ich das alte Konzept gerne i d Tonne.

Das eine sind akademisch aufbereitete Algorithmen, programmtechnisch sauber und elegant, unter Laborbedingungen angepasst und optimiert.
Das andere ist eine jahrzehntelange Inbetriebnahmepraxis von Großanlagen, wo jede Minute Inbetriebnahmezeit effektiv genutzt werden muss.

Grüße
 
OP
S

StefanTSM

Member
Beiträge
9
Punkte Reaktionen
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Code:
//Flankenauswertung DWORDs
"FC_Flankenauswertung_SCL"(Status:="DB_EA".X.DI_04,
FP=>"DB_EA".PF_X.DI_04,
FN=>"DB_EA".NF_X.DI_04,
HM:="DB_EA".HM_X.DI_04);

//DWORDs umkopieren auf BOOL-Structs
SCATTER(IN := "DB_EA".X.DI_04, OUT => "DB_EA".X2.DI_04);
SCATTER(IN := "DB_EA".PF_X.DI_04, OUT => "DB_EA".PF_X2.DI_04);
SCATTER(IN := "DB_EA".NF_X.DI_04, OUT => "DB_EA".NF_X2.DI_04);

//symbolische Verwendung der BOOL-Bits
#xTemp := "DB_EA".X2.DI_04.Bit00 AND "DB_EA".PF_X2.DI_04.Bit01;

Danke PN/DP das probier ich mal aus ... aber DWORD weise ...
 

PN/DP

User des Jahres 2011-2013; 2015-2017; 2020-2022
Power-User
Beiträge
19.632
Punkte Reaktionen
5.917
Code:
//Flankenauswertung DWORDs
"FC_Flankenauswertung_SCL"(Status:="DB_EA".X.DI_04,
FP=>"DB_EA".PF_X.DI_04,
FN=>"DB_EA".NF_X.DI_04,
HM:="DB_EA".HM_X.DI_04);

//DWORDs umkopieren auf BOOL-Structs
SCATTER(IN := "DB_EA".X.DI_04, OUT => "DB_EA".X2.DI_04);
SCATTER(IN := "DB_EA".PF_X.DI_04, OUT => "DB_EA".PF_X2.DI_04);
SCATTER(IN := "DB_EA".NF_X.DI_04, OUT => "DB_EA".NF_X2.DI_04);

//symbolische Verwendung der BOOL-Bits
#xTemp := "DB_EA".X2.DI_04.Bit00 AND "DB_EA".PF_X2.DI_04.Bit01;

Danke PN/DP das probier ich mal aus ... aber DWORD weise ...
??
Das ist doch DWORD-weise. Für 1 Eingangs-DWORD und die Ergebnis- und Hilfs-DWORDs

Harald
 
Oben