-> 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_BLOCKGruß,
Aksels
 
	 
  
 
		 
  
  
 
		 
  
 
		