Jump to content
PLC Forum


Sign in to follow this  
simonegr

Contatore a tempo

Recommended Posts

simonegr

Ciao a tutti,

 

forse è una cavolata da fare, ma vorrei fare un contatore a tempo che quando lo richiamo mi aumenta una variabile ogni tot. secondi

 

Grazie mille

Share this post


Link to post
Share on other sites

Livio Orsini

Imposti un timer con il tempo che ti necessita ed alla scadenza del timer incrementi la mtua variabile.

Share this post


Link to post
Share on other sites
simonegr

Grazie mille,

 

ho buttato giù questa roba

 

IF "Tag_28" = 1 THEN
    #"#Avvio" := 0;
    GOTO fine_ciclo;
ELSE
    #"#Avvio" := 1;
END_IF;
"IEC_Timer_0_DB".TP(IN := #"#Avvio",
                    PT := T#40s,
                    Q => "Tag_28",
                    ET => #"#Time_outti");

#"#Avvio" := 0;
#"#Contatore" := #"#Contatore" + 1;
fine_ciclo:;
 
ma non funziona in quanto il Tag_28 non va mai ad 1

Share this post


Link to post
Share on other sites
pigroplc
IF "Tag_28" = 1 THEN
    #"#Avvio" := 0;
	#"#Contatore" := #"#Contatore" + 1;
	"Tag_29":= 1;
	"Tag_28":= 0;
ELSE
    #"#Avvio" := 1;
END_IF;
"IEC_Timer_0_DB".TP(IN := #"#Avvio",
                    PT := T#40s,
                    Q => "Tag_28",
                    ET => #"#Time_outti");
IF "Tag_29" THEN
	"Tag_28":= 1;
	"Tag_29":= 0;
END_IF;

prova il codice qui di sopra:

nel tuo codice non hai MAI un ciclo macchina con il risultato logico combinatorio = 0 per far ripartire il timer.

Si potrebbe anche utilizzare l'istruzione di reset del timer

Consiglio: quando ci sono i timer non saltare mai altrimenti poi cadi nell'errore che hai fatto.

Io non ho testato il codice, Tieni conto che Tag_29 serve proprio a perdere quel famigerato ciclo macchina.

Inoltre dopo l'istruzione del timer tu azzeri sempre il flag.

 

In sintesi:

ho notato che gli errori fatti presuppongono una programmazione di uno che pensa che l'istruzione successiva sia eseguita solamente quando quella precedente è terminata (vedi timer). 
NO! Il timer deve sempre ciclare e quando finisce ti troverai il flag .q vero.

 

In alternativa potresti fare anche così:

(*
a fine conteggio ripristina il timer con un bel FALSE 
*)

IF "Tag_28" = 1 THEN
	#"#Contatore" := #"#Contatore" + 1;
	"Tag_28":= 0;
"IEC_Timer_0_DB".TP(IN := FALSE,	// RESET TIMER ONE SHOT
                    PT := T#40s");
ELSE
    #"#Avvio" := 1;
END_IF;
"IEC_Timer_0_DB".TP(IN := #"#Avvio",	// TIMER CHE CICLA SEMPRE ......
                    PT := T#40s,
                    Q => "Tag_28",
                    ET => #"#Time_outti");

 

Share this post


Link to post
Share on other sites
simonegr

Grazie mille pigroplc, ho testato il codice, ma dopo il primo ciclo non funziona più. 

 

Share this post


Link to post
Share on other sites
pigroplc

eh ho fatto casino,

nel primo caso al posto di Tag_28 metti avvio 

E' l'istruzione prima del reset di Tag_29

 

così lo fai ripartire

 

 

Share this post


Link to post
Share on other sites
batta
#TimerClock(IN:=NOT #Clock,
            PT:=T#10s,
            Q=>#Clock);

IF #Clock THEN
    #Cnt := #Cnt + 1;
END_IF;

 

Per l'esempio ho usato una FB.
Le variabili #Clock e #Cnt devono essere STAT. Usando le TEMP non può funzionare.
Se si vuole usare come variabile di conteggio una variabile esterna, deve essere passata alla funzione come IN_OUT.

Share this post


Link to post
Share on other sites
simonegr

Così lo devo modificare ?

 

IF "Tag_28" = 1 THEN
    #"#Avvio" := 0;
    #"#Contatore" := #"#Contatore" + 1;
    "Tag_29" := 1;
    #"#Avvio" := 0;
ELSE
    #"#Avvio" := 1;
END_IF;
"IEC_Timer_0_DB".TP(IN := #"#Avvio",
                    PT := T#20s,
                    Q => "Tag_28",
                    ET => #"#Time_outti");
IF "Tag_29" THEN
    #"#Avvio" := 1;
    "Tag_29" := 0;
END_IF;

Share this post


Link to post
Share on other sites
pigroplc

si

 

mentre io ho cercato di seguire parte del tuo ragionamento, Batta ti ha postato la soluzione più corta e performante.

Se sei alle prime armi ti suggerisco di provarle entrambe.

 

Share this post


Link to post
Share on other sites
batta

Ma cosa non ti piace del mio esempio?
Perché devi, a tutti i costi, complicarti la vita con variabili #Avvio, Tag_28, Tag_29, e un inutile IF-THEN-ELSE? A cosa servono?

Share this post


Link to post
Share on other sites
simonegr

Grazie mille a tutti, ma non riesco a capire l'esempio di batta ................

Mentre la modifica fatta da pigroplc a me non funziona correttamente

Share this post


Link to post
Share on other sites
batta

È molto semplice:
Se l'uscita del timer (la variabile #Clock) è FALSE, il timer conta (all'ingresso del timer c'è la condizione "NOT #Clock").

Quando il timer raggiunge il conteggio, #Clock diventa TRUE.

Se #Clock = TRUE, viene incrementato il conteggio.
Alla scansione successiva avremo #Clock = TRUE (quindi NOT #Clock = FALSE).

Il timer si resetta e imposta #Clock = FALSE.

Alla successiva scansione, con #Clock = FALSE, il timer ricomincia a contare.

 

È la stessa cosa che succede nell'altro esempio, senza utilizzare le variabili "TAG" e #Avvio.

 

Da tenere presente che il reale tempo di clock non sarà quello impostato come preset del timer, ma il valore di preset + il tempo di scansione (per una scansione il timer non conta).

Share this post


Link to post
Share on other sites
pigroplc
Quote

Ma cosa non ti piace del mio esempio?
Perché devi, a tutti i costi, complicarti la vita con variabili #Avvio, Tag_28, Tag_29, e un inutile IF-THEN-ELSE? A cosa servono?

 

Batta,

premesso che io sono d'accordo con te,

 

mi metto nei panni di uno che si approccia per la prima volta ad un linguaggio strutturato come SCL e che magari ha sempre visto solamente i contatti:

ha la tendenza a rendersi la vita "difficile".

 

Io cerco di assecondare e far digerire la soluzione, quindi quando funziona aggiungo un gradino di difficoltà ottimizzando (come nel tuo esempio).

Quanto a quello che ho buttato giù io senza stare troppo a pensare, personalmente mi viene la pelle d'oca a riguardare il codice, ma spero di aver chiarito il significato di quanto fatto.

 

 

simonegr:

la soluzione di Batta non parametrizzata:

 

"IEC_Timer_0_DB".TP(IN := NOT "IEC_Timer_0_DB".Q,
                    PT := T#20);
IF IEC_Timer_0_DB.Q THEN
	COUNTER:=COUNTER + 1;
END_IF;

 

Share this post


Link to post
Share on other sites
simonegr
17 ore fa, pigroplc scrisse:

IF "Tag_28" = 1 THEN
    #"#Avvio" := 0;
	#"#Contatore" := #"#Contatore" + 1;
	"Tag_29":= 1;
	"Tag_28":= 0;
ELSE
    #"#Avvio" := 1;
END_IF;
"IEC_Timer_0_DB".TP(IN := #"#Avvio",
                    PT := T#40s,
                    Q => "Tag_28",
                    ET => #"#Time_outti");
IF "Tag_29" THEN
	"Tag_28":= 1;
	"Tag_29":= 0;
END_IF;

prova il codice qui di sopra:

nel tuo codice non hai MAI un ciclo macchina con il risultato logico combinatorio = 0 per far ripartire il timer.

Si potrebbe anche utilizzare l'istruzione di reset del timer

Consiglio: quando ci sono i timer non saltare mai altrimenti poi cadi nell'errore che hai fatto.

Io non ho testato il codice, Tieni conto che Tag_29 serve proprio a perdere quel famigerato ciclo macchina.

Inoltre dopo l'istruzione del timer tu azzeri sempre il flag.

 

In sintesi:

ho notato che gli errori fatti presuppongono una programmazione di uno che pensa che l'istruzione successiva sia eseguita solamente quando quella precedente è terminata (vedi timer). 
NO! Il timer deve sempre ciclare e quando finisce ti troverai il flag .q vero.

 

In alternativa potresti fare anche così:


(*
a fine conteggio ripristina il timer con un bel FALSE 
*)

IF "Tag_28" = 1 THEN
	#"#Contatore" := #"#Contatore" + 1;
	"Tag_28":= 0;
"IEC_Timer_0_DB".TP(IN := FALSE,	// RESET TIMER ONE SHOT
                    PT := T#40s");
ELSE
    #"#Avvio" := 1;
END_IF;
"IEC_Timer_0_DB".TP(IN := #"#Avvio",	// TIMER CHE CICLA SEMPRE ......
                    PT := T#40s,
                    Q => "Tag_28",
                    ET => #"#Time_outti");

 

 

16 ore fa, batta scrisse:

#TimerClock(IN:=NOT #Clock,
            PT:=T#10s,
            Q=>#Clock);

IF #Clock THEN
    #Cnt := #Cnt + 1;
END_IF;

 

Per l'esempio ho usato una FB.
Le variabili #Clock e #Cnt devono essere STAT. Usando le TEMP non può funzionare.
Se si vuole usare come variabile di conteggio una variabile esterna, deve essere passata alla funzione come IN_OUT.

 

16 ore fa, pigroplc scrisse:

eh ho fatto casino,

nel primo caso al posto di Tag_28 metti avvio 

E' l'istruzione prima del reset di Tag_29

 

così lo fai ripartire

 

 

Grazie mille a tutti

Share this post


Link to post
Share on other sites
batta
Quote

Quanto a quello che ho buttato giù io senza stare troppo a pensare, personalmente mi viene la pelle d'oca a riguardare il codice, ma spero di aver chiarito il significato di quanto fatto.

Guarda che la mia non era una critica, tantomeno rivolta a te. Hai idea di quante cavolate scrivo io, che quando le riguardo mi chiedo se ero ubriaco?

Faccio questo lavoro da quasi trent'anni, e non c'è una sola volta che, finito un programma, non mi venga la voglia di ricominciarlo daccapo.

Riguardo le difficoltà per passare da un linguaggio a contatti al strutturato, nell'esempio specifico non ho fatto altro che scrivere in strutturato quello che abitualmente si fa in ladder: un timer che si autoresetta.

Share this post


Link to post
Share on other sites
batta

Da alcune prove fatte col simulatore, inserendo un ciclo FOR che calcola 10 mila volte una radice quadrata per allungare i tempi di scansione, sembra che ad ogni ciclo si perda non una, ma due volte il tempo di scansione.
Volendo, si può migliorare nel seguente modo:
 

#TimerClock(IN := TRUE,
            PT := T#10s,
            Q => #Clock);

IF #Clock THEN
    #Cnt := #Cnt + 1;
    RESET_TIMER(#TimerClock);
END_IF;

In questo modo verrebbe da pensare che non si dovrebbe perdere nemmeno una scansione ma, sempre dalle prove fatte col simulatore, sembra invece che si perda una scansione anziché due.
Probabilmente il timer ha comunque bisogno di una scansione per resettarsi, e in quella scansione non conta.

Share this post


Link to post
Share on other sites
simonegr
20 ore fa, pigroplc scrisse:

IF "Tag_28" = 1 THEN
    #"#Avvio" := 0;
	#"#Contatore" := #"#Contatore" + 1;
	"Tag_29":= 1;
	"Tag_28":= 0;
ELSE
    #"#Avvio" := 1;
END_IF;
"IEC_Timer_0_DB".TP(IN := #"#Avvio",
                    PT := T#40s,
                    Q => "Tag_28",
                    ET => #"#Time_outti");
IF "Tag_29" THEN
	"Tag_28":= 1;
	"Tag_29":= 0;
END_IF;

prova il codice qui di sopra:

nel tuo codice non hai MAI un ciclo macchina con il risultato logico combinatorio = 0 per far ripartire il timer.

Si potrebbe anche utilizzare l'istruzione di reset del timer

Consiglio: quando ci sono i timer non saltare mai altrimenti poi cadi nell'errore che hai fatto.

Io non ho testato il codice, Tieni conto che Tag_29 serve proprio a perdere quel famigerato ciclo macchina.

Inoltre dopo l'istruzione del timer tu azzeri sempre il flag.

 

In sintesi:

ho notato che gli errori fatti presuppongono una programmazione di uno che pensa che l'istruzione successiva sia eseguita solamente quando quella precedente è terminata (vedi timer). 
NO! Il timer deve sempre ciclare e quando finisce ti troverai il flag .q vero.

 

In alternativa potresti fare anche così:


(*
a fine conteggio ripristina il timer con un bel FALSE 
*)

IF "Tag_28" = 1 THEN
	#"#Contatore" := #"#Contatore" + 1;
	"Tag_28":= 0;
"IEC_Timer_0_DB".TP(IN := FALSE,	// RESET TIMER ONE SHOT
                    PT := T#40s");
ELSE
    #"#Avvio" := 1;
END_IF;
"IEC_Timer_0_DB".TP(IN := #"#Avvio",	// TIMER CHE CICLA SEMPRE ......
                    PT := T#40s,
                    Q => "Tag_28",
                    ET => #"#Time_outti");

 

 

20 ore fa, batta scrisse:

#TimerClock(IN:=NOT #Clock,
            PT:=T#10s,
            Q=>#Clock);

IF #Clock THEN
    #Cnt := #Cnt + 1;
END_IF;

 

Per l'esempio ho usato una FB.
Le variabili #Clock e #Cnt devono essere STAT. Usando le TEMP non può funzionare.
Se si vuole usare come variabile di conteggio una variabile esterna, deve essere passata alla funzione come IN_OUT.

 

20 ore fa, pigroplc scrisse:

eh ho fatto casino,

nel primo caso al posto di Tag_28 metti avvio 

E' l'istruzione prima del reset di Tag_29

 

così lo fai ripartire

 

 

Se invece dovessi incrementare ogni 10 secondi  ?

Share this post


Link to post
Share on other sites
batta
Quote

Se invece dovessi incrementare ogni 10 secondi  ?

Non ho capito la domanda.
Il tempo lo decidi tu, impostando il preset del timer. Puoi mettere il tempo che vuoi.
Ricorda che questo sistema, dato che sbaglia di una o due scansioni ad ogni ciclo (dipende dal codice che andrai ad utilizzare) va bene solo per tempi non troppo brevi, dove l'errore dovuto ai tempi di scansione è trascurabile.

Se vuoi maggior precisione, utilizza gli OB a tempo.

Share this post


Link to post
Share on other sites
simonegr
il ‎06‎/‎11‎/‎2017 at 15:09 , pigroplc scrisse:

IF "Tag_28" = 1 THEN
    #"#Avvio" := 0;
	#"#Contatore" := #"#Contatore" + 1;
	"Tag_29":= 1;
	"Tag_28":= 0;
ELSE
    #"#Avvio" := 1;
END_IF;
"IEC_Timer_0_DB".TP(IN := #"#Avvio",
                    PT := T#40s,
                    Q => "Tag_28",
                    ET => #"#Time_outti");
IF "Tag_29" THEN
	"Tag_28":= 1;
	"Tag_29":= 0;
END_IF;

prova il codice qui di sopra:

nel tuo codice non hai MAI un ciclo macchina con il risultato logico combinatorio = 0 per far ripartire il timer.

Si potrebbe anche utilizzare l'istruzione di reset del timer

Consiglio: quando ci sono i timer non saltare mai altrimenti poi cadi nell'errore che hai fatto.

Io non ho testato il codice, Tieni conto che Tag_29 serve proprio a perdere quel famigerato ciclo macchina.

Inoltre dopo l'istruzione del timer tu azzeri sempre il flag.

 

In sintesi:

ho notato che gli errori fatti presuppongono una programmazione di uno che pensa che l'istruzione successiva sia eseguita solamente quando quella precedente è terminata (vedi timer). 
NO! Il timer deve sempre ciclare e quando finisce ti troverai il flag .q vero.

 

In alternativa potresti fare anche così:


(*
a fine conteggio ripristina il timer con un bel FALSE 
*)

IF "Tag_28" = 1 THEN
	#"#Contatore" := #"#Contatore" + 1;
	"Tag_28":= 0;
"IEC_Timer_0_DB".TP(IN := FALSE,	// RESET TIMER ONE SHOT
                    PT := T#40s");
ELSE
    #"#Avvio" := 1;
END_IF;
"IEC_Timer_0_DB".TP(IN := #"#Avvio",	// TIMER CHE CICLA SEMPRE ......
                    PT := T#40s,
                    Q => "Tag_28",
                    ET => #"#Time_outti");

 

 

il ‎06‎/‎11‎/‎2017 at 15:49 , batta scrisse:

#TimerClock(IN:=NOT #Clock,
            PT:=T#10s,
            Q=>#Clock);

IF #Clock THEN
    #Cnt := #Cnt + 1;
END_IF;

 

Per l'esempio ho usato una FB.
Le variabili #Clock e #Cnt devono essere STAT. Usando le TEMP non può funzionare.
Se si vuole usare come variabile di conteggio una variabile esterna, deve essere passata alla funzione come IN_OUT.

 

il ‎06‎/‎11‎/‎2017 at 15:41 , pigroplc scrisse:

eh ho fatto casino,

nel primo caso al posto di Tag_28 metti avvio 

E' l'istruzione prima del reset di Tag_29

 

così lo fai ripartire

 

 

Ciao Batta, io ho copiato il tuo programma e lo sto simulando ma non mi sembra che il conteggio aumenti di uno ogni 10 secondi ...........

Share this post


Link to post
Share on other sites
batta
Quote

Ciao Batta, io ho copiato il tuo programma e lo sto simulando ma non mi sembra che il conteggio aumenti di uno ogni 10 secondi ...........

Se hai seguito tutte le istruzioni (la variabile #Clock NON deve essere una variabile temporanea), ti posso assicurare che funziona.

Share this post


Link to post
Share on other sites
pigroplc

 

Quote

Guarda che la mia non era una critica, tantomeno rivolta a te. 

Batta,

ti assicuro che non l'ho presa come una critica. :)

Siccome ritengo che tu sia un professionista, ho solamente espresso il mio parere per uno scambio costruttivo, dicendo che io il tuo esempio l'ho capito mentre per simonegr era un po' ostico. Tutto qui.

 

 

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this  

×
×
  • Create New...