TIA TON variable Vorgabe der Laufzeit

Zombie

Level-2
Beiträge
735
Reaktionspunkte
120
Zuviel Werbung?
-> Hier kostenlos registrieren
Hi zusammen,

Programmiert wird eine 1515F mit TIA V16.

Ich habe einen Palettenheber, der die Paletten immer genau so hoch heben soll, dass die oberste Lage Ware auf Hüfthöhe ankommt.
Das funktioniert in einer perfekten Welt auch schon, bei der die Werker die Palettenhöhe im Datensatz nach jeder Entnahme auch ordnungsgemäß reduzieren.
Weil wir eben in keiner perfekten Welt leben und das ganze mit einer Höhenkontrolle über Feinlichtschranke oder Ultraschall zu teuer ist, soll das im Hebevorgang mit einem TON und variabler Laufzeit geregelt werden, sobald die Ware eine Lichtschranke unterbricht.

Und da hab ich ein Problem. Wenn die LE die Lichtschranke beim heben unterbricht, gebe ich dem Timer die neue Zeit mit einer Variablen vor und starte den Timer.
Aber er übernimmt den neuen Zeitwert bisher nicht und läuft mit der Laufzeit vom letzten Vorgang weiter.

Muss ich eine spezielle Reihenfolge bei der Vorgabe einhalten?
Also, z.B. erst Zeit vorgeben, dann einen ganzen Zyklus warten und erst dann loslaufen lassen?
Aktuell gebe ich die Zeit vor und starte den Timer gleich danach.

Code:
//Zuweisung Laufzeit
If #sType <> #iType then
Case #iType of 
3: #sTime := 12s350ms;
#sType := #iType;
4: #sTime := 13s120ms;
#sType := #iType;
5: #sTime := 11s100ms;
Else
;
End_Case;
End_if;

#stBervz1(IN := #sType = #iType,
          PT := #sTime);
 
Ich bin mir gerade nicht ganz sicher, ob ich dein Problem bzw deine Programmierung richtig verstanden habe. Neue Laufzeiten an PT werden erst nach einer positiven Flanke an IN übernommen, sollte der Timer bereits laufen, so muss es eine neue positive Flanke am IN-Eingang geben, bevor die Zeit übernommen wird.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Wie, bzw. wann wird denn erfasst wie die neue Laufzeit des TONs zu sein hat? Oder sind die drei Zeiten oben immer fest?
Kannst du die neue Zeit vielleicht schon in den TON schreiben, sobald der Palettenheber auf dem Rückweg ist? Dann hättest du für den nächsten Hebevorgang schon die neue Laufzeit.
 
Wenn die Timer fúr der Zuweizung steht geht das wel.
Code:
//Zuweisung Laufzeit

#stBervz1(IN := #sType = #iType, 
          PT := #sTime);

If #sType <> #iType then
Case #iType of 
3: #sTime := 12s350ms;
#sType := #iType;

4: #sTime := 13s120ms;
#sType := #iType;

5: #sTime := 11s100ms;

#sType := #iType;
Else
;
End_Case;
End_if;[COLOR=#222222][FONT=Verdana]
[/FONT][/COLOR]
 
Genau das ist mein Problem. Wie groß muss der Zeitabstand zwischen Variable beschreiben und Positiver Flanke sein, damit der Timer den neuen Wert hat.
Der Case ergibt 3, in sTime steht auch 12s350ms drin, der Timer läuft aber nur 11s100ms (steht in ET drin), weil iType im Vorgang vorher 5 war.

Ich hab den Code auch aus dem Kopf geschrieben, das Projekt ist auf dem V16 PG und ich sitze gerade an einem anderen Rechner. Tut mir leid, wenn Sachen an dem Code fehlen.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Wie, bzw. wann wird denn erfasst wie die neue Laufzeit des TONs zu sein hat? Oder sind die drei Zeiten oben immer fest?
Kannst du die neue Zeit vielleicht schon in den TON schreiben, sobald der Palettenheber auf dem Rückweg ist? Dann hättest du für den nächsten Hebevorgang schon die neue Laufzeit.
Ja, die Laufzeiten ergeben sich aus der Höhe eines Packstücks, welches Palettenabhängig ist. Wenn er die LS unterbricht, soll er solange weiterfahren bis die Laufzeit abgelaufen ist, dann ist das oberste Packstück in Hüfthöhe.


Wenn die Timer fúr der Zuweizung steht geht das wel.
Code:
//Zuweisung Laufzeit

#stBervz1(IN := #sType = #iType, 
          PT := #sTime);

If #sType <> #iType then
Case #iType of 
3: #sTime := 12s350ms;
#sType := #iType;

4: #sTime := 13s120ms;
#sType := #iType;

5: #sTime := 11s100ms;

#sType := #iType;
Else
;
End_Case;
End_if;
Da muss ich den Kollegen vor Ort mal fragen, ob er das schon gemacht hat.
 
Zuletzt bearbeitet:
Hallo,

eventuell würde dir ein TONR helfen anstatt einem normalen TON.

Dort besitzt du die Möglichkeit das ET zurückzusetzen.
 
Code:
//Zuweisung Laufzeit
If #sType <> #iType then
Case #iType of 
3: #sTime := 12s350ms;
#sType := #iType;
4: #sTime := 13s120ms;
#sType := #iType;
5: #sTime := 11s100ms;
Else
;
End_Case;
End_if;

#stBervz1(IN := #sType = #iType,
          PT := #sTime);
Du hast doch am Parameter IN bei CASE 3 oder 4 konstant TRUE anliegen (also fast nie eine positive Flanke)!?
Versuchst Du an einer anderen ProgrammStelle noch, den Timer zu starten??? :confused:
 
Zuletzt bearbeitet:
Zombie schrieb:
Und da hab ich ein Problem. Wenn die LE die Lichtschranke beim heben unterbricht, gebe ich dem Timer die neue Zeit mit einer Variablen vor und starte den Timer.
Aber er übernimmt den neuen Zeitwert bisher nicht und läuft mit der Laufzeit vom letzten Vorgang weiter.
Gleichstromer schrieb:
Evtl. nützen die Anweisungen PRESET_TIMER und RESET_TIMER was ?
+1
PRESET_TIMER ist das Antwort zu das Problem.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Wie wird denn der Inhalt von #iType in Abhängigkeit vom LichtSchrankenSignal gebildet?
Warum wird die Zeit nicht immer durch die LS getriggert, sondern bestenfalls bei einem Wechsel des Inhalt von #iType - aber dann auch nur zufallsbedingt?
Der Code passt so gar nicht zur textlichen Beschreibung in #1.
Was soll der ProgrammSchnippsel denn wirklich tun?

@JoopB
Du hast bei CASE 5 die Zeile
#sType := #iType;
ergänzt. Das ist vermutlich OK, aber wahrscheinlich nur ein Teil des Problems.
 
Zuletzt bearbeitet:
//Zuweisung Laufzeit
If #sType <> #iType then
Case #iType of
3: #sTime := 12s350ms;
#sType := #iType;
4: #sTime := 13s120ms;
#sType := #iType;
5: #sTime := 11s100ms;
Else
;
End_Case;
End_if;

#stBervz1(IN := #sType = #iType,
PT := #sTime);

Der Code macht kein Sinn.

Im ersten Durchlauf würde ich mal, auf Grund der Beschreibung, davon ausgehen, dass Case 5 bearbeitet werden soll. Allerdings sehe ich keine eindeutige Zuweisung der Variablen #iType und #sType im Code. Ich gehe mal davon aus, dass es sich hierbei um temp Variablen handelt. D.h. mir ist unklar wie in #sTime beim ersten Durchlauf die 11.1s rein kommen.


Angenommen wir haben beim ersten Durchlauf den Case 5 durchlaufen und der Timer läuft mit 11.1s. Dann müsste, anhand des dargestellten Codes und der Beschreibung, #iType um 1 dekrementiert werden (getriggert durch die Lichtschranke), was ich allerdings nirgends sehe. Gehen wir mal davon aus, dass dies weiter unten im Code, getriggert durch die Lichtschranke, stattfindet. Dann würde im nächsten Durchlauf der Case 4 bearbeitet werden. In #sTime würden die 13.12s stehen und #iType wird #sType zugewiesen. Wenn dann wieder der Timer bearbeitet wird, wird dieser nicht neu gestartet, weill keine positive Flanke anliegt. Oder anders ausgedrückt, jedes mal wenn der Timer aufgerufen wird, liegt am #IN Parameter statisch 'TRUE' aber keine positive Flanke an, weil in der Zeit wo #iType ungleich #sType ist, der Timer nie aufgerufen wird. Deswegen steht auch in #ET immer die 11.1s, den in #ET wird der aktuelle Zeitwert hochgezählt und bei erreichen von #PT gestoppt bis der Timer neu gestartet wird.

Ich denke du solltest den Code nochmal genauer durchdenken...


Kleiner Tipp noch:

Wenn es sich bei #sType und #iType wirklich um temp Variablen handeln sollte, kann dass nach deinem Prinzip grundsätzlich nicht funktionieren. Also wenn du es schon so programmierst solltest du stattdessen static Variablen verwenden. Wobei es dann auch nur funktionieren kann, wenn der Timer mindestens 1 Zyklus bei #IN 'FALSE' hat.
 
Zuletzt bearbeitet:
Ich denke du solltest den Code nochmal genauer durchdenken...
... oder vorher noch den gewünschten Ablauf und ihn dann so beschreiben, dass man es in ein Programm umsetzen kann. ;)

Wie lange soll denn der TON überhaupt laufen, wenn es denn mal gelingen sollte, ihn mit der gewünschten Zeitwert zu starten?
Wäre es nicht sinnvoller, einen TOF zu verwenden und ihn mit einem 1-Zyklus langen Impuls zu starten?
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Hui, danke für die vielen Hilfen und Meinungen.

Der Code macht schon Sinn, ich hab auch geschrieben, dass ich den im ersten Post aus dem Kopf geschrieben habe, es fehlen einige Teile die im Baustein enthalten sind.
Corona sei Dank wurde der erste Code im März geschrieben und wird jetzt erst in Betrieb genommen und das auch nicht von mir weil ich daheim rumsitzen darf.
Der Baustein ist hier im Büro mit einer CPU getestet. Leider bin ich aber ein Idiot, der vergessen hat, dass die Palette bei fortschreitender Leerung die Lichtschranke auch mal verlässt, weshalb der Code hier mit CPU und per Hand eingetragenen Signalen funktionierte, in der Anlage aber nicht mehr. Was ich oben reinschrieb war das was ich als "Fehlermeldung" erhalten habe, aber das war nicht wirklich das Problem.

In Case 5 steht #sType := #iType schon mit drin, hab die Zeile vergessen im Codebeispiel zu kopieren, JoopB hat das erkannt.

Wenn die Lichtschranke unterbrochen wird, wird der Code abgearbeitet, iType wird 0, wenn der Datensatz vom Heber wieder runtergelöscht wird. Da sType nie 0 wird, ist die If Bedingung immer dann True, wenn eine neue Palette auf dem Heber ankommt. Ist sType und iType die gleiche Palette, sollte ja keine neue Zeit eigetragen werden, sondern die Zeit nur laufen.

Es soll niemals ein Casefall "zuerst" abgearbeitet werden, der Wert der Type im Datensatz hat, bestimmt die Zeit jedesmal neu, es sei denn es kommen zwei gleiche Paletten direkt nacheinander an.

iType kommt aus dem Datensatz der Palette auf dem Heber als Eingang in den FB, deshalb die i vor dem Variablennamen, sType ist eine statische Variable im FB, deshalb s davor. Gleiches gilt für sTime.
sTime hat immer die Zeit aus der letzten Auswertung.

Das Problem ist aber dass wie gesagt, die Palette die Lichtschranke ja auch irgendwann mal verlässt und der Timer dann nicht mehr aufgerufen wird. Etwas das ich hier im Büro beim testen komplett vergessen habe. Schande über mein Haupt.

Code:
If not iTrig then
[COLOR=#333333]//Zuweisung Laufzeit[/COLOR]
[COLOR=#333333]If #sType <> #iType then[/COLOR]
[COLOR=#333333]Case #iType of[/COLOR]
[COLOR=#333333]3: #sTime := 12s350ms;[/COLOR]
[COLOR=#333333]#sType := #iType;[/COLOR]
[COLOR=#333333]4: #sTime := 13s120ms;[/COLOR]
[COLOR=#333333]#sType := #iType;[/COLOR]
[COLOR=#333333]5: #sTime := 11s100ms;
[/COLOR][COLOR=#333333]#sType := #iType;[/COLOR]
[COLOR=#333333]Else[/COLOR]
[COLOR=#333333];[/COLOR]
[COLOR=#333333]End_Case;[/COLOR]
[COLOR=#333333]End_if;[/COLOR]

[COLOR=#333333]#stBervz1(IN := #sType = #iType,[/COLOR]
[COLOR=#333333]PT := #sTime);
[/COLOR]End_If;

Ist Falsch, Richtig wäre

Code:
If not iTrig then
[COLOR=#333333]//Zuweisung Laufzeit[/COLOR]
[COLOR=#333333]Case #iType of[/COLOR]
[COLOR=#333333]3: #sTime := 12s350ms;[/COLOR]
[COLOR=#333333]#sType := #iType;[/COLOR]
[COLOR=#333333]4: #sTime := 13s120ms;[/COLOR]
[COLOR=#333333]#sType := #iType;[/COLOR]
[COLOR=#333333]5: #sTime := 11s100ms;
[/COLOR][COLOR=#333333]#sType := #iType;[/COLOR]
[COLOR=#333333]Else[/COLOR]
[COLOR=#333333];[/COLOR]
[COLOR=#333333]End_Case;[/COLOR]
End_If;

If not iBel then
sType := 100;
End_If;

[COLOR=#333333]#stBervz1(IN := (#sType = #iType),[/COLOR]
[COLOR=#333333]PT := #sTime);
[/COLOR]
Die Palette verlässt den Platz, der Datensatz wird mit 0en überschrieben. iType wird 0 und der Timer wird zurückgesetzt. Ich musste jetzt nur noch sType löschen, wenn der Heber frei ist.
Sry, falls ich euch Hintergrundwissen vorenthalten habe, das für die Hilfe notwendig war. Soweit hab ich nicht gedacht. Was i,s usw, bedeuten.

Ich schau mir auch das mit dem Preset nochmal an, eventuell geht es damit eleganter.

Vielen Dank
 
Zuletzt bearbeitet:
Was willst Du wie mit der Anweisung
#stBervz1(IN := (#sType = #iType), PT := #sTime);
bewirken?
Den Timer starten, und zwar mit dem aktuellen Zeitwert aus sTime, nehme ich an.
Wodurch soll denn an dieser Programmstelle sType jemals ungleich iType werden, um mal eine ZustandsÄnderung (= Flanke) am Eingang IN zu bewirken?

Ich würde einen TOF verwenden und ihn mit einem Impuls von 1 Zyklus Länge starten (dabei übernimmt er "automatisch" den in sTime vorgegeben Wert).
Dann läuft genau diese Zeit (+ 1 Zyklus) ab, d.h. der Ausgang .Q ist dann (nur) während dieser Zeit TRUE.
Eine Notwendigkeit, den TOF jemals resetten zu müssen, sehe ich überhaupt nicht. Du kannst doch den Ausgang .Q noch mit irgendwas verUNDen, falls erforderlich.

Elegant finde ich das Abwürgen eines Timers eigentlich nie - das sollte eher eine ganz seltene Ausnahme bleiben.

PS:
Die Bedeutung der Buchstaben 'i' und 's' am Beginn von VariablenNamen waren mir durchaus plausibel/verständlich. ;)
 
Zuletzt bearbeitet:
Was willst Du wie mit der Anweisung
#stBervz1(IN := (#sType = #iType), PT := #sTime);
bewirken?
Den Timer starten, und zwar mit dem aktuellen Zeitwert aus sTime, nehme ich an.
Wodurch soll denn an dieser Programmstelle sType jemals ungleich iType werden, um mal eine ZustandsÄnderung (= Flanke) am Eingang IN zu bewirken?

Ich würde einen TOF verwenden und ihn mit einem Impuls von 1 Zyklus Länge starten (dabei übernimmt er "automatisch" den in sTime vorgegeben Wert).
Dann läuft genau diese Zeit (+ 1 Zyklus) ab, d.h. der Ausgang .Q ist dann (nur) während dieser Zeit TRUE.
Eine Notwendigkeit, den TOF jemals resetten zu müssen, sehe ich überhaupt nicht. Du kannst doch den Ausgang .Q noch mit irgendwas verUNDen, falls erforderlich.

Elegant finde ich das Abwürgen eines Timers eigentlich nie - das sollte eher eine ganz seltene Ausnahme bleiben.

PS:
Die Bedeutung der Buchstaben 'i' und 's' am Beginn von VariablenNamen waren mir durchaus plausibel/verständlich. ;)

Der Timer läuft los, wenn sType und iType gleich sind.
Folgender Ablauf:
Urzustand, Heber Leer, Datensatz 0, d.h. iType = 0 und sType ist 100. Bedingung für In des Timers ist FALSE, Timer läuft nicht.
Jetzt läuft ne Palette auf den Heber auf, der Datensatz wird in den Speicher kopiert, iType ist damit ungleich 0. Heber hebt und die Ware auf der Palette fährt in die Lichtschranke rein. iTrig, das Lichtschrankensignal wird 0, damit die If Abfrage True und Case wird ausgeführt. sTime wird ein Wert zugewiesen, und sType wird auf den Wert von iType gesetzt.

Jetzt sind sType und iType gleich, der Timer läuft los. Wenn er abgelaufen ist, wird der Hebevorgang unterbrochen. Da sType und iType gleich bleiben, bleibt der Timer True.
Heber senkt wieder und gibt die Palette ab. Mit der Abgabe der Palette nach Beendigung des Senkens wird der Datensatz vom Heber gelöscht, iType wird wieder 0 und die Bedingung an In des Timers ist wieder False. Geht die Palette vom Heber runter, wird die If Bedingung not iBel wahr und der Wert von sType wird mit 100 überschrieben. Der Timer bleibt False weil iType = 0 und sType = 100 sind.

Das mit dem Ton ist mir hintenraus zu kompliziert. Ich starte das Heben wenn der Timer- Ausgang .Q False ist. Dann wird er zwischendrin mal kurz True und wenn er dann wieder false wird, muss ich anhalten. Muss also das False während dem Beginn des Hebens irgendwie maskieren und dann die Maskierung wieder abschalten wenn er mal True war.
Denke mit der Lösung oben kommen die Instandhalter im Falle das, besser zurecht.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Das mit dem Ton ist mir hintenraus zu kompliziert. Ich starte das Heben wenn der Timer- Ausgang .Q False ist. Dann wird er zwischendrin mal kurz True und wenn er dann wieder false wird, muss ich anhalten. Muss also das False während dem Beginn des Hebens irgendwie maskieren und dann die Maskierung wieder abschalten wenn er mal True war.
Denke mit der Lösung oben kommen die Instandhalter im Falle das, besser zurecht.
Dann warten wir das doch einfach mal ab ...

Du wirst sicher verstehen, dass es für uns nicht wirklich möglich ist, Dir die passende Lösung zu liefern, wenn wir nicht wissen, in welcher zeitlichen Abfolge die EingangsSignale kommen und gehen und auch nicht wissen, welches Verhalten des AusgangsSignals gewünscht ist.
Durch Deine Beschreibung scheint es jetzt besser verständlich zu sein, aber es stellt sich die Frage, warum es nicht vorher schon funktioniert hat.
 
Zurück
Oben