# Systematik Bits in codesys



## SY50 (27 Februar 2015)

*Systemtakt Bits in codesys*

Hallo, gibt es bei einer codesys runtime auch Systemtakt Bits, wie die taktmerker bei Siemens?


----------



## RobiHerb (28 Februar 2015)

Mir ist nichts derartiges im Standard Codesys bekannt. Es kann aber sein, dass einer der Hardware Hersteller so etwas für seine PLC mit in die Firmware gepackt hat.


----------



## MasterOhh (28 Februar 2015)

Alle 50ms ein Byte um 1 erhöhen und schon hat man seine 8 Taktmerker Bits. 
Völlig unnötig soetwas hardwaremäßig fest zu rammeln, vorallem weil es so nur feste Teiler gibt und man sich sowieso alle anderen Frequenzen zurecht basteln muss.


----------



## mac203 (2 März 2015)

Vielleicht ne dumme Frage, aber wozu braucht man das (bei Siemens) ?


----------



## excelite (3 März 2015)

*Blink FB aus util.lib*

Hi Sy50,

nein gibt es nicht, aber es gibt die Bibliothek "util.lib" da ist ein "blink" FB drin. Den kannst du aufrufen und deinen Takt vorgeben. Du kannst im Prinzip jeden Takt abbilden sofern die Zeitvorgaben im Taskkontext sinnvoll sind. z.B. solltest du nicht eine Task mit 2s aufrufen und den Blink FB mit 10ms blinken lassen das wäre quatsch. 

@max203: Siemensprogrammierer nutzen das z.B.: um zyklisch irgend einen Zustand abzuprüfen oder ganz einfach die rote Lampe bei Fehler blinken lassen ala:

U Error
U M0.0
= Lampe an

hier ist das Merkerbyte 0 als Taktmerker definiert. M0.0 bis M0.7 haben eine feste Frequenz bzw. 1Hz, 2Hz,...

Ich hoffe geholfen zu haben.

Gruße excelite

Edit: Von harten Zählern wie vorgeschlagen, die jeden Zyklus hochzuzählen würde ich absehen da du im Falle, dass dein Code wiederverwendet werden soll immer beachten musst, dass die Task gleich aufgerufen wird wie beim letzten Mal. Außerdem kann es bei der Entwicklung eines Projektes dazu kommen dass Codeteile von einer Task ausgelagert werden in eine andere und dann der Ablauf nicht mehr sinnvoll arbeitet da nun eine andere Basis gilt. 
OK es gibt Funktionen die dir die aktuelle Taskzeit zurückgeben und du könntest das berücksichtigen beim hochzählen,... aber das macht alles kompliziert. Außerdem funktioniert das nicht bei Freewheel/freilaufenden Tasks. 

==> Beste Lösung: Blink FB nehmen oder selbst einen FB schreiben falls man die Bibliothek nicht verwenden möchte.


----------



## PN/DP (3 März 2015)

mac203 schrieb:


> Vielleicht ne dumme Frage, aber wozu braucht man das (bei Siemens) ?


Zur Zeitersparnis beim Erstellen der fast immer benötigten Blink-Bits. Außerdem gibt es nicht wenige Programmierer, welche die einfache Lösung mit dem 8-Bit-Zähler nicht kennen und die Aufgabe furchtbar umständlich lösen.
Außerdem sind die Systemtakt-Bits viel Zeit-genauer als mit Timern erstellte und zueinander phasenstarr. Vergleichbar genaue Taktbits kann man nicht mit Blink-FB in freilaufenden Task erzeugen sondern muß sie in Task mit festem Aufrufraster erzeugen. Und da wird es auch schon wieder komplizierter als einfach fertige Taktbits zu nutzen.

Harald


----------



## mac203 (3 März 2015)

Vielen Dank.
Es amüsiert doch immer wieder, wie "seltsam" bei Siemens manches gelöst ist.
Aber stimmt natürlich, ohne feste Zykluszeit wirds schwer einen solchen Blinker zu realisieren...
Bin da zu sehr in der komfortablen CoDeSys Welt verwurzelt....


----------



## MasterOhh (3 März 2015)

Jo bei Siemens ist so ein Taktmerker sicher noch sinnvoll weil der Standardzyklus nicht isochron ist. Viele Steuerungen (die meisten ?) arbeiten aber mittlerweile mit festen Taskzyklen deren Jitter max. im 2 stelligem µs Bereich liegt. Da funktionieren Timer schon recht genau.


----------



## HeHo (10 März 2015)

Hallo,
ich habe eine Funktion entwickelt die den Siemens Taktmerker recht genau und Recourcenschonend nachbildet (100,200,400,500,800,1000,1600,2000 ms) die funktioniert auch in freilaufenden Tasks, da die unterschiedlichen Zykluszeiten ausgeglichen werden. Funktioniert auch in der Simulation mit 65ms Zykluszeit!!! Allerdings ist dann der 100ms Takt relativ unterschiedlich ca. +- 30ms
Bei Interesse bitte Posten dann kann ich die Lib ja mal zum Testen einstellen.
Gruß


----------



## PN/DP (10 März 2015)

HeHo schrieb:


> Hallo,
> ich habe eine Funktion entwickelt die den Siemens Taktmerker recht genau und Recourcenschonend nachbildet (100,200,400,500,800,1000,1600,2000 ms) die funktioniert auch in freilaufenden Tasks, da die unterschiedlichen Zykluszeiten ausgeglichen werden. Funktioniert auch in der Simulation mit 65ms Zykluszeit!!! Allerdings ist dann der 100ms Takt relativ unterschiedlich ca. +- 30ms
> Bei Interesse bitte Posten dann kann ich die Lib ja mal zum Testen einstellen.
> Gruß


Ich habe Interesse, den Quelltext zu sehen, mit dem man "die Siemens Taktmerker recht genau und Recourcenschonend nachbildet" in freilaufenden Tasks.
Zeige uns den doch mal bitte.

Harald


----------



## HeHo (10 März 2015)

hallo harald,
bin heute abend(nachts) wieder an meinem entwicklungsrechner ;-)
werde dann mal ein demoprojekt posten

gruß


----------



## HeHo (11 März 2015)

Teil 1:
um und auf ist ein pulsgenerator der einen 100ms impuls liefert.
der impuls muss aber im durchschnitt!!! passen.
anbei eine meiner funktionen die genau das macht,
man kann den durchschnittlichen pulsinterval angeben ;-)

der rest zum taktmerker ist nur bitlogik und in ST ein zweizeiler! :razz::wink::grin:

gruß


```
FUNCTION_BLOCK _ah_Pulse_Gen
VAR_INPUT
    tmsec : DWORD;
END_VAR
VAR_OUTPUT
    Q : BOOL;
END_VAR
VAR
    finit : BOOL;
    t_old : BYTE;
    t_sum : DWORD;
END_VAR
VAR_TEMP
    t_now : BYTE;
END_VAR

(*
version 1.0    6. mar. 2013
programmer     horst
tested by    ???

Die Funktion startet mit einer positiven Flanke und erzeugt alle angegebenen Millisekunden wieder eine Flanke
wobei die Zykluszeiten ausgeglichen werden. D.h.z.B. 100+1 Impulse zu 100ms ergeben auch 10 Sekunden;-)  
*)
(* @END_DECLARATION := '0' *)


t_now    := TIME_TO_BYTE(TIME());
t_sum    := t_sum + SEL(finit, tmsec,t_now - t_old);
t_old    := t_now;

Q    := t_sum >= tmsec;

IF Q THEN
    t_sum := t_sum - tmsec;
    finit := TRUE;
END_IF;

END_FUNCTION_BLOCK
```


----------



## HeHo (12 März 2015)

*HeHo_Util_1.lib*

Anbei die LIB mit 2 Funktionen.
Hoffe es ist selbsterklärend.
bei der Datei einfach das .zip weglöschen.

gruß

Anhang anzeigen HeHo_Util_1.lib.zip


----------



## PN/DP (12 März 2015)

HeHo schrieb:


> Anbei die LIB mit 2 Funktionen.
> Hoffe es ist selbsterklärend.
> bei der Datei einfach das .zip weglöschen.


Schade, daß man um die paar Byte Lib zu sehen erst hunderte Megabyte Software installieren muß.

Ist Dein Programm in ST? Kannst Du das einfach als Textdatei hier hochladen oder direkt posten? Oder ein Bild von dem Quelltext, damit man einen Überblick über den Code bekommt?

Harald


----------



## HeHo (12 März 2015)

gelöscht weil doppelt


----------



## HeHo (12 März 2015)

habe gestern schon die kernfunktion und eben wieder als code im post eingestellt!!!
aber ich bekomme die meldung das es erst vom admin freigeschalten werden muss?!?


----------



## HeHo (12 März 2015)

*FUNCTION_BLOCK _ah_Pulse_Gen*

nochmal als *.txt anhang

kernstück ist die funktion die es ermöglicht alle xx millisekunden eine flanke
zu generieren wobei zykluszeiten ausgeglichen werden müssen.
mit der funktion wird ein 100ms takt erzeugt und der rest auf den "taktmerker"
ist nur noch "bitlogik" und in ST ein zweizeiler.
in der realität sind die 100ms zykluszeitabhängig aber der durchschnitt passt.

Anhang anzeigen _AH_PULSE_GEN.txt


----------



## PN/DP (12 März 2015)

Ah, OK, Du summierst die Zeitdauer des vergangenen freien Zyklus. Die Taktzeit schwankt dann also um bis zu einer Zykluszeit, was aber nicht schlimm ist, weil die Taktmerker ja auch so schwankend abgefragt werden.

Und wie sieht der Zweizeiler aus zur Erzeugung der 8 Taktmerkerbits  (100, 200, 400, 500, 800, 1000, 1600, 2000 ms)?

Harald


----------



## HeHo (12 März 2015)

b_500, xtakt : byte;

b_500 := (b_500 OR MUX(b_500 AND 2#0000_0111,  2#0101_0011, 0))+1;
xtakt := (((xtakt OR 2#0010_1000)+1) AND 2#0101_0111) OR (b_500 AND 2#1010_1000);

PS: feedback erwünscht


----------



## HeHo (12 März 2015)

> Ah, OK, Du summierst die Zeitdauer des vergangenen freien Zyklus. Die  Taktzeit schwankt dann also um bis zu einer Zykluszeit, was aber nicht  schlimm ist, weil die Taktmerker ja auch so schwankend abgefragt werden.



wobei aber die mehrzeit für die nächste periode berücksichtigt wird

horst


----------



## PN/DP (12 März 2015)

HeHo schrieb:


> b_500, xtakt : byte;
> 
> b_500 := (b_500 OR MUX(b_500 AND 2#0000_0111,  2#0101_0011, 0))+1;
> xtakt := (((xtakt OR 2#0010_1000)+1) AND 2#0101_0111) OR (b_500 AND 2#1010_1000);


OK 
	

	
	
		
		

		
			





, viele Programmierer hätten das weitaus umständlicher gelöst.

Man sieht aber schon, daß es effizienter und bequemer ist, einfach ein Taktmerker-Byte aus der Firmware zu nutzen, als dies selber zu erzeugen. Taktmerker/Blinkmerker braucht man ja eigentlich immer.


PS: man sollte noch erwähnen, daß der Zweizeiler immer ausgeführt werden muß, wenn der Q von dem FB _ah_Pulse_Gen TRUE ist.

Harald


----------



## HeHo (12 März 2015)

PN/DP schrieb:


> man sollte noch erwähnen, daß der Zweizeiler immer ausgeführt werden muß, wenn der Q von dem FB _ah_Pulse_Gen TRUE ist.



in der lib ist die funktion "_ah_Taktmerker" noch etwas optimiert und eigenständig,
die funktion wird auch intern ohne den pulsegenerator ausgeführt 
der pulsgenerator dient nur für eigenständige pulse

die deklaration im hauptprogramm sieht dann so aus



> PROGRAM PLC_PRG
> VAR
> takt : _ah_Taktmerker;
> x : BYTE;
> END_VAR



im programmteil wird dann die funktion jeden zyklus aufgerufen



> takt(xtakt := x);


----------



## HeHo (12 März 2015)

einen im durchschnitt genauen 100ms takt zu erzeugen geht auch kürzer!
aber die lösung ist einmal in ca. 50 tagen nicht genau (timer überlauf) 



> t_now    := TIME() / 100;
> 
> IF t_now <> t_old THEN
> t_old    := t_now;
> ...


----------



## HaraldT (15 April 2017)

Guten Tag,

ich weiß dass dieser Thread sehr alt ist aber trotzdem finde ich die Funktion von HeHo sehr gut.
Wenn ich seine Lib in der Simulation verwende dann ist alles okay.

Möchte ich das Projekt auf den Wago 750-880 Controller übertragen, dann bekomme ich den Fehler:
Folgende Funktionen konnten nicht gebunden werden


Laut Forenbeiträgen tritt dieser Fehler auf, wenn die Bibliothek als externe statt als interne gespeichert wurde.
Die Bibliothek ist Passwortgeschützt und lässt sich für mich nicht öffnen und damit neu speichern.


Über eine Antwort und eventuelle Hilfe würde ich mich freuen.

Schöne Ostern
Harald

PS. HeHo hatte ich bereits eine PM geschickt aber leider keine Antwort erhalten (bis jetzt)


----------



## HeHo (18 April 2017)

Hallo Harald,
jeweils als interne und externe Lib gespeichert.
PS: ich verwende absolut keine andere Lib in meinem Projekt!
Gruß


----------



## Mobi (4 Februar 2021)

Hey,

ich weiß auch, dass dieser Thread nun schon "ziemlich" alt ist, aber denke mal, dass ist und bleibt aktuell.
Der Vollständigkeit halber will ich meins auch mal zeigen.

Kommt ganz normal in PLC_PRG rein und wird alle 10ms aufgerufen. (Leider kennt die Forensoftware keine Tabs )

```
// MainTask wird alle 10ms aufgerufen
//Bits                   %MX0.7    %MX0.6    %MX0.5    %MX0.4    %MX0.3    %MX0.2    %MX0.1    %MX0.0
//Frequenz in Hz          0,5        0,625    1        1,25    2        2,5        5        10
//Periodendauer in Sek.    2        1,6        1        0,8        0,5        0,4        0,2        0,1
bCycles50MS := bCycles50MS - BYTE#1;
IF bCycles50MS = 0 THEN
    b50MS := b50MS + BYTE#1;
    bCycles50MS := 5;
END_IF


bCycles250MS := bCycles250MS - BYTE#1;
IF bCycles250MS = 0 THEN
    b250MS := b250MS + BYTE#1;
    bCycles250MS := 25;
END_IF


%MX0.0 := b50MS.0;
%MX0.1 := b50MS.1;
%MX0.2 := b50MS.2;
%MX0.3 := b250MS.0;
%MX0.4 := b50MS.3;
%MX0.5 := b250MS.1;
%MX0.6 := b50MS.4;
%MX0.7 := b250MS.2;
```


----------

