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:
// Esempio 1: accensione led
int led_1 = 8;
int led_2 = 9;
int btn_pin = 2;
void setup() {
pinMode(led_1, OUTPUT);
pinMode(led_2, OUTPUT);
pinMode(btn_pin, INPUT);
}
void loop()
{
int in = digitalRead(btn_pin);
if (in == LOW)
{
digitalWrite(led_1, LOW);
delay (2000);
digitalWrite(led_2, LOW);
delay (2000);
}
else
{
digitalWrite(led_1, HIGH);
delay (2000);
digitalWrite(led_2, HIGH);
delay (2000);
}
}
Non funziona molto bene, come si desume dal filmato vi sono alcune correzioni da fare:
Nell’if viene controllato se il pulsante non è stato premuto “in == LOW”, se vero vengono spenti in modo sequenziale i due LED, domanda:
Se una luce è già spenta perché aggiungere un ritardo?
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).
Nell’ultima esperienza di laboratorio ho introdotto l’uso dell’integrato 555 in configurazione astabile, di seguito vi riassumo velocemente ciò che abbiamo detto a lezione tralasciando i passaggi matematici già spiegati, tenete in conto che il 555 sarà anche argomento di 4′ e quindi avremo modo di approfondire e sperimentare ancor di più.
Il circuito dell’organo elettronico giocattolo è il seguente:
Lista componenti:
R1 = R2 = R3 = R4 = R5 = R6 = 1K?
R7 = 10 K?
C1 = 100 nF
C2 = 10 nF
C3 = 10 ?F
Alt = Altoparlante da 8 ?
IC = 555
da P1 a P6 pulsanti
Come detto il suo funzionamento è basato su questo schema:
fig. 1
in cui il gruppo di resistenze e pulsanti è sostituito dalla resistenza Rb.
La resistenza che permette la regolazione della temporizzazione è divisa in due parti: Ra ed Rb ed il piedino 7 è connesso al punto di giunzione tra Ra ed Rb.
Quando la tensione del condensatore C1 raggiunge i 2/3 di Vcc il condensatore C1 incomincia a scaricarsi verso massa attraverso la resistenza Rb.
Quando la tensione su C1 si porta ad 1/3 di Vcc riparte un nuovo ciclo di carica e l’uscita sul piedino 3 va al valore “alto” (a +Vcc)
Il condensatore C1 si carica e scarica periodicamente tra 2/3 Vcc e 1/3 Vcc (fig. 2) come conseguenza l’uscita varia tra 0 e +Vcc
fig. 2
L’uscita (piedino 3) sarà “alta” durante la parte di carica del ciclo, intervallo t1, secondo la seguente relazione:
L’uscita sarà “bassa” durante la parte di scarica, intervallo t2, secondo la relazione:
Il periodo totale sarà la somma dell’intervallo di carica e di quello di scarica:
La frequenza di uscita sarà quindi:
Vi ricordo che il duty cycle (ciclo di lavoro) indicato con la lettera D è il rapporto tra l’intervallo di tempo in cui il segnale è “alto” (in un ciclo) e la durata dell’intero ciclo:
Nel circuito dell’organo il trimmer R7 viene utilizzata per cambiare della stessa quantità i suoni generati premendo i pulsanti, ogni volta che viene premuto un pulsante, ad R7 si sommeranno le resistenze a monte del pulsante premuto (cambia la Rb nel circuito di fig. 2) e ciò farà variare la frequenza di uscita e quindi il suono generato.
Di seguito trovate i disegni del circuito su breadboard realizzati con Fritzing ed il video del prototipo che trovate in laboratorio.