Frequenzberechnung in SCL

M-Arens

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

ich habe ein kleines Problem. Ich soll eine Frequenzmessung programmieren, nach möglichkeit in SCL.
Dabei habe ich als zu verarbeitende Eingangsgröße nur ein Impuls der mir nach jeder Periode auf dem Scheitelwert gegeben wird. Das heißt der abstand zwischen 2 Impulsen ist meine Zeit T.
Als Ausgabe, soll die Frequenz im Real Format rauskommen.
Kann mir einer sagen wie man so was realisieren kann?

Vielen DANK für eure HILFE.
 
Mal eine Frage vorne weg. In welchem bereich bewegt sich die Frequenz denn?
von 0Hz...xxHz ??
 
@M-Arens

SCL ist nicht schlimm, du kannst dir erstmal einen neuen Baustein öffnen und dann einen kompletten Bausteinrahmen für FC/FB automatisch erzeugen lassen. Der Rest ist etwas Rechnerei für die Frequenz, das ist mit der Hilfefunktion zu bewältigen. Bei konkreten Fragen helfen wir sicher gern. Ich würde auch den OB35 hernehmen, anders geht es wahrscheinlich gar nicht.
Der OB wird in einem festen Zeitintervall aufgerufen. Jedesmal zählst du in ihm einen DINT-Wert um 1 hoch. Wenn du dein Spitzenpegelsignal bekommst, liest du diesen Wert aus und setzt ihn anschließend auf Null zurück (könnte auch besser sein, daß du dann einen Resetmerker in deinem SCL-Baustein setzt und wenn dieser True ist, in deinem OB35 das Null setzen des Zähler-DINT erledigst.) Mit dem Zählwert kannst du dann die Frequenz berechnen.
 
Habe jetzt ein kleines Problem mit dem SCL Programm, hier mal der Code
Code:
IF Impuls = true THEN
    T := Zaehlwert/10 ;
    T_REAL := DINT_TO_REAL ( T );
    F_REAL := 1/T_REAL ;
    Frequenz := ROUND(F_REAL) ;
    
    [B]IF Freigabe = true THEN
      Frequenz := ROUND(F_REAL) ;
      Freigabe := false ;
    END_IF;[/B]

    Reset := true;
    
  ELSE
    // Anweisungsteil_ELSE
    Reset := false;
    Freigabe := true ;
  END_IF;

Der Makierte Code teil soll nur einmal ausgeführt werden solange Impuls=true ist. Klappt aber nicht, kann mir einer erklären was ich da falsch mache?

Es soll halt die Frequenz berechnet werden, aber nur einmal pro Impuls raus gegeben werden, damit die Anzeige nicht ständig den Wert ändert.
 
Du musst wahrscheinlich noch Impuls auf false setzen.
Das geht nicht das ist eine Eingangs Variable die von außen beschaltet wird.

Hier sind noch die Variablen.
Code:
// Bausteinparameter
VAR_INPUT
  // Eingangsparameter
  Impuls    : BOOL;
  Zaehlwert  : DINT;     //Zählwert *100 = T in ms
END_VAR

VAR_IN_OUT
  // Durchgangsparameter
  Freigabe  : BOOL;
END_VAR

VAR_OUTPUT
 // Ausgangsparameter
  Reset     : BOOL;     //Rücksetzen des Zählers im OB35
  Frequenz  : DINT;     //Frequenz im REAL Format  
END_VAR

VAR_TEMP
  // temporäre Variablen
  T         : DINT;     //Zeitwert T als DINT
  T_REAL    : REAL;     //Zeitwert T als Real
  F_REAL    : REAL;     //Frequenz F als Real
END_VAR
 
Zuletzt bearbeitet:
Probiers mal so. Impuls_Fl als Boolsche Variable (statisch oder IN_OUT) definieren

Code:
IF Impuls = true  and not Impuls_Fl THEN
    T := Zaehlwert/10 ;
...
     END_IF;
Impuls_Fl := Implus

hth
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Probiers mal so. Impuls_Fl als Boolsche Variable (statisch oder IN_OUT) definieren

Code:
IF Impuls = true  and not Impuls_Fl THEN
    T := Zaehlwert/10 ;
...
     END_IF;
Impuls_Fl := Implus
hth
So klappt es gar nicht, da wird die If Bedingung nie erfüllt.
Code:
VAR_INPUT
  // Eingangsparameter
  Impuls    : BOOL;
  Zaehlwert  : DINT;     //Zählwert *100 = T in ms
END_VAR

VAR_IN_OUT
  // Durchgangsparameter
  Freigabe  : BOOL;
  Impuls_Fl : BOOL;
END_VAR

VAR_OUTPUT
 // Ausgangsparameter
  Reset     : BOOL;     //Rücksetzen des Zählers im OB35
  Frequenz  : DINT;     //Frequenz im REAL Format  
END_VAR

VAR_TEMP
  // temporäre Variablen
  T         : DINT;     //Zeitwert T als DINT
  T_REAL    : REAL;     //Zeitwert T als Real
  F_REAL    : REAL;     //Frequenz F als Real
END_VAR

  // Anweisungsteil
  // Zeitwert T auslesen und angleichen
  IF Impuls = true AND NOT Impuls_Fl THEN
    T := Zaehlwert/10 ;
    T_REAL := DINT_TO_REAL ( T );
    F_REAL := 1/T_REAL ;
    Frequenz := ROUND(F_REAL) ;
    
    IF Freigabe = true THEN
      Frequenz := ROUND(F_REAL) ;
      Freigabe := false ;
    END_IF;
    
    Impuls_Fl := Impuls;
    Reset := true;
    
  ELSE
    // Anweisungsteil_ELSE
    Reset := false;
    Freigabe := true ;
  END_IF;
 
Du musst:


Impuls_Fl := Impuls

natürlich ausserhalb deiner IF-Schleife setzen.


Mit was hast du die neue IN-OUT variable beschaltet ?

hth
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Also Irgendwie versteh ich deine Aufgabenstellung nicht so ganz, was soll der Baustein ausgeben, wenn kein Impuls da ist? Dir fehlt die Zuweisung dafür.

Wenn ich's richtig verstehe steht Imuls einige Zeit an und dabe soll einmal die Freigabeschleife durchgeführt werden?

Wenn ja, mach die Flankenabfrag halt in die innere IF-Schleife.

hth
 
Also wenn der Impuls ansteht soll der einmal die If schleife durchlaufen werden und dann das ergebnis in dem Ausgang Frequenz gespeichert werden. bis zum nächsten Impuls.
 
Und wann wird das Freigabesignal gesetzt, bzw. wo kommt es her?

Du solltest hierfür auf jeden Fall einen FB verwenden, falls noch nicht geschehen.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Du musst:


Impuls_Fl := Impuls

natürlich ausserhalb deiner IF-Schleife setzen.


hth

Das muß du ganz sicher so machen, Impuls_FI soll immer den Wert von Imuls zugewiesen bekommen und zwar nach Ausführung deines SCL-Bausteines, also am Ende. Wenn dann der Eingang (Impuls ist ein Eingang, wenn ich das richtig in Erinnerung habe) von False auf True wechselt ist Impuls_Fl noch False und zwar genau ein Mal.
Die Bedingeung If Impuls and not Impulse_Fl ist jetzt erfüllt.
Am Ende des Bausteins Imuls_Fl := Impuls.
Beim nächsten Durchgang dann ist deine Bedingung nicht erfüllt, da Impuls True und Impuls_Fl True. Wenn dann Impuls wieder False wird, ist deine Bedingung nicht erfüllt, da Impuls False und Impuls_Fl True.
Hier kommts jetzt, in deinem Code wird Impuls_Fl nie mehr False!!! Deshalb ans Ende mit der Zeile.
Ich würde RESET als INOUT-Variable anlegen und im OB35 zurücksetzen. Wenn der OB35 das Reset ausgeführt hat, soll er RESET False setze, sonst ist das nicht sicher, je nachdem ob der OB35 öfter aufgerufen wird als das restliche Programm, oder umgekehrt (Die SPS könnte auch mal 40ms Zykluszeit haben)
 
Also ich habe das alles jetzt mal in einen FB gemacht, aber der Aufruf kommt trotzdem nicht bei jedem Impuls.
Zum Testen habe ich an den Impuls Eingang einen Taktmerker mit 2Hz geschltet, mein OB 35 wird alle 10ms aufgerufen und zählt bei jedem auf 1 bei meinem Zählwert hinzu. Zurückgesetzt auf 0 wird der Zählwert wenn der Reset ausgang aus meinem Baustein kommt (habe Ihn jetzt mal als In-Out gemacht).
So, das ist jetzt mal der ganze FB:
Code:
FUNCTION_BLOCK FB102
TITLE = 'Frequenzberechnung'
//
// In diesem Baustein wird die Frequenz berechnet mit der, der
// Druck auf und abgebaut wird.
//
VERSION : '1.0'
AUTHOR  : MA
NAME    : F_Ber
FAMILY  : Tools


// Bausteinparameter
VAR_INPUT
  // Eingangsparameter
  Impuls    : BOOL;
  Zaehlwert  : DINT;     //Zählwert *100 = T in ms
END_VAR

VAR_IN_OUT
  // Durchgangsparameter
  Reset     : BOOL;     //Rücksetzen des Zählers im OB35
END_VAR

VAR_OUTPUT
 // Ausgangsparameter
 Frequenz  : DINT;     //Frequenz im REAL Format  
END_VAR

VAR_TEMP
  // temporäre Variablen

END_VAR
VAR
  // statische Variablen
  T         : DINT;     //Zeitwert T als DINT
  T_REAL    : REAL;     //Zeitwert T als Real
  F_REAL    : REAL;     //Frequenz F als Real
  Freigabe  : BOOL;
  Impuls_Fl : BOOL;
END_VAR

  // Anweisungsteil
  // Zeitwert T auslesen und angleichen
  IF Impuls = true AND NOT Impuls_Fl THEN
    T := Zaehlwert/10 ;
    T_REAL := DINT_TO_REAL ( T );
    F_REAL := 1/T_REAL ;
    Frequenz := ROUND(F_REAL) ;
    
       
    Reset := true;
    
  ELSE
    // Anweisungsteil_ELSE
    Reset := false;

  END_IF;
  
  Impuls_Fl := Impuls;
END_FUNCTION_BLOCK

Aber ich habe da noch ein Problem, wenn die Schleife ausgeführt wird, bekomme ich bei dieser Zeile F_REAL := 1/T_REAL ; ein falsches ergebnis.
T_REAL = 5.00 und er berechnet mir für F_REAL einen negativen Wert. Schaut es euch selber im Bild an.
 

Anhänge

  • sshot-1.jpg
    sshot-1.jpg
    95 KB · Aufrufe: 19
sorry, ich kann da keine negativen Wert erkennen !?

Wo soll der sein?

Ausserdem müßte der Zählwert doch eher f sein, dein FB funktioniert irgendwie grad reziprok (falschrum/Kehrwert)
 
Zuletzt bearbeitet:
Zurück
Oben