per i PLC S7 300
Nulla di nuovo sotto l’albero, in questo articolo
viene descritto in modo “il più chiaro possibile” come utilizzare strutture
indicizzate nella programmazione dei PLC S7 300 della Siemens
[1]
.
Questo articolo è dedicato a chiunque sia alle prime armi con l’ambiente di
sviluppo in oggetto.
Il seguente materiale è frutto dell’esperienza
dell’autore.
L’utilizzo del seguente materiale o parte di esso è
consentito se e solo se viene citata la fonte, l’autore, nonché l’autore stesso
venga messo al corrente dell’uso che se ne intende fare (eventualmente con
diritto di veto J ).
© Copyright –
Federico Milan, 2004 / PLC Forum ®
Qualunque FeedBack è sempre apprezzato.
L’autore non è responsabile di false citazioni, errori,
danni a cose e/o persone derivanti dalla lettura del seguente materiale.
Gli indirizzi di riferimento per contattare l’autore
sono:
federico@plcforum.it
Federico
Milan
Cittadella,
PD
|
0.0
Introduzione
Il seguente articolo pur essendo dedicato a chi è alle prime armi presuppone una certa dimestichezza con l’utilizzo dell’ambiente integrato ©SIMATIC Manager. L’ambiente di riferimento è la versione 5.2 + SP1.
Per una lettura efficiente il lettore dovrebbe avere assimilato il concetto di struttura dati su di un DB, l’utilizzo degli UDT, nonché saper utilizzare gli operatori di caricamento e trasferimento dati.
È necessario anche una piccola conoscenza di aritmetica e delle basi numeriche.
In questo articolo si prende in considerazione una delle possibili tecniche di indicizzazione dei dati. Si prenderanno in considerazione quindi gli array [2] e le strutture dati e gli UDT [3] .
1.0
Giocando con le strutture dati
Prima di entrare nel vivo della problematica vediamo come si costruiscono le strutture dati, e facciamo un piccolo confronto tra le strutture dati e gli UDT, sempre in termini molto “terra a terra” senza pretese di onniscienza J.
1.1
Inserimento di una DB
Sebbene si dovrebbe gia sapere utilizzare
l’ambiente di sviluppo vediamo brevemente come inserire le DB
|
Figura
1 – Inserimento di un DataBlock (DB).
|
A questo punto verrà data la possibilità di associare un nome simbolico alla DB creata, così come visualizzato dalla Figura 2.
|
Figura
2 – Inserimento di un DataBlock; nome simbolico
|
Non resta che premere il pulsante OK. La figura seguente da un’idea di cosa abbiamo creato J.
|
Figura
3 – Il DB è inserito J.
|
1.2
Inserimento dati e loro utilizzo nel programma
Iniziamo a inserire la prima struttura dati sulla DB creata. Iniziamo subito “alla grande”; inseriamo una struttura in grado di rappresentare uno spazio e un tempo, e ovviamente una velocità J.
|
Figura
4 – Ecco come si presenta la DB
|
Se volessimo a questo punto eseguire un calcolino della velocità, ecco quello che dovremmo fare:
|
Figura
5 – Nomi simbolici e effettivo indirizzo fisico delle variabili
|
Tutta la nostra fatica ovviamente non è sul ripasso delle leggi fisiche, ma su come vengono rappresentati i dati e la loro relazione con l’indirizzo fisico.
Il codice leggibile per gli esseri umani, potrebbe anche essere riscritto come segue, il che mette in luce che il simbolico utilizzato è solo utile alla compressione del testo, ma niente di utile per realizzare programmi “funzionanti”.
|
Figura
6 – Nomi simbolici e effettivo indirizzo fisico delle variabili
|
Fino a qui tutto dovrebbe essere chiaro. Le strutture dati servono solo a noi programmatori, al compilatore/interprete/PLC non interessano, a queste entità non servono a nulla! Ritornando ad uno dei mie primi articoli potremmo giocare con il codice, complicandolo come segue:
|
Figura
7 – come complicarsi la vita … Riferimento a dati tramite puntatore a 32bit.
|
Bene, a questo punto, oltre a giocare per farsi “male” L, potremmo giocare per semplificarci la vita J. Prima di fare questo è opportuno vedere brevemente gli UDT.
1.3
GLI UDT
Gli UDT sono dati creati dall’utente, si generano allo stesso modo delle DB, solo che non sono dati residenti in memoria, ma una loro descrizione.
Un esempio chiarificatore potrebbe essere il seguente.
|
Figura
8 – UDT1
|
Apriamo l’ UDT1 e inseriamo la nostra relazione fisica:
|
Figura
9 – Descrizione dei dati dell’UDT1
|
Notare che l’UDT presenta già il costrutto STRUCT. Ora, però, questi dati li possiamo solo rappresentare, ma per il momento non possiamo farci niente; i dati per essere usti devono essere prima mappati su di una DB.
È necessario quindi inserire in una nostra DB un nome e come tipo di dato il nome della UDT creata. Di seguito l’esempio.
|
Figura 10 – come si trasforma il codice |
Come si vede il simbolico è cambiato (di poco), ma l’indirizzo fisico no! Ancora una volta il simbolico serve solo per gli esseri umani, ma al PLC non serve a nulla.
L’utilizzo delle UDT è molto utile per descrivere dati di uso generico, ovviamente in questo articolo non se ne apprezzerà il vantaggio, ma con il passare del tempo, si apprezzerà la potenza descrittiva degli UDT.
2.0
Gli array
Ora introduciamo gli array, e iniziamo a fare sul serio. Anzi iniziamo a divertirci veramente J.
Per essere semplice e chiaro vediamo subito come inserire un array di 10 elementi nella nostra solita DB.
L’array dichiara un “insieme” di elementi indicizzati, tutti delle stesso tipo. È importante ricordare che gli elementi di un array devono essere dello stesso tipo, questo perché ogni elemento occupa una zona ben precisa di memoria.
|
Figura 11 – array di UDT |
Nel simbolico ogni elemento vene indicizzato, osservate la Figura 11.
Ancora una volta il simbolico è cambiato, ma l’indirizzo fisico è rimasto lo stesso (almeno per il primo elemento). Ora osservate la seguente figura (Figura 12) e capirete la relazione che esiste tra gli elementi dell’array.
|
Figura 12 – Relazione tra indirizzi … |
Come risulta chiaro dalla figura il primo elemento Fisica [4] : Fisica[1] è a offset 0, il secondo (Fisica[2]) è a offset 6 e così via.
La cosa interessante è che lo Spazio di Fisica[] si trova a offset 0 rispetto a Fisica[] mentre Tempo si trova a offset 2 rispetto a Fisica[]. A questo punto tutto diventa banale. Il puntamento a strutture, per quanto complesse siano, si basa su un calcolo di offset e su di uno di spiazzamento.
Per fare un esempio a parole, diciamo che se vogliamo puntare alla Velocità di Fisica[4] dovremmo trovare l’inizio di Fisica[4] che è alla WORD 18, e a questo sommare i 4 Byte di offset, ottenendo l’indirizzo DBW 22.
3.0
Funzioni per strutture indicizzate
Quello che si è detto sul paragrafo 2.0 consente già di per sé di trovare una soluzione al problema. Non ci resta che mettere sul fuoco un po’ di codice, e il gioco è fatto.
|
Figura 13 – Il codice per l’indiccizzazione |
Il codice che abbiamo scritto, mostra come andare a puntare ad un qualunque elemento dell’array. In questo caso il MW100 (ma poteva essere una qualunque memoria intera) rappresenta l’indice a cui puntare, oppure detto in altre parole, l’elemento desiderato dell’array.
Vediamo come lavora il codice:
Ipotiziamo
di voler puntare all’elemento 2.
MW100 = 2;
calcoliamo l’offset:
(2 – 1) * 6 = 6 à l’inizio della struttura del secondo
elemento è sul
sesto byte.
Trasformiamo il numero 6 in puntatore
[5]
e lo carichiamo sul registro
AR1. Ora
tramite la sintassi L DBW[AR1,P#x.y] possiamo puntare all’indirizzo caricato su
AR1, eventualmente sommando l’offset indicato da P#x.y
[6]
.
A questo punto tutto dovrebbe essere chiaro. Spesso, però non siamo fortunati, e non possiamo partire da offset 0. Questo non dovrebbe preoccuparci, perché, così come calcoliamo lo “spiazzamento” degli elementi dell’array, allo stesso modo possiamo calcolare anche l’offset dell’inizio array. Come fare? Semplice:
Aprendo
il DB si guarda a che byte inizia l’array.
Nel calcolo del
puntatore, all’inizio basta sommare il numero di byte a cui inizia l’array.
4.0
Conclusioni
Abbiamo visto come utilizzare gli array, come indicizzarli. Ora siamo in grado di programmare strutture in modo “dinamico”.
Solo una precisazione, abbiamo lavorato con interi, ma nulla toglie di utilizzare DINT, o Bit, basta slo utilizzare i rispettivi “operatori” DBD[], DBX[]. Ma ovviamente non ci possiamo solo limitare alla memoria delle DB, possiamo anche puntare anche puntare alle variabili locali, ampliando ulteriormente le nostre possibilità … a voi l’immaginazione.
E se l’array è multidimensionale? Del tipo una matrice? Ancora una volta un po’ di algebra ci aiuta:
es:
M[5][4] : immaginiamo
che la matrice sia composta da 4
colonne
e 5 righe.
Come
puntare all’elemento M[2][3]?
Seguiamo
il ragionamento:
dobbiamo
puntare alla colonna 3 riga 2, quindi matematicamente
significa puntare alla
zona di memoria indicata da:
(3-1) +( 2-1)*4 [trasformato
in puntatore secondo la regola
[7]
]
Quindi generalizzando
(y-1)*N_Colonne + (x-1).
Buon divertimento!
[1] Per maggiori dettagli consultare il sito www4.ad.siemens.de
[2] L’array può essere visto come un vettore mono o multidimensionale contenente degli oggetti di tipo bit, byte, word,… o addirittura strutture dati molto complesse. Gli oggetti devono essere tutti dello stesso tipo.
[3] Con la sigla UDT viene indicato un tipo di dati definito dall’utente.
[4] Fisica è il nome della struttura. È importante non confondere la struttura array con l’elemento di array che indichiamo come Fisica[4](ossia il quarto elemento dell’array).
[5] Il calcolo di puntatore viene eseguito con uno shift a sinistra del numero.
[6] Il puntatore è indicato con P#x.y dove x rappresenta il byte e y il bit. Per maggiori dettagli consultare la documentazione in linea.
[7] Il puntatore si trova moltiplicando l’indice del suo indirizzo per la dimensione dei dati in byte, quindi “shiftando” di 3 bit a sinistra.