Corso Base di Arduino

Indice

Presentazione
1: Arduino Uno
2: Scrivere e Trasferire programmi su Arduino
3: Programmazione
4: Finalmente un programma!: facciamo lampeggiare un LED
5: Il semaforo (il primo programma tutto nostro!)
6: I Cicli
7: Il misuratore di riflessi (Un programma con cui interagire!)
8: Un misuratore di riflessi migliorato
9: Le decisioni
10: Comunicazione bidirezionale da e verso Arduino
11: Regolatore di luminosità (PWM)
12: Più potenza:pilotare un motore elettrico


 

Presentazione

Essendo nato in ambiente scolastico e da me che sono pagato coi soldi pubblici la filosofia ispiratrice di questo lavoro è quella della libera condivisione e gratuità del sapere, e della comune proprietà delle cose.
(Per ora, stranamente, è considerato positivo farlo solo con le cose immateriali come questa ma…..nel futuro chissà :)))
Chiunque voglia usare, copiare, riprodurre, integralmente o in parte il presente ipertesto, per uso proprio, divulgativo, e soprattutto didattico, è FORTEMENTE INCORAGGIATO a farlo. Chiunque voglia contribuire al suo editing e ad aggiunte, approfondimenti,o comunque desideri collaborare in ogni forma, è incoraggiato a contattare Cristofori Andrea ed il Liceo Galilei per ottenere le credenziali di accesso al Wiki.
Le uniche limitazioni che sono imposte all’uso dell’ipertesto sono le seguenti: se il sapere è libero lo è per tutti, non ci potete fare dei soldi sopra rivendendo il contenuto o sue parti, e non potete poi rivendicare vostri diritti sull’opera derivata, ma la dovete lasciare di pubblico dominio e di libera fruizione.
Quanto esposto sopra si traduce sinteticamente nella formula: Creative Commons – Non commerciale – Condividi allo stesso modo

Note introduttive: La Storia

Arduino nasce in Italia, ad Ivrea, nel 2005. È concepito da Massimo Banzi, per offrire ai suoi studenti una piattaforma sperimentale a basso costo. Non trovandone di disponibili sul mercato, decise con alcuni collaboratori di produrla autonomamente. Dei 200 esemplari prodotti, 50 servirono alla sua scuola, ma gli altri 150, che si pensava rimanessero inutilizzati, vennero rapidamente richiesti. Da questo interesse e dalla conseguente messa in produzione di ulteriori schede, nacque il fenomeno Arduino.

 

arduinoteam

Il Team di creatori

Un documentario in lingua inglese che parala della nascita di Arduino:

https://vimeo.com/18539129

 

Note introduttive: Hardware Libero

Arduino è un progetto libero: ogni sua costituente elettronica e costruttiva è documentata, è possibile introdurre migliorie o specifiche differenti purché il prodotto di queste migliorie o variazioni venga nuovamente reso disponibile alla comunità. Il software con cui Arduino viene programmato è anche esso libero (e scritto basandosi su software libero preesistente). Si è creata inoltre attorno a questo dispositivo una enorme comunità internazionale di utilizzatori che sono ben disposti ad aiutarsi, a condividere il sapere. Ad oggi è la comunità il punto forte di Arduino: ci sono migliaia di esperimenti realizzati, migliaia di schemi collaudati, ma soprattutto ci sono moltissimi utilizzatori disponibili ad aiutare gli altri ed a condividere il proprio sapere in una gara di disponibilità, di mutuo aiuto, di ricerca di soluzioni ai problemi ed ai malfunzionamenti. Tutti si sentono parte di un gruppo partecipe e solidale dove le conoscenze sono condivise anche tra professionalità differenti: Arduino è una piattaforma che lega gli smanettoni elettronici agli studenti, agli artisti, agli appassionati, ai programmatori ed agli artigiani di tutto il mondo. Persone di ogni estrazione, di ogni cultura, di differente grado di preparazione si scambiano pareri, consigli, informazioni tecniche. Fino a tempi recenti la filosofia della condivisione, dell'”Open Source”, della libera disponibilità del proprio lavoro era pionieristica ed oltretutto limitata al Software, campo in cui non ci sono costi di copia, in cui quindi un prodotto dell’ingegno umano può essere utile a tutti senza comportare un aumento di risorse lavorative e di spesa. L’introduzione di un Hardware Libero, ed il suo sviluppo rapido e capillare costituiscono una novità ideologica per l’umanità. Finora il lavoro aveva portato a proteggere le creazioni dell’intelletto tramite la chiusura e la protezione (brevetti, diritto d’autore ecc.) mentre ora nasce, si sperimenta, ha successo, un meccanismo opposto: tanto più si condivide il proprio sapere, tanto più si ha successo in termini di diffusione delle proprie idee e anche in termini economici. Un modo di pensare a volte addirittura all’opposto a quello cui siamo abituati, che oggi sta diffondendosi sempre di più, mettendo in atto discussioni sociologiche ma soprattutto mettendo in giro un  sacco di oggetti interessanti e cambiando anche il mondo della scuola.

Insegnare usando questi strumenti, il cui costo economico è irrisorio (una Board Arduino Uno originale può essere acquistata a circa 20 Euro) utilizzando magari un testo creato con la stessa filosofia di libera condivisione e quindi fruibile a costo zero e disponibile sempre ed ovunque senza spreco di risorse naturali, potendo contare sul supporto di una comunità vastissima, è il sogno di docenti e studenti. Ciascuno studente può imparare (e divertirsi) sia a scuola che a casa, e una volta appreso come utilizzare lo strumento può costruire quello che gli pare, mentre il docente si libererà dai vincoli di disponibilità economica, di difficoltà a condividere la documentazione a causa dei diritti d’autore, e troverà in rete un’immensa casistica di temi trattati, di esercizi svolti, di programmi liberi che possono servire a creare documentazione ma anche ad insegnare meglio.

 

openhardware

Note introduttive: Schede Arduino

Arduino è diventato nel tempo non un solo prodotto ma una famiglia di prodotti in continuo aumento ed evoluzione. C’è la famosa scheda Arduino UNO che è giunta ormai alla terza versione (Arduino UNO R3), ma ci sono anche una serie di schede con differenti caratteristiche tecniche, differenti funzionalità, differenti utilizzi. L’aggiornamento delle caratteristiche e l’aumento del numero delle schede è ormai quasi frenetico: sempre nuove funzionalità, sistemi operativi, potenzialità, vengono offerte all’utilizzatore venendo a coprire davvero ogni esigenza tecnica. Ecco alcune schede con le rispettive caratteristiche:

nano

Arduino Nano

 

due

Arduino Due

 

mega

Arduino Mega

 

lilypad

Arduino Lilypad

 

tre

Arduino Tre

robot

Arduino Robot

torna all’indice

 

1: Arduino Uno

La scheda


Dovendo scegliere una scheda per realizzare questo corso la nostra scelta è rimasta sullo standard: Arduino Uno. Arduino Uno è il prodotto di gran lunga più diffuso, è il più economico, ed è pienamente sufficiente per le nostre esigenze.

Dimensioni in millimetri 68,6 mm × 53,3 mm
Interfacciamento al PC USB
Tipo Microcontrollore Atmel ATmega328
Tensione di lavoro: 5Vdc
Massima corrente per pin digitale 40mA
Tensione di alimentazione consigliata da  7Vdc a 12Vdc
Pin digitali 14 configurabili come ingressi o uscite
Uscite PWM 6
Pin analogici 6 ingressi
Velocità di clock del microcontrollore 16MHz
Memoria Flash 32KB
Memoria Ram 2KB

In sostanza la nostra scheda Arduino Uno è molto semplice economica e versatile: dispone di un buon microcontrollore, della possibilità di programmarlo ed alimentarlo al tempo stesso tramite un cavo USB standard, ha 14 ingressi/uscite digitali (delle quali 6 supportano il PWM), 6 ingressi analogici, la possibilità di essere alimentato anche da una tensione esterna,la possibilità di prelevare dalla scheda la tensione regolata di 5 Volt e di 3,3 Volt in modo da poter alimentare sensori esterni e piccoli carichi (Motori, Generatori di luce,suono ecc.) fino a 40 mA di corrente. Il fatto che il microprocessore sia montato su uno zoccolo ci permette di cambiarlo molto facilmente qualora venisse danneggiato. Il costo di un nuovo microprocessore è di qualche euro, quindi la riparazione non risulta né lunga e difficile né economicamente onerosa.

 

arduinouno_r3_commentato

 

 Il Micro


 Prendiamo adesso in considerazione le caratteristiche costruttive della scheda.

Prendiamola in mano ed iniziamo a familiarizzare con essa. Le principali caratteristiche delle varie componenti la scheda, perlomeno quelle di maggiore utilizzo e di più comune fruibilità, sono chiaramente indicate sulla scheda stessa. La nostra scheda è blu con delle serigrafie bianche impresse. Salta subito all’occhio il componente principale: il microprocessore Atmel ATmega328. Come già detto è montato su di uno zoccolo: se si dovesse bruciare sarà facile sostituirlo poiché entra ed esce semplicemente agendo meccanicamente su di esso.


Il Micro

Usiamo qui, in modo improprio,la parola gergale “Micro” per indicare il microprocessore o microcontrollore.I due termini hanno accezioni differenti, e la famiglia Arduino, vasta, variegata, ed in continuo sviluppo, monta caso per caso dispositivi molto differenti tra loro. Non è interessante trattare la questione all’interno del nostro corso,e quindi useremo il termine gergale per indicarli entrambi, ignorando per ora le differenze e le specificità.

Il micro è un dispositivo elettronico che assomma in sé molte caratteristiche e funzionalità pur essendo contenuto in un singolo chip. Il suo funzionamento è molto complesso: esso si compone di molti blocchi. Inoltre ogni micro ha delle caratteristiche differenti, e delle funzionalità che possono essere implementate o meno. Alcune di queste funzionalità sono però sempre presenti. La parte fondamentale del micro è la cosiddetta ALU (Unità Logico-Aritmetica), la parte che si occupa di “fare i conti” e cioè eseguire delle operazioni matematiche e logiche su dei dati che le vengono forniti.La ALU compie operazioni molto semplici ad una velocità elevatissima secondo una serie di regole o istruzioni codificate usando un linguaggio apposito. La ALU opera su dei dati che risiedono in particolari locazioni di memoria denominate REGISTRI. Del caricare i dati nei registri prima che vengano eseguite le operazioni e del trasferire i dati elaborati in memoria si incarica una Unità apposita di trasferimento e di indirizzo dei dati. Anche in questo caso ogni operazione sui dati è codificata attraverso un linguaggio. L’insieme delle operazioni che vengono svolte dal micro e che dunque compongono il suo linguaggio è detto Set di istruzioni. Oltre a queste unità il micro può avere (o non avere) molte altre funzioni: una unità GPU per esempio, che gli consente di gestire un display grafico, oppure della memoria cache (memoria molto veloce sulla/dalla quale trasferire i dati più frequentemente utilizzati). Può possedere più unità logico/aritmetiche in grado di svolgere parecchi compiti allo stesso tempo (in questo caso si dice che è “multicore”). Esistono oggi sul mercato moltissimi tipi di processori. Gli stessi dispositivi Arduino ne montano di molto diversi sulle varie schede (Atmel su Arduino Uno, Intel su Arduino Galileo, Arm su Arduino Due, Texas Instruments su Arduino Tre..). Ciascun micro usa un linguaggio differente per codificare le operazioni, ma per fortuna non è necessario che noi impariamo i vari linguaggi. La programmazione avviene utilizzando un linguaggio comune che viene poi tradotto nelle differenti istruzioni per i differenti processori da un software detto compilatore, che fa il lavoro per noi in maniera trasparente.


Il sistema binario

I dispositivi elettronici digitali vedono il mondo con occhi strani. Conoscono solo due situazioni: c’è tensione, o non c’è tensione. Se questo solo vedono, anche le cifre che conoscono sono solo 2. Dunque ogni valore numerico verrà rappresentato in un sistema elettronico da due sole cifre: 1 se c’è tensione e 0(zero) se non c’è tensione. Questo sistema di numerazione è detto binario, appunto perché basato solamente su due cifre. Esattamente come nel sistema decimale possiamo rappresentare una qualsiasi quantità usando dieci cifre, (se il numero da rappresentare eccede quello delle cifre facciamo uso di decine, centinaia, migliaia ecc.) anche nel sistema binario possiamo esprimere una qualsiasi quantità usando solo due cifre.


Tabella di numeri decimali espressi in binario
Decimale Binario
0 0
1 1
2 10
3 11
4 100
5 101
6 110
7 111
8 1000
9 1001

 

Input ed output


I vari pin (piedini) del microprocessore sono portati verso il bordo della scheda , dove ci sono due serie di contatti ad incastro (di plastica nera nella foto). Sono connettori strip femmina del passo di 2,54 mm (un decimo di pollice). In questo modo è semplicissimo connettere i vari pin del microprocessore a dispositivi esterni, siano essi degli utilizzatori (motori, lampadine, altoparlanti ecc.), oppure dei dispositivi che generano segnali (sensori, altri microprocessori, sonde esterne, microfoni ecc.).

Ogni pin è contrassegnato da un numero e da una sigla (a volte da una sigla e da un simbolo).

Ingressi/Uscite Digitali


I pin che stanno sul lato dove si trova la presa USB sono contrassegnati da numeri e simboli: sono gli INGRESSI/USCITE digitali e sono numerati da 0 a 13. Ogni singolo pin può essere settato come INGRESSO o come USCITA digitale via software.


Che cos’è un valore Digitale?

Digitale viene dall’inglese digit=cifra. Digitale significa che viene espresso tramite un valore numerico. Sappiamo che microprocessori e circuiti elettrici in genere sono sistemi basati sull’elettricità e le cifre che possiamo usare sono solamente due: la presenza o l’assenza di una tensione. Di conseguenza quando il processore vuole scrivere un valore digitale genera una tensione su un pin quando vuole dire 1 e non genera nulla quando vuole dire 0, mentre in fase di lettura di un valore digitale controlla se c’è tensione su un pin o se non c’è, e converte questi stati in cifra 1 e cifra 0 rispettivamente. Un semplice esempio di utilizzo delle porte digitali è questo: immaginiamo di voler utilizzare Arduino per accendere la luce automaticamente quando siamo sulle scale. Ci sarà un sensore con uscita digitale 1/0 che dirà ad Arduino se c’è una persona nelle vicinanze, e ci sarà di conseguenza un segnale da parte di Arduino, ancora una volta un segnale digitale, che accende la luce quando il sensore rileva la presenza di una persona (stato 1) e che spegne la luce (stato 0) quando non c’è più nessuno.


Ingressi Analogici


Che cos’è un valore Analogico?

Un valore Analogico, al contrario, è un valore di tensione che sta compreso tra 0 volt e la tensione di alimentazione del circuito elettronico, nel caso del nostro Arduino Uno 5 Volt. Ma come? Abbiamo appena detto che un dispositivo elettronico come il microprocessore è sensibile solo a due stati: presenza ed assenza della tensione su un filo, ed ora diciamo che invece è possibile che capisca anche le variazioni di tensione? Non c’è contraddizione, la cosa si può fare, ma serve un circuito elettronico intermedio tra il segnale ed il processore che converta i valori analogici in sequenze di 1 e di 0, un convertitore Analogico/Digitale. N.B. Nel nostro Arduino Uno, il convertitore funziona solo ingresso, e cioè converte solo VERSO il processore e non DAL processore. Quindi se è possibile leggere tensioni tra 0 e 5 volt non è invece possibile farle generare. (Altri microprocessori sono dotati di questa funzionalità, non quello che equipaggia Arduino Uno). Vediamo un esempio di utilizzo di un ingresso analogico: immaginiamo di voler capire a che velocità il vento fa girare un piccolo generatore che sta sul nostro tetto. Sappiamo che la tensione generata è proporzionale alla velocità, dunque basterà mandare la tensione generata in un ingresso analogico di Arduino. Il circuito convertitore Analogico/Digitale convertirà automaticamente il valore letto in un numero decimale e il processore potrà leggerlo ed elaborarlo (ad esempio mostrarlo sul monitor).


Uscite PWM


arduinouno_r3pwm

Alcuni dei pin di INPUT/OUTPUT digitale sono contrassegnati da una tilde oltre che dal numero corrispondente. (Osserva la figura sopra per capire, i pin di cui parliamo sono cerchiati in rosso).Sullo stampato è riportata inoltre la dicitura DIGITAL PWM ~ La tilde significa che sono dei pin particolari che in ingresso si comportano esattamente come ogni ingresso digitale, mentre in uscita possono comportarsi sia come normali pin digitali sia in questa modalità (PWM = Pulse Width Modulation).


Che cos’è il PWM?

Prima l’acronimo, bisogna levarcelo di torno: PWM sta per PULSE WIDTH MODULATION, modulazione a larghezza di impulso. Detto questo andremo a provare a far luce dentro a questo tecnicismo. Per capire cosa sia il PWM preferisco prima spiegare a cosa serve: abbiamo visto che la nostra scheda Arduino può leggere e scrivere valori digitali, abbiamo visto pure che può leggere valori analogici, ma quello che non sa fare è scrivere valori analogici. Insomma: quando “ascolta” può ricevere dati in entrambe le forme, ma quando comunica con l’esterno lo può fare solo in modo digitale: 1 e 0. Se devo accendere una lampadina, o spegnerla, 1 e 0 mi vanno bene. Se devo azionare un motore, sta ancora bene: 1 = motore acceso 0 = motore spento. Ma…se voglio accendere una lampadina in modo prima fioco poi intenso, o …. se voglio fare accelerare lentamente il mio motore? Non ci riesco senza una uscita analogica che cambi valore da zero e cresca lentamente. Potrei dotare il microprocessore di un convertitore Digitale-Analogico in uscita (su Arduino Uno c’è solo il convertitore Analogico-Digitale in ingresso), ma questo dispositivo è costoso da implementare su un microprocessore piccolo come quello che equipaggia Arduino Uno, e farebbe lievitare i costi di tutta la scheda. Ecco che allora utilizzo un “trucco”. Il PWM permette di “fare finta” di avere una tensione variabile in uscita, senza spendere troppo complicando il microprocessore.


Adesso che sappiamo a cosa serve e perché Arduino Uno ne è equipaggiato, vediamo di capire come funziona osservando la figura qui sotto:
pwm
La figura rappresenta l’andamento nel tempo della tensione su di un pin del microprocessore in 3 casi differenti, caso A (in alto) caso B (al centro) caso C (in basso). Nei 3 casi la tensione presente varia sempre da zero al valore V+ (nel caso di Arduino Uno 5 Volt) per poi tornare a zero, e risalire ciclicamente. Cosa cambia nei tre casi? Il tempo in cui le uscite rimangono a tensione alta o a tensione zero. Nel caso A la tensione rimane a 5 Volt solo per poco, mentre è lungo il periodo in cui rimane a zero, nel caso B l’uscita rimane a 5 Volt per circa lo stesso tempo, mentre nel caso C la tensione all’uscita è quasi sempre di 5 Volt, tranne piccoli intervalli in cui si porta a zero. La retta arancio, contrassegnata con V medi indica in ciascun caso la media della differenza di potenziale. È chiaro che il valore medio è maggiore nel caso C rispetto a B e ad A, perché l’uscita è stata mantenuta a 5 Volt per un tempo maggiore. La nostra lampadina ed il nostro motore sono degli utilizzatori che sono interessati al valore medio della tensione e non ai picchi. la conseguenza è che pur pilotando gli utilizzatori con una uscita digitale, possiamo creare valori medi di potenziale variabili in modo continuo perché cambiamo il tempo in cui l’uscita rimane a valore 1 o a valore zero, e siamo riusciti in questo modo a simulare una uscita analogica.

Altre Caratteristiche della scheda


arduinouno_r3accessori

I LED


La scheda è dotata di 4 LED. Accanto ad ognuno c’è una scritta che ne indica la funzione. ovviamente il LED cui è scritto accanto ON indicherà che la scheda è alimentata da tensione e quindi funzionante, sia che la tensione provenga dalla porta USB, sia che provenga da diversa alimentazione. Il LED vicino al piedino 13 (e ad esso connesso) ha una “L” stampata a fianco. Questo LED è comandato dal piedino 13 e serve per realizzare i primi programmini di test, oppure serve per segnalare con la sua accensione il verificarsi di una condizione che desideriamo comunicare senza dover osservare il dispositivo di output grafico. Insomma: il LED è a disposizione del programmatore che lo può fare accendere quando vuole. I restanti due LED, al cui fianco troviamo scritto TX ed RX, segnalano la trasmissione e la ricezione di segnali attraverso la porta seriale. La porta seriale serve sia a trasferire un programma dal computer all’Arduino Uno, sia allo stesso Arduino, durante l’esecuzione del programma, per mandare dei segnali al computer che li può utilizzare elaborandoli oppure semplicemente mostrandoli sul monitor. Insomma: il lampeggio dei LED TX e RX sta a significare o che il nostro Arduino sta ricevendo dei dati o che li sta trasmettendo ad altri dispositivi.

 

Il Pulsante di Reset


Cerchiato in fucsia nella foto, in alto a sinistra, c’è il Pulsante di Reset. Non è detto che sia in quella posizione, poiché nelle varie serie di Arduino Uno costruite nel tempo è stato posto in posizioni differenti (sì, perché la versione attuale di Arduino Uno è la R3, prima di essa sono state costruite R2 ed R1 che avevano piccole differenze rispetto alla versione attuale). La funzione del pulsante è simile a quella del Reset del vostro PC: toglie per un attimo la corrente in modo da costringere il sistema a reinizializzarsi ovvero a ripartire da zero. Si sa: Arduino è un dispositivo elettronico molto complesso e succede che anche lui ogni tanto si blocchi durante l’elaborazione. Se ciò accade, premere il pulsante di reset è una maniera veloce di uscire dai guai. Va reso noto (e ricordato), che le istruzioni del programma su Arduino risiedono in una memoria Flash, che non si cancella quando resettiamo. Quindi premere il pulsante di Reset non ci fa perdere affatto il programma che abbiamo caricato. La peculiarità di non perdere le istruzioni del programma anche se il dispositivo è scollegato dall’alimentazione elettrica rende ragione di un comportamento che spesso giudichiamo “strano”: anche dopo mesi, o anni, di inutilizzo, il nostro Arduino appena collegato all’alimentazione torna ad eseguire l’ultimo programma che abbiamo caricato. Si sa: la memoria degli umani è spesso labile. A volte non ricordiamo affatto che programma avevamo caricato. Addirittura non ricordiamo nemmeno di averlo fatto, ma lui non è un fallibile umano: è un computer e ricorda sempre.

Il connettore USB


Contrassegnato in verde sulla foto, così come in verde è contrassegnato sulla scheda il chip che la controlla.La USB è importantissima su Arduino e svolge più funzioni.

  • Serve per programmare il dispositivo, connettendolo ad un computer.
  • Serve per mandare segnali da Arduino verso il computer (e pure dal computer verso Arduino) in modo, ad esempio,da poter sfruttare il monitor del PC per visualizzare i dati.
  • Serve per alimentare elettricamente la scheda. Si deve però tener presente che la corrente massima che una USB può erogare è di 500 mA, che di norma è sufficiente ad alimentare sia Arduino che dei piccoli carichi ad esso connessi, ma non può dare più di quella corrente. Nel caso l’amperaggio non sia sufficiente si deve fornire una alimentazione esterna tramite la presa apposita.

Il Jack di alimentazione


La Presa (Jack) di alimentazione, cerchiata in fucsia nell’immagine, consente di alimentare Arduino anche senza averlo connesso ad una presa USB e quindi gli consente di funzionare anche quando fisicamente lontano da un computer. Spesso mentre sperimentiamo, programmiamo, testiamo i circuiti del nostro Arduino ci è conveniente averlo connesso al computer,ma poi quando il progetto che avevamo in mente termina la fase sperimentale ci diviene indispensabile rendere autonomo il dispositivo. Serve perciò una fonte di alimentazione elettrica. Arduino possiede un regolatore di tensione interno in grado di abbassare la tensione fino ai 5 Volt che gli sono necessari per funzionare, quindi non dobbiamo preoccuparci tanto di fornirgli una tensione di 5 Volt esatti. Una tensione dai 6 fino a 12 Volt è bene accetta. Ci sono un paio di cose importanti da tenere in considerazione sempre quando si alimenta la scheda:

  • Si deve assolutamente tenere presente che il polo positivo dell’alimentazione va collegato alla parte interna della spina di alimentazione
  • Si deve alimentare sempre in corrente continua e stabilizzata, usando batterie (ottima una da 9 Volt) o alimentatori stabilizzati
  • Qualora si alimentasse Arduino Tramite il Jack e nel contempo fosse connessa la presa USB (ad esempio per aggiornare il programma), si deve ricordare che solo se la tensione di alimentazione al Jack è superiore a 7,5 Volt Arduino userà l’alimentazione proveniente dal Jack.

Il Cablaggio


arduino_cablatoLa scheda Arduino ha tutti i collegamenti portati vicino al lato esterno per facilitare il cablaggio. Inoltre ha localizzato in punti differenti le uscite/ingressi digitali , gli ingressi analogici, e le uscite/ingressi di tensione elettrica. Tutto ciò porta ad una semplificazione notevole ed ad una grande chiarezza ed immediatezza: ogni pin ha una sigla facile da riconoscere. Inoltre, per quanto possibile, le varie schede sono standardizzate in modo da rendere possibile in molti casi utilizzare gli stessi cablaggi e le stesse schede di espansione su differenti modelli di Arduino. Per quanto concerne il cablaggio volante nei connettori strip femmina di cui è dotato Arduino si incastrano a pressione singoli fili con l’estremità rigida.
dupont
Oppure è possibile usare per il cablaggio gli “strip maschio”: conduttori rigidi e spaziati di 2,54 millimetri cui possono essere saldati dei fili ad una estremità in modo da costruire convenientemente dei connettori multipolari.

strip

Connessioni saldate con strip maschi:

arduinostripmaschio

 


Gli Shields


 

450px-arduino_shield

Arduino Uno cond due shields montati

Gli Shield sono una delle caratteristiche più interessanti e dei fattori che hanno contribuito al successo di Arduino. Uno Shield è una “scheda di espansione”, che aggiunta ad Arduino permette di svolgere con immediatezza determinati compiti. Il fatto che Arduino sia dotato degli strip femmina in cui inserire dei contatti a semplice pressione consente di progettare degli Shield dotati di strip maschio che semplicemente si incastrano sopra ad Arduino al momento dell’ utilizzo e che poi si possono togliere e sostituire con uno Shield diverso, oppure addirittura si possono impilare uno sull’altro. Nella figura infatti vediamo che sulla scheda Arduino sono stati inseriti due Shield uno sopra l’altro. Gli Shield prendono quasi sempre l’alimentazione ed i dati da Arduino tramite i pin ad incastro e quindi sono davvero comodi da utilizzare. Grazie alla standardizzazione dei contatti, uno Shield che va bene su una scheda Arduino Uno, può quasi sempre funzionare allo stesso modo su schede Arduino differenti. Questa versatilità ed intercambiabilità, unita al basso costo degli Shield, ha permesso e favorito il proliferare di una infinita disponibilità di schede di espansione di ogni tipo. Arduino insomma può essere dotato senza alcun problema e senza perdita di tempo di una serie infinita di schede aggiuntive che ne accrescono le potenzialità.

Ecco qui sotto alcuni shield con le loro caratteristiche:

758px-arduinowithethernetshield

Ethernet Shield

 

800px-arduinolcdshield

LCD Shield

 

sdcard

SD Card Shield

 

motor

Arduino+Motor Shield

gps

Arduino + GPS Shield

 

shieldstack

Stack di Shield

 

Questi sono solo alcuni esempi della miriade di Shield disponibili. Sul sito ufficiale di Arduino ce ne sono  moltissimi (molti altri sono disponibili in altri siti). Va rimarcato che gli Shield si incastrano sopra alla scheda Arduino ma non impediscono di utilizzare i pin della scheda originale, infatti basta osservare le foto per capire che gli Shield riportano nella loro parte superiore gli strip femmina con gli stessi contatti e gli stessi pin presenti sulla scheda Arduino. Ciò significa che le potenzialità della scheda sono salvaguardate anche se essa monta uno o più Shield e che si possono di norma utilizzare molti Shield uno sovrapposto all’altro.

torna all’indice

 

2: Scrivere e Trasferire programmi su Arduino


 

arduinoconnesso

Arduino connesso al PC

Finalmente ora conosciamo la nostra scheda, sappiamo le sue caratteristiche e potenzialità, ed è venuto il momento di iniziare a programmarla. La programmazione di Arduino avviene mediante un personal computer. Del PC sfruttiamo tastiera , monitor, capacità di calcolo.Quando abbiamo scritto il nostro programma lo mandiamo ad Arduino tramite USB. Anche su questo piano Arduino è rivoluzionario: il software per programmarlo è liberamente scaricabile da Internet, ed è scritto in Java. Il fatto che sia scritto in Java permette di farlo girare su quasi tutti i PC, con quasi tutti i sistemi operativi. Windows,Linux,Mac fanno girare il software di programmazione senza problemi. Con più difficoltà si può usare anche Android.

La comunità di utilizzatori


Il software di programmazione della scheda è gratis, e utilizzabile su ogni PC. Queste sono già due ottime credenziali. Ma non basta: la forza di Arduino sta soprattutto nella comunità di utilizzatori.Ogni problema che incontrerete ha quasi di certo una soluzione già sperimentata e c’è un trucco per uscire da ogni situazione critica, e se non fosse, se ancora non fosse stato sperimentato il problema che vi si presenterà, troverete migliaia di persone pronte ad aiutarvi a risolverlo. Ci sono molti tutorial in rete, molta gente che risponde sui forum a dubbi e perplessità, molto software già scritto che si può copiare così come è oppure analizzare per capire i trucchi usati da altri.Ci sono persone di ogni nazionalità e quindi la barriera della non conoscenza della lingua inglese (che nella programmazione di dispositivi elettronici è altrimenti un grosso problema) è aggirabile. Ci sono programmatori alle prime armi e geni che programmano assieme lo stesso apparecchio: per chi vuole imparare a programmare bene non c’è niente di più facile che analizzare le cose fatte da chi è più esperto ed imparare i trucchi usati.

Le librerie


Non basta ancora: poiché chi ha sviluppato Arduino ha posto grossa attenzione alla facilità di programmazione,e poiché Arduino si rivolge anche e soprattutto ad un pubblico di hobbisti che spesso non conoscono nei dettagli i trucchi per gestire l’hardware di sensori o attuatori,ci sono moltissime librerie già pronte che facilitano grandemente la vita ai programmatori.


Le librerie software

La libreria è un pezzo di codice già scritto, che può rimanere oscuro ad un utente inesperto (ma che comunque è visibile se lo si desidera) e che però mette a disposizione dell’ utente delle funzioni(solitamente di uso intuitivo)che gli consentono di ottenere la funzionalità desiderata semplicemente richiamandole.
Un esempio aiuta a capire:supponiamo di acquistare un sensore che legge la temperatura ambientale. Ci arriva a casa un coso in una bustina di plastica.
Ci verrà detto di connetterlo fisicamente a certi pin di Arduino e di alimentarlo con una certa tensione, ma poi,effettuati i collegamenti,si deve trovare,per farlo funzionare correttamente,un modo per fargli scambiare i dati col microprocessore. Se lo scambio di dati avviene in modo complicato da capire,una libreria può occuparsi di fare questo lavoro,e di mettere a disposizione dell’utente una funzione che,per esempio,si chiama “leggitemperatura”.
L’utente installa la libreria e chiama la funzione.Non sa esattamente (a meno che non voglia studiarsela) cosa ha fatto la libreria, ma chiamando la  funzione otterrà il valore della temperatura, che è quanto lui desiderava.


L’ IDE


Bisogna prima spiegare l’acronimo e poi renderlo comprensibile agli umani:
IDE = Integrated Developement Environment = Ambiente di Sviluppo Integrato.

Che vuol dire? Che qui dentro si sviluppano (si scrivono si correggono e si traducono per il processore di Arduino) i programmi che poi andranno trasferiti su Arduino.

In pratica l’ IDE è un programma complesso che ci permette di fare molte cose:

  • Scrivere i programmi, ed organizzare il loro salvataggio,
  • Svolgere l’operazione di debugging e cioè la correzione di errori prima del trasferimento del codice verso la scheda Arduino.
  • Compilare il codice, ovvero tradurre le istruzioni che noi abbiamo dato in un linguaggio comprensibile al processore di Arduino (ricordate che si diceva che ciascun processore ha un proprio “set di istruzioni?”.
  • Trasferire il codice compilato verso Arduino e controllare che l’operazione sia andata a buon fine.

Ci sono un certo numero di IDE per Arduino,e questo rientra pienamente nella filosofia del prodotto: ciascuno è libero di scegliere , di sviluppare, di usare sia l’hardware che il software prodotti da altri per creare poi i propri cambiamenti ed innovazioni, purché poi redistribuisca il prodotto secondo la stessa filosofia e cioè senza limitarne l’uso futuro e la modifica ad altri. Noi qui tratteremo solo l’IDE ufficiale Arduino, scaricabile dal sito www.arduino.cc, lo stesso sito dove troviamo i tutorial,la documentazione sulle librerie, tutta la documentazione ufficiale su Arduino.

L’IDE usato come editor


 

arduinoidevuota1

Schermata iniziale dell’ IDE

Vediamo innanzitutto come usare l’IDE per scrivere un programma e come essa organizza i files in modo da saperci destreggiare nel suo utilizzo. Un programma scritto per Arduino si chiama gergalmente “Sketch“. All’apertura dell’IDE ci viene presentato un foglio bianco,totalmente vuoto, e viene nominato automaticamente “Sketch_xxyyz” dove xx e yy sono giorno e mese corrente mentre z è una lettera dell’ alfabeto (Vedi figura sopra). Questo sistema di nomina dei files è comodo ma ovviamente il nome del file non dà nessuna indicazione del contenuto dello Sketch. E’possibile (e caldamente consigliabile) salvare il file con un nome a nostra scelta.

  • Il salvataggio avviene da menu FILE – SALVA CON NOME oppure FILE – SALVA.
  • Il salvataggio veloce avviene con l’icona arduinoiconasalva posta all’ estrema destra della barra delle icone (vedi figura).L’estensione di default degli sketch è .ino
  • Per caricare invece un file precedentemente salvato si usa il menu FILE-APRI oppure FILE-CARTELLA DEGLI SKETCH oppure si usa l’icona arduinoiconacarica presente sulla barra delle icone.
  • Per creare un nuovo file o dal menu scegliere FILE-NUOVO, oppure premere l’icona arduinoiconanuovo nella barra delle icone.
  • La IDE di Arduino contiene un sacco di esempi già pronti all’uso e già ordinati.
    Richiamare un esempio è facilissimo: dal menu FILE-ESEMPI navigare col mouse fino all’esempio che si desidera caricare.

Esempi e documentazione


L’IDE contiene un sacco di esempi già pronti, che riguardano molti argomenti di programmazione di base. Ne faremo uso anche noi all’interno del corso: sono utilissimi per imparare a muovere i primi passi ed anche se si è programmatori esperti aiutano a risparmiare un sacco di tempo nella stesura dei programmi. Scegliendo FILE-ESEMPI da menu a tendina si accede alla sezione degli esempi che sono organizzati per argomento e quindi di facile fruizione.

Altra interessantissima caratteristica della IDE è l’aiuto e la documentazione, cui si accede dalla voce AIUTO del menu. Ci sono un sacco di risorse che risiedono in locale (sul proprio PC), e c’è anche, sotto la voce AIUTO-VISITA ARDUINO.CC un link al sito online di Arduino che è una vera e propria bibbia di documentazione e di risorse per l’utente.

Compilazione


Che significa Compilare?

Compilare significa tradurre il codice scritto dal programmatore (un uomo) in un codice comprensibile ed utilizzabile dal microprocessore(una macchina). Agli albori della programmazione l’uomo-programmatore doveva conoscere il linguaggio del microprocessore, e scrivere i programmi direttamente in quel tipo di linguaggio. Pian piano i microprocessori sono diventati molti e diventava impossibile conoscere il linguaggio di tutti, e contemporaneamente i programmi diventavano sempre più grandi e complessi grazie alle maggiori capacità di memoria e di calcolo dei microprocessori.
Si è capito che per un uomo maneggiare e scrivere nel linguaggio del microprocessore diventava una grande perdita di tempo e di risorse.
Era molto più conveniente scrivere i programmi in un linguaggio più simile a quello umano e demandare ad una macchina (un software) il compito della traduzione del codice verso il microprocessore.
Sono nati quindi i “Linguaggi di alto livello” come il “C”, “Perl”, “Pascal”, “Python”, “Java”, “Basic” ecc.
Scrivere codice in un linguaggio di alto livello significa utilizzare costrutti e regole sintattiche molto più familiari agli esseri umani.
Questo significa maggiore facilità, maggiore velocità, più profonda comprensione, minore tasso di errori…e significa soprattutto che la programmazione è ormai alla portata del semplice amatore, hobbista.
Oggi programmare un dispositivo elettronico è alla portata di….. tutti?.Se non di tutti, di molti.


 

Abbiamo già detto che ogni processore ha un suo specifico insieme di istruzioni, ed abbiamo detto anche che la famiglia di schede Arduino è dotata di microprocessori di vario tipo. Ne consegue che prima di compilare uno Sketch devo dire assolutamente al compilatore per che tipo di microprocessore vado a compilare. Dal menu a tendina scelgo STRUMENTI – TIPO DI ARDUINO e scelgo il tipo di scheda dalla lista che si apre conseguentemente. Ovviamente scegliere il tipo di scheda equivale a dire al compilatore per quale processore deve tradurre il mio codice. L’IDE dovrebbe ricordare sempre il tipo di Arduino una volta specificato, ma spesso non è così. E’ utile verificare che la spunta sia sempre sul tipo di Arduino che possediamo.
Per compilare un programma scritto ci sono vari modi.Il più veloce è premere l’icona arduinoiconacompila2 che guarda caso è sulla barra delle icone. Cliccare quell’icona significa eseguire la compilazione.

Debugging


Che cosa è un Debugger?

Debug = “togliere le pulci”, correggere insomma, eliminare gli errori. Ogni programma, come tutte le cose umane, soprattutto quelle complesse, può contenere degli errori. Gli errori di programmazione possono essere a seconda del caso molto facili da scoprire oppure estremamente infidi. Una IDE con buone e complete funzioni di Debug può aiutare moltissimo il programmatore mettendogli a disposizione degli strumenti per scoprirli. Alcuni strumenti utili a questo scopo sono: la possibilità di fermare l’esecuzione di un programma in un certo punto, la possibilità di visualizzare il contenuto delle variabili, l’evidenziazione grafica degli errori di sintassi,ecc.


La IDE standard di Arduino non è una campionessa in fatto facilità e completezza di Debug. Ciò nonostante dispone delle caratteristiche di base che ci sono utili a trovare gli errori:

  • L’evidenziazione della giusta sintassi mediante la colorazione del testo: le parole chiave del linguaggio cambiano colore se sono scritte in modo esatto.
  • L’avvertimento che si è trovato un errore nel codice all’atto della compilazione e l’indicazione del tipo di errore.

Non ci sono comandi da impartire per eseguire il Debug di un progetto,si deve semplicemente compilare ed allo stesso tempo in cui il programma viene compilato viene eseguito anche il Debug. Nella figura qui sotto c’è un piccolo programmino scritto nell’IDE e contenente un errore. E’ stato ordinato di compilare il programma e si vedono i messaggi che il Debugger manda al programmatore per individuare l’errore. Sono evidenziati sia la sezione del programma in cui esso è stato trovato, sia la riga di programma, sia il tipo di errore.

461px-arduinoideerrore

Errore evidenziato dal debugger

 

Caricamento del software sul Arduino


L’IDE di Arduino contiene una funzionalità molto utile, anche se non immediatamente appariscente: permette, col semplice click su un’icona,di stabilire il contatto con la scheda Arduino, scaricare if software compilato su di essa e farlo eseguire automaticamente.
Cliccare l’icona arduinoiconacompila (in alto nella barra delle icone), significa compilare e contestualmente trasferire il codice alla scheda Arduino e farlo eseguire immediatamente senza nessun Hardware intermedio né alcuna operazione complicata.

 

Il Monitor Seriale


L’IDE non trasferisce i dati soltanto verso la scheda Arduino, ma permette una comunicazione bidirezionale. Il monitor seriale connette (via seriale appunto) la scheda Arduino al PC cui è collegato tramite USB in modo bidirezionale. E’ utilizzato soprattutto come canale di comunicazione da Arduino verso il PC, spesso per stampare valori numerici o scritte tramite il monitor del PC visto che Arduino non dispone di una periferica di output grafica, ma può essere usato anche al contrario, ad esempio per passare dei dati dal PC ad Arduino.

Per aprirlo , dalla IDE,premere sull’ icona monitorser in alto a destra.

 

 

arduinoserialmonitor

Il monitor Seriale usato per comunicare se c’è tensione ad un pin 

torna all’indice

 

 

3: Programmazione


 

Peculiarità del linguaggio di programmazione di Arduino


Il linguaggio di programmazione di Arduino si chiama Wiring, ma in sostanza è un parente molto prossimo del C. Le differenze col C standard servono a gestire con facilità le peculiarità del microprocessore. Per quanto riguarda invece i costrutti base del linguaggio, possiamo considerare il linguaggio che impareremo corrispondente al C standard.

Le Funzioni Setup e Loop


Ogni programma per Arduino deve contenere due funzioni: void setup() e void loop() Gli estensori del linguaggio hanno pensato di discostarsi dallo standard, che prevede un solo corpo obbligatorio, per meglio distinguere ed esplicitare la fase di inizializzazione e la fase di esecuzione del programma. Nei fatti, quella che ci viene richiesta è l’unica deviazione dalla struttura del C standard. Dobbiamo soltanto capire che c’è una sezione del programma dedicata all’inizializzazione ed un corpo principale.

La funzione di setup() sarà la prima ad essere eseguita dopo ogni accensione o reset di Arduino.

void setup( )
{
 // istruzioni varie;
}

Immediatamente dopo setup() viene eseguita la funzione loop()

void loop( )
 {
  // altre istruzioni;
 }

I nomi delle funzioni sono autoesplicativi : void setup() serve per il setup, e cioè per l’inizializzazione viene eseguita una volta sola all’ inizio del programma, mentre la funzione void loop() viene eseguita ciclicamente (Loop) ed è la sezione dedicata all’acquisizione, alla elaborazione, ed alla restituzione dei dati elaborati: il corpo principale del programma, insomma.

Carichiamo un primo esempio ed analizziamolo: Bareminimum


Iniziamo ad utilizzare la ricca base di file di esempio che ci arriva con l’ IDE di Arduino: FILE – ESEMPI – BASICS – BAREMINIMUM carica un esempio , minimale, contenente soltanto una funzione setup ed una funzione loopvuote. Queste funzioni sono necessarie in ogni programma per Arduino, e quindi caricare l’ esempio BAREMINIMUM è il punto di partenza per iniziare un qualsiasi programma.

arduinobareminimum

La sintassi colorata

Anche un piccolo esempio come questo ci permette di evidenziare alcune cose importanti. Da notare assolutamente le parole chiave del linguaggio evidenziate dai colori del testo. I nomi delle funzioni setup() e loop() sono scritti in color arancione. Provate a modificarli cambiando solo un carattere o inserendo una maiuscola al posto di una minuscola: vedrete che l’arancione scompare. Questo modo di visualizzare le parole chiave del linguaggio viene molto comodo al programmatore: se scrivo una parola chiave e non la vedo diventare arancione significa che qualcosa non va, probabilmente ho sbagliato a scrivere.

Le parentesi graffe

Da notare anche in questo piccolo esempio che i blocchi di codice iniziano con una graffa aperta {e finiscono con una graffa chiusa }. Le graffe sono molto importanti: sono i caratteri convenzionali che il “C” usa per indicare l’inizio e la fine dei blocchi di codice e d’ora in avanti le utilizzeremo sempre.

I commenti

Ultima cosa: dentro al codice del programma ci sono delle scritte in inglese precedute da due barre trasversali // (ottenute col tasto posto sopra all’ “8” nel tastierino numerico). Provando a compilare il codice,vedrete che è corretto. Non ci sono errori evidenziati all’atto della compilazione (e questo è ovvio: è un esempio ufficiale di Arduino,ci mancherebbe che fosse pieno di errori). Se provate a compilare il codice togliendo le barre trasversali davanti alle parole in inglese vedrete che compaiono immediatamente degli errori. Il compilatore è fatto per tradurre le istruzioni dal “C” al linguaggio del processore in questione, e non sa come interpretare il linguaggio umano. Potremmo risolvere non scrivendo niente altro che il codice “C”, ma questo sarebbe leggermente limitativo: immaginate un programma lungo e magari scritto da tante persone: poter inserire delle note di commento,spiegazione,o dei promemoria non è per nulla male. La soluzione allora quale è? Semplice: se un testo è preceduto dalle due barre oblique // semplicemente non viene preso in considerazione dal compilatore.Le due barre oblique è come se dicessero al compilatore: occhio,quello che viene scritto qui di seguito non lo devi considerare, è roba che interessa solo gli umani. In quel modo il compilatore non genera errori, e gli umani dispongono della possibilità di inserire istruzioni,commenti e promemoria.


La sintassi dei commenti

Ci sono tue tipi di commento: quelli che stanno su una singola riga e quelli che utilizzano più righe. Di quelli che stanno su una riga abbiamo parlato si ottengono facendolo precedere il testo da //.
I commenti su più righe ovvero i “blocchi di commento” iniziano con /* e terminano con */

Esempi:
// Questo è un commento su una riga
/* Questo è un commento
Su più righe */


COSA ABBIAMO IMPARATO

* L’IDE ci semplifica la vitta controllando la sintassi ed evidenziando col colore le parole chiave del linguaggio evidenziando subito se sono corrette.
* I blocchi di codice sono racchiusi sempre tra parentesi graffe.
* Abbiamo capito come inserire un commento di una o più righe nel codice


torna all’indice

 

4: Finalmente un programma!: facciamo lampeggiare un LED


 

Ancora non sappiamo fare un programma autonomamente, dobbiamo di nuovo caricare un esempio, ma stavolta avremo a che fare con un programma che fa qualcosa, e cominceremo a vedere il nostro Arduino in azione. FILE-ESEMPI-BASICS-BLINK è il file da caricare. Finalmente qualcosa che inizia a darci soddisfazione, e non è che l’inizio visto che d’ora in poi saremo capaci di fare dei programmi autonomamente,non più progetti fatti da altri , ma pensati da noi per fare quel che ci pare.

Osserviamo questo esempio ed analizziamo le sue componenti per capire alcuni concetti base. Blink vuol dire lampeggio: compiliamo il file aperto e carichiamolo sulla scheda,(mentre si carica sulla scheda osserviamo il lampeggiare dei led TX e RX che ci indicano che c’è uno scambio di dati tra PC ed Arduino).Una volta caricato il programma, Arduino lo manderà subito in esecuzione e noi vedremo uno dei led di cui è equipaggiata la scheda accendersi per un secondo, e poi per un secondo rimanere spento, e così via.

Ora che lo abbiamo visto funzionare proviamo ad analizzarlo osservando con attenzione il codice:

522px-arduinoblink

Bene, qui vediamo applicati i concetti appresi finora:

  • Ci sono sia commenti su una riga che su più righe.
  • Ci sono le due funzioni “obbligatorie”: setup (); e loop();
  • Il corpo di setup(); inizia con graffa aperta { e finisce con graffa chiusa } e lo stesso avviene con loop().

Queste sopra sono cose che già conosciamo e non ci serve dare loro tanta attenzione.

Vediamo invece una cosa nuova sulla quale vale la pena di concentrarsi: c’è del testo prima della funzione Setup() e non sappiamo cosa significa

int led = 13;


Questa è una DICHIARAZIONE DI VARIABILE e significa: dichiaro che utilizzo nel programma una VARIABILE di TIPO INTERO, la chiamo “led” e ci voglio immagazzinare il valore 13.
Nota: perché usiamo la porta 13? Se ricordate ne abbiamo già parlato nel nostro corso: al pin 13 è connesso un piccolo led presente sulla scheda.


Le variabili

Abbiamo incontrato un concetto fondamentale nella programmazione. Che cos’è una variabile? Possiamo pensare alla variabile come ad uno spazio di memoria in cui vengono immagazzinati dei dati, e che vogliamo identificare con un nome. Il nome lo scegliamo noi arbitrariamente (in questo caso il nome è led). I dati che posso memorizzare li scegliamo sempre noi, ma non possiamo metterci pere o mele: dobbiamo scegliere il tipo di dati tra un elenco di formati possibili. Il linguaggio “C” ci mette a disposizione un certo numero di formati: numeri interi,parole, caratteri, eccetera. In questo caso la variabile led è di tipo  

int e cioè un numero intero.

Ecco alcuni tipi di dati possibili:

byte = numero intero da 0 a 255
float =numero con la virgola
char= un carattere
string = una sequenza di caratteri (parola)


 Analalizziamo  adesso Setup():

void setup() { //initialize the digital pin as an output. pinMode(led, OUTPUT); }

Contiene un’ istruzione nuova e c’è un commento che ci spiega cosa fa: inizializza il pin digitale come OUTPUT. Beh questo non deve crearci imbarazzi ormai. Sappiamo che Arduino ha 14 pin digitali (da 0 a 13) e che ciascun pin digitale può essere usato come ingresso o come uscita. l’istruzione che è contenuta in setup (tra la graffa aperta e quella chiusa) pinMode(led, OUTPUT); significa: prendi il tredicesimo pin e usalo come OUTPUT.

 

La funzione pinmode();


La funzione pinmode();

è la funzione che stabilisce se un pin digitale è usato come ingresso od uscita.
Accetta due argomenti: il numero del pin, e INPUT O OUTPUT.
Esempi:
pinmode(5,INPUT);         (Il pin 5 è usato come INPUT)
pinmode(12,OUTPUT);   (Il pin 12 è usato come OUTPUT)


 

Ok ma perché s’è detto che pinMode(led, OUTPUT); significa : prendi il tredicesimo pin e usalo come OUTPUT? Perché 13°? Qui c’è scritto led, mica 13! Ma…..non abbiamo detto prima che la variabile intera led contiene il numero 13?
Allora adesso dire led è come dire 13, perché riferendoci alla variabile led indichiamo il suo contenuto, che abbiamo appena stabilito sia 13.

 

Per ultima esaminiamo la funzione Loop()

void loop() {digitalWrite(led, HIGH); // turn the LED on delay(1000); // wait for a second digitalWrite(led, LOW);// turn the LED off by making the voltage LOW delay(1000); // wait for a second }

Contiene 4 righe , tutte commentate per spiegarne il significato, ma le funzioni in gioco sono 2: digitaWrite() e delay().

 

La funzione digitalWrite();


La funzione digitalWrite();

che farà mai digitalWrite? Scrive su una uscita digitale!
Cosa si scrive su una uscita digitale? C’è corrente, o non c’è corrente,ricordate?
Uno o zero,o per usare le costanti che usa Arduino HIGH o LOW.
E’ la stessa cosa!
digitalWrite(7,LOW); vuol dire: niente tensione all’uscita digitale 7
digitalWrite(2, HIGH); vuol dire: caro microprocessore, dai tensione all’uscita 2. digitalWrite(led, HIGH); vorrà dire allora: voglio che ci sia tensione sull’uscita 13


La funzione delay();


La funzione delay();

delay(); vuol dire aspetta: l’istruzione delay vuol dire semplicemente al processore: fermo lì per un po’. Quanto è questo po’? Il valore tra parentesi in millesimi di secondo.

delay(1000); stai fermo per un secondo
delay(3300); stai fermo per 3,3 secondi


Adesso che abbiamo le idee chiare su tutte le funzioni che compongono il programma ripercorriamolo dall’inizio per capire la sua struttura logica.

  • Prima di tutto si dichiara la variabile.
  • Ora inizia la funzione setup() dove viene preparato il terreno alla successiva elaborazione: infatti dentro setup() si dice che la porta 13 è di output pinMode(led, OUTPUT);
  • Ora infine,la funzione loop() ripete all’infinito un ciclo in cuisi dà tensione alla porta 13 ………..digitalWrite(led, HIGH);si attende un secondo ………………delay(1000);si spegne il led ……………………….digitalWrite(led, HIGH);e si aspetta un altro secondo ……..delay(1000);

Notiamo ora un’ ultima cosa: le istruzioni del codice di Arduino (come anche del C standard) terminano sempre con un punto e virgola. Il punto e virgola è un separatore che divide un’ istruzione dalla seguente e quindi va sempre scritto, pena la generazione di errore da parte del compilatore.


COSA ABBIAMO IMPARATO

* Conosciamo le variabili, sappiamo a cosa servono e come dichiararle, e conosciamo alcuni tipi di variabili.
* Conosciamo la funzione pinmode();
* Conosciamo la funzione digitalWrite();
* Conosciamo la funzione delay();
* Sappiamo che le istruzioni del codice di Arduino (come anche del C standard), vanno concluse con punto e virgola;
* Per favore notate una cosa: l’utilità dei commenti nel codice.
Commentate anche voi i vostri codici, sarà utile a voi stessi e agli altri che leggeranno.


torna all’indice

 

5: Il semaforo (il primo programma tutto nostro!)


Stavolta niente esempi precotti: scriviamo il nostro programma da zero, ormai siamo pronti. Faremo un semaforo che accende 3 diodi LED in sequenza. Prima di pensare al codice c’è una cosa da imparare: come funzionano i LED.

Dovremo costruire un piccolo circuito, visto che non possiamo più usare quello integrato nella scheda Arduino, e dobbiamo sapere come fare per accenderli e  non bruciarli.
Vi chiederete perché la scorsa volta quando accendevamo il LED sulla basetta Arduino non abbiamo dovuto costruire nessun circuito: questo è dovuto al fatto che il circuito è già presente, seppure invisibile,sulla scheda.

Il diodo LED

arduinosemaforoled1arduinosemaforoled2


Il diodo LED

Un diodo LED è un dispositivo elettronico che si basa sulle proprietà dei semiconduttori come i transistor o i microprocessori.
Per farlo funzionare si deve trattarlo nel modo giusto e rispettare delle precise norme.
*Può funzionare solo se alimentato nel verso giusto.
*Può sopportare una corrente massima di 20 millesimi di Ampere.

Per quanto riguarda le polarità di alimentazione non abbiamo grosse difficoltà: i LED sono contrassegnati da una particolarità utile per capire come collegarli. La lunghezza dei due fili di collegamento non è la stessa, e la “gamba” più lunga va collegata sempre al positivo dell’ alimentazione. Quando anche ci trovassimo in mano un vecchio led a cui i piedini sono stati tagliati e quindi non sappiamo quale era il più lungo, basta guardarlo in trasparenza. Il piedino da collegare al positivo avrà la forma di una specie di “freccia” rivolta verso l’alto, come si vede chiaramente nelle immagini sopra.


 

Se risulta facile trovare quale piedino va collegato al positivo e quale al negativo, più difficile invece dosare la corrente che attraversa il LED. C’è bisogno di una piccola formula e di una legge fisica che dobbiamo imparare. Niente di difficile


La legge di Ohm

La legge di Ohm ci consente di calcolare la corrente (Ampere) che passa in un circuito elettrico, conoscendo tensione (Volt) e resistenza (Ohm).
La formula è:   I = V / R
dove
I è la corrente ,
V la tensione, 
R la resistenza. 

Se come dicevamo il diodo LED si brucia con più di 20 millesimi di Ampere, nel circuito deve passare una corrente massima di 20mA quindi I=20mA

La tensione viene dalla porta di Arduino e quindi è di 5 Volt (sapete che Arduino UNO  funziona a 5 Volt)

Con una piccola operazione matematica , usando la legge di OHM:

R=V/I   ⇒   R=5/0,020  ⇒  R =250Ω

(La lettera Ω è il simbolo usato per indicare la resistenza elettrica e si pronuncia “OHM”)


Bene, con questo facile conto abbiamo calcolato la resistenza che dobbiamo inserire nel nostro circuito per non bruciare il LED.

Poiché le resistenze a carbone hanno valori standard, non è possibile trovare in commercio resistenze da 250 Ohm, ma devo scegliere quella più simile disponibile in commercio. Lo standard prevede resistenze da 220 Ohm,approssimata per difetto ai 250 ottimali, oppure 270 Ohm approssimata per eccesso. Poiché anche il led ha una sua piccola resistenza che va sommata al resistore che gli applicheremo in serie, è meglio scegliere la resistenza da 220 Ohm: 220 Ohm di resistenza + quella incognita del LED si avvicinerà sufficientemente bene ai 250 Ohm teorici che mi servirebbero.

aaresistenze_1

Tabella dei colori delle resistenze elettriche


I valori delle resistenze

Le resistenze elettriche sono dei componenti molto comuni e molto economici. Hanno dei valori standard, ed uno speciale codice di colori che indica il loro valore a colpo d’occhio.Come spiega l’immagine in alto il colore della prima fascia colorata da sinistra equivale alla prima cifra del valore della resistenza. Il colore della seconda fascia da sinistra equivale alla seconda cifra del valore, mentre il colore della terza banda corrisponde al numero di zeri da aggiungere. Questo sito contiene un calcolatore dei valori delle resistenze. [2]


Per esemplificare: voglio una resistenza da 220 Ohm, il codice di resistenze mi dice:

  • Prima cifra 2= ROSSO
  • Seconda cifra ancora 2=ROSSO
  • Zeri da aggiungere 1= MARRONE

la mia resistenza avrà questi tre colori partendo da sinistra: ROSSO ROSSO MARRONE


Ora che sappiamo usare le resistenze elettriche siamo in grado di collegare 3 LED alle uscite dell’ Arduino e pilotarli.

Fritzing
Qui sotto vedrete uno schema dei collegamenti elettrici e dei componenti utilizzati. E’ fatto con un programma che si chiama Fritzing. E’ un programma di libera fruizione che gira sui sistemi operativi più usati (Win Mac Linux) e permette di fare facilmente cose molto belle: disegnare gli schemi con i componenti, e trasformarli in schemi elettrici. Quando sarete esperti e creerete le vostre realizzazioni personali, Fritzing vi farà addirittura lo schema delle “piste” sul circuito stampato, in modo che possiate creare da soli lo stampato a casa vostra. Date un’ occhiata al filmatino se siete curiosi [[3]]


Schema dei collegamenti


arduinosemaforofritzinng

3 LED connessi ad Arduino

 


La Breadboard

La Breadboard è una basetta realizzata per facilitare la realizzazione di circuiti di test. I componenti elettronici si inseriscono ad incastro senza bisogno di saldature, e con la stessa facilità si tolgono. La Breadboard è facile da utilizzare una volta imparate le sue caratteristiche. Sui suoi lati, entrambi, corrono due file di contatti: una fila è contrassegnata da una riga rossa ed il simbolo + , l’altra da una riga blu ed il simbolo -.
Come intuibile queste due file sono connesse rispettivamente al positivo ed al negativo dell’ alimentazione elettrica. I contatti più interni, invece, sono organizzati “per colonna”, e cioè ogni foro appartenente alla colonna è in contatto elettrico con gli altri, mentre le colonne non sono in contatto elettrico tra loro. Ne consegue che se vogliamo ricavare l’alimentazione elettrica possiamo utilizzare uno qualunque dei fori appartenenti alle righe laterali esterne, mentre se vogliamo inserire dei componenti, di dovremo inserire nella parte centrale della Breadboard e i loro piedini non potranno stare sulla stessa colonna ma su colonne separate.


 

Realizziamo il circuito sulla Breadboard inserendo prima le resistenze, poi i LED, infine i fili.Potete benissimo costruire il circuito in modo differente, sia chiaro. La logica della costruzione dei circuiti elettrici di solito è questa: prima le cose più piccole e più basse, poi via via le cose più ingombranti ed alte. Semplicemente per un motivo manuale e pratico: se aveste già molti fili montati diventerebbe scomodo spostarli con fatica senza scollegarli per andare ad inserire una resistenza.

Quando avete realizzato il circuito passiamo al codice da scrivere questa volta da zero senza copiare da esempi in memoria. Creiamo un nuovo sketch nell’IDE, diamogli subito un nome anche se è vuoto.Quindi nell’IDE scegliamo FILE-NUOVO e poi subito FILE-SALVA CON NOME e diamo un nome significativo. Essendo molto fantasiosi potremmo chiamarlo Semaforo 🙂

Scriviamo ora un commento che spieghi il significato del programma che stiamo per scrivere.

Per chi ha bisogno di suggerimenti (e per chi vuole controllare se la sua sintassi è giusta) ecco qui di seguito un programmino che funziona.

int Rosso=8;  //dichiaro una variabile intera che contenga 8, 
              //il pin cui collegherò il LED rosso
int Giallo=9; //dichiaro una variabile intera che contenga 9, 
              //il pin cui collegherò il LED giallo
int Verde=10; //dichiaro una variabile intera che contenga 10,
              //il pin cui collegherò il LED verde
void setup()
 { 
   pinMode(8,OUTPUT);  //dico ad Arduino che il pin 8 
                       //(ENTRATA/USCITA DIGITALE) va usato come OUTPUT 
   pinMode(9,OUTPUT);  //dico ad Arduino che il pin 9 
                       //(ENTRATA/USCITA DIGITALE) va usato come OUTPUT 
   pinMode(10,OUTPUT); //dico ad Arduino che il pin 10
                       //(ENTRATA/USCITA DIGITALE) va usato come OUTPUT 
 }
void loop()
 {
   digitalWrite(Rosso, HIGH); //Acceso Rosso
   digitalWrite(Giallo,LOW);  //Spento Giallo
   digitalWrite(Verde,LOW);   //Spento Verde
   delay(10000);               //Aspetta 10 secondi
   digitalWrite(Rosso, LOW); //Spento Rosso
   digitalWrite(Giallo,HIGH); //Acceso Giallo
   digitalWrite(Verde,LOW);  //Spento Verde
   delay(10000);                //Aspetta 10 secondi
   digitalWrite(Rosso, LOW); //Spento Rosso
   digitalWrite(Giallo,LOW); //Spento Giallo
   digitalWrite(Verde,HIGH); //Acceso Verde
   delay(10000);              //Aspetta 10 secondi
 }

Questo codice funziona perché i tre casi (acceso rosso spenti gli altri, acceso giallo spenti gli altri, acceso verde spenti gli altri) si susseguono ripetutamente e la funzione Loop() che viene eseguita ciclicamente, garantisce il ripetersi delle istruzioni.


COSA ABBIAMO IMPARATO

* Abbiamo preso dimestichezza con il diodo LED, imparato come collegarlo,e conosciamo un suo limite: si brucia se la corrente che lo attraversa è più grande di 20 mA
* Abbiamo imparato la legge di Ohm che lega i tre parametri fondamentali dei circuiti elettrici: Tensione, Corrente Resistenza. Sappiamo dimensionare a resistenza in modo da limitare la corrente.
* Conosciamo il programma Fritzing, e ce ne serviremo per disegnare i nostri schemi elettrici.

* Conosciamo la Breadboard e sappiamo fare i collegamenti elettrici da essa ad Arduino.
* Abbiamo scritto un programma! Da qui in avanti ci possiamo chiamare programmatori 🙂


torna all’indice

 

6: I Cicli


Un ciclo causa una ripetizione di istruzioni all’interno di un programma. La ripetizione può avvenire un numero determinato di volte, oppure un numero di volte non determinato, a seconda della situazione in cui ci si trova e del problema da risolvere. Può capitarci infatti nella vita e così anche nella programmazione (che serve a risolvere i problemi reali), di trovarci di fronte a dei problemi diversi: posso dover stampare 15 caratteri, e questo è chiaramente un problema che si risolve con un ciclo che va da 1 a 15, oppure dover trovare il numero più grande di 346 e che sia anche un numero primo: in questo caso non so a priori quanti cicli mi serviranno. In questi due casi distinti il C prevede due tipi di cicli . Se conosco a priori il numero di iterazioni necessarie userò un ciclo basato sull’istruzione for (“per” in inglese). Se non so a priori quante iterazioni userò un ciclo basato sull’istruzione while (“finché” in inglese). Ci sono altre istruzioni per creare dei cicli, ma sono tutte appartenenti a queste due tipologie.

For


Esempio: se ho 20 LED da accendere, li accendo uno alla volta usando un ciclo che va da 1 a 20. In questo caso è perfetta l’istruzione for. Vediamone un esempio

for (contatore=1; contatore < 15 ;contatore++)
{
  istruzione 1;
  istruzione 2;
  istruzione 3;
}

Istruzione dopo il ciclo;

Analizziamo il significato della sequenza di istruzioni (ciclo): partendo dalla condizione contatore=1 le istruzioni contenute tra le parentesi graffe vengono eseguite tutte, poi il programma riparte aumentando il valore di contatore (e quindi contatore=2) e riesegue le istruzioni contenute tra le graffe. Così via fin quando contatore diventa uguale a 15.

In quel caso il ciclo si interrompe e l’esecuzione del programma riparte dall’istruzione dopo il ciclo.

While


Esempio: voglio visualizzare i riflessi di un umano. Quando accendo il led verde del semaforo inizio un ciclo, che si fermerà quando l’umano compie una certa azione. Il numero di cicli tra l’accensione del LED e l’azione compiuta dall’umano sarà un indicatore della velocità di riflessi dell’ umano. Io (Arduino) adesso non so quanto tempo devo aspettare, quindi non posso usare il ciclo basato su for, ma userò invece un ciclo basato sull’istruzione while.

while (condizione == vera)
 {
   istruzione1;
   istruzione2;
   istruzione3;
 }

Istruzione dopo il ciclo
Questo ciclo si ripete, e continua dunque ad eseguire le istruzioni tra parentesi graffe, finché la condizione è vera.Quando (per effetto di una istruzione eseguita durante il ciclo o per effetto di un evento esterno) la condizione non è più vera, il ciclo si interrompe e l’elaborazione del programma prosegue dall’istruzione dopo il ciclo.
Non pensate che i cicli siano poco utili o semplici automatizzazioni di operazioni ripetitive:grazie alla velocità di elaborazione dei microprocessori, ed alla possibilità di eseguire dunque moltissime operazioni in sequenza in tempi brevi è possibile raggiungere risultati matematici finora impossibili da ottenere. Per esempio: nessun matematico è in grado di ottenere un valore del PI Greco più accurato rispetto a quello ottenuto con un semplice ciclo da un calcolatore elettronico.

Il semaforo (ri)fatto coi cicli


Ora che conosciamo i cicli possiamo riscrivere il programma semaforo usando un ciclo for, come è esemplificato qui sotto.Non modificate lo schema del circuito, e caricate su Arduino il listato che segue: è un programma che si comporta esattamente nella stessa maniera del semaforo visto prima, ma è scritto con un ciclo for. Risulta più breve del programma precedente, ma solo di poco.
Pensate però se i LED da accendere invece di 3 fossero 100.Il vantaggio sarebbe molto più grande.

Il codice

int contatore;
void setup()
 { 
  pinMode(8,OUTPUT); // Usa il pin 8 (ENTRATA/USCITA DIGIT.)come OUTPUT  
  pinMode(9,OUTPUT); // Usa il pin 9 (ENTRATA/USCITA DIGIT.)come OUTPUT
  pinMode(10,OUTPUT);//Usa il pin 10 (ENTRATA/USCITA DIGIT.)come OUTPUT
} 
  void loop() { 
    for (contatore=8; contatore<=10; contatore++) 
     { 
       digitalWrite(8, LOW); //Spento Rosso 
       digitalWrite(9,LOW); //Spento Giallo 
       digitalWrite(10,LOW); //Spento Verde 
       digitalWrite(contatore,HIGH);//Accendi LED che corrisp. a contat. 
       delay(10000); 
      } 
}

Analizziamo il codice dettagliatamente per capire. Mentre il contenuto di setup() rimane lo stesso rispetto al primo programma semaforo (e quindi non serve parlarne), loop() è differente, e contiene in pratica solo un ciclo for.

for(contatore=8;contatore<=10;contatore++) 
    {
      digitalWrite(8, LOW); //Spento Rosso
      digitalWrite(9, LOW); //Spento Giallo
      digitalWrite(10,LOW); //Spento Verde 
      digitalWrite(contatore,HIGH);//Acceso LED che corrisponde a cont.
      delay(10000);
    }

Il ciclo for modifica una variabile intera che si chiama contatore. Il suo valore parte da 8 fino a 10, e si incrementa di uno ogni volta. Una volta arrivato a 11 il ciclo finisce, ma anche se l’esecuzione esce dal ciclo rimane dentro alla funzione loop() che ci riporta all’inizio, per cui di nuovo incontrerà il ciclo for che assegna a contatore valori da 8 fino a 10.

Quindi i valori di contatore saranno: 8,9,10, 8,9,10, 8,9,10 e così via. Dentro al ciclo ci sono le istruzioni di spegnimento per tutti i LED:

digitalWrite(8,LOW); //Spento Rosso
digitalWrite(9,LOW);  //Spento Giallo
digitalWrite(10,LOW);   //Spento Verde

Subito dopo c’è l’accensione del LED al piedino indicato da contatore:

digitalWrite(contatore,HIGH);//Acceso Il LED che corrisponde a contat.

contatore vale 8, poi,9, poi 10 quindi in sequenza si accendono i LED a questi pin
per ultima l’istruzione di attesa di 10 secondi (col LED acceso)

delay(10000);

 torna all’indice

 

7:Il misuratore di riflessi (Un programma con cui interagire!)


In questo programma, a differenza del semaforo, non sappiamo a priori quanti cicli si dovranno fare, perché non conosciamo i riflessi dell’ essere umano che si sottoporrà alla prova, e quindi facciamo uso di un ciclo while invece che del for. Lo schema dei collegamenti elettrici va leggermente aggiornato:restano i tre LED e le resistenze, le uscite da Arduino verso i LED possono rimanere quelle solite, questa volta i LED si accenderanno brevissimamente e serviranno a dare il via per la prova riflessi. Al lampeggio del led Verde partirà un ciclo che incrementerà via via il valore di una variabile. Dovremo aggiungere però un qualcosa che fermi il tempo,consentendo di valutare i riflessi.Questo hardware può essere un pulsante,da premere oppure può essere realizzato semplicemente con due fili da unire al momento. Nel nostro caso realizziamo il circuito al massimo risparmio, usando solo due fili.Quando si vedrà il LED verde accendersi si uniranno i due fili. Un filo sarà connesso al positivo di alimentazione, mentre il secondo sarà connesso ad un INGRESSO DIGITALE. Quando i fili saranno uniti l’ingresso digitale verrà portato in posizione HIGH (in altre parole ci sarà tensione), il ciclo terminerà, e il valore finale della variabile indicherà la velocità dei riflessi.Resta allora inteso che per il funzionamento del programma servirà visualizzare il contenuto della variabile, e lo faremo usando il monitor del PC connesso ad Arduino.

576px-misurariflessi_bb

Schema dei collegamenti


 

Per fare questo schema abbiamo dovuto inserire delle nuove componenti hardware: un pulsante (oppure due fili da collegare assieme al momento opportuno), che porta,quando premuto,la tensione dal piedino dei 5 Volt sulla scheda Arduino al pin 7 (che useremo poi come INPUT DIGITALE). Il piedino 7 dovrebbe trovarsi in condizione normale a tensione elettrica zero (condizione logica 0 o LOW), mentre quando il pulsante è premuto, venendo collegato direttamente ai 5 Volt, dovrebbe andare in condizione logica 1 o HIGH. Non c’è problema, funziona ma……..ma poi è difficile farlo tornare in posizione logica 0, perché gli abbiamo dato i 5 Volt e lui se li tiene: che motivo ha di “scaricarsi?”.Dobbiamo trovare un “trucco”. A noi serve che il piedino vada in condizione logica 1 quando premiamo il pulsante,e poi torni velocemente a zero. Usiamo allora una resistenza, collegata al piedino 7 ad un capo ed a massa all’altro. Usando una resistenza di opportuno valore (nel nostro caso 1000 Ohm) porteremo la tensione al piedino 7 a scaricarsi verso massa nel tempo che ci fa comodo. Quindi alla pressione del pulsante avremo una condizione logica 1, il ciclo si fermerà, e poi la tensione calerà fino a condizione logica 0 in tempo per permetterci di iniziare un nuovo test di riflessi.

P.S. Una simile resistenza si dice “di pull-down” (spingi-giù) perché tende a tenere a zero il valore logico del pin cui è applicata.

Niente più da dire riguardo all’hardware. Ecco il codice e sotto ad esso il commento riga per riga (per le parti nuove):

Il codice


int Ritardo=0; //var. che conterrà il ritardo di risposta
int Rosso=8;  //var. intera che contenga 8,il pin del LED rosso
int Giallo=9; //var. intera che contenga 9,il pin del LED giallo
int Verde=10; //var. intera che contenga 10,il pin del LED verde
  void setup()  { 
   pinMode(8,OUTPUT);  //il pin 8  è da usare come OUTPUT
   pinMode(9,OUTPUT);  // il pin 9  è da usare come OUTPUT   
   pinMode(10,OUTPUT); // il pin 10 è da usare come OUTPUT  
   pinMode(7,INPUT);   //  il pin 7 è da usare come INPUT 
 }
void loop()
{
 digitalWrite(Rosso, HIGH); //Acceso Rosso
 digitalWrite(Giallo,LOW);  //Spento Giallo
 digitalWrite(Verde,LOW);   //Spento Verde
 delay(10000);               //Aspetta 10 secondi col rosso acceso
 digitalWrite(Rosso, LOW); //Spento Rosso
 digitalWrite(Giallo,HIGH); //Acceso Giallo
 digitalWrite(Verde,LOW);  //Spento Verde
 delay(2000);                //Aspetta 2 secondi col giallo acceso
 digitalWrite(Rosso, LOW); //Spento Rosso
 digitalWrite(Giallo,LOW); //Spento Giallo
 digitalWrite(Verde,HIGH); //Acceso Verde
 delay(50);  //Lampeggia solo un attimo col verde per dare il via 
 
   while (digitalRead(7) == LOW)//gira se sul pin 7 c'è segnale LOW
     {
       digitalWrite(Verde,LOW);  //Spento Verde
       Ritardo= Ritardo +1;//Aumento di 1 il val. della var.ritardo
       delay(10);             //Aspetto 10 millesimi di secondo
     }
  digitalWrite(Rosso, HIGH);//Acceso Rosso per segnal.fine contegg. 
  delay (500);
  Serial.println(Ritardo);// Scrivo il val.della var. ritardo 
  Ritardo=0;   // Azzero la variabile ritardo per una nuova prova
}

Analizziamo le parti nuove del codice dall’alto verso il basso:

Nella dichiarazione delle variabili c’è:

int Ritardo=0;

Perché serve una variabile intera con la quale misurare i riflessi,e che quindi misuri il ritardo tra un evento di partenza (accensione LED verde) ed un evento di Stop (pressione pulsante o collegamento dei fili)

setup() ha due nuove istruzioni:

pinMode(7,INPUT);

Serve un pin digitale (uso il 7) da usare come INPUT. Deve fermare il conteggio. Lo dichiariamo quindi dentro setup()

Serial.begin(9600);

Questa istruzione invece serve per inizializzare il monitor seriale. Alla fine del programma vogliamo stampare il valore del ritardo sul monitor del PC e per fare questo dobbiamo dire ad Arduino che useremo il monitor seriale con velocità 9600 baud.(baud=impulsi al secondo)

infine in loop() abbiamo:

while (digitalRead(7) == LOW)
     {
       digitalWrite(Verde,LOW);  //Spento Verde
       Ritardo= Ritardo +1; //Aumento di 1 il val. della var. ritardo
       delay(10);           //Aspetto 10 millesimi di secondo
     }

Un ciclo while while (digitalRead(7) == LOW) che gira fino a quando sul piedino 7 non c’è tensione

Dentro al ciclo le istruzioni sono:

digitalWrite(Verde,LOW);  //Spento Verde

spegne semplicemente il led verde che era servito a dare il via

Ritardo= Ritardo +1;//Aumento di 1 il valore della variabile ritardo

incrementa di 1 la variabile ritardo in modo da tenere traccia del tempo passato dal via

delay(10);

attende 10 millesimi di secondo prima di fare un altro ciclo.
Alla fine del ciclo, invece, abbiamo l’importante istruzione:

Serial.println(Ritardo); //Scrivo il val. di ritardo

che ci serve per scrivere  sul monitor seriale il valore della variabile ritardo

Ritardo=0;   // Azzero la variabile ritardo per una nuova prova

Azzera la variabile ritardo.


COSA ABBIAMO IMPARATO

* Sappiamo usare i cicli: quelli che fanno un numero preciso di iterazioni e quelli che invece ne fanno un numero indeterminato.
* Abbiamo riscritto il programma semaforo usando un ciclo for. Questo ci consente di vedere come un unico problema si può risolvere programmando in modi differenti.
* Abbiamo scritto di bel nuovo un programma per la misurazione dei riflessi, che usa un ciclo while.
* Abbiamo imparato ad utilizzare una resistenza di pull-down per scaricare verso massa la tensione positiva presente su un ingresso digitale.
* Abbiamo conosciuto le funzioni Serial.begin() e Serial.print() che ci consentono di usare il monitor seriale utilizzando il monitor del PC per l’output.


torna all’indice

 

8: Un misuratore di riflessi migliorato


Il misuratore di riflessi che abbiamo costruito è bellino, ma alcuni di voi si saranno certo accorti che è possibile “fregarlo”. Se leggiamo il codice infatti, capiamo che il LED rosso sta acceso 10 secondi, poi 2 secondi quello giallo, poi il verde lampeggia brevissimamente. Posso però “prepararmi” sapendo che il LED verde si accende 2 secondi dopo il giallo, e stare pronto a premere il pulsante o addirittura anticipare lo stop. Se voglio migliorare il codice, devo fare in modo che il led verde non si accenda secondo una sequenza sempre costante, ma che si accenda “a caso”. Allora, e solo allora , sarò sicuro che chi sta provando i suoi riflessi non ha anticipato i tempi. Per realizzare questo nuovo esperimento con Arduino non dovremo modificare in nessun modo l’hardware ma solamente il codice software, e così impareremo alcune cosette nuove.

Ecco qui sotto il codice seguito come al solito dal commento alle righe nuove.

Il codice


int Ritardo=0; //variabile che conterrà il ritardo di risposta
int Rosso=8;  //variabile intera che contenga 8, il pin del LED rosso
int Giallo=9; //variabile intera che contenga 9,il pin del LED giallo
int Verde=10; //variabile intera che contenga 10,il pin del LED verde
 void setup()
  { 
   pinMode(8,OUTPUT);  //il pin 8  è da usare come OUTPUT  
   pinMode(9,OUTPUT);  //il pin 9  è da usare come OUTPUT  
   pinMode(10,OUTPUT); //il pin 10 è da usare come OUTPUT  
   pinMode(7,INPUT);   //il pin 7  è da usare come INPUT 
   Serial.begin(9600);
  }
void loop()
{
  int caso;   // variabile che conterrà un valore intero casuale
  caso=random(10000);  // poni dentro alla variabile un numero casuale 
  digitalWrite(Verde,LOW); //spento Verde
  digitalWrite(Rosso, HIGH);//acceso rosso 
  digitalWrite(Giallo, LOW); // spento giallo
  delay(caso); //aspetta un poco (un intervallo tra zero 10 secondi);
  
  digitalWrite(Verde,HIGH); //Acceso Verde
  digitalWrite(Rosso, LOW); //spento rosso
  digitalWrite(Giallo, LOW); //spento giallo
  delay(50);     //Lampeggia solo un attimo col verde per dare il via 
  while ((digitalRead(7) == LOW) && (Ritardo <1000))//AND LOGICO
    {
      digitalWrite(Verde,LOW);  //Spento Verde
      Ritardo= Ritardo +1;      //Aumento di 1 il valore della var. ritardo
      delay(10);                //Aspetto 10 millesimi di secondo
    }

 digitalWrite(Giallo, HIGH); //Acceso giallo per segnalare fine conteggio  
 delay(500);
 Serial.println(Ritardo);  // Scrivo il val. di ritardo sul serial monitor 
 Ritardo=0;   // Azzero la variabile ritardo per una nuova prova
}

 

Nella sezione dichiarazioni di variabili, e nella sezione setup() non c’è niente di diverso dall’esempio precedente.
Dentro alla sezione loop() invece….c’è una cosa che non torna:

int caso;

 Ma come? Non si diceva che le variabili devono essere dichiarate in cima al programma, prima di loop() e di setup()?
In verità esistono due tipi di variabili: le globali e le locali. Le variabili globali vanno dichiarate all’inizio del programma come già detto.Le variabili locali invece possono essere dichiarate dentro a qualsiasi funzione, ma il loro campo di utilizzo rimane confinato alla funzione in cui è stata dichiarata la variabile. In altre parole,la variabile caso. Vale solo dentro a loop(). Se provo ad accedervi fuori dalla funzione ottengo un errore.

caso=random(10000);  // poni dentro alla variabile un numero casuale

Ecco una novità introdotta in questo programma: la funzione random.

caso=random(10000);

Vuol dire: metti dentro la variabile “caso” un numero casuale (random) che va da 0 a 9999.

digitalWrite(Verde,LOW); //spento Verde
digitalWrite(Rosso, HIGH);//acceso rosso 
digitalWrite(Giallo, LOW); // spento giallo
delay(caso); //aspetta un poco (un intervallo tra zero 10 secondi);

Vengono spenti i LED Giallo e Verde, ed acceso il LED Rosso, ad indicare l’attesa.
Il ciclo si interrompe per un tempo casuale che va da zero a 10000 (il valore casuale contenuto dentro la variabile “caso”. Poi, con le seguenti istruzioni:

digitalWrite(Verde,HIGH); //Acceso Verde
delay(50);      //Lampeggia solo un attimo col verde per dare il via

Parte l’accensione del LED verde per 50 millisecondi (segnale di partenza) e poi l’inizio del solito ciclo che calcola i riflessi. Altra novità la troviamo nel ciclo while:

while ((digitalRead(7) == LOW) && (Ritardo <1000))
 {
      digitalWrite(Verde,LOW);//Spento Verde
      Ritardo= Ritardo +1;//Aumento di 1 il valore della variabile ritardo
      delay(10);          //Aspetto 10 millesimi di secondo
 }

Notate che la condizione per cui viene eseguito il ciclo non è più semplice ma composta. Perché si esegua il ciclo devono valere due condizioni: (digitalRead(7) == LOW) ed anche (Ritardo <1000). In questo modo se la risposta al via tarda troppo ad arrivare (più di un secondo) il ciclo riparte da zero. Come si ottiene una condizione composta? Legando assieme due condizioni semplici con l’operatore logico && che significa “AND” e cioè, significa che entrambe le condizioni devono essere soddisfatte.


COSA ABBIAMO IMPARATO

* Abbiamo capito un nuovo ed importante concetto a riguardo delle variabili: possono esistere sia variabili globali che vanno dichiarate all’inizio del codice, che variabili locali,che si possono dichiarare ovunque nel programma.La loro validità ed accessibilità si limita alla procedura all’interno della quale sono state dichiarate (locali, appunto).
* Abbiamo imparato a conoscere la funzione random() che genera un numero casuale all’interno di un range. Questa funzione è molto importante per simulare all’ interno della programmazione, la situazione di indeterminazione delle condizioni iniziali che spesso accade nella realtà.
* Abbiamo combinato due condizioni logiche attraverso l’operatore  && (AND logico).


 

torna all’indice

 

 

9: Le decisioni


Siamo ad un punto cruciale del corso. Stiamo per vedere una cosa stupefacente: una macchina sa prendere delle decisioni. Il che equivale a dire, secondo un filone filosofico seguito dai sostenitori dell’ intelligenza artificiale forte[4], che una macchina può pensare. Mica male eh? Se funziona, tra noi ed Arduino c’è una grossa differenza: lui non mangia, non beve, e non muore. 🙂
In pratica l’universo dominato dalle macchine non solo è possibile , ma pure probabile.
Che abbiano ragione i sostenitori dell’ intelligenza artificiale forte o meno è un argomento appassionante ma esula dal nostro corso. Quel che invece è indubbio è che una macchina capace di fare delle scelte è una cosa a dir poco sensazionale. Da ora in poi spero guarderete la vostra scheda di Arduino Uno con rispetto, ed anche,chissà,un pelo di timore.:) Veniamo però a capire come si codificano le scelte nel linguaggio C, questo sì è argomento del nostro corso.

La funzione if


If in inglese vuol dire “se“. Viene di logica che causerà l’esecuzione di un blocco di codice se è verificata una certa condizione.Vediamo l’esempio sotto che è autoesplicativo:

if (luce>soglia)
{
  suona la sveglia;
  prepara il caffè;
}

Se la condizione espressa tra parentesi è vera, esegui le istruzioni comprese tra le parentesi graffe.Così com’è vediamo la forma più semplice dell’ istruzione if. Possiamo rendere la decisione più complessa ed articolata aggiungendo il costrutto else.

if (temperatura>5)
{
  suona la sveglia;
  prepara il caffè;
} 

else //(chevvordì altrimenti in inglese)
{
 Accendi la stufa;
}

Se è vera la condizione dopo if viene eseguita la porzione di codice tra le graffe e NON quella dopo else, mentre viceversa viene eseguita la porzione di codice tra le graffe dopo else e NON quella subito dopo if.

if ((luce>soglia) && (temperaturaesterna>10))
{
  suona la sveglia;
  prepara il caffè;
}

In questo caso abbiamo una espressione composita: se è vera la prima condizione (luce>soglia) ed anche la seconda condizione (temperatura>10) allora e solo allora viene eseguito il codice tra le graffe ,altrimenti l’esecuzione del ciclo continua dopo il blocco tra le graffe. Ci sono varie espressioni valide, ad esempio &&=and (il codice è eseguito se valgono entrambe le condizioni) ||=or, il codice viene eseguito se vale almeno una delle condizioni.

La funzione switch-case

switch (variabile) 
  {
   case 1:
     //fai qualcosa se variabile vale 1
     break;//esci dal ciclo
   case 2:
     //fai qualcosa se variabile vale 2
     break;//esci dal ciclo
   default: 
     // fai qualcosa se nessuno dei casi è verificato
     // nota bene: l'uso di default è opzionale
  }

La funzione switch-case è molto comoda quando ci sono da gestire situazioni che prevedono un grande numero di differenti risultati. Per la prima volta incontriamo qui la funzione break,che interrompe sempre,in qualunque blocco di istruzioni sia inserita,l’esecuzione del blocco di istruzioni corrente.Ossia,rimanda l’esecuzione a dopo la graffa che chiude il blocco di istruzioni.

Il misuratore di carica di una batteria


Abbiamo usato finora la parte di input e di output digitale della scheda Arduino. Niente riguardo agli ingressi analogici, che per noi sono ancora inesplorati. E’ tempo di mettere rimedio a questa lacuna, anche perché siamo stanchi di valori digitali. Il mondo non è solo bianco o solo nero, ma ha un sacco di valori intermedi che Arduino può interpretare e agire di conseguenza. Prendiamo dunque in mano il nostro Arduino UNO, e studiamo le caratteristiche dell’ hardware. Arduino come già sappiamo ha 6 porte analogiche: il segnale applicato su di esse viene fatto passare in un convertitore analogico-digitale, (interno al microprocessore) e poi elaborato. Il microprocessore lavora quindi sempre con segnali digitali (altro non sa fare) ma questi numeri digitali derivano da un valore analogico applicato all’ingresso. Dobbiamo conoscere le caratteristiche di Arduino, e del convertitore analogico-digitale interno al processore, prima di passare all’operatività pratica. Intanto,il range di tensione applicabile.Siccome Arduino va a 5 Volt,sarà in grado di accettare e di convertire segnali analogici nel range tra 0 Volt e 5 Volt. Poi c’è da tenere presente la risoluzione. La risoluzione è il numero di valori che il convertitore produce se l’input analogico passa dal valore minimo al massimo (0-5V per Arduino Uno).Nel nostro caso la conversione avviene con una scala che va da 0 a 1023,quindi a 0 Volt corrisponde il valore 0,a 5 Volt corrisponde 1023.

Schema riassuntivo:
N° Ingressi Analogici: 6 (Indicati sulla scheda dalle sigle A0-A5)
Max tensione: 5Volt
Risoluzione:10 bit (da 0 a 1023)

Ora che conosciamo a fondo le caratteristiche della scheda Arduino Uno, possiamo iniziare un nuovo progetto: un misuratore di carica per batterie. Quanto più una batteria è carica, tanto più alta è la sua tensione. Ci basterà quindi misurare la tensione ai capi della batteria, per conoscere approssimativamente lo stato di carica. Per misurare la tensione ai capi della batteria non possiamo certo utilizzare un ingresso digitale: come sappiamo accetta solo due valori, zero ed uno.Va usato invece l’input analogico.Come ingresso verso la scheda Arduino basta uno dei pin analogici.
Scegliamo l’ultimo : A5 (senza una ragione particolare, uno a caso).Come output invece teniamo i nostri LED che ereditiamo dai circuiti precedentemente assemblati.Sono perfetti per una indicazione sommaria dello stato di carica:

Verde=batteria carica
Giallo=batteria semiscarica
Rosso =batteria scarica

Schema dei collegamenti


 

800px-misuratensionebatteria_bb

Dei due fili che vanno attaccati alla batteria, per logica uno va a massa (stessa massa per Arduino e batteria),mentre il secondo,il positivo,va al pin analogico 5 di Arduino. Questa semplice configurazione certamente funziona,ma ha un difetto. A batteria scollegata il pin analogico 5 “vede” comunque una tensione in ingresso. Il motivo è che basta un disturbo elettromagnetico per indurre nel filo una tensione sufficiente a far rilevare qualcosa al convertitore analogico-digitale. Se non modifichiamo il circuito avremo spesso delle false letture quando non è connessa una batteria da misurare.Per evitare questo fastidioso inconveniente basta una resistenza di pull-down,che,come abbiamo visto nel misuratore di riflessi,porta a zero la tensione non desiderata su di un piedino quando esso non è alimentato.Stavolta useremo una resistenza grande, del valore di 10.000 Ohm,(marrone=1 nero=0 arancio=(3 zeri)=000) che comunque è sufficiente a “domare” i segnali spuri che arrivano al piedino analogico 5 e a far rimanere bassa la lettura quando non c’è batteria connessa.

Adesso facciamo due conti teorici per capire che cosa possiamo misurare e che tipo di dati aspettarci in uscita dal convertitore Analogico-Digitale. Dato che la massima tensione misurabile è di 5 Volt, è il caso di utilizzare il misuratore di carica sulle singole batterie,che hanno una tensione nominale, da cariche, di 1,5 Volt.Considereremo allora:

1,5-1,45 Volt Massima tensione, carica completa
1,45-1,3 Volt Media tensione, media carica 
1,3-0    Volt Minima tensione, pila scarica

E tareremo il codice su questo valore.

Se 5 Volt equivalgono a 1023

1,5 Volt equivalgono a 307 circa.
1,45 Volt = 297 circa.
1,3 Volt =266 circa

I valori che trovate nel codice (qui sotto) non sono questi, e sono stati calibrati provando sperimentalmente il circuito.La differenza però non è grande. Si sa: la teoria si discosta sempre un poco dalla pratica,ed anche nel nostro caso è così.

Dopo tutte queste noiose elucubrazioni teoriche siamo pronti, scriviamo il codice e commentiamo punto per punto le novità trovate.

Il codice

int valore;  //variabile che memorizza dato dal convert. analog.-digitale
int Rosso=8;  //variabile intera che contenga 8, il pin del LED rosso
int Giallo=9; //variabile intera che contenga 9, il pin del il LED giallo
int Verde=10; //variabile intera che contenga 10,il pin del LED verde

void setup()
 { 
  pinMode(8,OUTPUT);  //il pin 8  è da usare come OUTPUT  
  pinMode(9,OUTPUT);  //il pin 9  è da usare come OUTPUT  
  pinMode(10,OUTPUT); //il pin 10 è da usare come OUTPUT  
 }
void loop()
{
 delay(100); //aspetto un poco (100 millisecondi);
 valore=analogRead(5);//Leggo val. analog. al pin 5 e lo metto in "valore"
 if (valore>310) //se valore maggiore di 320 allora....
   {
     digitalWrite(Rosso,LOW);
     digitalWrite(Giallo,LOW);
     digitalWrite(Verde,HIGH);
   }
   if ((valore<310)&&(valore >=280)) //se val. > di 280 e val. < di 310 
   {
     digitalWrite(Rosso,LOW);
     digitalWrite(Giallo,HIGH);
     digitalWrite(Verde,LOW);
   }
   if (valore<280)//se valore minore di 280 allora....
   {
     digitalWrite(Rosso,HIGH);
     digitalWrite(Giallo,LOW);
     digitalWrite(Verde,LOW);
   }

 delay(500); //aspetto mezzo secondo 
}

Commentiamo il nostro sketch (come sempre istruzione per istruzione, dall’alto in basso):
All’inizio del programma:

int valore;

dichiaro una variabile che conterrà il valore di carica della batteria.

Dentro setup() niente di particolare. Dentro loop() invece alcune  novità:

valore=analogRead(5);//Leggo  val. analog. al pin 5 e lo metto in "valore"

assegno a “valore” il dato letto dalla porta analogica e convertito in digitale.

if (valore>310)//se valore maggiore di 310 allora....
   {
     digitalWrite(Rosso,LOW);
     digitalWrite(Giallo,LOW);
     digitalWrite(Verde,HIGH);
    }

Ora poi c’è il cuore della routine, la decisione, l’if. Se la condizione tra parentesi è vera (se valore è maggiore di 310) allora vengono eseguite le istruzioni tra le graffe: viene acceso il led Verde ad indicare carica completa.

if ((valore<310)&&(valore >=280)) //se valore > di 280 e valore < di 310 
   {
     digitalWrite(Rosso,LOW);
     digitalWrite(Giallo,HIGH);
     digitalWrite(Verde,LOW);
   }

una istruzione if composta per stabilire se la batteria è mezza carica. Qui devono valere entrambe le condizioni perché sia eseguito il blocco di codice tra le graffe, infatti viene usato && che sta per AND.

 if (valore<280)//se valore minore di 280 allora....
   {
     digitalWrite(Rosso,HIGH);
     digitalWrite(Giallo,LOW);
     digitalWrite(Verde,LOW);
    }

e ancora una istruzione if semplice per stabilire cosa fare quando “valore” è minore di 280. In quel caso si accende il led rosso ad indicare che la batteria è del tutto scarica.


COSA ABBIAMO IMPARATO

* Abbiamo compreso che un circuito elettronico è in grado di prendere delle decisioni.Abbiamo capito come codificare in “C” le istruzioni for,else, e case-switch. Abbiamo incontrato il concetto di intelligenza artificiale.
* Abbiamo lavorato e compreso il funzionamento delle porte analogiche di Arduino, e capito che usandole possiamo discriminare tra tanti valori discreti e stabilire noi le soglie per i nostri sensori analogici.
* Abbiamo usato una resistenza di pulldown per evitare di rispondere a dei falsi allarmi sugli ingressi analogici.


torna all’indice

 

10: Comunicazione bidirezionale da e verso Arduino


A questo punto del nostro corso abbiamo esplorato buona parte delle funzionalità di input e di output di Arduino Uno, e conosciamo anche alcuni costrutti base del linguaggio. Siamo quindi pronti per fare dialogare Arduino con altri dispositivi,e per imparare come è possibile scambiare dati col resto del mondo,ad esempio con altre schede Arduino, o con il PC che usiamo per programmarlo.
In questo esempio faremo dialogare bidirezionalmente tramite interfaccia seriale, in modo molto semplice, il Personal Computer e la scheda Arduino Uno.
Utilizzeremo a questo scopo il “Monitor Seriale” (che si apre premendo sulla lente di ingrandimento in alto a destra dentro all’IDE Arduino) e che già abbiamo utilizzato come OUTPUT per mostrare dei dati, e conosceremo le funzioni del linguaggio di Arduino per leggere da (e scrivere su) di esso.

Tramite le istruzioni impartite agendo sulla tastiera del PC accenderemo i LED del Semaforo, e utilizzeremo il monitor del PC per dare delle informazioni sullo stato del nostro programma, dichiarando per iscritto quale dei LED è stato acceso. Quello che vedete qui sotto è un esempio volutamente semplice e limitato: la comunicazione tra Arduino e un computer, ad esempio, può essere sfruttata per salvare i dati acquisiti dalla scheda Arduino ed utilizzarli nel tempo (un PC ha delle periferiche di archiviazione che Arduino non ha),può servire a costruire grafici, può essere realizzata una rete di comunicazione wireless tra varie schede Arduino e un PC che le controlla, ecc.
I limiti sono davvero pochi, ed i costi dell’ hardware davvero bassi: se associato ad altri dispositivi il nostro Arduino può fare delle cose a cui non avremmo mai pensato finora, quindi considerate la lezione di oggi come ad una delle più importanti del corso:vi permette di iniziare a pensare ad un'”Intelligenza Distribuita”,cioè a vari dispositivi di calcolo interconnessi tra di loro.
Questo schema è già oggi alla base di sistemi complessi ma sempre più presenti nella nostra quotidianità.
Pensate ad esempio ad una casa domotica, in cui gli oggetti interagiscono tra loro:se fuori c’è il sole le tapparelle si alzano e le luci elettriche si spengono, ecc.
Una “rete” diffusa e globale di questo tipo viene chiamata “Internet delle cose” e prevede la possibilità di fare la spesa automaticamente quando il frigo è vuoto,scaldare la casa di campagna qualche ora prima di arrivarci,ecc ecc.
Le applicazioni dell “Intelligenza distribuita” sono e saranno moltissime,e Arduino vi permetterà di iniziare a comprendere il loro funzionamento.

Schema dei collegamenti


548px-semaforo-comunicazioni_bb

Lo schema dei collegamenti ricalca specularmente quello del semaforo a 3 LED che abbiamo già realizzato in precedenza. L’unica peculiarità da far notare è che in questo caso non è possibile scollegare il cavo USB al temine del trasferimento del codice alla scheda.
Qualora fossimo abituati ad alimentare elettricamente Arduino non tramite la scheda USB ma tramite alimentazione esterna, dovremo comunque lasciare in sede il connettore USB di comunicazione col personal computer.

Il Codice

int comando=0;

void setup()
  {
   // inizializza la comunicazione seriale alla velocità di 9600 baud
   Serial.begin(9600);
   // usa i pin 8-9-10 come OUTPUT
   pinMode(8, OUTPUT);
   pinMode(9, OUTPUT);
   pinMode(10, OUTPUT);
   // Scrivi via seriale il messaggio di inizializzazione avvenuta
   Serial.println("Attendo un comando");
  }

void loop() 
{
 if (Serial.available() > 0) // Se c'è un dato sulla seriale
  {
   comando=Serial.read();    // Leggi dalla seriale
   switch (comando) 
   {
      digitalWrite(8, HIGH);
      Serial.println("Ho acceso il LED rosso");
      break;
    case 'g':                         // Se hai letto "g"
      digitalWrite(9, HIGH);
      Serial.println("Ho acceso il LED giallo");
      break;
    case 'v':                         // Se hai letto "v"
      digitalWrite(10, HIGH);
      Serial.println("Ho acceso il LED verde");
      break;
    default:       // Se hai letto qualcosa di diverso da "r" o "g" o "v"
      Serial.println("LED spenti");
      digitalWrite(8, LOW);
      digitalWrite(9, LOW);
      digitalWrite(10, LOW);
    } 
  } 
}

All’interno del codice troviamo alcune istruzioni nuove di cui è necessario parlare.

Serial.begin();

Dentro Setup() incontriamo la funzione Serial.begin() Questa funzione inizializza la comunicazione seriale ed accetta come argomento un valore numerico che specifica la velocità di trasferimento dei dati. Quantunque sia possibile usare altri valori, questo parametro tipicamente usa i seguenti:

300,600,1200,2400,4800,9600,14400,19200,28800,38400,57600,115200

Per chi fosse curioso, questi valori esprimono la velocità in baud (bit per secondo).
Nel nostro caso, la funzione Serial.begin(9600) inizializza la comunicazione seriale alla velocità di 9600 bit-secondo. Va messa nel setup(),ovviamente,perché è una inizializzazione: si fa una volta per tutte all’inizio del programma.

Serial.print();

Sempre dentro setup() c’è una funzione nuova da capire: Serial.println(). Questa funzione usa la seriale appena inizializzate per scrivere qualcosa sul monitor seriale infatti il suo nome è Serial.print(). Occhio: nel codice c’è Serial.println(), non Serial.print(). L’unica piccola differenza tra le due è che Serial.print() stampa su monitor seriale, mentre Serial.prinln() stampa e poi va a capo.

Serial.available();

Proseguendo nell’ analisi del codice troviamo la funzione Serial.available() che indica il numero di dati in lettura presenti sulla seriale. Se non ci sono dati da leggere varrà zero, se invece ci sono uno o più dati sarà maggiore di zero. Il programma dunque, se ci sono dei dati da leggere, li legge e li mette dentro la variabile intera “comando”, tramite l’ istruzione

comando = Serial.read(); 

Serial.read() ovviamente è l’istruzione per leggere dei dati dalla porta seriale.Una volta letto il dato si entra in un ciclo switch, che già conosciamo.Se il dato è ‘r’ viene messo allo stato HIGH il pin 8 (LED rosso acceso). Se il dato è ‘g’ il pin 9 (LED giallo acceso) , e se è ‘v’ il pin 10 (LED verde acceso).In ogni altro caso i pin 8-9-10 vengono portati allo stato LOW (LED spenti).

Su questo codice ci sono molte considerazioni e prove da fare. Provate per esempio ad inserire una sequenza di comandi invece di un comando solo, e notate il comportamento di Arduino.

 


COSA ABBIAMO IMPARATO

* Abbiamo messo in atto un ciclo case-switch completo, con 3 situazioni particolari contemplate e un “default” che viene eseguito in caso la situazione sia generica.
* Abbiamo visto come si legge dalla seriale, come si scrive sulla seriale e conosciute le funzioni Serial.read() Serial.write() e Serial.available().
* Abbiamo interfacciato Arduino con un altro dispositivo (il nostro PC).Allo stesso modo possiamo interfacciarlo con ogni dispositivo che supporti la comunicazione seriale. (altre schede Arduino per esempio)


torna all’indice

 

11: Regolatore di luminosità (PWM)


In questa sezione del corso useremo i pin analogici di Arduino per leggere dei sensori analogici,e ricevere informazioni sul mondo come la temperatura, la quantità di luce, i millimetri di pioggia che son caduti nella notte: tutte cose che prevedono un range di valori e che adesso sappiamo gestire.
Quel che non sappiamo fare al momento è invece pilotare dei dispositivi con gradualità. Sappiamo accendere un led o spegnerlo usando le uscite dei pin digitali, ma quelli o sono in stato HIGH o sono in stato LOW, quindi il dispositivo connesso o non funziona proprio, o va al massimo. Immaginiamo di salire in ascensore: il motore dell’ ascensore è spento quando saliamo. Se quando premiamo un tasto esso si mette in moto all’improvviso a piena potenza riceveremo una sgradevole “botta” : un’ accelerazione improvvisa che ci farà sobbalzare. Immaginate un’ auto o una moto elettrica il cui motore sia comandato da un’ uscita digitale: in partenza al semaforo il motore partirebbe a massima potenza,e se volessimo rallentare dovremmo farlo spegnendo ed accendendo il motore a scatti. Se dunque per certi utilizzi le uscite digitali sono ottime (esempio:accendere/spegnere la luce,o il televisore),a volte invece serve modulare la potenza dei dispositivi,e dare con gradualità una diversa percentuale di potenza.
L’ideale, per fare questo, sarebbe avere un convertitore DIGITALE-ANALOGICO, ma la nostra scheda Arduino Uno non ne è purtroppo dotata (essenzialmente per questione di costo). Il modo per supplire a questa mancanza è quello di usare il PWM. Vediamo qui di seguito come.

Se non ricordate cosa sia il PWM tornate all’inizio di questo documento e cliccate sulla voce “Le uscite PWM” nell’indice.

Sappiamo che le uscite PWM usano certi pin digitali usati come output. Non tutti i piedini di uscita digitali però sono PWM: solo quelli con la tilde(~) stampata sulla basetta blu.Stabilito quali pin usare, vediamo ora in che maniera usarli. Usare il PWM vuol dire mandare un’ onda quadra su uno dei pin contrassegnati dalla tilde. Un’ onda quadra però le cui caratteristiche non sono vincolate, ma saremo noi a deciderle per ottenere il risultato voluto.
La frequenza dell’ onda non è un parametro variabile: è prestabilita nel caso di Arduino al valore di 500 Hertz (500 pulsazioni al secondo).Il parametro su cui intervenire invece è il “Duty cycle” [4] e cioè il rapporto tra la durata del segnale “alto” e il periodo totale del segnale.

L’istruzione per usare i pin digitali con PWM  è :  analogwrite(pin,parametro);
dove pin=numero del pin,mentre “parametro” è un numero che va da 0 a 255 e fa variare il “Duty Cycle” come illustrato nella figura seguente.

pwm2

Occhio mi raccomando: analogWrite() di analogico ha solo il nome:l’output del pin rimane digitale e su di esso ci sono solo valori HIGH o LOW (0 oppure 5 Volt), ma il ripetersi in brevissimi intervalli di tempo di valori di tensione differenti simula una tensione variabile.

Il circuito elettrico


Questa volta non utilizziamo più il nostro circuito elettrico con 3 led,ne togliamo 2 e lasciamo solo uno (il colore non ha importanza). Colleghiamo però il LED rimanente non alle “normali” porte digitali, ma alla porta digitale 3 che come noterete ha la tilde (~) accanto. Questo vuol dire che è una delle porte che può lavorare in PWM (è proprio questa la caratteristica che vogliamo sfruttare).
Aggiungiamo inoltre un nuovo componente, un potenziometro.


Il potenziometro

Il potenziometro è una resistenza variabile. Ne esistono di vari tipi,i più comuni sono quello rotatorio e quello lineare. Il rotatorio, il tipo che usiamo noi, permette girando una manopola di variare la resistenza.Qui sotto potete vedere un’ immagine che esplica le caratteristiche meccanico-costruttive ed una che invece riguarda le caratteristiche di funzionamento logico. In pratica il potenziometro è dotato di 3 fili. Due di questi sono connessi alle estremità di una resistenza elettrica, mentre il terzo è collegato ad un cursore,collegato ad un perno rotante,in grado di muoversi da un estremo all’altro della resistenza. I due fili collegati alle estremità della resistenza vanno connessi uno al polo positivo di alimentazione e l’altro a massa (0 Volt).Sul terzo filo sarà presente una tensione compresa tra zero Volt e la tensione massima, a seconda della posizione in cui si trova. Ecco quindi che ruotando la manopola possiamo variare a nostro piacimento la tensione presente sul terzo filo.


 

 

potenziometrocostruttivopotenziometroconcettuale

 

Schema dei collegamenti


543px-pwmledpotenziometro_bb

Sullo schema elettrico c’è pochissimo da dire: il potenziometro, di cui ora conosciamo il funzionamento,è connesso con uno dei suoi fili laterali ai 5 Volt, col restante filo laterale a massa (0 Volt), mentre il filo centrale sul quale troveremo la tensione variabile a seconda della posizione del cursore andrà all’ingresso analogico A5 di Arduino. Su questo ingresso avremo dunque una tensione variabile, che trasformata in digitale dall’A/D converter (convertitore analogico-digitale) sarà utilizzata per generare un segnale PWM in uscita che sul piedino A3 della scheda ,che è connesso ad un LED. Il LED,come ormai usuale, è protetto dalla solita resistenza in modo che non passi troppa corrente.

Quello che abbiamo realizzato è un semplice controllo , che però ha applicazioni infinite. La bici elettrica di cui parlavamo prima nell’esempio , al semaforo accelera gradualmente e con dolcezza, mentre quando deve rallentare lo fa seguendo il comando impartito tramite il potenziometro. Possiamo simulare perfettamente il “gas” di un motorino. Allo stesso modo funziona la regolazione del il volume di un apparecchio radiofonico: girando una manopola ed otteniamo la variazione del volume del suono in uscita. Un passo ulteriore potrebbe essere quello di rendere elettronico anche il potenziometro. Questo è certamente possibile con Arduino, anche se va al di là degli intenti del nostro corso. Sappiate però, ad esempio, che esistono delle divertenti (ed utili) applicazioni basate proprio su Arduino, che regolano automaticamente il volume del televisore durante le pause pubblicitarie, quando artificiosamente viene alzato da parte delle emittenti, in modo da annullare il fastidioso aumento.

Il codice


int potenziometro;
int luminosita; //senza accento
void setup() 
 {
   pinMode(3, OUTPUT); 
   //Serial.begin(9600);
 }

void loop() 
 {
  potenziometro=analogRead(5);
  luminosita=potenziometro;
  analogWrite(3, luminosita/4);
  delay(100);
  //Serial.println(luminosita);
  //Serial.println(potenziometro);
 }

Commenti sul codice: il nome della variabile luminosita è scritto senza accento. Non è un errore, l’IDE non vuole nomi accentati. Poco male, tanto il concetto si capisce lo stesso, però ricordatevene o troverete degli errori inspiegabili.

Dentro setup() niente di speciale, si dichiara semplicemente il pin digitale 3 come OUTPUT

Dentro loop() abbiamo usato

analogRead();

che già conoscevamo ed abbiamo usato, mentre invece la novità assoluta è

analogWrite();

che serve a pilotare il Duty Cycle del PWM. Ancora una volta va sottolineato che il nome della variabile è AnalogWrite, ma di analogico non ha un bel niente: lavora in digitale,generando sul pin l’uscita di un’ onda di 500 Hertz e cambiando solo la forma dell’ onda in uscita in base al parametro numerico tra le parentesi tonde (0..255).


COSA ABBIAMO IMPARATO

* Abbiamo approfondito il funzionamento del PWM e sappiamo identificare le uscite PWM sulla scheda Arduino.
* Sappiamo usare la funzione analogWrite(); per pilotare le uscite PWM a nostro piacere
* Sappiamo correlare in tempo reale un OUTPUT PWM ad un INPUT ANALOGICO, in modo da pilotare dispositivi con gradualità ed in un ampio range di valori.


torna all’indice

 

12: Più potenza:pilotare un motore elettrico


Nel precedente capitolo abbiamo acceso e modulato l’intensità di un LED usando PWM. Bellino,niente da dire,ma gli esempi che abbiamo fatto per spiegare l’utilità del PWM riguardavano ascensore,bici elettriche,utilizzatori in grado di erogare una certa potenza. E’ proprio in questi casi che il PWM rende chiara la sua grande utilità pratica.Negli apparati elettronici moderni,la rotazione di un piccolo potenziometro può comandare degli utilizzatori enormi. Arduino ha dei limiti nel pilotare carichi energivori:se alimentato tramite USB può erogare al massimo 0,5 Ampere,e più limitante ancora:un singolo pin può dare una corrente massima di 40 mA. Per questo motivo negli esempi precedenti ci siamo limitati a gestire un LED,che, abbiamo visto,assorbe 20 mA al massimo.
Se vogliamo usare qualcosa di più potente dobbiamo modificare il circuito,e noi non vogliamo limitare il nostro Arduino ad accendere le lucette,vogliamo qualcosa di più,come ad esempio muovere un motore elettrico. Si può fare? Certo! Basta aggiungere un componente al nostro circuito: un Transistor.


Il Transistor

Il Transistor è un dispositivo a semiconduttore. Non vogliamo in questo corso spiegarne il funzionamento dettagliato,per il quale si rimanda alla imprescindibile relativa pagina di Wikipedia [[5]].Qui noi vogliamo solo capire quali sono le sue caratteristiche e come utilizzarlo in pratica nei nostri circuiti.
Per noi,il Transistor è un “amplificatore di corrente”.E’dotato di tre piedini:Collettore,Base,ed Emettitore.I nomi dei piedini sono esplicativi:Il Collettore porta la corrente al Transistor. L’Emettitore la emette. La Base permette, opportunamente alimentata,di far fluire corrente tra Collettore ed Emettitore oppure no.
Il meccanismo è questo:se alla base non arriva corrente,non passa corrente nel Transistor.Se alla base arriva un po’ di corrente,il transistor “entrerà in conduzione” e sarà attraversato da una corrente molto maggiore ma sempre proporzionale a quella che arriva alla Base.
Aumentando la corrente alla Base,aumenta proporzionalmente la corrente che attraversa il Transistor.Quindi basta una corrente di pochi millesimi di Ampere alla Base per averne parecchi che attraversano il Transistor.
Il Transistor è un compagno ormai quasi invisibile ma onnipresente nella nostra vita.L’invenzione di questo dispositivo ha cambiato totalmente il mondo: iniziando dalle prime radioline riceventi portatili (che venivano addirittura chiamate “Transistor”) passando ai televisori e diffondendosi sempre più, oggi tutta l’elettronica si basa su circuiti integrati di ogni tipo che ne contengono moltissimi,ed ovviamente anche i microprocessori sono tra questi.


arduinobjt

Schema dei collegamenti


636px-pwmtransistorpotenziometro_bb

Lo schema dei collegamenti prevede il pilotaggio di un motore invece del LED del circuito precedente. Rimane inalterato l’input analogico tramite un potenziometro collegato (piedino centrale) al sesto pin Analogico (A5). In base al segnale ricevuto su questo pin, verrà modulato il segnale PWM in uscita dal pin Digitale 3 (usato dunque come Output PWM). Dal pin 3 non andremo però direttamente al motore,in quanto la corrente in uscita deve essere amplificata. Andremo invece a pilotare la Base di un Transistor. Il codice di questo Transistor è BC 337, Il BC337 può sopportare una corrente di 800 mA,decisamente più dei 40 mA che può erogare un pin di Arduino.

bc337

Non possiamo però collegare direttamente il pin 3 alla Base, ma dobbiamo interporre una resistenza di adeguato valore,470Ohm(giallo, viola, marrone). L’Emettitore del Transistor va collegato a massa,mentre il Collettore va al positivo di alimentazione.In questo modo, quando fluisce una piccola corrente sulla Base del Transistor fluisce una corrente ben maggiore attraverso il Transistor stesso.
Dal positivo di alimentazione la corrente,passando per il Collettore,attraversa il Transistor,esce dall’Emettitore, e va a massa. Il Motore Elettrico è attraversato da questa corrente,nel nostro caso è inserito tra il positivo di alimentazione ed il Collettore delTransistor. Un piccolo accorgimento: tra i due fili di alimentazione del Motore c’è un Diodo.
Quando il circuito funziona normalmente il Diodo è ininfluente. Succede però, ad esempio, che il Motore avendo una certa inerzia meccanica, continui a girare anche se smettiamo di alimentarlo, e si comporti in questo caso anche come generatore di corrente. La corrente generata dal Motore, che girerebbe in senso opposto al dovuto,e che dunque potrebbe danneggiare il circuito elettronico,viene annullata dal Diodo.

Il codice


int potenziometro = A5; 
int motore =3;
int valorePot;

void setup() 
{
  pinMode(motore, OUTPUT);
  //Serial.begin(9600); 
}

void loop() 
 {
  valorePot = analogRead(potenziometro);    
  analogWrite(motore,valorePot/10);    
  delay(300);          
   //Serial.println(valorePot);
}

Analizzando il codice non troviamo niente di nuovo rispetto al caso precedente:un segnale analogico in ingresso viene usato per pilotare un PWM in uscita. Abbiamo all’inizio dichiarato 3 variabili intere:
potenziometro contiene il valore del pin analogico cui è connesso il potenziometro (A5)
motore contiene invece il valore del pin digitale da cui preleveremo il segnale PWM, mentre valorePot viene utilizzata per immagazzinare il dato presente sul piedino A5
(a valle del convertitore A/D).
Dentro setup() non ci sono sorprese: c’è solo la dichiarazione che useremo il piedino 3 come OUTPUT.
Dentro loop() niente di nuovo rispetto all’ esempio precedente tranne che……. analogWrite(motore,valorePot/10);
è differente rispetto a usato nell’esempio precedente. Si noti che per comandare il motore abbiamo diviso per 10 il dato contenuto in valorePot,mentre nell’esempio precedente avevamo diviso per 4. La ragione di questa diversità sta nella precauzione: non vogliamo che il motore giri troppo velocemente: richiederebbe troppa corrente e corriamo il rischio che la porta USB vada in crisi. Aumentare il fattore di divisione impedisce di pilotare il motore a piena potenza.


COSA ABBIAMO IMPARATO

* Abbiamo conosciuto il Transistor,il suo funzionamento,le sue componenti essenziali ed il modo di lavorare con esso. 
* Abbiamo imparato che l’uso di un dispositivo di amplificazione della corrente consente l’interfacciamento del microprocessore con ogni tipo di periferica,
piccola o grande essa sia, aprendo le porte dunque alla comunicazione tra il nostro piccolo Arduino e l’intero mondo.
* Abbiamo incontrato un nuovo Diodo, differente dal LED,e costruito essenzialmente per consentire alla corrente di fluire in un solo senso.


torna all’indice