TIA Pulsfolge erzeugen, benötige eure Tips

Horschd

Level-1
Beiträge
32
Reaktionspunkte
1
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo zusammen,

ich stehe gerade auf dem Schlauch.
Ich muss eine variable Pulsfolge erzeugen. Ähnlich einem PWM Signal.

Es wird eine High Time von 200ms und eine Pausenzeit von 500ms vorgeben.

Die Anzahl der Pule soll variabel sein.
Im fertigen Baustein soll auch die Pausen und die High Time einstellbar sein.

Ich habe mal ein Prototyp in SCL erstellt. Die Pulse werden auch erzeugt, aber er zählt die Pulse nicht.
Kann der eingeschlagene weg überhaupt zum erfolg führen?
Code:
FUNCTION_BLOCK "FB10_puls"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
   VAR_INPUT 
      number_of_pulses : Int;
      duration : Time;
      breake_time : Time;
      start : Bool;
   END_VAR
  
    VAR_OUTPUT 
      Q : Bool;
      finished : Bool;
   END_VAR
  
    VAR 
      HM_start : Bool;
      HM_01 : Bool;
      HM_02 : Bool;
      HM_03 : Bool;
      R_Trig_start {InstructionName := 'R_TRIG'; LibVersion := '1.0'} : R_TRIG;
      HM_number_of_pulses : Int;
      HM_breake_time : Time;
      HM_duration : Time;
      "counter" : Int;
      TP_Pulse {InstructionName := 'TP_TIME'; LibVersion := '1.0'} : TP_TIME;
      F_Trig_1 {InstructionName := 'F_TRIG'; LibVersion := '1.0'} : F_TRIG;
      TP_Breake {InstructionName := 'TP_TIME'; LibVersion := '1.0'} : TP_TIME;
      xxx : Int;
   END_VAR
Code:
BEGIN
 #R_Trig_start(CLK:=#start,
            Q=>#HM_start);
 
 
 IF (#HM_start = TRUE) THEN
     #HM_number_of_pulses := #number_of_pulses;
     #HM_duration := #duration;
     #HM_breake_time := #breake_time;
 END_IF;
 
 FOR #counter := 0 TO #HM_number_of_pulses DO
     #TP_Pulse(IN := #HM_start OR #HM_03,
               PT := #HM_duration,
               Q => #Q);
     #F_Trig_1(CLK := #TP_Pulse.Q,
               Q => #HM_01);
     #TP_Breake(IN := #HM_01,
                PT := #HM_breake_time,
                Q => #HM_02);
     "F_TRIG_DB"(CLK := #HM_02,
                 Q => #HM_03);
     
 END_FOR;
 
END_FUNCTION_BLOCK
 
Hi
Zum lernen schön, ansonsten ist das www voll von Blinkern...
Da muss dann nur noch der Zähler rein.
Morgen könnte ich ihn Posten, aber Oscar müsste auch helfen.
HtH


Gesendet von meinem ONEPLUS A3003 mit Tapatalk
 
Die Pulse werden auch erzeugt, aber er zählt die Pulse nicht.
Kann der eingeschlagene weg überhaupt zum erfolg führen?
Code:
... 
 FOR #counter := 0 TO #HM_number_of_pulses DO
      ...
    
 END_FOR;
 
END_FUNCTION_BLOCK
Nein, das kann nicht zum Erfolg führen.
Das Prinzip einer SPS wurde hier nämlich nicht beachtet (Hochsprachenprogrammierer?):
Die SPS liest die Eingänge ein, rattert ihr Programm einmal komplett durch und gibt dann entsprechend den letzten Ergebnissen die Ausgänge aus. Dann das Ganze von vorn.

Hier wird also die FOR-Schleife innerhalb eines jeden Zyklus einmal komplett durchlaufen und die Timer x-mal initialisiert bzw. ihr Zustand abgefragt. Es wird aber nicht erfasst, wie oft die Timer ihren Zustand gewechselt haben (wieviel Pulse über die vergangenen Zyklen bisher ausgegeben wurden).

Die FOR-Schleife ist demzufolge falsch ausgewählt (kann entfallen).
Statt dessen muss z.B. anhand der Flanken der Timer (die ja schon vorhanden sind) gezählt werden, wie oft diese tatsächlich einen Zustandswechsel durchlaufen.
 
Zuletzt bearbeitet:
Ich habe gerade die Dokumentation von Oscat gelesen, habe dort leider keinen Blinker gefunden, der mit variablen Zeitwerten konfigutiert werden kann.

Ich habe gestern leider nichts gefunden wie die Stuerung im Detail eine For schleife bearbeitet. wenn diese in jedem Zyklus komplett bearbeitet wird, kann dies nicht funktionieren.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Nein, das kann nicht zum Erfolg führen.
Das Prinzip einer SPS wurde hier nämlich nicht beachtet (Hochsprachenprogrammierer?):
Die SPS liest die Eingänge ein, rattert ihr Programm einmal komplett durch und gibt dann entsprechend den letzten Ergebnissen die Ausgänge aus. Dann das Ganze von vorn.


Nicht ganz, und das ist was viele und vor allend Dingen viele viele SPS Schulungsanbieter vergessen und wehalb auch fast alle Schaubilder im Netz falsch sind:

Der Zyklus beginnt mit dem schreiben des Prozessabbilds der Ausgänge und danach wird wer das PAE gelesen und DANN wird das Programm bearbeitet.

1500er PLC:

Im Betriebszustand "RUN" erfolgt die zyklische, zeit- und alarmgesteuerte Programmbearbeitung. Adressen, die im Prozessabbild "Automatische Aktualisierung" liegen, werden in jedem Programmzyklus automatisch aktualisiert:

  • Das Prozessabbild der Ausgänge wird ausgegeben.
  • Das Prozessabbild der Eingänge wird gelesen.
  • Das Anwenderprogramm wird abgearbeitet.
1200er PLC:

Ablauf der zyklischen Programmbearbeitung
Ein Zyklus der Programmbearbeitung umfasst folgende Schritte:


  1. Das Betriebssystem startet die Zyklusüberwachungszeit.
  2. Das Betriebssystem schreibt die Werte aus dem Prozessabbild der Ausgänge in die Ausgabebaugruppen.
  3. Das Betriebssystem liest den Zustand der Eingänge an den Eingabebaugruppen aus und aktualisiert das Prozessabbild der Eingänge.
  4. Das Betriebssystem bearbeitet das Anwenderprogramm und führt die im Programm angegebenen Operationen aus.



Schritt

Ich weiß das ist gerde extremes Korintenkacken aber spätestens wenn man mit echter Hardware arbeitet kann man bei Zeitlich engen Programmen auf Probleme stoßen wenn man das nicht weiß.
 
Nicht ganz, und das ist was viele und vor allend Dingen viele viele SPS Schulungsanbieter vergessen und wehalb auch fast alle Schaubilder im Netz falsch sind:
Der Zyklus beginnt mit dem schreiben des Prozessabbilds der Ausgänge und danach wird wer das PAE gelesen und DANN wird das Programm bearbeitet.
Ich weiss nicht so genau, auf welchen kleinen Unterschied Du hinweisen willst.
Laut der FussballerWeisheit "nach dem Zyklus ist vor dem Zyklus" ist es eigentlich schnuppe, welche Phase des Zyklus man als den StartPunkt des Zyklus ansieht.
Relevant für den "laufenden Betrieb" ist die Reihenfolge der Phasen. Einzige Ausnahme: der allererste Zyklus beim Hochlaufen der PLC.
 
Hi,
habe mal ein Beispiel in ST nachgebildet, zum Bsp. als Schrittkette.

Wie schon erwähnt, viele Wege führen nach Rom...

Wenn du den für dich angepasst bekommst, dürftest du in Sachen Zyklus eine Runde weiter sein :p

Viel Spaß
Code:
FUNCTION_BLOCK FB_Taktgeber
VAR_INPUT
    START : BOOL := TRUE;    (* Ein-, Ausschalten *)
    PTH : TIME;            (* Arbeitstakt *)
    PTL : TIME;            (* Pausentakt *)
    N    : UINT;        (* Anzahl der Impulse *)
END_VAR
VAR_OUTPUT
    Q      : BOOL;    (* Ausgang *)
    BUSY : BOOL;    (* Laeuft noch ? , nettes Schmankerl*)
END_VAR
VAR
    Timer : TON;    (* Damit wir alles realisiert *)
    cnt   : UINT;    (* Counter *)
    step  : USINT;    (* Schrittkette *)
END_VAR

Timer();        (* Immer laufen lassen *)

(* Nun die Schrittkette abarbeiten *)
CASE step OF

    0:    (*  INT: Am Anfang alles einstellen, nullstellen etc.*)
        cnt         := 0;
        Timer.IN     := FALSE;
        Q             := FALSE;
        BUSY         := FALSE;

        IF START THEN
            step := 10;
        END_IF

    10:    (* Es geht los: Timer fuellen und aktivieren fuer High *)
        Q      := TRUE;
        BUSY := TRUE;

        Timer.PT := PTH;
        Timer.IN := TRUE;
        IF Timer.Q THEN
            Timer.IN := FALSE;
            step      := 20;
        END_IF

    20:    (* Arbeitstakt ist zu ende, Nun Zaehlen und ggf. mit Pause weiter oder Ende *)
        Q     := FALSE;
        cnt := cnt +1;

        IF cnt < N THEN
            step := 30;
        ELSE
            step := 0;
        END_IF

    30:    (* Identisch mit 10, jedoch Pausentakt, könnte man alles mit Toggle-Vars erledigen *)
        Q          := FALSE;
        Timer.PT := PTL;
        Timer.IN := TRUE;

        IF Timer.Q THEN
            Timer.IN := FALSE;
            step      := 10;
        END_IF


END_CASE



END_FUNCTION_BLOCK
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Wer kann sich etwas unter "Flankengetriggertes Wischrelais" vorstellen?

Bei der LOGO ist das eine Sonderfunktion:

"Kurzbeschreibung
Ein Eingangsimpuls erzeugt nach einer parametrierbaren Zeit am Ausgang eine parametrierbare
Anzahl Signale von parametrierbarer Ein-/Aus-Dauer (retriggerbar)."

Ist das nicht genau das, was hier gesucht wird? Zur Not die anfängliche Verzögerung auf ein erträgliches Mass reduzieren und die Retriggerbarkeit austricksen?

Für den Fall, dass es doch lieber SCL sein soll, mit dem Zähler als "führendem Element" und absolut ungetestet:
Code:
// Jede PulsFolge besteht aus n_pulses Pulsen und n_pulses Pausen.
// Sie beginnt mit dem ersten Puls und endet mit der letzten Pause.
// Der counter wird mit 2 * n_pulses geladen, sofern er auf 0 steht UND run = TRUE ist.
// Bei jedem Ablaufen einer Puls- oder Pause-Zeit wird counter dekrementiert bis counter=0.
// Es werden 3 Zustände unterschieden:
// - counter = 0 : idle (= NOT busy) - die Ausgabe einer PulsFolge ist inaktiv.
// - counter enthält eine gerade Zahl <> 0: TON_Pulse läuft mit hi_time.
// - counter enthält eine ungerade Zahl: TON_Pause läuft mit lo_time.
// Durch Laden oder Dekrementieren von counter wechselt der Zustand und
// dadurch wird der entsprechende TON gestartet. 
// Das Laden des counter (= Start der Ausgabe einer PulsFolge) geschieht, wenn
// - schon oder noch run=TRUE ist und der counter in den Zustand idle übergeht,
// - sich der counter im Zustand idle befindet und run in den Zustand TRUE wechselt.
FUNCTION_BLOCK FB_Taktgeber
VAR_INPUT   
    run       : BOOL;  
    n_pulses  : INT;  
    hi_time   : TIME;  
    lo_time   : TIME;  
    END_VAR  
   
VAR_OUTPUT   
    pulse     : BOOL;  
    busy      : BOOL;  
    END_VAR  
   
VAR    
    counter   : INT;  
    TON_Pulse : TON;  
    TON_Pause : TON;  
    END_VAR  
   
VAR_TEMP   
    odd       : BOOL;  
    END_VAR  
   
// Zähler laden ==> PulsFolge Starten 
IF (counter = 0) AND run THEN  
    counter := n_pulses * 2; // Anzahl Pulse + Anzahl Pausen
    END_IF;
// Zähler: 0 ==> inaktiv, ungerade ==> Pause, gerade UND counter<>0 ==> Puls 
odd := (counter MOD 2)<>0;  
// Timer starten 
TON_Pulse(IN:=(counter<>0) XOR odd, PT:=hi_time); 
TON_Pause(IN:=odd, PT:=lo_time); 
// Zähler dekrementieren bei Ablauf von Puls oder Pause 
IF TON_Pulse.Q OR TON_Pause.Q THEN 
    counter := counter - 1;
    END_IF;
// Ausgänge 
busy := counter<>0; // PulsFolge ausgeben ist aktiv 
pulse := ((counter MOD 2)<>0) XOR busy; 
END_FUNCTION_BLOCK
PulsFolgeBsp3.jpg
 
Zuletzt bearbeitet:
Zurück
Oben