Wiederkehrend zur bestimmten Uhrzeit ausführen

Schakus

Level-1
Beiträge
20
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Liebes Forum,

ich möchte immer zu einer bestimmten Uhrzeit des Tages einmalig eine Funktion ausführen.
Ich habe dies versucht mit
Code:
IF NOT WagoAppTime.FuTimeDifference(tdTime1:= zielzeit, tdTime2:= aktuellezeit) THEN
    
tu was...



END_IF
und muss dann die aktuelle Zeit in Millisekunden angeben, sowie die Zielzeit in Millisekunden.
Ich denke dies ist ziemlich CPU belastend, denn jede Millisekunde wird die Bedingung geprüft.

Gibt es eine elegantere Lösung?
Grüß
 
Moin, hol dir doch regelmäßig mit einem Timer die Systemzeit und vergleiche diese in selben moment mit deiner "Zielzeit".
Wenn es nicht auf Millisekunden ankommt kannst du ja einen Timer als Taktgeber nutzen um die Funktion Zeitvergleichen nur jeder Sekunde aufzurufen.

Code:
Ton_Interval(In := TRUE,PT:= T#1s);
IF Ton_Interval.Q = TRUE THEN
   Ton_Interval(In := FALSE,PT:= T#1s);
   Ton_Interval(In := TRUE,PT:= T#1s);
   Systemzeit := ....;


   bDoSomeThing := FALSE;
   IF Act_hh = Set_HH THEN
     IF Act_mm = Set_MM THEN
       IF Act_ss >= Set_SS THEN
         bDoSomeThing := TRUE;
       END_IF;
     END_IF;
   END_IF;

   rTrig(CLK := bDoSomeThing);
   IF rTrig.Q THEN
     ;/* Funktionsaufruf
   END_IF;
END_IF;

Damit wird dein CPU zumindest ein wenig entlastet.

Grüße
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Hendrik,
danke für deinen Code. Ich verstehe den Code leider nicht komplett und bekomme diesen auch nicht compiliert.
Mir ist nicht ganz klar, wie ich das deklarieren muss.

Deine Bedingung wird jede Sekunde aufgerufen, was machen die nachfolgenden beiden Ton_Intervals ?

Was soll in die Act_xx hinein? Die Zielzeit, wann die Funktion aufgerufen werden soll?

Danke dir!
 
Hallo Schakus,
ich möchte immer zu einer bestimmten Uhrzeit des Tages einmalig eine Funktion ausführen.
Ich habe dies versucht mit
Code:
IF NOT WagoAppTime.FuTimeDifference(tdTime1:= zielzeit, tdTime2:= aktuellezeit) THEN
    
tu was...
END_IF
und muss dann die aktuelle Zeit in Millisekunden angeben, sowie die Zielzeit in Millisekunden.
Ich denke dies ist ziemlich CPU belastend, denn jede Millisekunde wird die Bedingung geprüft.
Du solltest Dich etwas mit der Funktionsweise von SPSen beschäftigen, denn Du hast da vermutlich falsche Vorstellungen. Die Bedingung würde nur dann jede Millisekunde geprüft, wenn Deine Zykluszeit 1ms beträgt. Standardmäßig beträgt die Zykluszeit bei den meisten Steuerungen 10ms. Belastend ist Deine Abfrage eher nicht für die CPU, kann aber nicht funktionieren. Du fragst auf die Millisekunde genau die Zeit ab und das würde höchstens bei einer Zykluszeit von <= 1ms funktionieren.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Moin Schakus,

der Intervallgeber wenn man in so nennt ist ein TON.

du kannst den Code so nicht compilieren weil ich nicht alles geschrieben habe.

In Act_hh steht die aktuell ausgelesene Systemzeit natürlich nur die Stunden (hh = Stunden, mm= Minuten, ss = Sek) die du aus deinem System ausgelesen hast.

Ich hoffe ich konnte dir hiermit weiterhelfen.

 
Den Ansatz, mit der Differenz zwischen ZielZeit und AktuelleZeit zu arbeiten ...
Code:
IF NOT WagoAppTime.Fu[B]TimeDifference[/B](tdTime1:= zielzeit, tdTime2:= aktuellezeit) THEN
... finde ich gar nicht so verkehrt.
Jedenfalls besser, als den Vergleich SekundenVonAktuelleZeit >= SekundenVonZielZeit.
Die "Reserve", die man sich mit ">=" (gegenüber "=") vermeintlich schafft, schrumpft nämlich erbärmlich, wenn SekundenVonZielZeit = 59.

Ich würde es sinngemäss mit ...
Code:
  DiffZeit := ABS(SollZeit - IstZeit); // alternativ z.B. DiffZeit := MAX(SollZeit, IstZeit) - MIN(SollZeit, IstZeit)
  bDiffPos := DiffZeitAlt < DiffZeit; // DiffZeit und bDiffPos dürfen lokal/temporär sein
  bDoSomeThing := bDiffPos AND NOT bDiffPosAlt; // Impuls, 1 Zyklus lang
  DiffZeitAlt := DiffZeit; // DiffZeitAlt und ...
  bDiffPosAlt := bDiffPos; // ... bDiffPosAlt müssen im nächsten Zyklus unverändert zur Verfügung stehen
... versuchen, damit Überläufe gegenstandslos werden.
Ob es wirklich ZyklusZeit spart, eine Mimik drum herum zu bauen, die zyklisch bearbeitet werden muss, um in den meisten Zyklen die "eigentliche" RechenArbeit zu "überspringen"?
Könnte man untersuchen - aber sicher ist, der Code wird dadurch umfangreicher und unübersichtlicher. Und der eine Zyklus mit der "eigentlichen" RechenArbeit beansprucht mehr Zeit MIT der ZusatzMimik.

PS:
Warum benutzt Du nicht die WagoAppScheduler?
Es gibt hier im Forum schon sooo viele Threads, in denen der TE nach DER massgeschneiderten Funktionalität von der Stange sucht ...
Man muss sich doch auch mal Gedanken machen dürfen, wie man das eine oder andere Problem lösen könnte ... sonst ist demnächst keiner mehr in der Lage, etwas ohne solche vorgefertigten Funktionalitäten zu lösen - geschweige denn, eine solche Funktionalität vorzufertigen! :ROFLMAO:
 
Zuletzt bearbeitet:
Ich habe jetzt versucht den Scheduler zum laufen zu bekommen:

Code:
PROGRAM LoopTime
VAR
    firstRun: BOOL := TRUE;

    scheduler1: WagoAppScheduler.FbScheduler;
    typScheduler: WagoAppScheduler.typScheduler;
    typSpecialPeriodConfig: WagoAppScheduler.typSpecialPeriod;
    switch: REAL := 0;
    timeOn: TIME_OF_DAY := TIME_OF_DAY#7:0; // time in ms
    timeOff: TIME_OF_DAY := TIME_OF_DAY#22:0;
    dateOn: DATE := DATE#1970-1-1;
    dateOff: DATE := DATE#2100-1-1;
END_VAR

Code:
IF firstRun THEN
    typSpecialPeriodConfig.xActivate := TRUE;
    typSpecialPeriodConfig.rSwitchValue := switch;
    typSpecialPeriodConfig.todOnTime := timeOn;
    typSpecialPeriodConfig.todOffTime := timeOff;
    typSpecialPeriodConfig.bStatus := 2#100010; 
    typSpecialPeriodConfig.datStartDate := dateOn;
    typSpecialPeriodConfig.datEndDate := dateOff;
    typSpecialPeriodConfig.xMonday := TRUE;
    typSpecialPeriodConfig.xTuesday := TRUE;
    typSpecialPeriodConfig.xWednesday := TRUE;
    typSpecialPeriodConfig.xThursday := TRUE;
    typSpecialPeriodConfig.xFriday := TRUE;
    typSpecialPeriodConfig.xSaturday := TRUE;
    typSpecialPeriodConfig.xSunday := TRUE;
    typSpecialPeriodConfig.xYearly := TRUE;
        
    typScheduler.aSpecialPeriod := typSpecialPeriodConfig;
    
    firstRun := FALSE;
END_IF

scheduler1(
    xEnable:= TRUE, 
    dtActualDateTime:= WagoAppTime.FuGetLocalDateAndTime(), 
    xManualOperation:= FALSE, 
    xManualSwitch:= FALSE, 
    rManualValue:= 0, 
    xPartySwitch:= FALSE, 
    oPublicHoliday:= , 
    oStatus=> , 
    sStatus=> , 
    xSwitch=> , 
    rSwitchValue=> , 
    iTimeBeforeOperation=> , 
    bPriority=> , 
    typConfigParameters:= typScheduler);

Zunächst initialisiere ich alle Parameter, dann soll die Funktion um 7 Uhr morgens und um 22 Uhr abends die Switch-Variable umschalten. Da weiß ich noch nicht, was mit der Variable passiert, da es ein REAL ist und kein BOOL?

Er will es nicht kompilieren und meckert bei:
Code:
    typScheduler.aSpecialPeriod := typSpecialPeriodConfig;

Jemand einen Tipp für mich?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hast Du den Anwendungshinweis zur WagoAppScheduler gelesen?

xSwitch=> ist ein Digitalausgang der Zeitschaltuhren
rSwitchValue=> ist ein REAL Ausgang, um z.B. per Zeitschaltuhr Leuchten auf 30% zu dimmen u.ä.

Und warum nimmst Du SpecialPeriod (Jahreszeitschaltuhr)?

...sollte nicht Weekly genügen?

Auch hier, wie bei der HVAC- App sind die typVariablen bereits in der Lib enthalten...

wenn Du wie im Anwendungshinweis die passende Visualisierungsbausteine verwendest, werden automatisch die Initialisierungswerte gesetzt usw.
 
Zuletzt bearbeitet:
Danke für deine Hinweise. Ich kämpfe mich mit der Dokumentation des Bibliotheksverwalters durch.
Das mit dem xSwitch habe ich überlesen und danke für die Erklärung von rSwitchValue.

Ich habe mir den FB aus "Kompakte Zeitschaltprogramme" herausgesucht und bin dann die Datentypen durch. Habe mich dann für den SpecialPeriod entschieden, das dies für die Jahreszeitschaltuhr verwendet wird, war mir nicht klar. Ich wechsel zur Weekly - danke!

Wie meinst du das, mit Visualisierungsbausteine? Für die Webvisualisierung? Die würde ich dafür nicht verwenden wollen, möchte dies mit ST realisieren und ausführen.

Ich habe es jetzt auf Weekly geändert, habe jedoch immer noch das gleiche Problem, dass ich dem typScheduler das struct nicht zuweisen möchte.
Wie kann ich das lösen? Oder sollte ich das noch mal alles ändern?

Code:
IF firstRun THEN
    typScheduleWeeklyConfig.xActivate := TRUE;
    typScheduleWeeklyConfig.rSwitchValue := switch;
    typScheduleWeeklyConfig.todOnTime := timeOn;
    typScheduleWeeklyConfig.todOffTime := timeOff;
    typScheduleWeeklyConfig.bStatus := 2#100010; 
    typScheduleWeeklyConfig.xMonday := TRUE;
    typScheduleWeeklyConfig.xTuesday := TRUE;
    typScheduleWeeklyConfig.xWednesday := TRUE;
    typScheduleWeeklyConfig.xThursday := TRUE;
    typScheduleWeeklyConfig.xFriday := TRUE;
    typScheduleWeeklyConfig.xSaturday := TRUE;
    typScheduleWeeklyConfig.xSunday := TRUE
        
    typScheduler.aScheduleWeekly := typScheduleWeeklyConfig;
    
    
    
    firstRun := FALSE;
END_IF

scheduler1(
    xEnable:= TRUE, 
    dtActualDateTime:= WagoAppTime.FuGetLocalDateAndTime(), 
    xManualOperation:= FALSE, 
    xManualSwitch:= FALSE, 
    rManualValue:= 0, 
    xPartySwitch:= FALSE, 
    oPublicHoliday:= , 
    oStatus=> , 
    sStatus=> , 
    xSwitch=> timeSwitch, 
    rSwitchValue=> , 
    iTimeBeforeOperation=> , 
    bPriority=> , 
    typConfigParameters:= typScheduler);
 
Die Visualisierungsbausteine können auch in Visualisierungseiten ohne Webfunktionalität verwendet werden.
Diese können dann z.B. nur innerhalb e!Cockpit, Online mit dem Controller, benutzt werden.
Ist bei Inbetriebnahmen, Störungssuche, DALI Konfiguration usw. hilfreich.

Deine Variable typScheduler ist bereits als typSinleScheduleWeekly deklariert. Fensterteil oben (Deklarationsfenster) zeigt alle deklarierten Variablen an.
In etwa so:
Code:
PROGRAM PLC_PRG
VAR
    yy: WagoAppScheduler.FbScheduleWeekly;
    
END_VAR
VAR RETAIN PERSISTENT
    typConfig: typSingleScheduleWeekly;
END_VAR



Also lösche
"typScheduler.aScheduleWeekly := typScheduleWeeklyConfig;"

aus der FirstRun IF Schleife
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ah super jetzt hab ich es verstanden.

Er führt den Code aus, setzt jedoch die xSwitch Variable nicht. Hast du eine Idee, woran das liegt oder wie ich das Problem identifizieren kann?
 
Woher hast du die Dokumentation? Das sieht viel hübscher aus, als im Bibliotheksverwalter :)

Leider läufts bei mir immer noch nicht. Ich habe eine Vermutung: ich setze zwar die typSingleScheduleWeekly Parameter, weise sie ihm aber nirgends zu.
Hast du deinen Codeschnipsel, wo du die Uhrzeit usw. setzt?

Bei mir ist es nun so:

Code:
PROGRAM LoopTime
VAR
    firstRun: BOOL := TRUE;

    scheduler1: WagoAppScheduler.FbScheduler;
    typScheduler: WagoAppScheduler.typScheduler;
    typScheduleWeeklyConfig: WagoAppScheduler.typSingleScheduleWeekly;
    
    timeOn: TIME_OF_DAY := TIME_OF_DAY#18:47; 
    timeOff: TIME_OF_DAY := TIME_OF_DAY#18:48;
    timeSwitch: BOOL;
    
END_VAR
Code:
IF firstRun THEN
    typScheduleWeeklyConfig.xActivate := TRUE;
    typScheduleWeeklyConfig.todOnTime := timeOn;
    typScheduleWeeklyConfig.todOffTime := timeOff;
    typScheduleWeeklyConfig.xMonday := TRUE;
    typScheduleWeeklyConfig.xTuesday := TRUE;
    typScheduleWeeklyConfig.xWednesday := TRUE;
    typScheduleWeeklyConfig.xThursday := TRUE;
    typScheduleWeeklyConfig.xFriday := TRUE;
    typScheduleWeeklyConfig.xSaturday := TRUE;
    typScheduleWeeklyConfig.xSunday := TRUE;
        
    
    
    
    firstRun := FALSE;
END_IF

scheduler1(
    xEnable:= TRUE, 
    dtActualDateTime:= WagoAppTime.FuGetLocalDateAndTime(), 
    xManualOperation:= , 
    xManualSwitch:= , 
    rManualValue:= , 
    xPartySwitch:= , 
    oPublicHoliday:= , 
    oStatus=> , 
    sStatus=> , 
    xSwitch=> timeSwitch, 
    rSwitchValue=> , 
    iTimeBeforeOperation=> , 
    bPriority=> , 
    typConfigParameters:= typScheduler);
 
Zuviel Werbung?
-> Hier kostenlos registrieren
versuche es mal damit ;-)

Code:
typScheduler.aScheduleWeekly[1] := typScheduleWeeklyConfig;

Auch wenn bei Wago und e!Cockpit viele Bausteine per Mausklick konfiguriert werden können, ist es zumindest nicht verkehrt zu verstehen wie solche mächtige Bausteine korrekt verschalten werden. Also immer schön die Dokumentation lesen.
 
Woher hast du die Dokumentation? Das sieht viel hübscher aus, als im Bibliotheksverwalter ;) (hatte ich dich schon gefragt)


Danke es funktioniert!
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Eine weitere Version wäre die Systemzeit zu zerlegen.
FU_Detailtime von Wago.

Dann kann man mit EQ (z.b.) die Stunden vergleichen und und mit einem R_TRIG eine Aktion einmal ausführen.

Detailtime.bhour = 22 (immer um 22:00 Uhr)

Man kann auch mehrer Teile mit einer AND-Verknüpfung verbinden.

Detailtime.bhour = 22
AND
Detailtime.bminute =15 (immer um 22:15 Uhr)

Nur so als Option...
 
Zurück
Oben