Basi · 11 min di lettura

Blocco se Arduino: pulsante e LED con if-else, a blocchi e in C++

Blocco se Arduino con pulsante e LED: leggere un pin, if-else, confronti =, ≠, <, >, condizioni annidate, on/off, antirimbalzo e luce notturna LDR.

Il blocco se in Arduino permette a un programma di scegliere una di due strade in base a una domanda: «Il pulsante è premuto? Se sì, accendi il LED, altrimenti spegnilo». Nel C++ di Arduino questa struttura si chiama if/else, e il blocco «se … fai … altrimenti» della programmazione a blocchi di BlueGrays ne è l'equivalente esatto. In questo articolo userai un progetto pulsante e LED per imparare a impostare un pin come ingresso e a leggerlo, poi il blocco se, gli operatori di confronto, le condizioni annidate e come unire due condizioni con «e», blocco per blocco e riga per riga.

Questo articolo è la parte 3 della serie Dai blocchi al codice. Nella parte precedente abbiamo scritto il primo programma e fatto lampeggiare un LED con i blocchi; nella prossima vedremo cicli e variabili.

Finora i nostri programmi facevano sempre la stessa cosa: il LED si accendeva, aspettava, si spegneva e aspettava di nuovo. Non ascoltavano mai il mondo esterno. Con le condizioni, la scheda decide guardando un pulsante, un sensore di luce o una distanza che misura, ed è lì che comincia il vero divertimento della programmazione robotica. Tutti gli esempi vengono da progetti a blocchi gratuiti: puoi aprirne blocchi e codice nella pagina programmazione a blocchi o nell'app e seguire in parallelo.

Ingresso e uscita: in che direzione lavora un pin?

I pin digitali di Arduino fanno uno di due lavori. Un pin impostato come uscita fornisce 5 V (HIGH) o 0 V (LOW); è così che si comanda un LED, un buzzer o un relè. Un pin impostato come ingresso non fornisce nulla, ascolta solo la tensione presente: su un Arduino Uno legge HIGH sopra circa 3 V e LOW sotto 1,5 V. Nei blocchi questa scelta si fa nella sezione di setup: il blocco «imposta pin 13 come INGRESSO» diventa pinMode(13, INPUT); in C++, e «imposta pin 7 come USCITA» diventa pinMode(7, OUTPUT);. Per leggere il pin si usa il blocco «leggi pin 13». Ha un aspetto diverso dagli altri: non è un comando da impilare, ma un blocco valore arrotondato che si incastra in uno spazio di un altro blocco. Il suo equivalente in C++ è digitalRead(13), che restituisce HIGH o LOW. Dato che in Arduino HIGH vale 1 e LOW vale 0, puoi anche salvare il risultato in una variabile come un numero. In breve, i blocchi comando fanno qualcosa, i blocchi valore danno un risultato, e lo spazio della condizione del blocco se si riempie solo con un risultato del genere.

BloccoEquivalente C++Cosa fa
imposta pin 13 come INGRESSOpinMode(13, INPUT);Mette il pin in ascolto (una volta, nel setup)
imposta pin 7 come USCITApinMode(7, OUTPUT);Permette al pin di fornire tensione
leggi pin 13digitalRead(13)Restituisce HIGH (1) o LOW (0)
scrivi ALTO sul pin 7digitalWrite(7, HIGH);Porta 5 V sul pin, il LED si accende
lettura analogica A0analogRead(A0)Restituisce un numero da 0 a 1023
se … fai … altrimentiif (…) { … } else { … }Esegue una di due strade in base alla condizione

Collegamento: pulsante sul 13, LED sul 7, resistenza pull-down obbligatoria

Nel progetto Accendere un LED con un pulsante (Push) il pulsante è su D13 e il LED su D7. Un piedino del pulsante va a 5V, l'altro a D13, e tra D13 e GND c'è una resistenza di pull-down da 10 kΩ. A pulsante rilasciato la resistenza porta il pin a GND e si legge LOW. Quando premi, i 5V arrivano direttamente sul pin e si legge HIGH. Dato che la resistenza è grande, durante la pressione da 5V a GND passa solo circa mezzo milliampere. Il piedino lungo del LED va a D7 attraverso una resistenza da 220 Ω, quello corto a GND.

ComponenteSi collega aPin Arduino Uno
Pulsante, piedino 1Direttamente5V
Pulsante, piedino 2 (in diagonale)DirettamenteD13
Resistenza da 10 kΩ (pull-down)Tra D13 e GNDD13 – GND
Piedino lungo del LED (anodo)Attraverso una resistenza da 220 ΩD7
Piedino corto del LED (catodo)DirettamenteGND
Se salti la resistenza di pull-down, a pulsante rilasciato D13 non è collegato a niente; si parla di ingresso flottante. Il pin capta disturbi elettrici, digitalRead() restituisce HIGH e LOW a caso e il LED sfarfalla senza che tu tocchi nulla, o si accende addirittura quando avvicini la mano. Nei pulsanti a quattro piedini, i due dello stesso lato sono già collegati all'interno: usa quindi i piedini in diagonale. Per i dettagli leggi come collegare un pulsante ad Arduino e resistenze pull-up e pull-down.

Il blocco se e if/else: il LED si accende finché premi

La versione a blocchi del progetto ha due sezioni. In «setup (una volta)» il pin 13 viene impostato come INGRESSO e il pin 7 come USCITA. In «ripeti per sempre» c'è un unico grande blocco: se … fai … altrimenti. Il suo spazio esagonale per la condizione contiene il confronto «leggi pin 13 = ALTO». Se la condizione è vera viene eseguito il blocco «scrivi ALTO sul pin 7» del ramo «fai»; se è falsa, il blocco «scrivi BASSO sul pin 7» del ramo «altrimenti».

Blocco se Arduino con pulsante e LED: blocchi del progetto Accendere un LED con un pulsante (Push)
Il pin 13 è INGRESSO e il pin 7 USCITA; se il pin 13 legge ALTO il LED si accende, altrimenti si spegne.
C++ (Arduino IDE)
1void setup() {
2  pinMode(13, INPUT);    // Buton girişi (harici pull-down) / Button input (external pull-down)
3  pinMode(7, OUTPUT);    // LED çıkışı / LED output
4}
5
6void loop() {
7  if (digitalRead(13) == HIGH) {   // Buton basılı mı? / Is the button pressed?
8    digitalWrite(7, HIGH);         // Basılı: LED yanar / Pressed: LED on
9  } else {
10    digitalWrite(7, LOW);          // Bırakıldı: LED söner / Released: LED off
11  }
12}
13

Metti il codice accanto ai blocchi e la corrispondenza è evidente. La parola if corrisponde a «se», la condizione digitalRead(13) == HIGH tra parentesi allo spazio della condizione, la prima coppia di graffe al ramo «fai» ed else con le sue graffe al ramo «altrimenti». Ogni blocco che metti in un ramo diventa una riga dentro le graffe corrispondenti. Poiché loop() gira decine di migliaia di volte al secondo, la scheda rilegge il pulsante di continuo; appena sollevi il dito, al giro successivo la condizione è falsa e il LED si spegne. Ecco perché il progetto si chiama «Push»: il LED resta acceso solo finché tieni premuto. Il ramo «altrimenti» è facoltativo; un blocco se con il solo ramo «fai» diventa un if senza else. Ma se qui togli il ramo «altrimenti», una volta acceso il LED non si spegne più, perché non resta nessuna riga che lo spenga. Pensare a entrambi i rami di ogni condizione è una buona abitudine.

Blocchi di confronto: =, ≠, < e >

Simbolo nel bloccoC++SignificatoEsempio dai progetti
===uguale adigitalRead(13) == HIGH (LED con pulsante, Push)
≠!=diverso dabutton != lastButton (accendere e spegnere un LED)
<<minore divalue < 50 (luce notturna con LDR)
>>maggiore didistance > minDistance (distanza HC-SR04)
Il segno «=» del blocco di confronto in C++ si scrive ==. Un solo uguale in C++ non confronta, ma assegna. Se scrivi if (button = 1), il compilatore non ti ferma: button diventa 1, il risultato è diverso da zero, quindi la condizione è vera a ogni giro e il LED si accende senza mai guardare il pulsante. Con i blocchi questo errore non puoi farlo, perché assegnazione («imposta … a …») e confronto sono blocchi separati. Quando passi al codice, però, è l'errore più comune in assoluto.

Accendi e spegni con un pulsante: se annidati e variabile di stato

Nel progetto Push il LED restava acceso solo finché tenevi premuto il pulsante. Se vuoi che si comporti come un vero interruttore, «premi una volta per accendere, di nuovo per spegnere», il programma deve ricordare due cose: se il LED è acceso in questo momento e cosa ha letto il pulsante al giro precedente. Il progetto Accendere e spegnere un LED con un pulsante dichiara per questo due interi nella sezione «variabili globali (all'inizio)»: ledState (0 = spento, 1 = acceso) e lastButton (la lettura precedente). Il circuito è lo stesso: pulsante su D13 con pull-down esterna, LED su D7.

Blocchi del progetto Accendere e spegnere un LED con un pulsante: se annidato, confronto ≠ e blocco non
Il se esterno rileva un cambiamento del pulsante, quello interno controlla che sia una pressione; non ledState inverte lo stato del LED.
C++ (Arduino IDE)
1int ledState = 0;     // LED durumu: 0 = sönük, 1 = yanık / LED state: 0 = off, 1 = on
2int lastButton = 0;   // Butonun önceki okuması / Previous button reading
3
4void setup() {
5  pinMode(13, INPUT);   // Buton girişi (harici pull-down) / Button input (external pull-down)
6  pinMode(7, OUTPUT);   // LED çıkışı / LED output
7}
8
9void loop() {
10  int button = digitalRead(13);   // Butonu oku / Read the button
11  if (button != lastButton) {     // Buton durumu değişti / Button state changed
12    if (button == 1) {            // Yalnız basış anında (LOW -> HIGH) / Only at the press (LOW -> HIGH)
13      ledState = !ledState;       // Durumu ters çevir / Flip the state
14      digitalWrite(7, ledState);
15    }
16    delay(50);                    // Sıçramayı atlamak için kısa bekleme / Short wait to skip the bounce
17    lastButton = button;          // Bu okumayı sakla / Store this reading
18  }
19}
20
BloccoRiga C++Compito
dichiara intero (int) ledState = 0int ledState = 0;Memorizza lo stato del LED
dichiara intero (int) lastButton = 0int lastButton = 0;Memorizza la lettura precedente del pulsante
imposta button a leggi pin 13int button = digitalRead(13);Legge lo stato attuale del pulsante
se button ≠ lastButtonif (button != lastButton) {Entra se lo stato del pulsante è cambiato
se button = 1if (button == 1) {Entra se il cambiamento è una pressione (da 0 a 1)
imposta ledState a non ledStateledState = !ledState;Trasforma 0 in 1 e 1 in 0
scrivi ledState sul pin 7digitalWrite(7, ledState);Porta il LED nel nuovo stato
attendi 50 msdelay(50);Salta il rimbalzo del contatto
imposta lastButton a buttonlastButton = button;Salva questa lettura per il giro successivo

Il cuore del programma sono i due blocchi se annidati. La condizione esterna button ≠ lastButton è vera solo nel giro in cui lo stato del pulsante cambia; nelle migliaia di giri in cui tieni premuto o non tocchi il pulsante non succede nulla. Un cambiamento può andare in due direzioni: pressione (da 0 a 1) o rilascio (da 1 a 0). La condizione interna button = 1 sceglie solo la pressione. Così il LED cambia una volta per pressione e per niente al rilascio. Nel codice gli if annidati si vedono come graffe dentro graffe. Nei blocchi il se interno si trova nel ramo «fai» di quello esterno, e si capisce a colpo d'occhio quale riga dipende da quale condizione.

Il blocco non ledState in C++ si scrive !ledState. Il punto esclamativo dà il contrario logico: il contrario di 0 è 1, quello di qualsiasi numero diverso da zero è 0. Assegnare a ledState il suo contrario inverte lo stato a ogni pressione. Il blocco successivo, «scrivi ledState sul pin 7», è la riga digitalWrite(7, ledState); poiché HIGH vale 1 e LOW vale 0, il valore della variabile si può scrivere direttamente sul pin. Alla fine lastButton riceve la lettura di questo giro, così il confronto del giro successivo è corretto. Se dimentichi questa assegnazione, lastButton resta sempre 0; finché tieni premuto, la condizione esterna è vera a ogni giro e il LED lampeggia velocissimo.

Il blocco attendi 50 ms non è decorativo, è una forma semplice di antirimbalzo (debounce). I contatti metallici di un pulsante, quando si chiudono, si aprono e chiudono più volte per qualche millisecondo; la scheda legge così in fretta che può scambiare una pressione per diverse, e il LED resta acceso o spento a caso. Attendere 50 ms dopo un cambiamento dà al rimbalzo il tempo di esaurirsi. Mentre delay() aspetta, la scheda non può fare altro; per temporizzare senza fermare il programma leggi millis() e delay().

Condizione analogica: luce notturna con LDR

Le condizioni non servono solo con HIGH e LOW. Nel progetto Luce notturna con LDR, il blocco «imposta value a lettura analogica A0» converte la tensione su A0, dove è collegata la LDR, in un numero tra 0 e 1023; in C++ è la riga value = analogRead(A0);. Poi il blocco se controlla value < 50. Se il valore è sotto 50 si considera buio e il LED su D13 si accende, altrimenti si spegne. La struttura è la stessa del progetto Push; cambia solo il confronto nello spazio della condizione.

Blocchi del progetto Luce notturna con LDR: lettura analogica A0 e condizione value < 50
La lettura analogica dà un numero da 0 a 1023; se value è minore di 50 il LED si accende, altrimenti si spegne.
C++ (Arduino IDE)
1int value;   // Işık okuması (0-1023) / Light reading (0-1023)
2
3void setup() {
4  pinMode(13, OUTPUT);   // LED çıkışı / LED output
5}
6
7void loop() {
8  value = analogRead(A0);   // Işık seviyesini oku / Read the light level
9
10  // Eşik 50: altı karanlık sayılır, hassasiyeti bu sayıyla ayarla
11  // Threshold 50: anything below counts as dark. Tune the sensitivity with this number
12  if (value < 50) {
13    digitalWrite(13, HIGH);   // Karanlık: LED yanar / Dark: LED on
14  } else {
15    digitalWrite(13, LOW);    // Aydınlık: LED söner / Bright: LED off
16  }
17}
18

A seconda della tua LDR e della resistenza nel circuito, la soglia di 50 può risultare troppo bassa o troppo alta per la tua stanza. Per trovare il numero giusto, usa prima il progetto Misurare l'intensità luminosa con LDR e osserva nel monitor seriale i valori con la luce e al buio, poi metti la soglia a metà. Se il valore oscilla proprio intorno alla soglia il LED può sfarfallare; usare due soglie diverse per accendere e spegnere risolve bene il problema. Come funziona una LDR lo trovi nell'articolo sensore di luce LDR.

Combinare condizioni: il blocco e e &&

A volte una condizione non basta. Nel progetto HC-SR04 Misura della distanza (display seriale) la distanza misurata viene stampata sul monitor seriale solo se è tra 3 cm e 100 cm. Nei blocchi due confronti vengono uniti fianco a fianco da un blocco e: «distance > minDistance e distance < maxDistance». In C++ la riga diventa if (distance > minDistance && distance < maxDistance). L'operatore && dà vero solo se entrambi i lati sono veri; se anche uno solo è falso, la condizione è falsa. Così i valori senza senso fuori dal campo del sensore non arrivano mai sullo schermo. In C++ «oppure» si scrive || e basta che una condizione sia vera. Puoi provare le tabelle di verità di AND, OR e NOT con lo strumento porte logiche.

Le stesse condizioni su ESP32: pull-up interna e logica invertita

Il progetto Controllo LED ESP32 con pulsante (Push) usa lo stesso blocco se su un ESP32, con due differenze. Il LED è su GPIO 5, il pulsante su GPIO 4, e al pin del pulsante viene data l'opzione di ingresso con pull-up del blocco del pin. In C++ è pinMode(BUTTON_PIN, INPUT_PULLUP);: una resistenza interna al chip porta il pin a HIGH e non serve una resistenza esterna. Questa volta il pulsante va a GND, quindi il pin legge LOW quando premi e la condizione diventa «leggi pin BUTTON_PIN = BASSO». Il progetto Controllo LED ESP32 con pulsante (Toggle) gestisce accensione e spegnimento con il blocco del tempo trascorso, millis(), invece di un'attesa di 50 ms, e unisce di nuovo due condizioni con un blocco e. I pin dell'ESP32 lavorano a 3,3 V; non collegare il pulsante a 5 V.

Errori frequenti e soluzioni

ErroreSintomoSoluzione
Nessuna resistenza di pull-downIl LED sfarfalla da solo e si accende avvicinando la manoMetti 10 kΩ tra D13 e GND, oppure usa INPUT_PULLUP e inverti la logica
Un solo uguale nella condizione: if (button = 1)Il LED è sempre acceso e ignora il pulsanteUsa == per i confronti
Punto e virgola alla fine della riga ifIl codice tra graffe gira a ogni giro qualunque sia la condizioneCancella il ; dopo if (…)
Piedini del pulsante dallo stesso latoIl pin legge sempre HIGH o sempre LOWUsa i piedini in diagonale
lastButton non aggiornato o manca l'attesaIl LED lampeggia tenendo premuto o resta a casoAggiungi lastButton = button e l'attesa di 50 ms
Considerare HIGH come premuto con INPUT_PULLUPIl LED funziona al contrario e si accende al rilascioCon la pull-up interna, LOW significa premuto
Soglia della LDR non adatta alla stanzaIl LED non si accende mai o resta sempre accesoOsserva il valore nel monitor seriale e scegli una nuova soglia

Aprire blocchi e codice fianco a fianco nell'app

Tutti i progetti di questo articolo sono tra i progetti a blocchi gratuiti dell'app BlueGrays. Attiva l'interruttore Mostra a blocchi nella sezione del codice di un progetto e il codice viene sostituito dallo stesso programma a blocchi; tocca l'immagine per aprirla a schermo intero. La scheda Capire i blocchi spiega il programma passo per passo: ogni passo mostra solo i suoi blocchi e cosa fanno, così puoi seguire i blocchi se annidati uno alla volta. Anche gli esempi di if/else e digitalRead della Guida al codice sono mostrati a blocchi. I blocchi non vengono caricati direttamente sulla scheda e per ora non puoi comporre programmi tuoi con i blocchi; sulla scheda va sempre il vero codice C++ del progetto, che copi nell'Arduino IDE e carichi. Se vuoi ripassare, le Domande del giorno ti propongono 5 domande ogni giorno, dal livello A1 al C2.

Ora che conosci le condizioni, il passo successivo è gestire ripetizioni e contatori: nella parte su cicli e variabili vedrai come «ripeti per sempre» si collega a loop() e il blocco di conteggio a un ciclo for. Nel frattempo, nell'app BlueGrays puoi guardare lo schema e il codice dei progetti LED con pulsante, luce notturna con LDR e pulsante su ESP32, passare alla vista a blocchi con Mostra a blocchi e alla spiegazione passo per passo con Capire i blocchi.

Domande frequenti

A cosa serve il blocco se nella programmazione a blocchi?

Il blocco se permette a un programma di prendere una decisione: se la condizione è vera vengono eseguiti i blocchi del ramo «fai», se è falsa quelli del ramo «altrimenti». Nei progetti Arduino si usa soprattutto per controllare se un pulsante è premuto o se il valore di un sensore ha superato una soglia. Il suo equivalente in C++ è l'istruzione if/else.

Qual è la differenza tra if ed else in Arduino?

if esegue il codice tra le sue graffe quando la condizione tra parentesi è vera. else è facoltativo e contiene il codice che gira solo quando la condizione è falsa. Senza else, quando la condizione è falsa non succede nulla e il programma passa alla riga successiva.

Qual è la differenza tra = e == in Arduino?

Un solo uguale (=) assegna un valore a una variabile, il doppio uguale (==) confronta due valori. Scrivere if (x = 1) assegna 1 a x e rende la condizione sempre vera; la forma corretta è if (x == 1). Nei blocchi il segno «=» del blocco di confronto viene tradotto in == nel codice.

Perché il LED di Arduino si accende senza premere il pulsante?

Molto probabilmente il pin del pulsante è flottante, cioè manca la resistenza di pull-down o di pull-up. Il pin legge allora i disturbi dell'ambiente e sembra HIGH o LOW a caso. Metti una resistenza da 10 kΩ tra il pin e GND, oppure usa pinMode(pin, INPUT_PULLUP) e collega il pulsante a GND.

Come accendere e spegnere un LED con un pulsante su Arduino?

Tieni lo stato del LED in una variabile (ledState) e la lettura precedente del pulsante in un'altra (lastButton). Quando lo stato del pulsante cambia e il nuovo stato è premuto, inverti lo stato con ledState = !ledState e scrivilo sul LED con digitalWrite. Aggiungi una breve attesa, per esempio 50 ms, per saltare il rimbalzo; il progetto Accendere e spegnere un LED con un pulsante fa proprio questo.

Posso caricare i blocchi di BlueGrays sul mio Arduino?

No, i blocchi non vengono caricati direttamente sulla scheda. Corrispondono uno a uno al vero codice del progetto e servono a capire il programma. Sulla scheda carichi sempre il codice C++ del progetto, copiandolo nell'Arduino IDE.

Vedi tutti i progetti
Accendere un LED con un pulsante (Push)
#9Principiante

Accendere un LED con un pulsante (Push)

Come un campanello: la luce resta accesa finché premi e si spegne quando lasci. L'Arduino ascolta il pulsante di continuo; mentre è premuto accende il LED, e appena togli il dito lo spegne. Con questo

4.8(113)
229
Accendere e spegnere un LED con un pulsante
#10Principiante

Accendere e spegnere un LED con un pulsante

Premi il pulsante una volta e la luce si accende, premilo di nuovo e si spegne, proprio come l'interruttore della tua stanza. L'Arduino si accorge di ogni pressione e porta il LED nello stato opposto,

4.8(100)
167
Luce notturna con LDR
#12Principiante

Luce notturna con LDR

Una piccola luce notturna che si accende da sola quando fa buio e si spegne quando arriva il mattino. Un sensore di luce misura quanto è illuminata la stanza, e l'Arduino accende il LED quando è abbas

4.8(102)
205
HC-SR04 Misura della distanza (display seriale)
#27Principiante

HC-SR04 Misura della distanza (display seriale)

Il sensore HC-SR04 funziona come un pipistrello che trova la strada al buio: manda un suono che non puoi sentire, ne ascolta l'eco e misura quanto è lontano l'oggetto davanti a sé. L'Arduino scrive qu

4.6(46)
71
Controllo LED ESP32 con pulsante (Push)
#104Principiante

Controllo LED ESP32 con pulsante (Push)

Il LED si accende quando il pulsante viene premuto e si spegne quando viene rilasciato. Mostra come vengono utilizzati il pin di ingresso digitale dell'ESP32 e la resistenza di pull-up interna. Grazie alla modalità INPUT_PULLUP, non è necessaria alcuna resistenza esterna.

4.6(36)
55
Controllo LED ESP32 con pulsante (Toggle)
#105Principiante

Controllo LED ESP32 con pulsante (Toggle)

Ogni volta che si preme il pulsante, lo stato del LED cambia: se è acceso si spegne, se è spento si accende. Classico schema toggle. Con il debounce puliamo il rumore meccanico del pulsante per garantire una singola commutazione con una sola pressione.

4.6(39)
57
Misurare l'intensità luminosa con LDR
#11Principiante

Misurare l'intensità luminosa con LDR

Vuoi vedere quanto è luminosa la tua stanza sotto forma di numero? L'LDR, un piccolo componente sensibile alla luce, misura la luce ambiente e l'Arduino scrive il valore sullo schermo del computer ogn

4.6(81)
139
LED lampeggiante
#1Principiante

LED lampeggiante

Il primissimo ciao dell'elettronica: accendere e spegnere un solo LED. L'Arduino accende e spegne il LED a intervalli brevissimi, così la luce lampeggia veloce. Vedi nel modo più semplice come la sche

4.6(188)
1127