Autor Thema: einfache einkanalige Zeitschaltuhr  (Gelesen 10564 mal)

Offline radar17892

  • Sr. Member
  • ****
  • Beiträge: 788
  • Think easy!
    • mollgruppe
einfache einkanalige Zeitschaltuhr
« am: Februar 17, 2019, 18:14:58 Nachmittag »
Moin Leute,

nach längerer Pause möchte ich mal wieder einen Baustein hier einstellen.
Es handelt sich um eine einfach gehaltene einkanalige Schaltuhr mit kleinster Schaltzeit 1min. Visufreundlich kann man mit nur 4 Byte die Schaltzeiten ( h:m ein + h:m aus) vorgeben. Durch ein Modusbit kan man den Ausgang von EIN-AUS auf Impuls Umstellen. Bedeutet, ist dei Einschaltzeit erreicht wird ein 1Zykl Impuls ausgegeben.
Man kann den FB leicht auf mehrere Schaltzeiten erweitern, oder ihn einfach instanzieren für mehrere Kanäle.
Bei interesse kann ich das auch noch hier einstellen.

FUNCTION_BLOCK HD1
(*
##############################################################
Programmbeschreibung:
Einfache Einkanalige Schaltuhr mit kleinster Schaltzeit 1min
Umschaltbarer Modus von ON-OFF Zeit auf Impulsausgang(1 Zykl)
Lib: standart
getestet: auf XV100  v3.5.11
##############################################################
Änderungsindex
Name:TL Version:0.1 Datum: 17.03.2017 Grund: neu

##############################################################
*)
VAR_INPUT
Uhrzeit: TOD; //aktuelle Uhrzeit
h1_on: BYTE; //Einschaltzeit Stunde
m1_on: BYTE; //Einschaltzeit Minute
h1_off: BYTE; //Ausschaltzeit Stunde
m1_off: BYTE; //Ausschaltzeit Minute
Mode: BOOL:=0; //0=on/off, 1=Impulsausgang
END_VAR
VAR_OUTPUT
Q1: BOOL;
END_VAR
VAR
Uhrzeit_s: DWORD; //akt Uhrzeit in Sekunden
Zeit_on: DWORD; //Einschaltzeit in Sekunden
Zeit_off: DWORD; //Ausschaltzeit in Sekunden
H1on: DWORD; // begrenzte Einschaltzeit Stunden
M1on: DWORD; // begrenzte Einschaltzeit Minuten
H1off: DWORD; // begrenzte Ausschaltzeit Stunden
M1off: DWORD; // begrenzte Ausschaltzeit Minuten
Einschalten: R_TRIG; //Einschaltflanke
Ausschalten: R_TRIG; //Ausschaltflanke
END_VAR


//Zeitwerte begrenzen und in Sekunden ausgeben
H1on :=(BYTE_TO_DWORD (LIMIT (0, h1_on, 23) )*3600);
M1on :=(BYTE_TO_DWORD (LIMIT (0, m1_on, 59) )*60);
H1off :=(BYTE_TO_DWORD (LIMIT (0, h1_off, 23) )*3600);
M1off :=(BYTE_TO_DWORD (LIMIT (0, m1_off, 59) )*60);
Zeit_on:=H1on + M1on;
Zeit_off:=H1off + M1off;
//Uhrzeit in Sekunden wandeln
Uhrzeit_s:= TOD_TO_DWORD(Uhrzeit) / 1000;

IF Mode THEN //Schaltimpuls ausgeben
Einschalten(CLK:= (Uhrzeit_s = Zeit_on), Q=> Q1 );
ELSE // EIN-AUS Schalten
Einschalten(CLK:= (Uhrzeit_s = Zeit_on), Q=> );
IF Einschalten.Q AND NOT Q1 THEN
Q1:= TRUE;
END_IF
Ausschalten(CLK:= (Uhrzeit_s = Zeit_off), Q=> );
IF Ausschalten.Q AND Q1 THEN
Q1:= FALSE;
END_IF
END_IF

Viel Spass noch!

Gruß Thomas
Weil Einfach einfach Einfach ist!

Offline radar17892

  • Sr. Member
  • ****
  • Beiträge: 788
  • Think easy!
    • mollgruppe
Antw:einfache einkanalige Zeitschaltuhr
« Antwort #1 am: Februar 24, 2019, 20:18:51 Nachmittag »
Eine Zeitschaltuhr [HD] mit [5] Schaltzeiten, [1]Einkanalig

FUNCTION_BLOCK HD51
(*
##############################################################
Programmbeschreibung:
Einfache Schaltuhr 5 Schaltzeiten, Einkanalig mit kleinster
Schaltzeit 1minn
Eine Schaltzeit = 00:00 wird als deaktiv interpretiert
Umschaltbarer Modus von ON-OFF Zeit auf Impulsausgang(1 Zykl)
Lib: standart
getestet: auf XV100 v2.3.9 + v3.5.12 OK
##############################################################
Änderungsindex
Name:TL Version:0.1 Datum: 17.02.2019 Grund: neu

##############################################################
*)
VAR_INPUT
Uhrzeit: TOD; (*aktuelle Uhrzeit*)
Zeiten: strHD51; (*Struktur mit Schaltzeiten*)
Mode: BOOL:=0; (*0=on/off, 1=Impulsausgang*)
END_VAR
VAR_OUTPUT
Q1: BOOL;
END_VAR
VAR
Uhrzeit_s: DWORD; (*akt Uhrzeit in Sekunden*)
Zeit_on: ARRAY [1..5] OF DWORD;
Zeit_off: ARRAY [1..5] OF DWORD;
Impuls: R_TRIG; (*Flanke*)
Einschalten: R_TRIG; (*Einschaltflanke*)
Ausschalten: R_TRIG; (*Ausschaltflanke *)
i: INT := 1; (* Laufvariable*)
ein: BOOL;(*Hilfsmerker*)
aus: BOOL;(*Hilfsmerker*)
END_VAR



(*Zeitwerte begrenzen und in Sekunden ausgeben*)
FOR i := 1 TO 5 DO
Zeit_on[i]:=(BYTE_TO_DWORD (LIMIT (0, Zeiten.h_ein[i], 23) )*3600) + (BYTE_TO_DWORD (LIMIT (0, Zeiten.m_ein[i], 59) )*60);
Zeit_off[i]:=(BYTE_TO_DWORD (LIMIT (0, Zeiten.h_aus[i], 23) )*3600) + (BYTE_TO_DWORD (LIMIT (0, Zeiten.m_aus[i], 59) )*60);
END_FOR

(*Uhrzeit in Sekunden wandeln*)
Uhrzeit_s:= TOD_TO_DWORD(Uhrzeit) / 1000;
(*Hilfsmerker Nullsetzen*)
ein:= FALSE;
aus:= FALSE;
IF Mode THEN (*Modus: Schaltimpuls ausgeben*)
FOR i := 1 TO 5 DO
(*Wenn Schaltzeit = 0 ->dann nicht verwenden*)
IF (Zeit_on[i] <> 0) AND (Uhrzeit_s = Zeit_on[i]) THEN
ein:= TRUE;
EXIT;
END_IF
END_FOR
Impuls(CLK:= ein, Q=> Q1 );
ELSE (* Modus: EIN-AUS Schalten*)
FOR i := 1 TO 5 DO (*Einschaltzeiten mit Uhrzeit vergleichen*)
(*Wenn Schaltzeit = 0 ->dann nicht verwenden*)
IF (Zeit_on[i] <> 0) AND (Uhrzeit_s = Zeit_on[i]) THEN
ein:= TRUE;
EXIT;
END_IF
END_FOR
Einschalten(CLK:= ein, Q=> );
IF Einschalten.Q AND NOT Q1 THEN
Q1:= TRUE;
END_IF
FOR i := 1 TO 5 DO (*Ausschaltzeiten mit Uhrzeit vergleichen*)
(*Wenn Schaltzeit = 0 ->dann nicht verwenden*)
IF (Zeit_off[i] <> 0) AND (Uhrzeit_s = Zeit_off[i]) THEN
aus:= TRUE;
EXIT;
END_IF
END_FOR
Ausschalten(CLK:= aus, Q=> );
IF Ausschalten.Q AND Q1 THEN
Q1:= FALSE;
END_IF
END_IF


die  zugehörige Struktur mit den Schaltzeiten. sie sollte global min remanent deklariert werden.
TYPE strHD51 :
STRUCT
h_ein: ARRAY[1..5] OF BYTE; (*Einschaltzeiten Stunden*)
m_ein: ARRAY[1..5] OF BYTE; (*Einschaltzeiten Minuten*)
h_aus: ARRAY[1..5] OF BYTE; (*Ausschaltzeiten Stunden*)
m_aus: ARRAY[1..5] OF BYTE; (*Ausschaltzeiten Minuten*)
END_STRUCT
END_TYPE
Weil Einfach einfach Einfach ist!

Offline radar17892

  • Sr. Member
  • ****
  • Beiträge: 788
  • Think easy!
    • mollgruppe
Antw:einfache einkanalige Zeitschaltuhr
« Antwort #2 am: September 05, 2023, 14:52:24 Nachmittag »
Moin Leute,

ich hab die Schaltuhr mal etwas Rechenzeit-optimiert.
Schaltzeiten werden intern nur jede Minute aktualisiert und die anderen FOR-Schleifen nur jede Sekunde ausgeführt.
So werden nur minimalste Rechenzeiten der CPU benötigt.



FUNCTION_BLOCK HD51_2
(*
##############################################################
Programmbeschreibung:
Einfache Schaltuhr 5 Schaltzeiten, Einkanalig mit kleinster
Schaltzeit 1min
Eine Schaltzeit = 00:00 wird als deaktiv interpretiert
Umschaltbarer Modus von ON-OFF Zeit auf Impulsausgang(1 Zykl)
Bei Impulsbetrieb werden nur Einschaltzeiten ausgewertet
Lib: standart
getestet: auf XV100  v3.5.12 OK
##############################################################
Änderungsindex
Name:TL Version:0.1 Datum: 17.02.2019 Grund: neu
Name:TL Version:0.2 Datum: 06.09.2023 Grund: Zykluszeitoptimiert
Berechnung nur beim Wechsel der Sekunden und interne Schaltzeitberechnung 1x/min

##############################################################
*)
VAR_INPUT
Uhrzeit: TOD; (*aktuelle Uhrzeit*)
Zeiten: strHD51; (*Struktur mit Schaltzeiten*)
Mode: BOOL:=0; (*0=on/off, 1=Impulsausgang*)
END_VAR
VAR_OUTPUT
Q1: BOOL;
END_VAR
VAR
Uhrzeit_s: DWORD; (*akt Uhrzeit in Sekunden*)
Uhrzeit_s_alt: DWORD; (*letzte Sekunde*)
Zeit_on: ARRAY [1..5] OF DWORD;
Zeit_off: ARRAY [1..5] OF DWORD;
Impuls: R_TRIG; (*Flanke*)
Einschalten: R_TRIG; (*Einschaltflanke*)
Ausschalten: R_TRIG; (*Ausschaltflanke *)
i: INT := 1; (* Laufvariable*)
ein: BOOL;(*Hilfsmerker*)
aus: BOOL;(*Hilfsmerker*)
Sekundentrigger: bool;
i_sec: int; (* Laufvariable*)
END_VAR


*************************************************************

(*Uhrzeit in Sekunden wandeln*)
Uhrzeit_s:= TOD_TO_DWORD(Uhrzeit) / 1000;
IF Uhrzeit_s <> Uhrzeit_s_alt THEN
Sekundentrigger:= true;
Uhrzeit_s_alt:= Uhrzeit_s;
ELSE Sekundentrigger:= false;
END_IF

(*Schaltzeiten begrenzen und in Sekunden ausgeben, nur 1x/min berechnen*)
IF Sekundentrigger and (i_sec = 0) THEN
FOR i := 1 TO 5 DO
Zeit_on[i]:=(BYTE_TO_DWORD (LIMIT (0, Zeiten.h_ein[i], 23) )*3600) + (BYTE_TO_DWORD (LIMIT (0, Zeiten.m_ein[i], 59) )*60);
Zeit_off[i]:=(BYTE_TO_DWORD (LIMIT (0, Zeiten.h_aus[i], 23) )*3600) + (BYTE_TO_DWORD (LIMIT (0, Zeiten.m_aus[i], 59) )*60);
END_FOR
END_IF
//Aktualisierunginterwall der Schaltzeiten
IF Sekundentrigger THEN
i_sec:= i_sec + 1;
IF i_sec >= 60 THEN //wenn schneller aktualisiert werden soll hier Takte runter setzen
i_sec:= 0;
END_IF
END_IF
(*Hilfsmerker Nullsetzen*)
ein:= FALSE;
aus:= FALSE;
IF Mode THEN (*Modus: Schaltimpuls ausgeben*)
IF Sekundentrigger THEN  //nur 1x/sec ausführen
FOR i := 1 TO 5 DO
(*Wenn Schaltzeit = 0 ->dann nicht verwenden*)
IF (Zeit_on[i] <> 0) AND (Uhrzeit_s = Zeit_on[i]) THEN
ein:= TRUE;
EXIT;
END_IF
END_FOR
END_IF
Impuls(CLK:= ein, Q=> Q1 );
ELSE (* Modus: EIN-AUS Schalten*)
IF Sekundentrigger THEN  //nur 1x/sec ausführen
FOR i := 1 TO 5 DO (*Einschaltzeiten mit Uhrzeit vergleichen*)
(*Wenn Schaltzeit = 0 ->dann nicht verwenden*)
IF (Zeit_on[i] <> 0) AND (Uhrzeit_s = Zeit_on[i]) THEN
ein:= TRUE;
EXIT;
END_IF
END_FOR
FOR i := 1 TO 5 DO (*Ausschaltzeiten mit Uhrzeit vergleichen*)
(*Wenn Schaltzeit = 0 ->dann nicht verwenden*)
IF (Zeit_off[i] <> 0) AND (Uhrzeit_s = Zeit_off[i]) THEN
aus:= TRUE;
EXIT;
END_IF
END_FOR
END_IF
Einschalten(CLK:= ein, Q=> );
IF Einschalten.Q AND NOT Q1 THEN
Q1:= TRUE;
END_IF
Ausschalten(CLK:= aus, Q=> );
IF Ausschalten.Q AND Q1 THEN
Q1:= FALSE;
END_IF
END_IF


Weil Einfach einfach Einfach ist!