Linotix Inserito: 15 novembre 2018 Segnala Share Inserito: 15 novembre 2018 Salve.Qual’e secondo voi il metodo migliore per fare questa cosa: Ho 64 ingessi in un array all’interno di una fc che gestiscono 64 uscite in un altro array con varie funzioni. Devo ora inserire una memoria che una volta settata faccia si che l’ultimo ingresso alzato oltre a settare l’uscita spenga anche le uscite precedentemente accese. In pratica un ingressimo alza l’uscita e mette a zero le altre. Qual’è il metodo migliore in awl? Grazie Link al commento Condividi su altri siti More sharing options...
Livio Orsini Inserita: 15 novembre 2018 Segnala Share Inserita: 15 novembre 2018 1 ora fa, Linotix scrisse: In pratica un ingressimo alza l’uscita e mette a zero le altre. ma è un ingresso preciso o l'ultimo in ordine di tempo? Link al commento Condividi su altri siti More sharing options...
Linotix Inserita: 15 novembre 2018 Autore Segnala Share Inserita: 15 novembre 2018 Qualsiasi ingresso. L’utimo In ordine di tempo deve azzerare il precedenti Link al commento Condividi su altri siti More sharing options...
Livio Orsini Inserita: 15 novembre 2018 Segnala Share Inserita: 15 novembre 2018 Come fai a stabilire se è l'ultimo o se ne arriveranno altri? Devi impostare un tempo massimo. se allo scadere di questo temporizzatore non ci sono state variazioni dello stato degli ingressi, considiri l'ultimo ingrsso variato. Ogni volta che varia un ingresso lo memorizzi nella memoria "ultimo ingresso", poi fai partire il temporizzatore, se il temporizzatore si azzera consideri avvenuto lo stato di ultimo ingresso variato ed esegui la funzione Link al commento Condividi su altri siti More sharing options...
Linotix Inserita: 15 novembre 2018 Autore Segnala Share Inserita: 15 novembre 2018 Non c’entrano niente I temporizzatori. Cerco di spiegarmi meglio. Se io ho 10 ing. alti, e a quel punto alzo la mem “ resetta ing precedenti” il primo ingresso che si setta azzererà tutti gli altri. Da quel punto in poi, ogni ingresso che si alzerà azzererà il precedente ovviamente. Link al commento Condividi su altri siti More sharing options...
Livio Orsini Inserita: 16 novembre 2018 Segnala Share Inserita: 16 novembre 2018 (modificato) 12 ore fa, Linotix scrisse: Se io ho 10 ing. alti, e a quel punto alzo la mem “ resetta ing precedenti” il primo ingresso che si setta azzererà tutti gli altri. Da quel punto in poi, ogni ingresso che si alzerà azzererà il precedente ovviamente. Qual'è il problema allora? Se non ti spieghi chiaramente non si riesce a comprendere cosa vuoi realmente fare e qauli sono le condizioni. Forse alzare la memoria "resetta ing precedenti" ? Ma se non conosci-spieghi le condizioni per cui setti, e resetti, questa memoria il problema è senza soluzioni. Poi c'è un'altra cosa che non chiarisci. Gli ingressi fisici non li puoi "resettare" perchè il loro stato dipende dal segnale esterno. Anche se sono ingressi che vengono passati alla funzione dall'esterno non li puoi resettare perchè al prossimo richiamo della funzione saranno ripristinati. Tutto quello che puoi fare è metterli in AND con un consenso che puoi chiamare "resetta ing precedenti". Però non puoi usare l'ingresso così cope è ma devi memorizzarne la sequenza di arrivo per poter stabilire la sequenza temporale dell'avvenuta variazione. Modificato: 16 novembre 2018 da Livio Orsini Link al commento Condividi su altri siti More sharing options...
batta Inserita: 16 novembre 2018 Segnala Share Inserita: 16 novembre 2018 Nel primo post dici che "l'ultimo ingresso setta la sua uscita ed azzera le altre". Nei successivi post dici che "l'ultimo ingresso azzera gli altri ingressi". Per quanto riguarda la seconda modalità, come dice Livio, non puoi "azzerare gli ingressi". Consideriamo quindi solo l'azzeramento di tutte le uscite, e l'attivazione della sola uscita relativa all'ultimo ingresso attivato. In pratica, devi rilevare i fronti di salita degli ingressi e, quando arriva un fronte di salita, resettare tutte le uscite e poi settare solo l'uscita interessata. Se lavori a bit, diventa una cosa infinita. Meglio quindi appoggiare i 64 bit di ingresso su 2 variabili DWord. Un esempio di programma potrebbe essere questo: L #Input_DW // DWord ingressi L #InvInput // DWord con stato invertito ingressi precedente scansione UD T #XOS // DWord con fronti salita ingressi L DW#0 ==D SPB M000 // Se non ci sono stati fronti di salita, saltare a M000 L #XOS T #Output_DW // Scrivi fronti di salita in DWord uscite M000: L #Input_DW INVD T #InvInput // Scrivi stato invertito ingressi per controllo prossima scansione Con questo sistema te la cavi con poche righe di codice (dovresti ripeterlo per gli altri 32 bit), ma ha un inconveniente: se vanno alti contemporaneamente (nella stessa scansione) 2 o più ingressi, verranno attivate 2 o più uscite. Altra possibilità, fai un LOOP, dove controlli uno ad uno tutti gli ingressi, ed esci dal loop al primo fronte di salita rilevato, così eviti l'eventuale attivazione di più di una uscita. Con un 1500 nel loop potresti usare una sintassi del tipo IN_Array[id] (dove id è l'indice dell'array), ma nel 300 questa sintassi non è accettata, e devi lavorare con i puntatori. Oppure fai un ciclo FOR in SCL. Link al commento Condividi su altri siti More sharing options...
Linotix Inserita: 16 novembre 2018 Autore Segnala Share Inserita: 16 novembre 2018 (modificato) Ok grazie. In effetti avevo pensato anch’io ad una soluzione come questa e mi era appoggiato a delle Ld temporanee del fc. La soluzione del loop mi sembra migliore. Saresti così gentile da farmi un esempio in awl? Grazie Modificato: 16 novembre 2018 da Linotix Link al commento Condividi su altri siti More sharing options...
batta Inserita: 16 novembre 2018 Segnala Share Inserita: 16 novembre 2018 Perché non vuoi usare SCL? Link al commento Condividi su altri siti More sharing options...
Linotix Inserita: 16 novembre 2018 Autore Segnala Share Inserita: 16 novembre 2018 Ho provato il codice che mi hai suggerito, del resto avevo provato già qualcosa di simile , usando direttamente il fronte delle uscite. Però se io attivo un ingresso, e poi attivo un secondo ( e il primo rimane alto) invece di spegnersi la prima uscita e accendersi la seconda , le uscite iniziano a lampeggiare alternativamente. Link al commento Condividi su altri siti More sharing options...
Linotix Inserita: 16 novembre 2018 Autore Segnala Share Inserita: 16 novembre 2018 Non voglio usare slc perché non ho molta confidenza. Vorreibriuscire a farlo in awl Link al commento Condividi su altri siti More sharing options...
batta Inserita: 16 novembre 2018 Segnala Share Inserita: 16 novembre 2018 Quote Ho provato il codice che mi hai suggerito, del resto avevo provato già qualcosa di simile , usando direttamente il fronte delle uscite. Però se io attivo un ingresso, e poi attivo un secondo ( e il primo rimane alto) invece di spegnersi la prima uscita e accendersi la seconda , le uscite iniziano a lampeggiare alternativamente. Io l'ho provato col simulatore, e funziona. Sicuro di averlo copiato correttamente? Come hai dichiarato le variabili? In particolare, le variabili #XOS e #InvInput NON devono essere TEMP. Comunque, ho buttato giù qualcosa in AWL. Ecco il sorgente: FUNCTION_BLOCK "Test" { S7_Optimized_Access := 'FALSE' } VERSION : 0.1 VAR_INPUT In_DW : DWord; RstOut : Bool; END_VAR VAR_OUTPUT NewInDetected : Bool; END_VAR VAR_IN_OUT Out_DW : DWord; END_VAR VAR XOS : DWord; END_VAR VAR_TEMP id : Int; adrIn : DInt; adrOut : DInt; adrXos : DInt; END_VAR BEGIN NETWORK TITLE = SET; R #NewInDetected ;// Azzera variabile OUT "rilevato nuovo ingresso" L P##In_DW;// Carica indirizzo variabile immagine ingressi T #adrIn; L P##Out_DW;// Carica indirizzo variabile immagine uscite T #adrOut; L P##XOS;// Carica indirizzo variabile immagine rilevamento fronti salita T #adrXos; L 32;// Imposta numero cicli loop NEXT: T #id; U DIX[ #adrIn];// Leggi stato ingresso FP DIX[ #adrXos];// Rileva fronte salita ingresso SPBN M000;// Se non è stato rilevato fronte salita, salta a M000 L DW#0; T #Out_DW;// Azzera tutte le uscite SET; S DIX[ #adrOut];// Setta uscita corrispondente a ingresso del quale è stato rilevato fronte S #NewInDetected;// Setta variabile OUT "rilevato nuovo ingresso" M000: L #adrIn; + 1; T #adrIn;// Incrementa di 1 bit indirizzo variabile immagine ingressi L #adrOut; + 1; T #adrOut;// Incrementa di 1 bit indirizzo variabile immagine uscite L #adrXos; + 1; T #adrXos;// Incrementa di 1 bit indirizzo variabile immagine rilevamento fronti L #id;// Carica indice loop LOOP NEXT ;// Decrementa indice e, se indice > 0, torna a NEXT UN #RstOut;// Comando reset uscite SPB M001; L DW#0; T #Out_DW; M001: NOP 0; END_FUNCTION_BLOCK Anche questo l'ho provato col simulatore, e funziona. La funzione è fatta sempre per 32 ingressi. Nel tuo caso, per fare i 64 ingressi, dovresti richiamarla due volte (con diverso DB di istanza). In uscita ho messo anche il rilevamento di un fronte di salita. Questo flag lo potresti usare per azzerare le uscite dell'altro blocco. IMPORTANTE!!! Visto che si fa uso dei puntatori, non si può richiamare la FB come multiistanza. Nel caso volessi richiamarla come multiistanza, dovresti passare alla funzione l'offset dell'indirizzo della funzione stessa. Link al commento Condividi su altri siti More sharing options...
batta Inserita: 16 novembre 2018 Segnala Share Inserita: 16 novembre 2018 Io continuo però a sostenere che in SCL sarebbe più facile, anche se non hai dimestichezza con questo linguaggio. Ecco come potrebbe essere: FUNCTION_BLOCK "Test_scl" { S7_Optimized_Access := 'FALSE' } VERSION : 0.1 VAR_INPUT IN : Array[1..#n] of Bool; RstOut : Bool; END_VAR VAR_OUTPUT NewInDetected : Bool; END_VAR VAR_IN_OUT OUT : Array[1..#n] of Bool; END_VAR VAR XOS : Array[1..#n] of Bool; END_VAR VAR_TEMP fs : Bool; i : Int; j : Int; END_VAR VAR CONSTANT n : Int := 64; END_VAR BEGIN // Inizializzo flag rilevamento nuovo ingresso FALSE #NewInDetected := FALSE; #fs := false; FOR #i := 1 TO #n DO // Rilevo fronte salita ingresso #fs := #IN[#i] AND #XOS[#i]; #XOS[#i] := NOT #IN[#i]; IF #fs THEN // Eseguo ciclo FOR per azzeramento di tutte le uscite FOR #j := 1 TO #n DO #OUT[#j] := FALSE; END_FOR; // Imposto uscita relativa ad ingresso attivato #OUT[#i] := TRUE; // Imposto flag rilevamento attivazione nuovo ingresso #NewInDetected := TRUE; END_IF; END_FOR; // Azzero uscite con comando da ingresso funzione IF #RstOut THEN FOR #j := 1 TO #n DO #OUT[#j] := FALSE; END_FOR; END_IF; END_FUNCTION_BLOCK In questo caso, lavoro direttamente con gli array. La dimensione dell'array la imposti nella costante "n" all'interno del blocco. Link al commento Condividi su altri siti More sharing options...
Linotix Inserita: 17 novembre 2018 Autore Segnala Share Inserita: 17 novembre 2018 Grazie mille gentilissimo In effetti avevo usato variabili temporanee. Problema risolto. Per quanto riguarda SCL, tutto il resto del programma è in awl quindi vorrei lasciarlo così. Dovrei aggiungere quella parte sulla fc fatta in awl, o aggiungere un altra fc solamente per le istruzioni scl?Poi quando viene compilato diventa normale awl? Link al commento Condividi su altri siti More sharing options...
batta Inserita: 17 novembre 2018 Segnala Share Inserita: 17 novembre 2018 Quote Per quanto riguarda SCL, tutto il resto del programma è in awl quindi vorrei lasciarlo così. Dovrei aggiungere quella parte sulla fc fatta in awl, o aggiungere un altra fc solamente per le istruzioni scl?Poi quando viene compilato diventa normale awl? Sì, dovresti fare una FB (non FC, perché ha bisogno di variabili STAT), da richiamare dove vuoi. Se compili il sorgente, ti risulta un FB con parametri IN/OUT. Richiami la FB e colleghi direttamente gli array di 64 bool. Se preferisci fare una FC, devi dichiarare la variabile XOS come IN_OUT (e non come STAT, come nell'esempio), e collegare un array di 64 bool (variabile NON TEMP). Non è strano, anche in un programma interamente in awl, inserire una routine in altri linguaggi. Per quanto riguarda la compilazione, se lavori con il 300 tutto viene sempre convertito in awl. Con le CPU 1200/1500 invece no. Link al commento Condividi su altri siti More sharing options...
Linotix Inserita: 17 novembre 2018 Autore Segnala Share Inserita: 17 novembre 2018 Ok ci provo. Grazie ancora. Link al commento Condividi su altri siti More sharing options...
Linotix Inserita: 17 novembre 2018 Autore Segnala Share Inserita: 17 novembre 2018 Solo un ultima cosa non mi è completamente chiara rispetto al tuo primo esempio. Ho fatto una prova con alcune uscite e funziona. Però io all’inizio avevo usato delle memorie temporanee perche mi era comodo, visto che in uscita della funzione una volta richiamata deve esserci un array da 64 bit. In quel modo potevo creare un array temporaneo e usare delle LD perché avevo a disposizioni gli indirizzi nella dichiarazione delle variabili del blocco e le connessione con l’array di uscita della fc era già fatto. Però se devo appoggiarmi a delle MD dovrò poi trasferire le memorie nell’array delle uscite , e scrivere su tutti i 64 bit la connessione tra i singoli bit M e l’array In uscita, visto che non voglio trovarmi 64 uscite quando richiamo la FC. C’e un metodo più pratico per connettere i bit dell’array alle Md? Spero di essere stato abbastanza chiaro. Link al commento Condividi su altri siti More sharing options...
Linotix Inserita: 17 novembre 2018 Autore Segnala Share Inserita: 17 novembre 2018 Poi perché con le temporanee non funziona visto che le connessioni tra ingressi e uscite sono tutte scritte all’interno della funzione senza richiami all’esterno? Scusate per le tante domande ma voglio capire fino in fondo quello che sto facendo. Link al commento Condividi su altri siti More sharing options...
batta Inserita: 17 novembre 2018 Segnala Share Inserita: 17 novembre 2018 Gli esempio che ho fatto sono per la creazione di una FB alla quale passi in ingresso lo stato degli ingressi, e come IN/OUT lo stato delle uscite. Le variabili usate sono variabili STAT all'interno della funzione. Non serve quindi tirare in ballo merker od altro. È il modo più comodo per gestire la cosa. Se non vuoi creare una FB, in ogni caso lascia perdere i merker, e usa i DB. Se il codice lo scrivi all'interno di una FB, dichiara le variabili come STAT. Se sei all'interno di una FC, crea dei DB con le variabili che ti servono. Quote Poi perché con le temporanee non funziona visto che le connessioni tra ingressi e uscite sono tutte scritte all’interno della funzione senza richiami all’esterno? Scusate per le tante domande ma voglio capire fino in fondo quello che sto facendo. Per rispondere a questa domanda, dovrei vedere il tuo programma. Da quello che scrivi non capisco quali siano le variabili TEMP Link al commento Condividi su altri siti More sharing options...
Linotix Inserita: 17 novembre 2018 Autore Segnala Share Inserita: 17 novembre 2018 20 ore fa, batta scrisse: o l'ho provato col simulatore, e funziona. Sicuro di averlo copiato correttamente? Come hai dichiarato le variabili? In particolare, le variabili #XOS e #InvInput NON devono essere TEMP. Mi riferivo a queste variabili. Comunque penso di aver capito che che con le temp non funziona perché azzerandosi ad ogni ciclo non memorizzano lo stato per fare il confronto. Grazie del tuo aiuto. Link al commento Condividi su altri siti More sharing options...
Linotix Inserita: 17 novembre 2018 Autore Segnala Share Inserita: 17 novembre 2018 Anche se sinceramente per quanto riguarda la variabile xos non mi sembra serva salvare lo stato del ciclo precedente visto che i fronti li rileva ad ogni ciclo. Link al commento Condividi su altri siti More sharing options...
batta Inserita: 18 novembre 2018 Segnala Share Inserita: 18 novembre 2018 Quote Anche se sinceramente per quanto riguarda la variabile xos non mi sembra serva salvare lo stato del ciclo precedente visto che i fronti li rileva ad ogni ciclo. Il rilevamento del fronte di salita viene fatto confrontando lo stato attuale con lo stato precedente. Lo stato precedente deve essere memorizzato, quindi non può essere una variabile TEMP. Link al commento Condividi su altri siti More sharing options...
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