TIA SCL Anfänger: Zeiger-Bewegung auswerten

Dende

Level-1
Beiträge
2
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo liebes Forum,
ich bin Student und sitze gerade an einem kleinen Projekt. Dabei hat sich mir ein Problem aufgetan.

Vorweg: Ich bin Anfänger in SCL und generell noch nicht sehr erfahren was Programmierung angeht. Ich arbeite mit TIA V17. Dies ist mein erstes Projekt welches ich in SCL lösen soll, vorher habe ich in TIA nur in FUP programmiert. Deshalb wurde mir aufgetragen, erstmal nur mit Schleifen zu programmieren, d.h. ich verwende für das Gesamt- und dieses Teilprogramm nur IF- und FOR-Schleifen.

Das Ziel des Teilprogrammes ist es, per Betätigung eines Tasters, x-Einträge (x = beliebige Zahl welche manuell eingegeben wird) von einem Array (Array_1) in das andere Array (Array_2) zu kopieren. Beide Arrays haben maximal 1000 Einträge.
Bsp.: Wenn ich die letzten 50 Einträge von Array_1 in Array_2 kopieren möchte, ich mich aber in Eintrag 10 von Array_1 befinde, soll er sobald er den Eintrag 0 kopiert hat, bei Eintrag 999 fortsetzen und noch bis Eintrag 960 kopieren.
Nun das eigentliche Problem: Wie finde ich die Differenz raus, damit das Programm weiß wie viele Einträge er, nach Eintrag 0 von Array_1, noch kopieren muss?
Meine Idee: Einen Zeiger anlegen, welcher sich beim kopieren in Array_1 mitbewegt, dessen Bewegung auswerten und daraus die Differenz bilden.

Ist meine Idee denn überhaupt so umsetzbar? Und wenn ja, wie lege ich einen Zeiger an und wie werte ich seine Bewegung aus? Ich habe bereits in diversen pdf´s und Foren geschaut, aber leider nix hilfreiches bzw. für mich umsetzbares gefunden.

Ich bin für jede Hilfe und neue Ideen dankbar,

MFG Dende
 
Was meinst du mit „im Array auf Platz 10“ befinde? Du meinst dein „Zeiger“ steht auf 10? Und wird nur durch kopieren verändert?

Ich denke was du als Zeiger bezeichnet ist einfach der Index des Arrays, das ist die Zahl/Variable in der eckigen Klammer.

Kopieren von gleichen Datentypen funktioniert mit einer einfachen Zuweisung.
Code:
Array_1[#Index_1].Inhalt := Array_2[#Index_2].Inhalt

In einer For-Schleife (Hilfe von TIA nutzen) lässt du die Laufvariable solange inkriminierten wie du Einträge kopieren möchtest. In der Schleife prüfst du mittels IF(das ist keine Schleife) ob der Index überläuft und korrigierst den Index entsprechend.

Den Index erhöhst/verringerst du bei jedem Schleifendurchlauf
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Zeiger brauchst Du dafür nicht. Du kannst direkt mit den Indizes rechnen, z.B. mit MOD. Stell Dir das Ziel-Array als Ringpuffer vor. Oder in der FOR-Schleife einfach mitzählen, wieviele Einträge kopiert wurden.

Welche CPU willst Du programmieren?

PS, der Klassiker: "Es gibt keine IF-Schleifen" ;)

Harald
 
Deshalb wurde mir aufgetragen, erstmal nur mit Schleifen zu programmieren, d.h. ich verwende für das Gesamt- und dieses Teilprogramm nur IF- und FOR-Schleifen.
Diesen Auftrag solltest Du ganz schnell in die Tonne treten bzw. nicht zu ernst nehmen.
Klar, man kann in SCL sehr bequem FOR-Schleifen oder WHILE-Schleifen programmieren. Aber man muss dabei im Hinterkopf immer den Einfluss auf die ZyklusZeit bzw. auf mögliche ZyklusZeitÜberschreitungen haben.
Schleifen, die nur dazu dienen auf einen bestimmten Zustand (z.B. 'Taste gedrückt' oder 'Lichtschranke unterbrochen') zu warten oder eine vorgegebene Zeit zu "verbraten", sind absolutes Tabu!
IF-Schleifen gibt es nicht! IF ist Bestandteil einer 'Selektion', also einer Auswahl aus zwei oder mehr verschiedenen Möglichkeiten.
IF kann allerdings benutzt werden, eine Schleife zu beenden bzw. "vorzeitig" abzubrechen.
Beide Arrays haben maximal 1000 Einträge.
Sehr gut, das passt gut zu SCL.

Zeiger brauchst Du dafür nicht. Du kannst direkt mit den Indizes rechnen, z.B. mit MOD. Stell Dir das Ziel-Array als Ringpuffer vor. Oder in der FOR-Schleife einfach mitzählen, wieviele Einträge kopiert wurden.
Jain, Harald. Du verstehst unter Zeiger das, was unter S7 als Zeiger bezeichnet wird.
In Hochsprachen wir der Begriff Zeiger oft als Synonym für einen ArrayIndex benutzt.

Bsp.: Wenn ich die letzten 50 Einträge von Array_1 in Array_2 kopieren möchte, ich mich aber in Eintrag 10 von Array_1 befinde, soll er sobald er den Eintrag 0 kopiert hat, bei Eintrag 999 fortsetzen und noch bis Eintrag 960 kopieren.
Das ist also schon der von Harald empfohlene "RingPuffer"!

Nun das eigentliche Problem: Wie finde ich die Differenz raus, damit das Programm weiß wie viele Einträge er, nach Eintrag 0 von Array_1, noch kopieren muss?
Meine Idee: Einen Zeiger anlegen, welcher sich beim kopieren in Array_1 mitbewegt, dessen Bewegung auswerten und daraus die Differenz bilden.
Ich kann Dir nicht so ganz folgen, worin das Problem besteht.
Zäumst Du das Pferd von hinten auf?
Bevor Dein Programm seine Arbeit aufnimmt und anfängt, x ArrayElemente aus Array A nach Array B zu kopieren, muss es doch schon "wissen" wieviele Elemente es kopieren soll, sonst kann es doch gar nicht erst sinnvoll mit seiner Arbeit beginnen, weil es doch zuviele Elemente kopieren könnte, wenn es blindlings damit anfangen würde?

Sag uns doch ganz einfach mal, welche Informationen vorliegen, aus denen Du die Anzahl ermitteln sollst.
Woher erfährst Du, ab welchem Index im QuellArray und zu welchem Index im ZielArray kopiert werden soll?
 
Zuletzt bearbeitet:
Vielen Dank für eure Antworten, ihr habt mir wirklich geholfen und einen guten Denkanstoß gegeben. (y)Es hapert bei mir wohl noch ein wenig am Verständnis, wie gewisse Sachen im Programm ablaufen.

Ich denke ich habe es jetzt geschafft, kann es allerdings erst morgen vor Ort probieren.
Ich würde, falls es jemanden interessiert, morgen nochmal schreiben ob es geklappt hat und ggf. ein Screenshot vom Teilprogramm teilen.

Ich denke was du als Zeiger bezeichnet ist einfach der Index des Arrays, das ist die Zahl/Variable in der eckigen Klammer.
Genau das war mein Problem, dadurch hatte ich komplett falsch gedacht.

In einer For-Schleife (Hilfe von TIA nutzen) lässt du die Laufvariable solange inkriminierten wie du Einträge kopieren möchtest. In der Schleife prüfst du mittels IF(das ist keine Schleife) ob der Index überläuft und korrigierst den Index entsprechend.

Den Index erhöhst/verringerst du bei jedem Schleifendurchlauf
Oder in der FOR-Schleife einfach mitzählen, wieviele Einträge kopiert wurden.
So habe ich es jetzt auch umgesetzt

Welche CPU willst Du programmieren?
CPU 1516-3 PN/DP V2.9

IF(das ist keine Schleife)
PS, der Klassiker: "Es gibt keine IF-Schleifen" ;)
IF-Schleifen gibt es nicht! IF ist Bestandteil einer 'Selektion', also einer Auswahl aus zwei oder mehr verschiedenen Möglichkeiten.
IF kann allerdings benutzt werden, eine Schleife zu beenden bzw. "vorzeitig" abzubrechen.
Ok das werde ich mir merken :LOL:
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Wie finde ich die Differenz raus, damit das Programm weiß wie viele Einträge er, nach Eintrag 0 von Array_1, noch kopieren muss?
Die Differenz musst Du eigentlich gar nicht berechnen. Du musst ja nicht den Zeiger (Index in das Array) als FOR-Schleifenvariable nehmen, sondern die Anzahl Kopiervorgänge (Zählvariable). Also nicht so
Code:
#Ziel_Endindex := (#Ziel_Startindex + #Anzahl_Kopier - 1) MOD 1000; //(ungefähr geschätzt)
#Ptr_2 := 0;                //Anfang Quellbereich

FOR #i := #Ziel_Startindex TO 999 DO
  Array_1[#i] := Array_2[#Ptr_2];

  #Ptr_2 += 1;
END_FOR;

FOR #i := 0 TO #Ziel_Endindex DO
  Array_1[#i] := Array_2[#Ptr_2];

  #Ptr_2 += 1;
END_FOR;

sondern so
Code:
#Ptr_1 := #Ziel_Startindex;  //Anfang Zielbereich im Ringpuffer
#Ptr_2 := 0;                 //Anfang Quellbereich

FOR #i := 1 TO #Anzahl_Kopier DO
  IF #Ptr_1 > 999 THEN #Ptr_1 := 0; END_IF;

  Array_1[#Ptr_1] := Array_2[#Ptr_2];

  #Ptr_1 += 1;
  #Ptr_2 += 1;
END_FOR;

PS: bei der oberen (nicht empfohlenen) Variante müsste auch noch zusätzlich geprüft werden, ob der Kopiervorgang überhaupt das Array-Ende überlappt (#Ziel_Endindex < #Ziel_Startindex), und das Ende der ersten FOR-Schleife müsste variabel berechnet sein und die zweite FOR-Schleife ggf. gar nicht ausgeführt werden.

Harald
 
Zuletzt bearbeitet:
Bsp.: Wenn ich die letzten 50 Einträge von Array_1 in Array_2 kopieren möchte, ich mich aber in Eintrag 10 von Array_1 befinde, soll er sobald er den Eintrag 0 kopiert hat, bei Eintrag 999 fortsetzen und noch bis Eintrag 960 kopieren.
Daraus lese ich, dass Du den Index / die Indizes dekrementierst (-1) statt sie zu inkrementieren (+1).
Das kann man tun und ist auch grundsätzlich überhaupt kein Problem. Die meisten neigen dazu, bevorzugt zu inkrementieren (siehe u.a. in den obigen Beiträgen). Manchmal gibt es - je nach AnwendungsFall - auch tatsächlich Gründe, sich eindeutig für das oder andere zu entscheiden.
Ich will hier aber das Thema nicht unnötig breittreten.

Die von Harald angeschnittene Thematik, den für das jeweilige Array definierten Bereich nicht zu unterschreiten (verwendeter Index wird kleiner als definiert) und nicht zu überschreiten (verwendeter Index wird grösser als definiert) ist natürlich sehr wichtig, damit die SPS nicht in Stopp geht oder es sogar schafft, im Speicher unbeabsichtigt etwas vor oder hinter den vom Array belegten Bereich zu schreiben.

Viele neigen dazu, den Index bei 1 beginnen zu lassen und bis n (n = Anzahl der ArrayElemente) laufen zu lassen.
Oft ist es günstiger, bei 0 zu beginnen und bis maximal n-1 zu gehen (n = Anzahl der ArrayElemente).
Z.B., wenn sich die Indizes nur im positiven Bereich bewegen und man das Unter- und Unterschreiten der IndexGrenzen mit dem MODulo-Operator verhindern will, kann man schreiben:
Code:
#Idx1 := (#Idx1 +1) MOD #n ;       // sorgt dafür, dass 0 <= Idx1 < n
#Idx2 := (#Idx2 - 1 + #n) MOD #n ; // sorgt dafür, dass 0 <= Idx2 < n
Der "Zusatz" ' + n ' in der unteren der beiden obigen Zeilen, also beim Vermindern des Index, kann überflüssig sein ... oder aber notwendig - je nach dem, wie sich das MOD in der jeweiligen Sprache bei negativen Dividenden verhält! Notfalls testen, um das Verhalten zu prüfen/ermitteln!
Man muss also nicht per IF-Anweisung prüfen, ob ein Unterlauf bzw. ein Überlauf stattfinden würde und ggfs handeln, man kann durch MOD grundsätzlich dafür sorgen, dass kein Unterlauf und kein Überlauf stattfindet.
Bei RingPuffern bietet sich dieses Verfahren allemal an.
Ansonsten, falls man z.B. bei unerwarteten Unter-/Überläufen mit einer Meldung oder sonstwie reagieren möchte, hat man ja ohnehin eine IF-Abfrage, in die man die Unter-/ÜberlaufBehandlung integrieren kann.

... Es hapert bei mir wohl noch ein wenig am Verständnis, wie gewisse Sachen im Programm ablaufen.
Nur Mut!
Es ist noch kein Meister vom Himmel gefallen ... höchstens von der Leiter!
Bisher habe ich den Eindruck, dass es bei Dir an einer anderen Stelle hapern könnte.
Ich vermute nämlich, dass Du noch sehr bzw. zu zögerlich bist, wenn es darum geht, Entscheidungen zu treffen.
Du bist als Programmierer selbst dafür zuständig, zu entscheiden, wie Dein Code im einzelnen ablaufen soll.
Natürlich musst Du dabei gewisse Vorgaben/RandBedingungen berücksichtigen (Schnittstellen zu anderen ProgrammAbschnitten, Verhalten von Sensoren, KundenWünsche, Anforderungen, Möglichkeiten und Eigenschaften der SPS, ..., u.s.w., ...).
Aber Du hast meist trotzdem ein weites Feld, in dem Du selbst entscheiden und handeln kannst.
Die Frage "Wie finde ich die Differenz raus, damit das Programm weiß wie viele Einträge er, nach Eintrag 0 von Array_1, noch kopieren muss?" sollte sich normalerweise nicht stellen. Wie man eine Differenz ausrechnet, weisst Du sicherlich. Dass das Ergebnis der Differenz manchmal "haarscharf daneben" ist, gemessen an dem, was man eigentlich berechnen will, daran wirst Du Dich sicherlich schnell gewöhnen.
Beispiel: AnzahlArrayElemente = maximalerIndex - minimalerIndex + 1

Mach Dir ein einfaches Beispiel und rechne mal, zunächst ohne auf eine evtl. Umsetzung im Programm zu schielen.
Oder schnapp Dir ein paar Gegenstände und schieb sie hin und her - oder was auch immer, um Dir Dein Problem für Dich anschaulich zu gestalten.
Genier Dich nicht, zu fragen bzw. darauf hinzuweisen, wenn die Aufgabenstellung sich als nicht so klar erweist, wie es auf den ersten (zu oberflächlichen?) Blick zu sein schien. Aufgabenstellungen sind leider oft nur recht oberflächlich durchdacht/formuliert.
Allein das Stellen einer Frage oder das Beschreiben eines Problems führt oft dazu, dass man selbst schon merkt, wo man sich verrant oder einen kleinen GedankenSprung gemacht hat.
Sprich mit Deinen Kommilitonen oder Kollegen, die unter ähnlichen oder sogar denselben Aufgaben "leiden".
Dumme Fragen gibt es (angeblich) nicht. Aber es kann recht dumm sein, wenn man sich nicht traut zu fragen.
Aber Du fragst ja schon, sonst wäre Dein Thread nicht hier im Forum zu sehen. (y)
Weiter so! Und bemüh Dich, die Aufgabenstellung so rüberzubringen, dass man sie verstehen kann. ;)
 
Zurück
Oben