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).
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
Un video da vedere assolutamente!
Un tour virtuale guidato di Arduino Uno. Un modo divertente e ritengo didatticamente attraente che vuole essere una descrizione sulle varie parti che costituiscono la scheda.
Ogni elemento di questo video è stato realizzato con elementi di pubblico dominio.
Per maggiori informazioni andate su Engineer Zero.
Impariamo in questa lezione ad usare un sensore per controllare l’accensione di un diodo led. Useremo il più semplice dei sensori: il pulsante.
Scopo della lezione:
realizzare un programma che permette di accendere una luce quando premiamo un pulsante e quando viene nuovamente premuto il pulsante spegne la luce, comportamento analogo a quello che si ha per un impianto di illuminazione.
Per controllare lo stato di un pulsante utilizzeremo l’istruzione digitalRead(), questa istruzione legge il valore su uno specifico pin digitale che può assumere due valori, HIGH o LOW, detto in modo meno informatico e più elettronico, verifica se su un determinato pin è applicata una tensione di +5V (definito HIGH) o 0V (definito LOW).
Nella lezione 2 abbiamo realizzato un programma che permetteva di far lampeggiare un led, con la nuova istruzione digitalRead() siamo in grado di eseguire qualcosa di più evoluto, l’accensione di un led solamente se cambia una situazione esterna, in questo esercizio, lo stato di un pulsante.
Quindi con digitalRead() possiamo leggere uno stato di un sensore e memorizzare questo stato nella memoria di Arduino per fare qualcosa.
Per procedere con questa lezione abbiamo necessità di un po’ di hardware elettronico:
1 breadboard
1 pulsante
1 diodo led
1 resistenza da 10 K Ohm
filo elettrico per breadboard
ed ovviamente Arduino duemilanove 🙂
Il circuito che deve essere realizzato è il seguente.
l’immagine è stata realizzata utilizzando Fritzing
Dettagli sui collegamenti:
Questo l’immagine del circuito reale:
Ricordate di collegare il catodo del diodo LED su GND e l’anodo all’uscita digitale 13.
Questo il codice usato per controllare il LED:
// Esempio 01: accendi il led appena è premuto il pulsante
#define LED 13 // LED collegato al pin digitale 13
#define BUTTON 7 // pin di input dove è collegato il pulsante
int val = 0; // si userà val per conservare lo stato del pin di input
void setup() {
pinMode(LED, OUTPUT); // imposta il pin digitale come output
pinMode(BUTTON, INPUT); // imposta il pin digitale come input
}
void loop() {
val = digitalRead(BUTTON); // legge il valore dell'input e lo conserva
// controlla che l'input sia HIGH (pulsante premuto)
if (val == HIGH) {
digitalWrite(LED, HIGH); //accende il led
}
else {
digitalWrite(LED, LOW); //spegne il led
}
}
Come potete constatare oltre all’istruzione digitalRead() in grado di leggere lo stato di un sensore esterno abbiamo anche l’istruzione if e if…else
L’istruzione if…else consente di prendere delle decisioni in funzione del fatto che una determinata condizione logica sia VERA o FALSA.
Nel caso in cui la condizione sia VERA viene eseguito il primo blocco di istruzioni, nel caso in cui la condizione sia FALSA, viene eseguito il secondo blocco di memoria.
La condizione logica espressa tra parentesi tonde, segue la parola if
Esempio:
if (x < 100)
{
// blocco A
}
else
{
// blocco B
}
Se la condizione X<100 è vera viene eseguito il blocco di istruzioni del “blocco A”, se la condizione X<100 è falsa viene eseguito il blocco di istruzioni del “blocco B”.
Nota:
Dire che una condizione è VERA vuol dire che assume un valore binario pari a 1, ma in senso booleano, è VERA qualsiasi condizione diversa da zero, per cui -50, -7, -1, 3, 9 sono tutti considerati VERO in senso booleano.
Per maggiori dettagli si consulti il reference su Arduino.cc
Tornando al codice del programma “Esempio 1” notate che ho usato “==” invece che “=” per confrontare due elementi.
Nel linguaggio di programmazione di Arduino il simbolo “==” (vai al manuale) viene utilizzato per confrontare due entità (confronto logico) e restituisce TRUE o FALSE, mentre il simbolo “=” (vai al manuale) viene utilizzato per assegnare un valore ad una variabile.
Analizziamo il programma
Poiché vogliamo ottenere una funzionalità simile a quello di un interruttore per attivare l’illuminazione in una casa, bisogna in qualche modo ricordare lo stato del pulsante, per far ciò definiamo una variabile intera di nome val a cui assegnamo inizialmente il valore 0.
Come potete vedere nel programma useremo val per conservare il valore di digitalRead()
I valori di qualsiasi variabile usata con Arduino vengono inseriti nella memoria RAM, valori che vengono persi una volta che si toglie l’alimentazione alla scheda Arduino.
All’interno della codice di loop() viene assegnata alla variabile val lo stato del valore di input mediante l’istruzione digitalRead(BUTTON), ovvero l’istruzione legge il valore dell’input (pulsante) e restituisce un valore 0 oppure 1:
// legge il valore dell'input e lo conserva
val = digitalRead(BUTTON);
successivamente viene controllato mediante l’istruzione if…else se il pulsante è premuto:
// controlla che l'input sia HIGH (pulsante premuto)
if (val == HIGH) {
digitalWrite(LED, HIGH); //accende il led
}
else {
digitalWrite(LED, LOW); //spegne il led
}
}
Se il valore di val è HIGH (valore logico 1) vuol dire che il pulsante è premuto e allora, tramite l’istruzione “digitalWrite(LED, HIGH);” viene acceso il LED, se il primo confronto risulta falso, ciò vuol dire che il pulsante non è premuto come conseguenza viene eseguita la parte di codice else che spegne il LED, ciò viene eseguito con l’istruzione: “digitalWrite(LED, LOW);”
Però lo scopo di questa terza lezione è quello di realizzare un circuito simile a quello di un impianto di illuminazione: “premo il pulsante accendo la luce, premo una seconda volta e spengo la luce”, l’esempio 1, ci costringe a mantenere il dito sul pulsante per mantenere acceso il led.
Questa la prima versione del programma che risolve il problema:
// Esempio 02: accendi il led appena è premuto il pulsante mantenendolo acceso quando si rilascia
// premendo una seconda volta il pulsante spegne il led
#define LED 13 // LED collegato al pin digitale 13
#define BUTTON 7 // pin di input dove è collegato il pulsante
int val = 0; // si userà val per conservare lo stato del pin di input
int stato = 0; // ricorda lo stato in cui si trova il led, stato = 0 led spento, stato = 1 led acceso
void setup() {
pinMode(LED, OUTPUT); // imposta il pin digitale come output
pinMode(BUTTON, INPUT); // imposta il pin digitale come input
}
void loop() {
val = digitalRead(BUTTON); // legge il valore dell'input e lo conserva
// controlla che l'input sia HIGH (pulsante premuto)
// e cambia lo stato del led
if (val == HIGH) {
stato = 1 - stato;
}
if (stato == 1) {
digitalWrite(LED, HIGH); // accende il led
}
else {
digitalWrite(LED, LOW); //spegne il led
}
}
Prima di provare il risultato su Arduino vediamo come funziona il programma.
Passo 1: pulsante non premuto – diodo spento
Il valore assunto da val è 0 in quanto il pulsante non è premuto (l’istruzione “digitalRead(BUTTON);” restituisce 0), la condizione logica val == HIGH del prim if restituisce falso e la variabie stato resta al valore iniziale 0.
Poiché il confronto stato == 1 del secondo if restituisce falso, viene eseguito l’else in cui è presente l’istruzione “digitalWrite(LED, LOW);” che spegne il diodo led.
Passo 2: pulsante premuto – diodo acceso
Il valore assunto da val è 1 in quanto il pulsante è premuto (l’istruzione “digitalRead(BUTTON);” restituisce 1), la condizione logica val == HIGH del primo if restituisce vero e la variabie stato viene impostata a stato = 1 – 0, cioè a 1.
Poiché il confronto stato == 1 del secondo if restituisce vero, viene eseguita l’istruzione che segue, cioè: “digitalWrite(LED, HIGH);” che accende il diodo led.
Passo 3: pulsante premuto – diodo spento
Il valore assunto da val è 1 in quanto il pulsante è premuto (l’istruzione “digitalRead(BUTTON);” restituisce 1), la condizione logica val == HIGH del primo if restituisce vero e la variabie stato viene impostata a stato = 1 – 1 (stato è stato impostato ad 1 nel passo precedente), cioè a 0.
Poiché il confronto stato == 1 del secondo if restituisce falso, viene eseguito l’else in cui è presente l’istruzione “digitalWrite(LED, LOW);” che spegne il diodo led.
Se provate il programma noterete un funzionamento molto strano, potrebbe capitare che premendo e rilasciando il pulsante il led non si accende e si spegne correttamente, ad esempio premo e non si accende oppure se acceso premendo il pulsante non si spegne il led. Ciò è dovuto al fatto che Arduino legge le istruzioni del vostro programma ad una velocità di milioni di istruzioni al secondo ciò vuol dire che la lettura dello stato del pulsante viene letta moltissime volte al secondo e l’accensione e lo spegnimento del diodo led potrebbe essere imprevedibile.
Per comprendere questa situazione immaginate che al Passo 3 precedente si continui a mantenere premuto il pulsante, noterete che la variabile stato ad ogni ciclo, assume valori diversi che possono portare ad una situazione di accensione o spegnimento del diodo.
Per ovviare a questo problema bisogna riuscire a identificare il momento esatto in cui il pulsante viene premuto è questo può essere fatto conservando in una variabile lo stato del pulsante al passo precedente:
// Esempio 03: antirimbalzo
// accendi il led appena è premuto il pulsante mantenendolo acceso quando si rilascia
// premendo una seconda volta il pulsante spegne il led
#define LED 13 // LED collegato al pin digitale 13
#define BUTTON 7 // pin di input dove è collegato il pulsante
int val = 0; // si userà val per conservare lo stato del pin di input
int vecchio_val = 0; // si userà vecchio_val per conservare lo stato del pin di input al passo precedente
int stato = 0; // ricorda lo stato in cui si trova il led, stato = 0 led spento, stato = 1 led acceso
void setup() {
pinMode(LED, OUTPUT); // imposta il pin digitale come output
pinMode(BUTTON, INPUT); // imposta il pin digitale come input
}
void loop() {
val = digitalRead(BUTTON); // legge il valore dell'input e lo conserva
// controlla se è accaduto qualcosa
if ((val == HIGH) && (vecchio_val == LOW)){
stato = 1 - stato;
}
vecchio_val = val; // ricordiamo il valore precedente di val
if (stato == 1) {
digitalWrite(LED, HIGH); // accende il led
}
else {
digitalWrite(LED, LOW); //spegne il led
}
}
In questo caso usiamo la variabile vecchio_val per conservare lo stato al ciclo precedente, in questo modo verifichiamo lo stato effettivo del pulsante verificando se lo stato attuale è “pulsante premuto” E “pulsante non premuto al passo precedente“, se la condizione è vera viene modificato lo stato.
L’operatore boleano utilizzato è AND che nel linguaggio di programmazione si indica con &&.
La cosa più bella nell’applicare l’informatica al mondo reale e che è indispensabile far i conti con le caratteristiche fisiche dei dispositivi su cui operiamo.
Come potete vedere dal filmato, non appena aumentiamo la frequenza con cui premete il pulsante, si ricade in una situazione di incongruenza per cui il led non risponde più ai comandi. Questo problema avviene perché il pulsante è un apparato meccanico costituito da contatti elettrici ed una molla, quando premiamo e rilasciamo, si manifestano situazioni di rimbalzo del contatto che creano dei segnali non corretti, detti spuri, che modificano lo stato del diodo led.
Per risolvere il problema è sufficiente attendere che questi rimbalzi spuri si concludano e quindi bisogna attendere una certa quantità di tempo dopo che è stato rilevato un cambiamento di stato, provate con valori non superiori a 50 millisecondi, nell’esempio ho introdotto un valore di 15 millisecondi di ritardo.
// Esempio 04: antirimbalzo2 - accendi il led appena è premuto il pulsante mantenendolo acceso quando si rilascia
// premendo una seconda volta il pulsante spegne il led
#define LED 13 // LED collegato al pin digitale 13
#define BUTTON 7 // pin di input dove è collegato il pulsante
int val = 0; // si userà val per conservare lo stato del pin di input
int vecchio_val = 0; // si userà vecchio_val per conservare lo stato del pin di input al passo precedente
int stato = 0; // ricorda lo stato in cui si trova il led, stato = 0 led spento, stato = 1 led acceso
void setup() {
pinMode(LED, OUTPUT); // imposta il pin digitale come output
pinMode(BUTTON, INPUT); // imposta il pin digitale come input
}
void loop() {
val = digitalRead(BUTTON); // legge il valore dell'input e lo conserva
// controlla se è accaduto qualcosa
if ((val == HIGH) && (vecchio_val == LOW)){
stato = 1 - stato;
delay(15); // attesa di 15 millisecondi
}
vecchio_val = val; // ricordiamo il valore precedente di val
if (stato == 1) {
digitalWrite(LED, HIGH); // accende il led
}
else {
digitalWrite(LED, LOW); //spegne il led
}
}
Ora come esercizio uniamo ciò che abbiamo imparato nella lezione n. 2 e ciò che abbiamo imparato in questa lezione.
Esercizio:
realizzare un programma che esegue questa funzione: quando si preme un pulsante il diodo led lampeggia, quando premo una seconda volta il pulsante il led termina di lampeggiare:
// Esempio 05: led lampeggia se premo il pulsante
// premendo una seconda volta il pulsante si spegne il led
#define LED 13 // LED collegato al pin digitale 13
#define BUTTON 7 // pin di input dove è collegato il pulsante
int val = 0; // si userà val per conservare lo stato del pin di input
int vecchio_val = 0; // si userà vecchio_val per conservare lo stato del pin di input al passo precedente
int stato = 0; // ricorda lo stato in cui si trova il led, stato = 0 led spento, stato = 1 led acceso
void setup() {
pinMode(LED, OUTPUT); // imposta il pin digitale come output
pinMode(BUTTON, INPUT); // imposta il pin digitale come input
}
void loop() {
val = digitalRead(BUTTON); // legge il valore dell'input e lo conserva
// controlla se è accaduto qualcosa
if ((val == HIGH) && (vecchio_val == LOW)){
stato = 1 - stato;
delay(15); // attesa di 15 millisecondi
}
vecchio_val = val; // ricordiamo il valore precedente di val
if (stato == 1) {
digitalWrite(LED, HIGH); // accende il LED
delay(1000); // aspetta un secondo
digitalWrite(LED, LOW); // spegne il LED
delay(1000); // aspetta un secondo
}
else {
digitalWrite(LED, LOW); //spegne il led
}
}
Un piccolo esercizio.
Se provate ad aumentare la frequenza con cui premete il pulsante noterete che non riuscite a spegnere il diodo led, siete in grado di risolvere questo problema?