Zähler für Dumi

Genius2222

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

Erst mal will mich kurz vorstellen.
bin 36 und Schlosser. Und programmiere nur so zum Spaß.

Ich brauch eine Zähler wie CTU nur er mus weiter Zählen als 32767

Wie geht das.

MFG
Genius
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Dann bau dir einen eigenen Zähler-FB der ein DWORD verwendet:

Bsp in ST:

Code:
VAR_INPUT
  CU :BOOL;
  Reset :BOOL;
END_VAR
VAR_OUTPUT
  Q :BOOL;
  CV :DWORD;
END_VAR
VAR
  M :BOOL;
END_VAR

(*Aufaddieren bei steigender Flanke an CU*)
IF CU and not M THEN
  CV := CV+1;
END_IF

M := CU; (*Flankermerker setzen*)

(*Reset Zähler*)
IF Reset THEN
  CV:=0;
END_IF

Q := CV = 16#FFFFFFFF; (*Signal bei Erreichen des DWORD End-Werts*)

Ich weiss jetzt nicht wie sich der offizielle CTU beim erreichen des Endwertes verhält. Bleibt der auf dem Wert bis ein reset kommt, oder springt er automatisch auf 0 zurück (überlauf)?
Der Zähler im Beispiel läuft einfach über und springt auf 0 zurück.
 
Zuletzt bearbeitet:
Wie weit Zählt der Zähler?

Änderung ich hab ihn getestete und gesehen er geht nur bis 10.

Wieso das?
 
Zuletzt bearbeitet:
Wie weit Zählt der Zähler?
Mit DWORD kann man bis 4.294.967.295 zählen (0 bis DW#16#FFFFFFFF). (DWORD ist eigentlich nicht korrekt, es müßte ein DINT oder UDINT verwendet werden.)

Änderung ich hab ihn getestete und gesehen er geht nur bis 10.
Dann hast Du irgendwas falsch gemacht. Hast Du den Baustein als FB programmiert oder als Function?

Harald
 
Zuletzt bearbeitet:
So hab den Fehler gefunden.
Aber wie bekomme ich es hin das der Zähler nach neustart der Steuerung gespeichert bleibt?
Beim CTU konnte ich ja die Variablen Deklarieren.
 
wenn Du o.g. Code verwendest hast Du doch im oberen Teil ebenfalls Variablen deklariert - wo ist da der Unterschied zu dem fertigen Baustein?
 
Ja, der unterschied liegt daran, das Du den CTU mit einer Variable von außen beschaltest - diese ist im Hauptprogramm deklariert oder global.
Interne Variablen einer Funktion oder eines Unterprogramms sind aber nur in diesem bekannt.

Die Variable CV ist als Var_out deklariert - damit stellt sie (bei FUP-Darstellung) einen Ausgang aus dem Funktionsblock zur Verfügung an denen Du Deine Variable (nennen wir sie mal ZÄHLWERT) schreibst, in die das Ergebnis geschrieben werden soll. Diese Ergebnis-Variable ZÄHLWERT könnte man speichernd machen, das hat aber zur Folge, das in Deiner Variable ZÄHLWERT beim Wiederanlauf ein Wert drin steht, Dein Zähler aber bei null startet...
Beim nächsten schreiben auf die Variable wird diese auf den aktuellen Wert des Zählers gesetzt - ist also keine Lösung für Dein Problem.

Um das Problem besser zu verstehen:
Versuch mal die Variable CV global zu deklarieren und dann als Retain bzw. Persistent. Dann solltest Du diese Variable direkt weiterverwenden können in anderen Programmteilen und der Zähler sollte beim Wiederanlauf den Wert noch haben.
Problematisch bei dieser Lösung ist, das Du den Schreibzugriff auf CV dann nicht auf bestimmte Programmteile (z.B. Deinen Zähler) beschränken kannst - d.h. wenn irgendein anderes Code-Schnippsel auf die Variable CV SCHREIBEND zugreift, so zerhaut es Dir den Zähler.

Ich denke die "sauberste" Lösung wäre, CV global zu machen und damit den aktuellen Wert über den Spannungsausfall zu retten - gleichzeitig im Zähler eine Out-Variable zu haben, die den Wert von CV abbildet. Damit kannst Du außerhalb des Zählers mit Deiner Variable ZÄHLWERT weiterarbeiten.
ABER: Wenn Du das Programm kopierst, weil Du einen zweiten, unabhängigen Zähler brauchst musst Du zwingend CV umbenennen - sonst greifen alle Deine Zähler auf die selbe globale Variable zu...

Ich hoffe das hat ein klein wenig weitergeholfen
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich denke die "sauberste" Lösung wäre, CV global zu machen und damit den aktuellen Wert über den Spannungsausfall zu retten - gleichzeitig im Zähler eine Out-Variable zu haben, die den Wert von CV abbildet. Damit kannst Du außerhalb des Zählers mit Deiner Variable ZÄHLWERT weiterarbeiten.
ABER: Wenn Du das Programm kopierst, weil Du einen zweiten, unabhängigen Zähler brauchst musst Du zwingend CV umbenennen - sonst greifen alle Deine Zähler auf die selbe globale Variable zu...
Also dieses Kuddelmuddel mit globalen Variablen in Instanzen würde mir überhaupt nicht gefallen. Da kann man dann ja gar nicht mehr mehrere unabhängige Instanzen deklarieren.

Kann man denn nicht einfach die ganze Zähler-Instanz als RETAIN+PERSISTENT deklarieren?
Oder CV und M als VAR_IN_OUT deklarieren und mit RETAIN+PERSISTENT-Variablen beschalten?

Harald
 
Hallo Harald,

ich gebe Dir recht, daher hatte ich das "sauber" in Anführungszeichen gesetzt. Schön ist das so nicht.
Den Weg, die gewünschten Variablen als Var_out zu beschalten hatte ich ja oben schon beschrieben.
Würde man stattdessen Var_In_Out wählen, so muss in dem Code zunächst die bestehende Variable eingelesen werden - diese sollte ja eigentlich den selben Wert haben wie die interne - dann wird inkrementiert und dann die Variable wieder geschrieben.
Von der Logik her sollte das gehen - müsste ich mal ausprobieren, ob das wirklich sauber läuft.

Kann man denn nicht einfach die ganze Zähler-Instanz als RETAIN+PERSISTENT deklarieren?
Die Antwort, ob der Code beim TE in einer Funktion, Funktionsblock oder einem Programm läuft ist er uns leider noch schuldig geblieben.
Ich war einfach mal von einem Programm ausgegangen.

Ich bin mir nicht sicher, ob das so geht - zumindest bleibt die Problematik, das die Variablen nicht außerhalb der jeweiligen POU bekannt sind.
 
Stimmt bin sie aber nicht mit Absicht schuldig geblieben.

Es läuft im Als Funktionsblock.

Gesendet von meinem C6603 mit Tapatalk
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Es läuft im Als Funktionsblock.

Wie schon erwähnt ist es für einen einfachen Zähler eigentlich übertrieben den als FB zu deklarieren.
Ich mach die immer so.

Code:
FUNCTION "Betriebsstunden" : VOID
TITLE =
VERSION : 0.1




VAR_INPUT
  Obj : BOOL ;    //Objekt dessen Betriebsstunden zu zählen sind
  Sekundentakt : BOOL ;    //Sekundentakt (achtung darf nur ein Zyklus je Sekunde anstehen)
END_VAR
VAR_IN_OUT
  Save : DINT ;    //Betriebsstundenzähler inhalt in Sekunden
END_VAR
BEGIN
NETWORK
TITLE =


      U     #Obj; 
      U     #Sekundentakt; 
      SPBN  Upcn; 
      L     #Save; 
      L     1; 
      +D    ; 
      T     #Save; 
Upcn: NOP   0; 


END_FUNCTION

An IN_OUT hängt man dann einfach eine Remanente Variable, ob das nun ein Merker oder DB ist, ist irrelevant. Ich bevorzuge Merker und Mappe diese um wenn ich sie auf nem DB brauche, da es ja immerwieder mal passieren kann (vor allem in TIA) das ein DB geladen und reinitialisiert wird und die Werte wieder die Startwerte annehmen.

mfG René
 
Zurück
Oben