Indice |
Introduzione
Pur essendo un sostenitore della "programmazione diretta", ovvero della scrittura diretta dei codici, e credendo che questa operazione sia essenziale quando si vuole avere il pieno controllo su ciò che si intende realizzare, ho scritto questo articolo per parlare della possibilità di usare software che possano generare codici partendo da approcci più grafici e in ambienti che permettano la simulazione dell'interazione tra "mondo software" e "mondo hardware". Più in particolare ho utilizzato due tool del software Matlab della Mathworks, ovvero Simulink e Real-Time Workshop, per generare dei codici per l'ormai famosissimo (o inflazionatissimo?) Arduino UNO.
Il perché risiede in tre motivi particolari:
- Lavorare in ambiente Simulink può permettere di simulare con molta semplicità l'insieme del mondo controllistico e della realtà fisica con la quale si intende interfacciarsi in modo da far coincidere le fasi di sviluppo e di simulazione;
- Esistono situazioni in cui viene richiesto di certificare i codici che si producono e la generazione automatica (code generation) è un modo molto utilizzato in ambiente industriale.
- Oltre che per Arduino, il codice può essere generato per diversi tipi di micro controllori, DSP, nonché per sistemi "hobbistici" come LEGO Mindstorms.
Qui di seguito ho cercato di spiegare passo passo le operazioni da seguire per controllare un semplice sistema che regola la luminosità di un LED in base alla tensione presente ai capi di un potenziometro, utilizzando gli strumenti sopra citati.
Breve introduzione a Simulink e Real-Time Workshop
Simulink è un tool per la modellazione, simulazione e analisi di sistemi dinamici tramite l'utilizzo di schemi a blocchi. E' un software integrato nell'ambiente Matlab ed è quindi in grado di dialogare con il suo workspace e i restanti tool. Uno di questi tool è proprio Simulink Coder o, più propriamente, Real-Time Workshop: un software che, a partire dal modello costruito in ambiente Simulink, è in grado di generare e scaricare in modo automatico il codice da caricare sul nostro micro controllore facendo quello che, in gergo, viene definita programmazione host-target. Naturalmente, in questo caso, l'host e il target saranno rispettivamente il nostro computer e il micro controllore montato sulla scheda Arduino.
Per una descrizione più dettagliata vi rimando al sito della casa produttrice:
Breve introduzione ad Arduino
Sicuramente non è il caso di dilungarsi molto nel parlare di Arduino; basta dire che si tratta di una scheda sulla quale è montato un micro controllore e l'elettronica ausiliaria che ne permette il corretto funzionamento, la corretta alimentazione e il dialogo con l'esterno tramite vari modi tra cui la porta USB del computer. Il micro controllore permette di ricevere in ingresso segnali digitali (0-5 V) e segnali analogici (anche questi per un picco massimo di 5 V) e permette di generare dei segnali digitali. Come ausilio, si hanno a disposizione anche dei canali di alimentazione a 5 e a 3.3 V.
Naturalmente non esiste una sola versione di scheda Arduino: queste variano per il micro controllore utilizzato e, di conseguenza, anche per il numero e il tipo di pin che abbiamo a disposizione.
La scheda utilizzata in questo caso è la versione Rev 3 di Arduino UNO.
Per chi volesse approfondire può cliccare qui.
Per sapere come collegare, alimentare ed installare Arduino, basta seguire le indicazioni presenti sul
sito ufficiale
Il progetto d'esempio
Per comprendere il funzionamento e l'integrazione di tutti gli oggetti sopra descritti, ho pensato ad un progetto piuttosto semplice; quello che vogliamo far fare al micro controllore è leggere la tensione ai capi del potenziometro e regolare la luminosità di un LED in base alla tensione letta.
I collegamenti da realizzare e lo schema elettrico vengono presentati nelle due immagini seguenti.
Con R1=0-10 kΩ, R2=10 kΩ, R3=330 Ω
Entrambe le resistenze ausiliarie (R2 ed R3) hanno il compito di limitare la corrente che fluirebbe dai pin del micro controllore evitando di provocare possibili danni al componente.
Schema di Simulink
Passiamo ora alla realizzazione dello schema a blocchi in ambiente simulink. Per farlo abbiamo bisogno di alcune operazioni preliminari che permettano a Simulink di sapere che stiamo costruendo un modello che servirà alla generazione di codice per Arduino.
Per farlo basta digitare targetinstaller nella Command Windows di Matlab e seguire passo passo le istruzioni.
Per precauzione, prima di procedere all'installazione del target Arduino, verifichiamo l'avvenuta installazione di Real-Time Workshop digitando il comando rtwintgt -setup.
Lasciamo che Matlab scarichi in automatico da internet i file che ci interessano.
Tra le varie opzioni di target che vengono visualizzate, scegliamo Arduino Uno.
Al termine di queste operazioni preliminari, siamo in grado di iniziare con la costruzione del nostro modello.
Come prima cosa apriamo Simulink digitando semplicemente simulink nella Command Window, oppure premendo l'apposita icona.
Se conoscevate già l'ambiente Simulink, potete notare che, tra l'elenco dei blocchi, sono comparsi dei blocchi particolari che si riferiscono alle operazioni base che è possibile compiere tramite i pin di Arduino.
Per chi ha già dimestichezza con Arduino non avrà problemi ad intuire la funzione di ogni blocco. Non volendo dilungarmi eccessivamente, preferisco non spiegare il funzionamento di tutti i blocchi che vedete (magari ci sarà modo di farlo in un prossimo articolo!), ma soffermarmi su quelli utili ai fini del progetto. D'altro canto è sufficiente cliccare su un blocco per avere informazioni circa il suo impiego.
Sostanzialmente useremo solo due blocchi specifici per Arduino, ovvero il blocco Analog Input e il blocco PWM mentre, per il funzionamento del sistema, useremo due blocchi standard di Simulink ovvero il blocco "Constant" e il blocco "Divide": il primo genera un valore costante definito da noi e il secondo divide il segnale sul primo ingresso per il segnale collegato al secondo ingresso.
Per iniziare a costruire lo schema, dopo aver compiuto le operazioni preliminari appena descritte e avviato Simulink, occorre aprire un nuovo file cliccando sulla classica icona con il foglio bianco.
Per inserire i blocchi nel nuovo file, è possibile ricorrere ad un semplice drag and drop oppure cliccare con il tasto destro del mouse sul blocco e selezionare Add to untitled (ovvero il nuovo modello che stiamo costruendo).
Una volta inseriti i blocchi, non resta che collegarli cliccando su un ingresso o una uscita di un blocco e, mantenendo premuto il tasto del mouse, avvicinarsi al punto in cui vogliamo effettuare il collegamento; quando il puntatore diventa una doppia croce possiamo rilasciare il tasto.
Questo è come dovrebbe presentarsi lo schema completo.
A questo punto non resta che settare i blocchi. Per farlo è sufficiente fare doppio click su di essi e impostare i parametri.
- Analog Input: questo blocco permette di settare un pin al quale associare la funzione di input analogico ovvero, nel nostro caso, il pin sul quale leggeremo la tensione presente ai capi del potenziometro. I pin utilizzabili sono quelli indicati, sulla scheda Arduino, da un numero tra 0 e 5 preceduto dalla lettera A. Nel nostro caso quindi, facendo riferimento agli schemi riportati all'inizio, setteremo per tale funzione il pin A0.
- PWM: questo blocco permette di settare un pin al quale associare una variazione dello stato logico (0-5 V) con una frequenza proporzionale al valore in ingresso. Quando il pin digitale sarà in uno stato HIGH, la tensione tra il pin e il ground del sistema sarà di 5V e, poichè da un pin del micro controllore è possibile far passare una corrente fino a 20 mA, questo alimenterà il LED permettendone l'accensione. Variando la frequenza con la quale il pin permane sugli stati logici HIGH-LOW (ovvero tensione 5 o 0 V) è possibile far variare il valore medio della tensione che alimenta il LED.
Per tale scopo possiamo utilizzare il pin 6.
- Constant e Divide questi blocchi sono necessari per adattare il valore in uscita dal blocco Analog Input e quello in ingresso al blocco PWM. Questa operazione è necessaria poiché il campionamento per la conversione AD di Arduino avviene su 10 bit e quindi fornisce valori compresi tra 0 e 1023 mentre il blocco PWM accetta valori su 8 bit, ovvero con valori compresi tra 0 e 255. Da quanto detto, è immediato capire che il valore del blocco Constant va settato a 4 in modo da riscalare in modo adeguato il segnale in ingresso al blocco PWM.
Piccola nota: in alternativa ai due blocchi Constant e Divide sarebbe stato possibile utilizzare il blocco Gain settandolo ad un valore pari a 0.25. Questo blocco, rappresentato da un triangolo, effettua una operazione di moltiplicazione sul segnale in ingresso (da cui si capisce che, per dividere per 4, occorre moltiplicare per 0.25).
Una volta conclusa la costruzione del modello occorre salvare il file all'interno della cartella C:\MATLAB\Targets\R2012a (naturalmente l'ultima parte dell'indirizzo dipende dalla versione che avete installato sul vostro computer).
Colleghiamo Arduino e generiamo il codice
Una volta terminata la costruzione del modello in Simulink, si arriva al momento della generazione del codice. Come prima cosa occorre collegare Arduino alla porta USB del nostro computer. Non appena il device viene riconosciuto, dal menù Tools, selezioniamo Run On Target Hardware e quindi facciamo click su Prepare to Run, come mostrato in figura.
Matlab avvia in automatico il riconoscimento dell'hardware collegato (quello che in gergo viene detto Target) e, al termine dell'operazione, compare la schermata mostrata in figura.
Questa schermata permette di agire sui parametri del codice generato, sulla velocità di trasmissione attraverso la porta seriale, sul compilatore etc. etc.
Per questo primo esempio è sufficiente lasciare che Matlab scelga per noi e cliccare su OK.
Una volta fatto questo occorre ritornare sul menù Tools e aprire nuovamente la tendina Run On Target Hardware: noteremo che, dove prima compariva l'opzione Prepare to Run, compare l'opzione Run che noi, naturalmente, dobbiamo selezionare!
Nella schermata di Simulink, in basso, noteremo che il processo di code generation e di programmazione del target è in esecuzione e, nello stesso momento, potremo vedere che i led sulla scheda Arduino contrassegnati dalle sigle TX e RX lampeggiano: questi led indicano che è in corso un processo di lettura/scrittura della memoria del micro controllore.
Al termine del processo Arduino sarà pronto ad eseguire il compito per il quale è stato programmato!
Video finale di dimostrazione
Ecco a voi il risultato finale!
Conclusioni
Questo articolo propone un esempio semplice per il quale l'uso di Simulink rappresenta senz'altro una complicazione ed un allungamento dei tempi di sviluppo rispetto alla scrittura diretta del codice. Il ricorso ad un caso banale come quello mostrato dà comunque modo di evidenziare una possibilità. Nella mia esperienza personale ho trovato molto utile questa tecnica nella programmazione di macchine a stati finiti con un numero elevato di stati, dove, l'uso di metodi grafici rappresenta una enorme semplificazione nella costruzione degli algoritmi, nella loro visualizzazione e nella loro verifica. Spero quindi che abbiate potuto trovare questo articolo di una qualche utilità per i vostri progetti futuri.