Vai al contenuto
PLC Forum


Contatore a tempo


simonegr

Messaggi consigliati

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

Link al commento
Condividi su altri siti


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
Link al commento
Condividi su altri siti

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");

 

Link al commento
Condividi su altri siti

#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.

Link al commento
Condividi su altri siti

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;

Link al commento
Condividi su altri siti

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.

 

Link al commento
Condividi su altri siti

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?

Link al commento
Condividi su altri siti

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

Mentre la modifica fatta da pigroplc a me non funziona correttamente

Link al commento
Condividi su altri siti

È 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).

Link al commento
Condividi su altri siti

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;

 

Link al commento
Condividi su altri siti

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

Link al commento
Condividi su altri siti

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.

Link al commento
Condividi su altri siti

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.

Link al commento
Condividi su altri siti

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  ?

Link al commento
Condividi su altri siti

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.

Link al commento
Condividi su altri siti

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 ...........

Link al commento
Condividi su altri siti

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.

Link al commento
Condividi su altri siti

 

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.

 

 

Link al commento
Condividi su altri siti

Crea un account o accedi per commentare

Devi essere un utente per poter lasciare un commento

Crea un account

Registrati per un nuovo account nella nostra comunità. è facile!

Registra un nuovo account

Accedi

Hai già un account? Accedi qui.

Accedi ora
×
×
  • Crea nuovo/a...