Vai al contenuto
PLC Forum

Partecipa anche tu alla Live su Youtube martedì 28/01/2025 per festeggiare i 24 anni di PLC Forum

Per ulteriori informazioni leggi questa discussione: https://www.plcforum.it/f/topic/326513-28012025




Awl Per Calcoli! - Aiuto su come fare calcoli in awl per risparmiare memoria


Messaggi consigliati

Inserito:

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 – DHFC

PFT e PCT = sono delle analogiche

Dhfc = è una costante real

B) EXP = (DPET/(0,6*Ho)) * 100

DPET = analogica letta

Ho = costante real

c) GSI = (DPT/(Ho*Vi))*100

DPT = analogica letta ( dopo 60' che la merker m76.6 è andata a 1 )

Ho = costante con due decimali

Vi = Qe/(nf*sf) dove: Qe è una variabile già calcolata, nf e sf sono due costanti intere

d) DPTrel = DPT * (1/Vt) * (1/Ho)*100

DPT = già calcolata nella formula a

Ho = costante con due decimali

Vt(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 decimale

il 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!


Inserita:

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

L #Pct

-R

L #Dhfc

-R

T #Dpt

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

Inserita:

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?

Inserita: (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: da mubeta
Inserita:

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

Inserita:

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.

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