TIA [SCL] Takt erkennen

Alde_Oma

Level-2
Beiträge
103
Reaktionspunkte
5
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo zusammen,

ich bekomme von einer Presse digitale Signale, welche ich weiterarbeiten muss.
Nun steht ich allerdings vor dem Problem, dass 2 dieser Signale blinkend sein können.
So stehen z.B. bei einem Signal folgende Zustände an:

dauerhaft Ein = läuft
schnell blinken = Fehler 1
blinken = Fehler 2
dauerhaft Aus = Aus

Die Taktfrequenz der Signale ist mir bisher unbekannt und kann erst vor Ort eingesehen werden.

Ich habe bereits versucht über das Mitzählen der Flanken über einen bestimmten Zeitraum, auf für mich verwartbare Signale zu kommen.
Ebenso das arbeiten mit Timern verschiedener Dauer. Je nachdem welche Timer gesetzt sind, kann ich auf die Taktfrequenz schließen.
Mein dritter Ansatz war der, das ich die Dauer von positiver und negativer Flanke messe und daraus auf die Taktfrequenz komme.

Alle drei Versuche haben allerdings gezeigt, das die Auswertung nicht so funktioniert wie gewollt und das es zu Überschneidungen meiner Signale kommt,
bzw. das die Auswertung der bis ich mein verwendbares Signal bekomme einfach zu lange dauert.

Hier der Code mit allen 3 Beispielen: "DB_IBN".xTakt ist der Taktgeber
Code:
FUNCTION_BLOCK "FB_Press"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
   VAR 
      xBad : Bool;
      iBadCount : Int;
      TON_BadShort {OriginalPartName := 'IEC_TIMER'; LibVersion := '1.0'} : TON_TIME;
      TON_BadLong {OriginalPartName := 'IEC_TIMER'; LibVersion := '1.0'} : TON_TIME;
      TON_RefShort {OriginalPartName := 'IEC_TIMER'; LibVersion := '1.0'} : TON_TIME;
      TON_RefMiddle {OriginalPartName := 'IEC_TIMER'; LibVersion := '1.0'} : TON_TIME;
      TON_RefLong {OriginalPartName := 'IEC_TIMER'; LibVersion := '1.0'} : TON_TIME;
      TON_Bad {OriginalPartName := 'IEC_TIMER'; LibVersion := '1.0'} : TON_TIME;
      FE_Bad {OriginalPartName := 'F_TRIG_1500'; LibVersion := '1.0'} : F_TRIG;
      RE_Bad {OriginalPartName := 'R_TRIG_1500'; LibVersion := '1.0'} : R_TRIG;
      RE_BadNeu {OriginalPartName := 'R_TRIG_1500'; LibVersion := '1.0'} : R_TRIG;
      tFE_Bad : Time;
      tRE_Bad : Time;
      FE_BadNeu {OriginalPartName := 'F_TRIG_1500'; LibVersion := '1.0'} : F_TRIG;
      TON_BadNeu {OriginalPartName := 'IEC_TIMER'; LibVersion := '1.0'} : TON_TIME;
      Static_1 : Bool;
      TON_Output {OriginalPartName := 'IEC_TIMER'; LibVersion := '1.0'} : TON_TIME;
      Merker : Int;
      TON_Dauer {OriginalPartName := 'IEC_TIMER'; LibVersion := '1.0'} : TON_TIME;
      TON_Test {OriginalPartName := 'IEC_TIMER'; LibVersion := '1.0'} : TON_TIME;
      Test : Bool;
   END_VAR

   VAR_TEMP 
      RetVal : Int;
      T1 : Time;
   END_VAR

   VAR CONSTANT 
      constDif_1 : Time := T#250ms;
      constDif_2 : Time := T#750ms;
      constDif_3 : Time := T#1100ms;
      constDif_4 : Time := T#1200ms;
   END_VAR


BEGIN


    // Blinktakt z.B. 2 Hz.
    
    
    // Funktionsfähig mit kleinen Problemen bei Übergang von 0-2 und 2-0 (ab und an wird 1 ausgegeben)
    #RE_BadNeu(CLK := "DB_IBN".xTakt);
    #FE_BadNeu(CLK := "DB_IBN".xTakt);
    
    // IF #RE_BadNeu.Q THEN
    //     #tRE_Bad := TIME_TCK();
        
    // END_IF;
    
    // IF #FE_BadNeu.Q OR #TON_BadNeu.Q THEN
    //     #tFE_Bad := TIME_TCK();
        
    //     #T1 := #tFE_Bad - #tRE_Bad;
        
    //     IF #TON_BadNeu.Q THEN
    //         #Merker := 3;
    //         // Reset
    //         #tFE_Bad := T#0ms;
    //         #tRE_Bad := T#0ms;
            
    //     ELSIF (#T1 > #constDif_1) AND (#T1 < #constDif_2) THEN
    //         #Merker := 1;
    //         // Reset
    //         #tFE_Bad := T#0ms;
    //         #tRE_Bad := T#0ms;
        
    //     ELSIF (#T1 > #constDif_2) AND (#T1 < #constDif_3) THEN
    //         #Merker := 2;
    //         // Reset
    //         #tFE_Bad := T#0ms;
    //         #tRE_Bad := T#0ms;
    
    //     END_IF;
        
    // ELSIF #TON_Bad.Q THEN
    //     #Merker := 0;
        
    // END_IF;
    
    // // Für Dauerhaft aus
    // #TON_Bad(IN:=NOT "DB_IBN".xTakt,
    //          PT:=#constDif_3);
    
    // // Für Dauerhaft ein
    // IF #RE_BadNeu.Q THEN
    //     #Static_1 := TRUE;
        
    // END_IF;
    
    // #TON_BadNeu(IN := #Static_1,
    //             PT := #constDif_3);
    
    // IF #FE_BadNeu.Q OR #TON_BadNeu.Q THEN
    //     #Static_1 := FALSE;
        
    // END_IF;
    
    // // Output to DB
    // IF #TON_Output.Q THEN
    //     "DB_Press".Inputs.Bad := #Merker;
        
    // END_IF;
    
    // #TON_Output(IN:=NOT #TON_Output.Q,
    //             PT:=#constDif_4);
    
    
    
    // *****************************************************
    
    
    
    
    #TON_Bad(IN:=#xBad,
             PT:=T#3000ms);
    
    #xBad := TRUE;
    
    IF #TON_Bad.Q = TRUE THEN
        #xBad := FALSE;
    END_IF;
    
    #RE_Bad(CLK := "DB_IBN".xTakt AND #xBad);
    #FE_Bad(CLK := "DB_IBN".xTakt AND #xBad);
    
    IF #RE_Bad.Q OR #FE_Bad.Q THEN
        #iBadCount := #iBadCount + 1;
        
    END_IF;
    
    IF #xBad = FALSE THEN
        
        IF #iBadCount = 3 THEN // Schnell Takt 1 (1 Hz)
            "DB_Press".Inputs.Bad := 3;
            
        ELSIF #iBadCount = 2 THEN // Langsam Takt 2 (2 Hz)
            "DB_Press".Inputs.Bad := 2;
            
        ELSIF #iBadCount = 1 THEN // Ein Takt 3
            "DB_Press".Inputs.Bad := 1;
            
        ELSIF #iBadCount = 0 THEN // Aus Takt 0
            "DB_Press".Inputs.Bad := 0;
        END_IF;
        
        #iBadCount := 0;
        
    END_IF;
    
    
    
    // *****************************************************
    
    
    
    
    // #Test := "DB_IBN".xTakt;
    
    // #TON_BadLong(IN:=#Test,
    //              PT:=T#750ms);
    
    
    // #TON_Test(IN := #Test,
    //          PT := T#250ms);
    
    // IF #RE_BadNeu.Q THEN
    //     #Static_1 := TRUE;
    // END_IF;
    
    // #TON_Dauer(IN := #Static_1,
    //            PT := T#1000ms);
    
    // IF #TON_Test.Q AND #TON_BadLong.Q THEN
    //     #Merker := 2;
        
    // ELSIF #TON_Test.Q AND (NOT #TON_BadLong.Q) THEN
    //     #Merker := 1;
        
    // ELSIF (NOT #TON_Test.Q) AND (NOT #TON_BadLong.Q) THEN
        
    //     #Merker := 0;
    // END_IF;
    
    
    // IF #TON_Dauer.Q THEN
        // IF #TON_Test.Q AND #TON_BadLong.Q THEN
             // "DB_Press".Inputs.Bad := #Merker;
            
        // ELSIF #TON_Test.Q AND (NOT #TON_BadLong.Q) THEN
        //     "DB_Press".Inputs.Bad := 1;
            
        // ELSIF (NOT #TON_Test.Q) AND (NOT #TON_BadLong.Q) THEN
            
        //     "DB_Press".Inputs.Bad := 0;
        // END_IF;
        
    //     #Static_1 := FALSE;
        
    // END_IF;
    

    
    
END_FUNCTION_BLOCK

Habt ihr einen Rat, wie ich das Problem in den Griff bekomme?

MfG Oma
 
So in etwa würde ich es aber grundsätzlich machen.
Einen Timer starten wenn der Input = 1 ist und einen weiteren Timer starten wenn der Input = 0 ist. Als Timer würde ich einen TON nehmen mit einer vorgewählten Zeit, die etwas größer als deine maximale Impuls- bzw. Pausenzeit ist.
Kann der Timer_1 durchlaufen dann hast du ein Dauersignal "1"
Kann der Timer_0 durchlaufen dann hast du ein Dauersignal "0"
Ändert sich der Status des Input so liest du die ET (Elapsed Time = abgelaufene Zeit) deines IEC-Timers ein und hast damit die jeweilige Impuls bzw.Pausenzeit - und zwar so genau, wie es die Zykluszeit deiner SPS zuläßt.

Gruß
Larry
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Danke für die Hilfe.
Habe deinen Vorschlag folgendermaßen umgesetzt und es funktioniert wunderbar.

Code:
// rising edge Bad Signal
#RE_Bad(CLK := "DB_IBN".xTakt);

// falling edge Bad Signal
#FE_Bad(CLK := "DB_IBN".xTakt);

// get elapsed time
IF #FE_Bad.Q THEN
    #tETBad := #TON_RE_Bad.ET;
     
END_IF;

// start time rising edge
#TON_RE_Bad(IN := "DB_IBN".xTakt,
            PT := #constMaxCycleTime);

// start time falling edge
#TON_FE_Bad(IN:=NOT "DB_IBN".xTakt,
            PT:=#constMaxCycleTime);

// evaluation of flashing signals
IF #tETBad > T#450ms AND #tETBad < T#550ms THEN
    "DB_Press".Inputs.Bad := 2;
    
ELSIF #tETBad > T#950ms AND #tETBad < T#1050ms THEN
    "DB_Press".Inputs.Bad := 3;
    
END_IF;

// steady 1
IF #TON_RE_Bad.Q THEN
    "DB_Press".Inputs.Bad := 1;
    
    // steady 0
ELSIF #TON_FE_Bad.Q THEN
    "DB_Press".Inputs.Bad := 0;
    
END_IF;

Vielen Dank ;)
 
Zurück
Oben