gomez Inserito: 11 giugno 2008 Segnala Inserito: 11 giugno 2008 Ciao a tutti, sono nuovo del forum come anche del mondo plc e linguaggio programmazione AWL. A causa di memoria ormai scarsa in un Siemens S7 400, mi trovo a dover fare dei calcoli all'interno di una supervisione, che purtroppo spesso non vanno a buon fine a causa della lentezza nella lettura dei dati dell'opc server. Devo quindi in qualche modo farli fare al plc!Sono 5 calcoli, che vanno fatti per otto "vasche". Non è necessario che siano effettuati contemporaneamente, quindi pensavo che una volta scritta il bloccco di calcolo, si potesse passare ad esempio tramite 8 db distinte, gli 8 valori di processo delle 8 vasche.Sono a chiedervi disperato aiuto / codice :-) su come implementare tutto ciò:a) DPT = PFT – PCT – DHFCPFT e PCT = sono delle analogicheDhfc = è una costante real EXP = (DPET/(0,6*Ho)) * 100DPET = analogica lettaHo = costante real c) GSI = (DPT/(Ho*Vi))*100DPT = analogica letta ( dopo 60' che la merker m76.6 è andata a 1 )Ho = costante con due decimaliVi = Qe/(nf*sf) dove: Qe è una variabile già calcolata, nf e sf sono due costanti intere d) DPTrel = DPT * (1/Vt) * (1/Ho)*100DPT = già calcolata nella formula aHo = costante con due decimaliVt(t+tf)=vedi calcolata sopra solo che deve essere calcolata a intervalli di tempo tf e) GI = 100*(Vmaxi/Vt)^alfa*(DPT/DPTmaxi)alfa = costante decimaleil resto valori già calcolati.Certo del vostro aiuto e della vostra collaborazione che spero prima o poi di ricambiare, saluti tutti e aspetto con impazienza!
mubeta Inserita: 11 giugno 2008 Segnala Inserita: 11 giugno 2008 Per come scrivi, sembra quasi che tu stia chiedendo il codice per fare cosa ti occorre.Ti consiglio vivamente di valutare anche il linguaggio SCL, che, per come hai riportato le tue richieste, si avvicina meglio alle esigenze.In AWL, per quanto scrivi, puoi crearti una funzione FC, od FB, dichiarando delle variabili di ingresso, uscita, in_out e temporanee secondo cosa ti occorre. Puoi usare per tutte il formato real, convertendo all'esterno i dati che non lo sono.Se utilizzi l'edito AWL/KOP/FUP, la dichiarazione la fai, graficamente, nella finestra di programmazione della funzione stessa.Effettivamente se devi risparmiare spazio in memoria, hai solo l'AWL e l'SCL come risorse.In AWL, parte del tuo esempio potrebbe essere:L #PftL #Pct-RL #Dhfc-RT #DptIl linguaggio ti mette a disposizione due accumulatori, ACCU1 ed ACCU2, sui cui sono poi fatte le operazioni.Con l'istruzione L, (load), carichi il dato in ACCU1, automaticamente, il dato in ACCU1 preesistente, finisce in ACCU2.L'istruzione -R esegue la sottrazione in formato real, tra ACCU2 ed ACCU1, il risultato è emesso in ACCU1, sempre con la regola che il dato preesistente finisce in ACCU2.Come vadi, fatta la prima sottazione, si carica il terzo parametro; il risultato precedente finisce in ACCU2, e puoi rifare la seconda sottrazione.Il risultato finale che si trova ancora in ACCU1, lo trasferisci con l'istruzione T, (Move), nella variabile di destinazione, sempre, nel caso un real.Tutte le operazioni logiche sono fatte tra valore di ACCU2 e valore di ACCU1, anche i confronti.Nel tuo caso vedo solo operazioni matematiche, che sono, in reale, +R, -R, /R, *R. (Vado a memoria).La guida siemens, è comunque ben fatta, basta usare il trova. Certo è scritta in "Siemensesco", all'inizio ci va pazienza ed interpretazione, ma trovi praticamente tutto.Visto che devi risparmiare spazio per il codice, a volte ti capita che un dato utile sia in ACCU2, mentre lo vorresti in ACCU1 per andare avanti coi calcoli; l'istruzione TAK inverte i due accumulatori, poi hai a disposizione ITD per convertire un intero in doppio intero, e DTR per convertire il doppio intero in reale. (se non ricordo male, quando carichi con L una variabile intera, i due byte più alti vengono azzerati comunque e puoi usare direttamente il DTR, senza trovarti dati sporchi, al limite verifica sull'. cosa fa il load).A questo punto puoi iniziare a scrivere il tuo codice, a limite lo posti se non ti funziona.
gomez Inserita: 11 giugno 2008 Autore Segnala Inserita: 11 giugno 2008 Si effettivamente un pò di codice lo cercavo... cercavo proprio un aiutino per cominciare, e già la tua risposta mi aiuta un pò! Ti ringrazio tantissimo! Posso caricare db diverse ( ciascuna contenente un'array di dati delle diverse 8 unità ) tramite awl, in modo da utilizzare a livello di spazio di memoria solo una volta il mio FC o FB contentente i calcoli e ad ogni ciclo macchina caricare un'array diversa?
mubeta Inserita: 11 giugno 2008 Segnala Inserita: 11 giugno 2008 (modificato) Si, puoi eccome. Osserva il codice qui sotto:NETWORK TITLE =Preparo i puntatori di lavoro L P##DataPtr; // Recupero il Ptr dell'area dati LAR1 ; LAR2 P##tPtr; // Recupero il Ptr locale dell'area dati L D [AR1,P#0.0]; // Copio il Ptr dalla VAR_INPUT di input T LD [AR2,P#0.0]; // nella VAR_LOCAL L D [AR1,P#4.0]; T LD [AR2,P#4.0]; L W [AR1,P#8.0]; T LW [AR2,P#8.0]; // Ora in tPtr c'è il Ptr passato da DataPtr NETWORK TITLE =Refresh data from data block CALL SFC 20 (// Copia l'area di memoria in locale SRCBLK := #tPtr, RET_VAL := #vI0, DSTBLK := #Data); Il codice è di tipo "sorgente", ma lo puoi copiare pari, pari, nell'editor grafico, senza le righe NETWORK e TITLE, che sono appunto, l'inizio di un nuovo segmento ed il suo titolo. Te lo descrivo rapidamente: La tua funzione deve avere un variabile di ingresso che si chiama "DataPtr" di tipo ANY; Inoltre nelle variabili temporali, devi averne una che si chiama "tPtr" sempre di tipo ANY; Ancora nelle temporanee devi avere una struttura, o meglio una UDT, che è la formattazione dei tuoi dati. (creati una UDT con tutte le dichiarazioni che ti occorrono per prima cosa). Questa struttura si chiamerà "Data", come nel mio esempio. A questo punto metti questo codice come PRIMI DUE SEGMENTI della dua funzione. Il codice recupera il puntatore ANY che passerai alla funzione quando devi dirgli quale elemento di array gestire, lo copia in locale, quindi copia, con blkmov, in locale i dati dell'array specificato. Fai tutte le elaborazioni che ti servono, non dimenticare che le variabili sono nella struttura "data" e quindi quando scrivi il codice devi scrivere il percorso completo della variabile : L #Data.Variabile , e alla fine della funzione RIFAI LA COPIA DELL'ARRAY IN SENSO INVERSO. CALL SFC 20 (// Copia l'area di memoria da locale a destinazione SRCBLK := #Data, RET_VAL := #vI0, DSTBLK := #tPtr); In entambi i casi, la viaribile vI0 è un intero locale che la SFC20 usa per dirti come è andata. (Deve darti 0 per andare bene). Ora non ti resta che creare laDB dei dati. Crei una nuova DB, e semplicemente dichiari l'array, una cosa del tipo: DATI ARRAY[0..n] UDT.... (numero della tua UDT) Così hai creato una DB che contiene per (n+1) volte la struttura dati creata come UDT. (La UDT in C++ la chiamaremmo "struct" giusto per capirci).Quando richiami la funzione, in KOP/FUP/AWL, e devi passargli, tra le altre cose, l'array da usare della tua db, nella forma simbolica scriverai semplicemente:simbolo_db.DATI[n] (qui poi l'editor ti convertità l'indirizzo sotto forma di puntatore "P#DBxx.DBXnnn") andando a pescare il primo bit d'inizio della tua struttura.Ed hai fatto tutto cosa domandavi. Modificato: 11 giugno 2008 da mubeta
JumpMan Inserita: 11 giugno 2008 Segnala Inserita: 11 giugno 2008 In alternativa può fare un FB con 8 DB d'istanza, solo che in questo caso le DB sono dedicate solo a quella funzione.Oppure può fare un FC con parametri in cui scrivere uno per uno gli indirizzi degli operandi (che possono essere in qualsiasi DB).
gomez Inserita: 12 giugno 2008 Autore Segnala Inserita: 12 giugno 2008 Ragazzi, voglio ringraziarvi tutti enormente per gli aiuti/suggerimenti! Veramente gentili, ora proverò a cimentarmi nella sconfitta di questo mostro chiamato AWL! Ciao e grazie ancora.
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