-> Hier kostenlos registrieren
Liebe Mitleser,
ich habe ein Problem mit meiner Wochenschaltuhr. Die SPS geht immer mal wieder in Stop. Klar liegt das an Bereichslängenfehlern. :???:
Und ich weiss, dass diese Art zu programmieren fehleranfällig ist.
Aber vielleicht findet jemand das Rohprogramm doch nützlich und schaut es sich kurz an und sagt: ja klar, Du hast da was vergessen.
Gruß,
Aksels
ich habe ein Problem mit meiner Wochenschaltuhr. Die SPS geht immer mal wieder in Stop. Klar liegt das an Bereichslängenfehlern. :???:
Und ich weiss, dass diese Art zu programmieren fehleranfällig ist.

Aber vielleicht findet jemand das Rohprogramm doch nützlich und schaut es sich kurz an und sagt: ja klar, Du hast da was vergessen.

Code:
FUNCTION_BLOCK "FB_Schaltuhren_SCL_1x00"
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
VAR_INPUT
i_DaT_Zerl {InstructionName := 'DTL'; LibVersion := '1.0'} : DTL;
END_VAR
VAR
s_UhrenDaten : Array[1.."c_Anz_Schaltuhren"] of "DT_Schaltuhr_1x00" := [((), (), (), (), (), (), (), (), (), (), (), (), (), (), 1, (), (), ()), ((), (), (), (), (), (), (), (), (), (), (), (), (), (), 1, (), (), ()), ((), (), (), (), (), (), (), (), (), (), (), (), (), (), 1, (), (), ()), ((), (), (), (), (), (), (), (), (), (), (), (), (), (), 1, (), (), ()), ((), (), (), (), (), (), (), (), (), (), (), (), (), (), 1, (), (), ()), ((), (), (), (), (), (), (), (), (), (), (), (), (), (), 1, (), (), ()), ((), (), (), (), (), (), (), (), (), (), (), (), (), (), 1, (), (), ()), ((), (), (), (), (), (), (), (), (), (), (), (), (), (), 1, (), (), ()), ((), (), (), (), (), (), (), (), (), (), (), (), (), (), 1, (), (), ()), ((), (), (), (), (), (), (), (), (), (), (), (), (), (), 1, (), (), ())];
S_Index_Akt : Int := 1;
S_Index_Alt : Int := 1;
s_Aktiv : "DT_Schaltuhr_1x00";
s_AnzeigeUebernehmen : Bool;
s_AnzeigeGeaendert : Bool;
END_VAR
VAR_TEMP
t_a : SInt;
t_Von_Sek : UDInt;
t_Bis_Sek : UDInt;
t_Akt_Sek : UDInt;
t_WoTa_OK : Bool;
t_Von_OK : Bool;
T_Bis_OK : Bool;
t_Gruppen : Array[1.."c_Anz_Schaltuhren"] of Bool;
END_VAR
BEGIN
#t_Akt_Sek := USINT_TO_UDINT(#i_DaT_Zerl.SECOND) + USINT_TO_UDINT(#i_DaT_Zerl.MINUTE) * 60 + USINT_TO_UDINT(#i_DaT_Zerl.HOUR) * 60 * 60;
//Kontrolle Index
IF #S_Index_Akt <= 0 THEN
#S_Index_Akt := "c_Anz_Schaltuhren";
END_IF;
IF #S_Index_Akt > "c_Anz_Schaltuhren" THEN
#S_Index_Akt := 1;
END_IF;
//Genauso viele Schaltuhren es gibt, so viel Gruppen kann man anlegen. Wenn eine Schaltuhr true ausgibt wird der zugehörige Gruppenausgang auch true.
//Hier werden die Temporärdaten initialisiert. Und geprüft ob ungültige Werte in den Gruppen stehen. Wichtig, sonst geht SPS in Stop.
FOR #t_a := 1 TO "c_Anz_Schaltuhren" DO
#t_Gruppen[#t_a] := false;
IF #s_UhrenDaten[#t_a].i_Gruppe_Nr <= 0 THEN
#s_UhrenDaten[#t_a].i_Gruppe_Nr := 1;
END_IF;
IF #s_UhrenDaten[#t_a].i_Gruppe_Nr > "c_Anz_Schaltuhren" THEN
#s_UhrenDaten[#t_a].i_Gruppe_Nr :="c_Anz_Schaltuhren";
END_IF;
END_FOR;
//Schaltuhren bearbeiten.
FOR #t_a := 1 TO "c_Anz_Schaltuhren" DO
CASE #i_DaT_Zerl.WEEKDAY OF
1: // Sonntag
#t_WoTa_OK:=#s_UhrenDaten[#t_a].I_So;
2: // Montag
#t_WoTa_OK:=#s_UhrenDaten[#t_a].I_Mo;
3: //Dienstag
#t_WoTa_OK:=#s_UhrenDaten[#t_a].I_Di;
4: //Mittwoch
#t_WoTa_OK:=#s_UhrenDaten[#t_a].I_Mi;
5: //Donnerstag
#t_WoTa_OK:=#s_UhrenDaten[#t_a].I_Do;
6: //Freitag
#t_WoTa_OK:=#s_UhrenDaten[#t_a].I_Fr;
7: //Samstag
#t_WoTa_OK:=#s_UhrenDaten[#t_a].I_Sa;
ELSE // Darf nicht vorkommen, sonst Daten korrupt.
;
END_CASE;
// In Sekunden rechnet es sich einfacher.
#t_Von_Sek:=USINT_TO_UDINT(#s_UhrenDaten[#t_a].I_UZ_Von_h) * 60 * 60 + USINT_TO_UDINT(#s_UhrenDaten[#t_a].I_UZ_Von_m) * 60 + USINT_TO_UDINT(#s_UhrenDaten[#t_a].I_UZ_Von_s);
#t_Bis_Sek := USINT_TO_UDINT(#s_UhrenDaten[#t_a].I_UZ_Bis_h) * 60 * 60 + USINT_TO_UDINT(#s_UhrenDaten[#t_a].I_UZ_Bis_m) * 60 + USINT_TO_UDINT(#s_UhrenDaten[#t_a].I_UZ_Bis_s);
//Ist Aus kleiner ein geht die Schaltzeit über 0:00 hinüber.
IF #t_Von_Sek > #t_Bis_Sek THEN
//Von > Bis
//AKtuelle Zeit zwischen Von und 23:59:00
IF #t_Akt_Sek >= #t_Von_Sek AND #t_Akt_Sek <= 86399 THEN
#t_Von_OK := true;
ELSE
#t_Von_OK := false;
END_IF;
//Aktuelle Zeit zwischen 0:00:00 und Bis
IF #t_Akt_Sek < #t_Bis_Sek AND #t_Akt_Sek>=0 THEN
#T_Bis_OK := true;
ELSE
#T_Bis_OK := false;
END_IF;
ELSE
//Von < Bis
IF #t_Akt_Sek >= #t_Von_Sek THEN
#t_Von_OK:=true;
ELSE
#t_Von_OK := false;
END_IF;
IF #t_Akt_Sek < #t_Bis_Sek THEN
#T_Bis_OK := true;
ELSE
#T_Bis_OK := false;
END_IF;
END_IF;
#s_UhrenDaten[#t_a].O_Ein := #T_Bis_OK AND #t_Von_OK AND #t_WoTa_OK AND #s_UhrenDaten[#t_a].I_Aktiv;
IF #s_UhrenDaten[#t_a].O_Ein THEN
//Temporärdaten für Gruppe aktualisieren. Heikel. Hier darf nie eine falsche Gruppe drin stehen, sonst geht SPS in Stop. Wird deswegen ganz oben abgeprüft.
#t_Gruppen[#s_UhrenDaten[#t_a].i_Gruppe_Nr] := true;
END_IF;
END_FOR;
//Richtige Gruppen mit Temporärdaten befüttern.
FOR #t_a := 1 TO "c_Anz_Schaltuhren" DO
#s_UhrenDaten[#t_a].O_Gruppe_Ein:= #t_Gruppen[#t_a] ;
END_FOR;
//Ab hier Anzeige aufbereiten.
//Wurde der Index geändert? Dann Anzeigedaten aufbereiten
IF #S_Index_Akt = #S_Index_Alt THEN
#s_Aktiv.O_Ein := #s_UhrenDaten[#S_Index_Akt].O_Ein;
ELSE
#S_Index_Alt := #S_Index_Akt;
#s_Aktiv := #s_UhrenDaten[#S_Index_Akt];
END_IF;
//Wenn auf Speichern geklickt wurde Anezigedaten in Datenbestand übernehmen.
IF #s_AnzeigeUebernehmen THEN
#s_AnzeigeUebernehmen := false;
#s_UhrenDaten[#S_Index_Akt] := #s_Aktiv;
ELSE
;
END_IF;
//Auswerten, ob Angezeigte Daten geändert wurden. Dann kann man den Speichernbutton einblenden und blinken lassen.
//Gefällt mir noch nicht. Muss man doch eleganter lösen können (Bei änderung eines Feldes im HMI)?
#s_AnzeigeGeaendert := false;
IF #s_Aktiv.I_Name = #s_UhrenDaten[#S_Index_Akt].I_Name THEN
;
ELSE
#s_AnzeigeGeaendert := true;
END_IF;
IF #s_Aktiv.I_Aktiv = #s_UhrenDaten[#S_Index_Akt].I_Aktiv THEN
;
ELSE
#s_AnzeigeGeaendert := true;
END_IF;
IF #s_Aktiv.I_Mo = #s_UhrenDaten[#S_Index_Akt].I_Mo THEN
;
ELSE
#s_AnzeigeGeaendert := true;
END_IF;
IF #s_Aktiv.I_Di = #s_UhrenDaten[#S_Index_Akt].I_Di THEN
;
ELSE
#s_AnzeigeGeaendert := true;
END_IF;
IF #s_Aktiv.I_Mi = #s_UhrenDaten[#S_Index_Akt].I_Mi THEN
;
ELSE
#s_AnzeigeGeaendert := true;
END_IF;
IF #s_Aktiv.I_Do = #s_UhrenDaten[#S_Index_Akt].I_Do THEN
;
ELSE
#s_AnzeigeGeaendert := true;
END_IF;
IF #s_Aktiv.I_Fr = #s_UhrenDaten[#S_Index_Akt].I_Fr THEN
;
ELSE
#s_AnzeigeGeaendert := true;
END_IF;
IF #s_Aktiv.I_Sa = #s_UhrenDaten[#S_Index_Akt].I_Sa THEN
;
ELSE
#s_AnzeigeGeaendert := true;
END_IF;
IF #s_Aktiv.I_So = #s_UhrenDaten[#S_Index_Akt].I_So THEN
;
ELSE
#s_AnzeigeGeaendert := true;
END_IF;
IF #s_Aktiv.I_UZ_Von_h = #s_UhrenDaten[#S_Index_Akt].I_UZ_Von_h THEN
;
ELSE
#s_AnzeigeGeaendert := true;
END_IF;
IF #s_Aktiv.I_UZ_Bis_h = #s_UhrenDaten[#S_Index_Akt].I_UZ_Bis_h THEN
;
ELSE
#s_AnzeigeGeaendert := true;
END_IF;
IF #s_Aktiv.I_UZ_Von_m = #s_UhrenDaten[#S_Index_Akt].I_UZ_Von_m THEN
;
ELSE
#s_AnzeigeGeaendert := true;
END_IF;
IF #s_Aktiv.I_UZ_Bis_m = #s_UhrenDaten[#S_Index_Akt].I_UZ_Bis_m THEN
;
ELSE
#s_AnzeigeGeaendert := true;
END_IF;
IF #s_Aktiv.I_UZ_Von_s = #s_UhrenDaten[#S_Index_Akt].I_UZ_Von_s THEN
;
ELSE
#s_AnzeigeGeaendert := true;
END_IF;
IF #s_Aktiv.I_UZ_Bis_s = #s_UhrenDaten[#S_Index_Akt].I_UZ_Bis_s THEN
;
ELSE
#s_AnzeigeGeaendert := true;
END_IF;
IF #s_Aktiv.i_Gruppe_Nr = #s_UhrenDaten[#S_Index_Akt].i_Gruppe_Nr THEN
;
ELSE
#s_AnzeigeGeaendert := true;
END_IF;
END_FUNCTION_BLOCK
Gruß,
Aksels