roberto1972 Inserito: 26 novembre 2013 Segnala Inserito: 26 novembre 2013 Ciao a tutti, Avrei bisogno di contare il tempo di lavoro totale di un motore senza usare contatori. So' che e' un argomento stratrattato ma non sono riuscito a capire come fare. Dopo varie ricerche sul forum mi piacerebbe sviluppare la soluzione proposta da Batta qualche anno fa...( l'ho riportata sotto) non so' pero' come fare ad incrementare una Dword ogni secondo , ho provato con ADD_I ed un clock di un secondo ma non funziona!!! Come si fa' poi a convertire la Dword in ( o con l'uso delle istruzioni /D e MOD) HH:MM:ss ??? Il programma e' su una CPU 318. Grazie a tutti Buona giornata Roberto Post di Batta Inviato 20 dicembre 2008 - 22:40 Se ne è parlato più volte. Io ti sconsiglierei l'uso dei contatori, che hanno valore massimo di conteggio di 999. Certo, potresti utilizzare un contatore per i secondi, uno per i minuti e uno per le ore. Uno spreco enorme! A mio avviso, il sistema più comodo è quello di incrementare una DWORD ogni secondo. Si ottiene un conteggio accurato e, con una DWORD, si arriva a contare fino a circa 68 anni. Insomma, con un semplice clock di un secondo (ricavabile anche da merker di clock configurabili della cpu), ottieni un contasecondi semplicissimo da gestire. Personalmente considero i contaore fatti incrementando i secondi, poi i minuti (ogni 60 secondi), poi le ore (ogni 60 minuti), una inutile complicazione. Se poi ti serve la visualizzazione in hh:mm:ss, puoi seguire due strade: o la conversione fatta direttamente dall'interfaccia operatore (se presente ed in grado di farlo), o con l'uso delle istruzioni /D e MOD. Dei semplici contasecondi sono anche facili da usare quando c'è da dare alternanza al funzionamento di utenze: basta una semplicissima comparazione per capire qual è l'utenza che ha lavorato meno, e decidere di farla partire per prima. Se si parte con la gestione separata di ore, minuti e secondi, servono più comparazioni per arrivare al risultato.
Lucky67 Inserita: 26 novembre 2013 Segnala Inserita: 26 novembre 2013 (modificato) ho provato con ADD_I scusa ADD a cosa? Immagino tu abbia messo anche l'altro addendo (1). In ogni caso io avrei utilizzato le funzioni di INCremento. Modificato: 26 novembre 2013 da Lucky67
batta Inserita: 26 novembre 2013 Segnala Inserita: 26 novembre 2013 ho provato con ADD_I ed un clock di un secondo ma non funziona!!! Se non fai vedere il codice, come possiamo capire dove hai sbagliato? O meglio, un errore si vede subito: hai utilizzato l'istruzione ADD_I , che è la somma fra interi a 16 bit, con variabili a 32 bit. Casomai dovresti usare ADD_DI. Ma immagino ci sian anche altri errori. Se non vuoi complicarti la vita allegando immagini del codice scritto in KOP, convertilo in AWL ed incollalo in un post. Per l'utilizzo delle istruzioni /D e MOD dovresti prima studiare il manuale, è poi chiedere cosa non capisci. In breve: l'istruzione /D è una divisione fra interi. L'istruzione MOD ti dà invece il resto della divisione (sempre tra interi). Per esempio, se il mio contatore è arrivato a contare 7418 secondi, con l'istruzione /D calcolo 7418 / 3600 = 2 (ovvero due ore). Con MOD ottengo il resto della divisione, ovvero 218 secondi. Poi posso dividere i 218 secondi per 60 (con /D) ed ottengo 3. Con MOD ottengo nuovamente il resto, che è 38 secondi. Quindi 7418 secondi corrispondono a 2 ore, 3 minuti e 38 secondi.
roberto1972 Inserita: 26 novembre 2013 Autore Segnala Inserita: 26 novembre 2013 (modificato) il codice che ho iniziato a testare e' il seguente: La prima parte conta il numero di accensioni con un contatore e funziona , La seconda parte e' quella che faccio fatica a capire...scusate ma e' la prima volta che scrivo in AWL e non conoscevo la funzione INC con i vari accumulatori. Ho cercato di seguire l' . di siemens ma non riesco a capire come fare!!! in rosso la parte che non funziona. La funzione di INC si verifica ad ogni ciclo del programma a prescindere dalle istruzioni precedenti? FUNCTION FC 9 : VOID TITLE = VERSION : 0.1 BEGIN NETWORK TITLE =Start Motore A DB3.DBX 2.0; = DB9.DBX 14.1; NETWORK TITLE = NETWORK TITLE =numero di cicli di partenza A DB9.DBX 14.1; //contatto di motore acceso CU C 60; BLD 101; A M 0.1; //Contatto sempre on L C#0; S C 60; NOP 0; NOP 0; LC C 60; // contatore del numero di accensioni T DB9.DBW 12; NOP 0; NETWORKTITLE =Tempo totale di accensione motore A DB9.DBX 14.1; //contatto di motore acceso A M 4.1; // clock con frequenza 1 HZ L DB9.DBB 15; ////// il valore va da 00 a ff in modo rapido senza mai fermarsi, io pensavo che solo se le due condizioni precedenti davano RLC 1 si passasse ad incrementare di uno il valore della DB9.DBB 15. INC 1; T DB9.DBB 15; NETWORK TITLE = L DB9.DBB 15; T DB9.DBW 18; NOP 0; END_FUNCTION Grazie Batta , la parte /D e MOD ora mi e' chiara. Grazie per la pazienza.... Modificato: 26 novembre 2013 da roberto1972
Lucky67 Inserita: 27 novembre 2013 Segnala Inserita: 27 novembre 2013 La funzione di INC si verifica ad ogni ciclo del programma a prescindere dalle istruzioni precedenti? Si almeno finchè RLC è 1- Se utilizzi un clock ad onmda quadra di 1 Hz avrai il segnale di clock a 1 per 500 ms e quindi INC continuerà a incrementare finchè il clock stesso non andrà nella fase di "riposo" ( o chiaramente il motore si fermerà). Devi mettere un fronte di salita dopo il clock in modo che ti dia solo un impulso ogni volta che RLC va ad uno e che quindi possa incrementare di uno solo ogni volta che sale il clock.
batta Inserita: 27 novembre 2013 Segnala Inserita: 27 novembre 2013 (modificato) Tutte le istruzioni che scrivi vengono eseguite, indipendentemente dallo stato di RLC. Se vuoi che alcune istruzioni non vengano eseguite, devi fare un salto. Ti sconsiglio inoltre di usare l'istruzione INC che lavora solo su variabili a 8 bit. Vedo infatti che utilizzi la variabile DB9.DBB15 per fare l'incremento con INC, e poi trasferisci questa variabile di tipo BYTE nella variabile DB9.DBW18. Questo non ha alcun senso. Il tuo conteggio andrà da 0 a 255. Potresti riscrivere il codice come segue: TITLE =Tempo totale di accensione motore A DB9.DBX 14.1 //contatto di motore acceso A M 4.1 // clock con frequenza 1 HZ JCN M000 //Se RLC=1 non saltare L DB9.DBW 18 //Incrementa conteggio + 1 T DB9.DBW 18 M000: NOP 0 Tieni presente che usando per il conteggio una word (16 bit) puoi contare al massimo fino a 32767 secondi, che corrispondono a poco più di 9 ore. Se hai bisogno di andare oltre questo limite, utilizza una DWord (32 bit), ed arrivi a contare fino a circa 68 anni. Modificato: 27 novembre 2013 da batta
roberto1972 Inserita: 27 novembre 2013 Autore Segnala Inserita: 27 novembre 2013 (modificato) Grazie Con le vostre dritte sono riuscito ad andare avanti TITLE =Tempo totale di accensione motore A DB9.DBX 14.1 //contatto di motore acceso A M 4.1 // clock con frequenza 1 HZ FP M 99.0 // fronte positivo di salita JCN M000 //Se RLC=1 non saltare L DB9.DBD 18 //Incrementa conteggio con Dword + 1 T DB9.DBD 18 M000: NOP 0 Ora con la Dword calcolo i tempi L DB9.DBD 18 //totale secondi L 3600 /D T DB9.DBD 22 //ore L DB9.DBD 18 L 3600 MOD T DB9.DBD 26 //resto L DB9.DBD 26 L 60 /D T DB9.DBD 30 //minuti L DB9.DBD 26 L 60 MOD T DB9.DBD 34 //resto dei secondi Si puo' ora creare in un unico dato le ore/minuti/secondi usando dbd22:dbd30:dbd34 ? Modificato: 27 novembre 2013 da roberto1972
roberto1972 Inserita: 27 novembre 2013 Autore Segnala Inserita: 27 novembre 2013 per visualizzare i valori di ore minuti secondi non in forma esadecimale ho usato il move E' corretto fare cosi? L DB9.DBD 22 // dato in Dword T DB9.DBD 38 // dato in Dint NOP 0
batta Inserita: 27 novembre 2013 Segnala Inserita: 27 novembre 2013 Il move da DB9.DBD22 a DB9.DBD38 non ti serve. Che tu abbia dichiarato la DB9.DBD22 come DWORD o come DINT non cambia nulla. Puoi sempre decidere di visualizzare il valore in decimale o in esadecimale, ma si tratta solo di diversa visualizzazione del valore. Il valore però è sempre lo stesso. Inutile poi "sprecare" delle DWORD (o DINT) soprattutto per contenere minuti e secondi, che non vanno oltre il 59. Meglio usare dei semplici byte o, al massimo, delle word (o INT, che è lo stesso). Anche se il risultato della divisione con /D e del resto con MOD è un valore a 32 bit, almeno per quanto riguarda minuti e secondi non potrà mai essere maggiore di 59. Puoi quindi trasferire il risultato in un byte, senza bisogno di trasformazioni di formato. Quindi potresti benissimo scrivere: L DB9.DBD 18 //totale secondi L 3600 /D T DB9.DBW 22 //ore L DB9.DBD 18 L 3600 MOD T #tmp_resto L 60 /D T DB9.DBB 24 //minuti L #tmp_resto L 60 MOD T DB9.DBB 25 //resto dei secondi Per le ore ho ipotizzato che un conteggio fino a 32767 ore potesse bastare, quindi ho usato una variabile a 16 bit. Per il resto della divisione ho usato una variabile temporanea. Visto che divido per 3600 il resto non potrà mai superare il valore di 3599, quindi anche questa variabile può essere a 16 bit. Per i minuti e per i secondi, ho usato un byte. Se metti i valori di DB9.DBD18, DB9.DBW22, DB9.DBB24 e DB9.DBB25 in una tabella di variabili, puoi visualizzare i valori in formato decimale e vedere che tutto funziona. Anche nel blocco di codice puoi scegliere il formato di visualizzazione, semplicemente cliccando col tasto destro del mouse sui valori visualizzati.
roberto1972 Inserita: 28 novembre 2013 Autore Segnala Inserita: 28 novembre 2013 grazie Batta, ho fatto le modifiche consigliate e modificato la lettura in decimale, tutto ok. fatta anche la tabella variabili, ora posso controllare i tempi di accensione . Mi manca solo il fatto di avere questi 3 dati hh mm ss in uno unico , ho gia' letto che esiste il dato TIME ma come faccio a comporlo con i miei DB9.DBW22, DB9.DBB24 e DB9.DBB25 ? Lo vorrei fare per poi provare a spostarlo sul' HMI winflex 2008 SP2 che gestisce il tutto... se riesco...questo non e' fondamentale. Probabilmente ho bisogno dalle ore totali ricavare i giorni ma questo ora non ""piu'""( grazie a voi ) un problema usero' ancora /D e MOD , modifico il dato db9.dbw22 in byte e uso un'altra word per i giorni. grazie dell'aiuto
batta Inserita: 28 novembre 2013 Segnala Inserita: 28 novembre 2013 Il dato in formato TIME non è altro che il tempo in millisecondi. Se utilizzi un pannello operatore Siemens, non hai bisogno di scomporre i secondi totali in hh:mm:ss, ma ti basta moltiplicare per 1000 e mettere il risultato in una variabile dichiarata come TIME. Il pannello operatore farà tutto il resto. In questo modo però limiti il conteggio massimo fino a circa 24 giorni. Se devi superare questo limite, mantieni le variabili separate e sul pannello operatore le visualizzi una vicina all'altra. Se hai bisogno anche dei giorni, in testa al procedimento precedente (che comincia con la divisione per 3600 per calcolare le ore) inserisci una divisione per 86400, che sono i secondi di un giorno. Il resto lo dividi per 3600 e calcoli le ore, e così via. Tieni presente che la variabile temporanea usata per il resto della divisione in questo caso può arrivare ad un valore massimo di 86399, quindi non può più essere una INT come nell'esempio precedente, ma deve per forza essere una DINT. Per la dimensione delle variabili potresti quindi utilizzare una word per i giorni, e un byte per le ore, per i minuti e per i secondi. Se poi preferisci usare word anche per ore minuti e secondi, non saranno certo quei tre byte utilizzati in più a creare problemi.
roberto1972 Inserita: 28 novembre 2013 Autore Segnala Inserita: 28 novembre 2013 (modificato) grazie batta e lucky67 siete stati di grande aiuto funziona tutto ciao Modificato: 28 novembre 2013 da roberto1972
roberto1972 Inserita: 29 novembre 2013 Autore Segnala Inserita: 29 novembre 2013 "Il dato in formato TIME non è altro che il tempo in millisecondi. Se utilizzi un pannello operatore Siemens, non hai bisogno di scomporre i secondi totali in hh:mm:ss, ma ti basta moltiplicare per 1000 e mettere il risultato in una variabile dichiarata come TIME. Il pannello operatore farà tutto il resto." ho provato ma non mi funziona...ho cantato vittoria troppo presto In winflex ho richiamato la variabile che conta i millisecondi *1000 del blocco DB che e' impostata in formato TIME e' db9.dbd18*1000 = db9.dbd24 DB9.dbd24 TIME T#1H1M1S T#1H1M1S in simatic funziona vedo ore minuti secondi scorrere. quando creo una campo O in winflex non mi da' la possibilita' di impostarlo in formato TIME , imposto come valore da acquisire db9.dbd24 Se in winflex lo imposto in formato decimali vedo i millisecondi che scorrono ma non hh mm ss Perche' non ho l'opzione time nel campo Output? cosa sbaglio!!! le ho provate tutte grazie ciao
batta Inserita: 29 novembre 2013 Segnala Inserita: 29 novembre 2013 Sì, hai ragione. Per visualizzare automaticamente il tempo in hh:mm:ss il formato della variabile deve essere TIME_OF_DAY, e non TIME. In questo caso però, la visualizzazione è corretta solo fino a 23:59:59.
roberto1972 Inserita: 29 novembre 2013 Autore Segnala Inserita: 29 novembre 2013 perfetto ora si vede. Se io pero' arrivato a 23:59:59 resetto i millisecondi e riparto da 0 e nello stesso tempo incremento di uno il conteggio dei giorni poi il time riparte da 0:00:00 e cosi' non sbaglia, giusto ? Ora provo.
batta Inserita: 30 novembre 2013 Segnala Inserita: 30 novembre 2013 Sì, ma a questo punto devi comunque visualizzare sul pannello operatore due variabili, una INT per i giorni e una TIME_OF_DAY per ore minuti e secondi. Se è questa la strada che intendi seguire, piuttosto che fare incremento dei giorni e azzeramento dei millisecondi, ti conviene usare sempre il metodo della divisione con il resto (partendo dalla variabile che contiene il conteggio totale in secondi). Con una divisione per 86400 ricavi direttamente il numero dei giorni, mentre con MOD ti rimane il resto in secondi. Moltiplichi il resto per mille e metti il risultato nella variabile TIME_OF_DAY. Esempio: L DB9.DBD 18 //Var DINT conteggio totale in secondi L L#86400 //Secondi in un giorno /D T DB9.DBW 22 //Totale Giorni L DB9.DBD 18 //Var DINT conteggio totale in secondi L L#86400 //Secondi in un giorno MOD //Calcola resto L L#1000 *D //Moltiplica resto per 1000 T DB9.DBD 24 //Trasferisci in variabile tipo TIME_OF_DAY
roberto1972 Inserita: 1 dicembre 2013 Autore Segnala Inserita: 1 dicembre 2013 Il dubbio che mi ha portato a far resettare il conteggio di DB9.DBD18 era al superamento di 86400, ma giustamente tu usi il resto della divisione e quindi questo resto non potra' mai superare 23:59:59 ( scusa me lo spiego a me stesso...) Come dicevi anche tu in un precedente post il limite e' di circa 24 gg . Ho utilizzato sia il conteggio che il calcolo dei giorni come hai detto nel post.Tutto ok. Ora pero' giusto per capire se volessi resettarlo ad ogni giorno raggiunto e' corretto scrivere cosi' dopo il calcolo del Time_OF_DAY? Al raggiungimento di 86400 incrementa di 1 i giorni e poi resetta i secondi L DB9.DBD 18 //Var DINT conteggio totale in secondi L L#86400 ==D JCN M002 L DB9.DBW 22 //Totale Giorni + 1 T DB9.DBW 22 L 0 T DB9.DBD 18 M002: NOP 0 grazie ciao
batta Inserita: 1 dicembre 2013 Segnala Inserita: 1 dicembre 2013 Sì, certo. Apporterei solo una piccola modifica: usare >= al posto di == In realtà funziona tutto perfettamente anche con == . L'unico inconveniente si potrebbe verificare solo se la DB9.DBD18 venisse modificata manualmente impostando un valore superiore a 86400.
roberto1972 Inserita: 1 dicembre 2013 Autore Segnala Inserita: 1 dicembre 2013 grazie sei stato di grande aiuto devo studiare un po di awl!!! ciao
Messaggi consigliati
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 accountAccedi
Hai già un account? Accedi qui.
Accedi ora