Sono in procinto di partire con il corso Arduino con i miei allievi di 4′ Elettronici, le esercitazioni saranno svolte usando computer con sistema operativo Ubuntu. Nelle scorse mattinate ho effettuato l’installazione e gli aggiornamenti necessari sul sistema operativo per poter utilizzare Arduino.
Durante questa installazione ho pensato di realizzare una serie di screenshot per mantenere memoria di tutte le fasi necessarie. I computer sono attualmente dotati di Ubuntu 9.10 (karmic), per l’installazione sull’ultima versione 10.10 si procede in modo simile.
Per poter utilizzare Arduino è necessario installare:
Arduino (nel mio caso ho scaricato la versione a 32 bit)
Questa la versione del Sistema Operativo:
Per l’installazione di OpenJDK, potete a scelta utilizzare Ubuntu Software Center oppure il gestore pacchetti, io per questioni di velocità ho preferito di usare Ubuntu Software Center:
A margine di NIDays2011, abbiamo incontrato Massimo Banzi che ci ha spiegato il senso profondo del progetto Arduino nonché i suoi programmi per il futuro, specie nel campo della Robotica Educativa.
Quando mi hanno detto che una delle keynote di NIDays 2011- l’annuale Forum Tecnologico sulla Progettazione Grafica di Sistemi di National Instruments che si è svolto di recente a Milano – sarebbe stata tenuta da Massimo Banzi, in un primo momento ho pensato: “che ci fa uno dei guru dell’open source in una manifestazione come questa?” La risposta me l’ha fornita la brochure di presentazione dell’evento che quest’anno (ma non solo) aveva come tema centrale la necessità di inventare e innovare.
E chi se non un innovatore come Massimo Banzi poteva fornire una personalissima risposta a questa esigenza?
Una risposta che anche National Instruments con i propri prodotti e le applicazioni presentate dai numerosi partner tecnologici ha messo in mostra nel corso della manifestazione.
Durante il suo intervento, Banzi ha introdotto l’innovativo concetto di hardware open source mostrando decine di applicazioni realizzate con la piattaforma Arduino e conquistando letteralmente il pubblico in sala.
Prima del suo intervento, ho avuto l’occasione di intervistare Massimo Banzi al quale ho rivolto una serie di domande facendomi portavoce anche di molti nostri lettori…
La versatilità di Arduino come piattaforma di prototipazione elettronica è nota, ma sapevate che è possibile donare la vista 🙂 ad Arduino ? L’idea è di David Chatting che ha realizzato questo interessante shield, che ha chiamato Arduino Eye Shield, consente di interpretare video analogici (PAL o NTSC) da una fotocamera o altra fonte.
Questa lezione nasce da un commento di Aldo Biscotti(seguite il link), che ha la necessità di realizzare l’illuminazione temporizzata delle scale di casa. Si sta cimentando in questo progetto e la sua richiesta di aiuto mi da parecchi spunti per la realizzazione di una lezione ad hoc per i miei allievi.
Per la realizzazione del suo progetto avrà la necessità di usare dei sensori di presenza, che in questa lezione saranno sostituiti da semplici pulsanti.
Dal commento che mi è stato lasciato desumo che la necessità descritta da Aldo è quella di comandare due lampade di due ambienti diversi mediante due distinti rilevatori di presenza.
Nel realizzare un primo prototipo di studio Aldo giustamente, visto che sta imparando a programmare Arduino, utilizza i pulsanti in sostituzione dei rilevatori e i diodi led in sostituzione delle lampade.
Questa la sua necessità :
Pulsante 1:
(salita) start,
accensione del led 1,
dopo 2 secondi accensione led 2,
dopo 2 secondi spegnimento led 1,
dopo 2 secondi spegnimento led 2,
end.
Pulsante 2:
(discesa) start,
accensione del led 2,
dopo 2 secondi accensione led 1,
dopo 2 secondi spegnimento led 2,
dopo 2 secondi spegnimento led 1,
end.
Grazie Aldo.
Risponderò ad Aldo prendendo in analisi il suo primo sketch e da questo ne svilupperò una serie di programmi in cui introdurrò nuovi concetti.
Innanzitutto realizziamo il primo circuito di test, costituito da due diodi led, una resistenza ed un pulsante, in questa lezione vedrete che utilizzerò sia una scheda Arduino UNO, che Arduino 2009, assolutamente simili dal punto di vista della programmazione:
Ciò implica che se il programma è in esecuzione nella prima parte dell’if non verrà rilevata la presenza di una persona al massimo per 4 secondi ed è come dire che appena entro nella stanza sarò al buio per 4 secondi prima che le luci vengano accese e quindi una persona potrà :
fermarsi ed attendere 4 secondi
oppure camminare per 4 secondi al buio compiendo circa 5 metri di spazio camminando, presumibilmente supererà la prima stanza al buio.
Questa la mia prima variazione:
// Esempio 2: accensione temporizzata di un led in una sola direzione
#define led_1 8 // il pin 8 è usato per il LED
#define led_2 9 // il pin 9 è usato per il LED
#define btn_pin 2 // il pin 2 è usato per il PULSANTE 1
// Variabili
int in = 0;
void setup() {
pinMode(led_1, OUTPUT); // impostiamo il pin led_1 come output
pinMode(led_2, OUTPUT); // impostiamo il pin led_2 come output
pinMode(btn_pin, INPUT); // impostiamo il pin btn_pin come input
}
void loop()
{
in = digitalRead(btn_pin); // assegna lo stato del pulsante
if (in == HIGH) // controlla se il pulsante è stato premuto
{
digitalWrite(led_1, HIGH); // accendiamo il LED 1
delay (2000); // attesa di 2 sec
digitalWrite(led_2, HIGH); // accendiamo il LED 2
delay (2000); // attesa di 2 sec
digitalWrite(led_1, LOW); // spegniamo il LED 1
delay (2000); // attesa di 2 sec
digitalWrite(led_2, LOW); // spegniamo il LED 2
}
}
Controllo se il pulsante e premuto, se vero inizia la sequenza di accensione, altrimenti se il pulsante non è premuto l’if non viene eseguito, le luci continuano a rimanere spente e ricomincia nuovamente il loop().
Ovviamente se durante la sequenza di accensione e spegnimento di 6 secondi viene premuto nuovamente il pulsante non accade nulla, vedremo più avanti che questa soluzione potrebbe causare qualche problema.
Vediamo adesso come utilizzare due pulsanti (o rilevatori di presenza) per governare l’accensione in senso opposto, il circuito realizzato è il seguente:
Questo lo sketch
// Esempio 3: accensione temporizzata di due led
// in due direzioni con uso dell'if
#define led_1 8 // il pin 8 è usato per il LED
#define led_2 9 // il pin 9 è usato per il LED
#define btn_pin1 2 // il pin 2 è usato per il PULSANTE 1
#define btn_pin2 3 // il pin 3 è usato per il PULSANTE 2
// Variabili
int in1 = 0; // variabile per memorizzare lo stato del PULSANTE 1
int in2 = 0; // variabile per memorizzare lo stato del PULSANTE 2
void setup() {
pinMode(led_1, OUTPUT);
pinMode(led_2, OUTPUT);
pinMode(btn_pin1, INPUT);
pinMode(btn_pin2, INPUT);
}
void loop()
{
in1 = digitalRead(btn_pin1);
in2 = digitalRead(btn_pin2);
if (in1 == HIGH && in2 == LOW) // se PULSANTE 1 premuto e PULSANTE 2 no sequenza 1
{
digitalWrite(led_1, HIGH);
delay (2000);
digitalWrite(led_2, HIGH);
delay (2000);
digitalWrite(led_1, LOW);
delay (2000);
digitalWrite(led_2, LOW);
}
if (in1 == LOW && in2 == HIGH) // se PULSANTE 1 premuto e PULSANTE 2 no sequenza 2
{
digitalWrite(led_2, HIGH);
delay (2000);
digitalWrite(led_1, HIGH);
delay (2000);
digitalWrite(led_2, LOW);
delay (2000);
digitalWrite(led_1, LOW);
}
}
Come potete notare ho usato l’operatore logico AND (&&) che effettua un controllo su quale dei pulsanti è acceso in questo modo controllo la direzione di accensione.
Per chiarire meglio ho realizzato uno schema che visualizza meglio cosa accade:
Si ricordi che la progettazione viene fatta usando pulsanti, ma voi estrapolate e pensate a dei rilevatori di presenza.
Supponiamo che la direzione sia da destra a sinistra, la persona 1 viene rilevata dal sensore R1, si accende la luce L1 per 2 secondi, entra nella stanza 2 e supponendo che non sia più veloce di due secondi, rischiando di entrare in una stanza buia, viene rilevato dal sensore R2, si accende la luce L2 e dopo 4 secondi si spegne la luce L1.
Ma cosa accade se nei primi 2 secondi entra un’altra persona nella prima stanza a destra?
La seconda persona resta al buio.
Stesso inconveniente accade nella direzione opposta da sinistra verso destra.
Quindi per superare questo incoveniente è necessario che l’accensione delle luci non duri solamente per un tempo prefissato, ma per tutto il tempo in cui la persona è presente nel locale, dopo di che la luce può spegnersi.
La soluzione più semplice di tutte è quella descritta dallo sketch che segue, si ricordi che premere il pulsante corrisponde a: “persona rilevata”
// Esempio 4: accensione di due led comandati da due pulsanti
#define led_1 8 // il pin 8 è usato per il LED
#define led_2 9 // il pin 9 è usato per il LED
#define btn_pin1 2 // il pin 2 è usato per il PULSANTE 1
#define btn_pin2 3 // il pin 3 è usato per il PULSANTE 2
// Variabili
int in1 = 0;
int in2 = 0;
void setup() {
pinMode(led_1, OUTPUT);
pinMode(led_2, OUTPUT);
pinMode(btn_pin1, INPUT);
pinMode(btn_pin2, INPUT);
}
void loop()
{
in1 = digitalRead(btn_pin1);
in2 = digitalRead(btn_pin2);
if (in1 == HIGH) // PULSANTE 1 premuto
{
digitalWrite(led_1, HIGH); // accensione LED 1
}
else
{
digitalWrite(led_1, LOW); // seil PULSANTE 1 non premuto LED 1 spento
}
if (in2 == HIGH) // PULSANTE 2 premuto
{
digitalWrite(led_2, HIGH); // accensione LED 2
}
else
{
digitalWrite(led_2, LOW); // seil PULSANTE 2 non premuto LED 2 spento
}
}
Per evitare che ci sia uno spegnimento brusco dell’illuminazione appena si esce dalla stanza, ritardo lo spegnimento dell’illuminazione della stanza che ho appena abbandonato:
// Esempio 5: accensione di due led comandati da due pulsanti
// con ritardo di spegnimento di due secondi
#define led_1 8 // il pin 8 è usato per il LED
#define led_2 9 // il pin 9 è usato per il LED
#define btn_pin1 2 // il pin 2 è usato per il PULSANTE 1
#define btn_pin2 3 // il pin 3 è usato per il PULSANTE 2
// Variabili
int in1 = 0;
int in2 = 0;
void setup() {
pinMode(led_1, OUTPUT);
pinMode(led_2, OUTPUT);
pinMode(btn_pin1, INPUT);
pinMode(btn_pin2, INPUT);
}
void loop()
{
in1 = digitalRead(btn_pin1);
in2 = digitalRead(btn_pin2);
if (in1 == HIGH){ // PULSANTE 1 premuto
digitalWrite(led_1, HIGH); // accensione LED 1
delay (2000); // ritardo di 2 sec
}
else
{
digitalWrite(led_1, LOW); // se il PULSANTE 1 non premuto LED 1 spento
}
if (in2 == HIGH){ // PULSANTE 2 premuto
digitalWrite(led_2, HIGH); // accensione LED 2
delay (2000); // ritardo di 2 sec
}
else
{
digitalWrite(led_2, LOW); // seil PULSANTE 2 non premuto LED 2 spento
}
}
Nella prossima lezione al fine di rendere più utile e gradevole il controllo sull’illuminazione della stanza vedremo come aumentare e diminuire gradualmente l’illuminazione usando una tecnica che sfrutta la modulazione di larghezza di impulso (PWM).
Prenderò spunto dal commento che mi è stato lasciato da un mio studente per introdurre l’uso delle istruzioni:
if
if...else
Switch Case
Lo scopo di questa lezione è quello di realizzare un programma che conta quante volte il pulsante viene premuto, per un ciclo di 4 pressioni, alla quinta pressione il led lampeggia una volta e poi si riavvia il ciclo.
Per questa lezione useremo:
breadboard
4 diodi led
1 pulsante
1 resistenza da 10KOhm
Arduino duemilanove
La prima versione del programma è quella che è stata realizzata dal mio studente, realizzazione di uno sketch per effettuare la seguente funzione:
Prima pressione: led lampeggia ogni mezzo secondo
Seconda pressione: led lampeggia ogni secondo
Terza pressione: led lampeggia ogni secondo e mezzo
Quarta pressione: led si spegne
Realizziamo un circuito come indicato nelle immagini che seguono:
La proposta interessante ed elegante dell’allievo, sfrutta l’istruzione “Switch Case” che permette di definire quale porzione di codice eseguire in funzione del valore di una variabile. Ciò consente di evitare lunghe catene di if-else.
Il “break” alla fine di ogni “case” viene usato per interrompere il controllo degli altri “case“.
// Esempio 05:
// Primo tocco: led lampeggia ogni mezzo secondo
// Secondo tocco: led lampeggia ogni secondo
// Terzo tocco: led lampeggia ogni secondo e mezzo
// Quarto tocco: led si spegne
const int BUTTON = 2; // pin di input a cui è collegato il pulsante
const int LED = 13; // LED collegato al pin digitale 13
// Variabili globali (tutti interi)
int statoButton = 0; // stato del pulsante (inizialmente non premuto)
int lastStatoButton = 0; // ultimo stato del pulsante (per ora non premuto)
int countButton = 0; // Conteggio del bottone
// Avvio dell'applicazione
void setup()
{
pinMode(LED, OUTPUT); // imposta il pin digitale come output
pinMode(BUTTON, INPUT); // imposta il pin digitale come input
}
// Avvio del loop
void loop()
{
// Verifico se l'utente ha premuto il bottone
if(digitalRead(BUTTON))
{
// Aspetto 15ms per far alzare il dito all'utente
delay(15);
// Cambio l'ultimo stato del bottone
if(lastStatoButton==0) lastStatoButton=1;
else lastStatoButton=0;
// Aumento il count del bottone
if(countButton<=3) countButton=countButton+1;
else countButton=0;
}
// In base allo stato del bottone scelgo l'azione del led
switch (countButton)
{
// Led lampeggia ogni mezzo secondo
case 1:
digitalWrite(LED, HIGH); // accende il LED
delay(500); // aspetta un secondo
digitalWrite(LED, LOW); // spegne il LED
delay(500); // aspetta un secondo
break;
// Led lampeggia ogni secondo
case 2:
digitalWrite(LED, HIGH); // accende il LED
delay(1000); // aspetta un secondo
digitalWrite(LED, LOW); // spegne il LED
delay(1000); // aspettaun secondo
break;
// led lampeggia ogni secondo e mezzo
case 3:
digitalWrite(LED, HIGH); // accende il LED
delay(1500); // aspetta un secondo
digitalWrite(LED, LOW); // spegne il LED
delay(1500); // aspetta un secondo
break;
// Led si spegne
case 0:
delay(15);
digitalWrite(LED, LOW);
delay(5000); // aspetta un secondo
break;
}
}
Il programma come si intuisce dal filmato, presenta alcuni problemi.
Rimbalzo
Il problema dei segnali spuri dovuti al rimbalzo del pulsante non consente di controllare esattamente la selezione.
Attesa
Durante l’attesa, mentre si vede lampeggiare il led, premendo il pulsante non si ha cambiamento di stato fino a quando non termina il tempo in cui lampeggia il led.
Discriminare
Difficoltà di discriminare in quale situazione ci si trova, tempi troppo brevi per percepire la differenza delle 4 condizioni.
Per risolvere i problemi sopra elencati vi propongo 6 varianti all’esempio 1, ciò mi permetterà di introdurre nuove istruzioni del linguaggio di programmazione.
Prima di fornirvi le mie soluzioni ho necessità di introdurre l’uso dell’istruzioni Serial ed utilizzare il programma “StateChangeDetection” che potete trovare in File > Examples > 2.Digitale > StateChangeDetection o direttamente on-line sul sito Arduino che trovate di seguito