ATLANTE / IMPARA FACENDO

Arduino.
Dal primo LED
al progetto solido.

Una guida pratica da zero alle competenze avanzate di programmazione: leggi, monta, modifica il codice e verifica il risultato.

16 lezioni14 sketch commentatiUNO R3
Comincia da zero →
Fotografia di una Arduino UNO R3 con connettore USB, microcontrollore e file di pin
La scheda di riferimento: UNO R3. Foto e licenza in fondo alla pagina.

Un percorso pratico, un passo alla volta

Non serve sapere programmare. Inizia dalle lezioni Base e passa oltre soltanto quando sai spiegare e ripetere la prova. Le sezioni Professionale insegnano metodo, test e documentazione: completarle non conferisce una qualifica professionale.

Occorrente iniziale: UNO R3, cavo USB dati, PC con Arduino IDE 2, breadboard, cavetti, LED rosso, resistenza 330 Ω, pulsante e potenziometro 10 kΩ. Le lezioni I²C e interrupt richiedono hardware aggiuntivo scelto e verificato separatamente.

Su Android puoi leggere la guida e usare il simulatore Atlante; questa guida non aggiunge compilazione o caricamento USB dal telefono. Il simulatore non esegue automaticamente tutti gli sketch del corso.

Scarica guida completa

Progressi conservati solo su questo dispositivo.

Guarda i componenti, segui i collegamenti

Breadboard vista sopra e sotto: le lamelle metalliche mostrano quali fori sono collegati
La breadboard, sopra e sotto: le lamelle uniscono gruppi di fori. Alcune barre di alimentazione possono essere interrotte: verifica il tuo modello.
D9, resistenza 330 ohm, anodo LED rosso, catodo e GND in serie
Le illustrazioni mostrano i collegamenti elettrici. Le posizioni dei blocchi non sono posizioni reali dei pin.

Due video per iniziare

Risorse del canale Arduino, in inglese. Controlla sul player la disponibilità di sottotitoli. Il video viene caricato da YouTube solo quando premi Riproduci; se non parte, usa il collegamento esterno. Riproduzione non verificata in questa sessione.

Preparare gli strumenti

Prima della lezione 1: orientati fra scheda e strumenti.

Apri su YouTube ↗

Il tuo primo circuito

Prima delle lezioni 2–3: osserva LED e pulsante.

Apri su YouTube ↗
Altri video ufficiali Arduino →

01 / Base

Il primo programma: dal PC al LED

Caricare un programma e riconoscere le sue due parti.

Uno sketch è il programma di Arduino. setup() viene eseguito una volta dopo accensione o reset; loop() viene richiamato continuamente. Le parentesi graffe delimitano un blocco, il punto e virgola chiude molte istruzioni. Il testo dopo // è un commento. Per cominciare usa soltanto il LED già sulla scheda: non serve costruire un circuito.

Illustrazione: Il primo programma: dal PC al LED
Illustrazione originale · tocca per aprire più grande.

Fai così

  1. Su un PC Windows, macOS o Linux installa Arduino IDE 2 dalla pagina ufficiale. Usa un cavo USB che trasmetta anche dati.
  2. Nel gestore schede installa Arduino AVR Boards; seleziona Arduino Uno e la porta della tua UNO R3. Conserva nel quaderno la versione del core.
  3. Crea uno sketch, sostituisci il contenuto con il programma qui sotto e premi Verifica. Poi premi Carica e osserva il LED L.
Componenti e collegamenti

UNO R3 collegata al PC via USB; nessun filo esterno.

Programma commentato

#include <Arduino.h>
// Atlante: esempio originale per UNO R3.
// Verificare core, cablaggio e hardware prima dell’uso.
void setup() {
  pinMode(LED_BUILTIN, OUTPUT); // LED L: uscita
}
void loop() {
  digitalWrite(LED_BUILTIN, HIGH);
  delay(400); // millisecondi acceso
  digitalWrite(LED_BUILTIN, LOW);
  delay(800); // millisecondi spento
}
Scarica .ino

pinMode sceglie il ruolo del pin. digitalWrite imposta HIGH o LOW. delay ferma il normale avanzamento del programma: per questo primo esempio va bene; più avanti lo elimineremo.

Adesso prova tu

Cambia 400 in 100 e 800 in 900. Prima prevedi il risultato, poi carica.

Come verificare

Il LED resta acceso circa 0,1 s e spento circa 0,9 s. Sai distinguere Verifica (compilazione) da Carica (scrittura sulla scheda).

Se qualcosa non funziona

Porta assente: controlla cavo dati e collegamento. Errore di compilazione: leggi il primo messaggio e la riga indicata. Upload fallito: verifica scheda e porta; non cambiare codice a caso.

Approfondimento ufficiale ↗

02 / Base

Variabili, costanti e LED esterno

Dare un nome ai pin e separare configurazione e comportamento.

Una costante descrive qualcosa che non deve cambiare durante il programma, come il numero di un pin. Una variabile conserva un valore che può cambiare. byte è utile per piccoli numeri non negativi; bool contiene true o false. Scegli nomi che spieghino il compito: ledSegnale è più chiaro di x. Una breadboard collega alcuni fori al suo interno: controlla i gruppi di contatti, non affidarti alla sola vicinanza.

Illustrazione: Variabili, costanti e LED esterno
Illustrazione originale · tocca per aprire più grande.

Fai così

  1. Scollega USB prima di spostare i fili. Inserisci LED e resistenza in serie.
  2. Collega il pin D9 alla resistenza, poi all’anodo del LED. Collega il catodo a GND.
  3. Carica lo sketch e modifica soltanto intervalloMs.
Componenti e collegamenti

D9 → resistenza 330 Ω → anodo LED rosso; catodo → GND. Un LED rosso con caduta indicativa 2 V assorbe circa (5−2)/330 = 9 mA. La caduta reale dipende dal componente.

Programma commentato

#include <Arduino.h>
// Atlante: esempio originale per UNO R3.
// Verificare core, cablaggio e hardware prima dell’uso.
const byte ledSegnale = 9;
const unsigned long intervalloMs = 500;
bool acceso = false;
void setup() { pinMode(ledSegnale, OUTPUT); }
void loop() {
  acceso = !acceso; // inverte true e false
  digitalWrite(ledSegnale, acceso ? HIGH : LOW);
  delay(intervalloMs);
}
Scarica .ino

const protegge il nome da assegnazioni successive. ! inverte un valore logico. L’espressione condizione ? valore1 : valore2 sceglie il valore da scrivere.

Adesso prova tu

Rinomina ledSegnale in luceBanco in ogni punto. Imposta 250 ms.

Come verificare

La compilazione riesce; il periodo completo è 500 ms, non 250 ms.

Se qualcosa non funziona

LED spento: controlla polarità, resistenza e GND. Non collegare il LED direttamente fra un pin e GND. Due terminali nella stessa fila collegata possono cortocircuitare il componente.

Approfondimento ufficiale ↗

03 / Base

Pulsante: ingresso e decisioni

Leggere un ingresso e comandare un’uscita con if.

Con INPUT_PULLUP il pin ha uno stato definito quando il pulsante è aperto. Premendo, il collegamento a GND porta la lettura a LOW. La variabile premuto traduce questo livello elettrico in un significato: true vuol dire premuto. In C++, = assegna un valore; == confronta due valori. if esegue un blocco quando la condizione è vera.

Illustrazione: Pulsante: ingresso e decisioni
Illustrazione originale · tocca per aprire più grande.

Fai così

  1. Collega un contatto del pulsante a D2 e l’altro a GND. Per pulsanti a quattro piedini identifica prima i contatti già uniti.
  2. Carica il codice. Premi e rilascia: il LED integrato segue il contatto.
  3. Nel simulatore aggiungi un pulsante e un LED, poi osserva i nomi delle variabili nel codice generato.
Componenti e collegamenti

D2 → pulsante → GND; LED integrato. Nessuna resistenza esterna di pull-up in questo esempio.

Programma commentato

#include <Arduino.h>
// Atlante: esempio originale per UNO R3.
// Verificare core, cablaggio e hardware prima dell’uso.
const byte pulsante = 2;
void setup() {
  pinMode(pulsante, INPUT_PULLUP);
  pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
  bool premuto = (digitalRead(pulsante) == LOW);
  if (premuto) digitalWrite(LED_BUILTIN, HIGH);
  else digitalWrite(LED_BUILTIN, LOW);
}
Scarica .ino

Il confronto == LOW produce un bool. Il programma legge e aggiorna continuamente: non conserva l’accensione dopo il rilascio.

Adesso prova tu

Inverti il comportamento: LED acceso soltanto con pulsante rilasciato.

Come verificare

Premuto: LED spento; rilasciato: LED acceso. Sai spiegare perché LOW può significare true.

Se qualcosa non funziona

Ingresso casuale: controlla INPUT_PULLUP e massa. Il rimbalzo meccanico diventa importante quando conti pressioni o cambi stato: verrà gestito nella lezione 8.

Approfondimento ufficiale ↗

04 / Base

Leggere un valore analogico

Osservare misure nel monitor seriale e distinguere numero e unità.

analogRead su UNO R3 restituisce un conteggio a 10 bit, da 0 a 1023. Non è automaticamente una temperatura o una tensione precisa. Per trasformarlo in una grandezza servono riferimento, scala e caratteristiche del sensore. Inizia con un potenziometro da 10 kΩ: il cursore fornisce una tensione regolabile. Serial invia informazioni al PC; monitor e programma devono usare la stessa velocità.

Illustrazione: Leggere un valore analogico
Illustrazione originale · tocca per aprire più grande.

Fai così

  1. Collega i due terminali esterni del potenziometro a 5 V e GND; il cursore centrale va ad A0.
  2. Carica e apri Monitor seriale a 115200 baud.
  3. Ruota lentamente e annota minimo, centro e massimo.
Componenti e collegamenti

Potenziometro 10 kΩ: estremi a 5 V/GND, cursore ad A0. Valori riferiti a UNO R3; non trasferire 5 V a una scheda a 3,3 V.

Programma commentato

#include <Arduino.h>
// Atlante: esempio originale per UNO R3.
// Verificare core, cablaggio e hardware prima dell’uso.
void setup() { Serial.begin(115200); }
void loop() {
  int conteggio = analogRead(A0);
  Serial.print("ADC=");
  Serial.println(conteggio);
  delay(100);
}
Scarica .ino

int contiene il conteggio. print continua sulla stessa riga; println aggiunge un fine riga. Il ritardo rende leggibile l’uscita seriale.

Adesso prova tu

Aggiungi una variabile bool sopraSoglia = conteggio >= 600 e stampala dopo il conteggio.

Come verificare

Intorno a metà corsa il valore è vicino a 512, con tolleranze. Non chiamare la lettura “gradi” senza una conversione verificata.

Se qualcosa non funziona

Valori che saltano: controlla cursore e GND. Testo incomprensibile: controlla i baud. Non superare i limiti elettrici dell’ingresso.

Approfondimento ufficiale ↗

05 / Intermedio

PWM: regolare la luminosità

Trasformare una lettura in un comando di uscita.

PWM alterna velocemente acceso e spento. Cambia il rapporto fra tempo acceso e periodo, detto duty cycle. Su UNO R3 analogWrite usa normalmente valori da 0 a 255 sui pin PWM: non è un’uscita analogica continua. Qui usiamo D9 e convertiamo il conteggio 0–1023 in 0–255. Non alimentare motori o carichi di potenza direttamente da un pin.

Illustrazione: PWM: regolare la luminosità
Illustrazione originale · tocca per aprire più grande.

Fai così

  1. Mantieni il potenziometro su A0. Aggiungi il LED esterno con resistenza come nella lezione 2.
  2. Carica il codice; ruota il potenziometro e osserva la luce.
  3. Confronta valori minimi, centrali e massimi. La percezione della luminosità non è lineare.
Componenti e collegamenti

Potenziometro su A0; D9 → 330 Ω → LED rosso → GND.

Programma commentato

#include <Arduino.h>
// Atlante: esempio originale per UNO R3.
// Verificare core, cablaggio e hardware prima dell’uso.
const byte ledPwm = 9;
void setup() { pinMode(ledPwm, OUTPUT); }
void loop() {
  int lettura = analogRead(A0);
  int comando = lettura / 4; // 0..1023 diventa 0..255
  analogWrite(ledPwm, comando);
}
Scarica .ino

La divisione intera scarta la parte frazionaria. analogWrite mantiene il PWM mentre loop continua. D9 è una scelta specifica per UNO R3.

Adesso prova tu

Limita il comando massimo a 128. Confronta il risultato con 255.

Come verificare

Zero spegne; 255 imposta il massimo. Sai distinguere conteggio ADC, comando PWM e tensione misurata.

Se qualcosa non funziona

Un pin non PWM non offre la stessa regolazione. Se aggiungi librerie che usano timer, verifica eventuali conflitti con PWM.

Approfondimento ufficiale ↗

06 / Intermedio

Funzioni, cicli e array

Ridurre le ripetizioni senza perdere chiarezza.

Una funzione raccoglie un compito. Un parametro è un valore che le passi; return restituisce il risultato. Un array conserva più elementi dello stesso tipo. Gli indici partono da zero: per tre elementi sono 0, 1 e 2. Un ciclo for è comodo per elaborare una piccola quantità di dati; non deve però bloccare per molto tempo il resto del programma.

Fai così

  1. Usa solo la scheda USB. Leggi la funzione media prima di setup.
  2. Prevedi il valore calcolato dai tre numeri nell’array.
  3. Apri il monitor a 115200 e confronta previsione e risultato.
Componenti e collegamenti

Nessun componente esterno: esempio di organizzazione C++.

Programma commentato

#include <Arduino.h>
// Atlante: esempio originale per UNO R3.
// Verificare core, cablaggio e hardware prima dell’uso.
int media(const int valori[], byte quanti) {
  if (quanti == 0) return 0;
  long somma = 0;
  for (byte i = 0; i < quanti; i++) somma += valori[i];
  return somma / quanti;
}
void setup() {
  Serial.begin(115200);
  const int campioni[] = {100, 200, 300};
  Serial.println(media(campioni, 3));
}
void loop() {}
Scarica .ino

const impedisce alla funzione di modificare i valori ricevuti. long rende la somma più ampia di int su UNO R3. La dimensione passata deve corrispondere agli elementi disponibili.

Adesso prova tu

Sostituisci i campioni con 0, 512 e 1023. Spiega l’arrotondamento.

Come verificare

Il primo risultato è 200; il secondo è 511 per divisione intera. Non accedi mai all’indice 3 di un array da tre elementi.

Se qualcosa non funziona

Dimensioni errate possono leggere memoria estranea senza un errore evidente. Non usare <= quanti nel ciclo.

Approfondimento ufficiale ↗

07 / Intermedio

Fare due cose insieme con millis

Eliminare le attese bloccanti dal ciclo principale.

Non serve un secondo processore per alternare attività brevi. loop legge un pulsante continuamente e controlla se è passato abbastanza tempo per cambiare il LED. millis fornisce un contatore di millisecondi. Su UNO R3 si riavvolge dopo circa 49,7 giorni: il confronto mediante sottrazione unsigned gestisce il passaggio, purché il controllo sia eseguito regolarmente e l’intervallo sia appropriato.

Illustrazione: Fare due cose insieme con millis
Illustrazione originale · tocca per aprire più grande.

Fai così

  1. Collega il pulsante D2–GND.
  2. Carica: premendo il pulsante il lampeggio diventa più rapido.
  3. Cerca nel codice tutte le chiamate a delay: non ce ne sono.
Componenti e collegamenti

D2 → pulsante → GND; LED integrato.

Programma commentato

#include <Arduino.h>
// Atlante: esempio originale per UNO R3.
// Verificare core, cablaggio e hardware prima dell’uso.
const byte pulsante = 2;
unsigned long ultimo = 0;
bool acceso = false;
void setup() {
  pinMode(pulsante, INPUT_PULLUP);
  pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
  unsigned long ora = millis();
  unsigned long periodo = digitalRead(pulsante) == LOW ? 120UL : 700UL;
  if (ora - ultimo >= periodo) {
    ultimo = ora;
    acceso = !acceso;
    digitalWrite(LED_BUILTIN, acceso ? HIGH : LOW);
  }
}
Scarica .ino

ultimo conserva quando è avvenuto l’ultimo cambio. UL indica una costante unsigned long. Ogni passaggio di loop resta breve; questo non è parallelismo hardware.

Adesso prova tu

Prevedi quanto impiega il LED a reagire al cambio di periodo. Aggiungi una stampa ogni secondo con un secondo timestamp.

Come verificare

Il pulsante influenza il ritmo senza attendere un delay. Sai spiegare perché ora >= ultimo + periodo è meno robusto al riavvolgimento.

Se qualcosa non funziona

Non usare int per millis. Una stampa seriale eccessiva o una libreria bloccante possono comunque rallentare loop.

Approfondimento ufficiale ↗

08 / Intermedio

Una pressione, un evento: antirimbalzo

Cambiare stato una sola volta per pressione.

Un pulsante reale può aprire e chiudere il contatto più volte in pochi millisecondi. Il programma mantiene una lettura grezza e uno stato stabile: accetta la nuova lettura solo dopo 30 ms senza variazioni. Il cambio del LED avviene sul fronte che porta lo stato stabile a premuto, non mentre il pulsante rimane tenuto.

Illustrazione: Una pressione, un evento: antirimbalzo
Illustrazione originale · tocca per aprire più grande.

Fai così

  1. Riutilizza D2 e il LED integrato.
  2. Premi lentamente dieci volte: ogni pressione deve invertire il LED una sola volta.
  3. Tieni il pulsante premuto due secondi; il LED non deve continuare a cambiare.
Componenti e collegamenti

D2 → pulsante → GND con INPUT_PULLUP.

Programma commentato

#include <Arduino.h>
// Atlante: esempio originale per UNO R3.
// Verificare core, cablaggio e hardware prima dell’uso.
const byte pulsante = 2;
bool grezzo = HIGH, stabile = HIGH, acceso = false;
unsigned long cambiato = 0;
void setup() {
  pinMode(pulsante, INPUT_PULLUP);
  pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
  unsigned long ora = millis();
  bool lettura = digitalRead(pulsante);
  if (lettura != grezzo) { grezzo = lettura; cambiato = ora; }
  if (ora - cambiato >= 30 && stabile != grezzo) {
    stabile = grezzo;
    if (stabile == LOW) acceso = !acceso;
  }
  digitalWrite(LED_BUILTIN, acceso ? HIGH : LOW);
}
Scarica .ino

!= significa diverso. cambiato viene aggiornato a ogni variazione grezza, facendo ripartire il tempo di stabilizzazione.

Adesso prova tu

Confronta 5, 30 e 100 ms. Registra conteggi errati e ritardo percepito; non assumere che lo stesso valore vada bene per ogni interruttore.

Come verificare

Una pressione mantenuta genera un evento. Una sequenza di rimbalzi più breve di 30 ms non viene accettata come pressioni multiple.

Se qualcosa non funziona

Contare ogni LOW dentro loop produce migliaia di eventi. L’antirimbalzo software non risolve cablaggi errati o disturbi elettrici fuori specifica.

Approfondimento ufficiale ↗

09 / Intermedio

Sensori: filtro, isteresi e calibrazione

Evitare che un’uscita oscilli vicino a una soglia.

Un filtro riduce le variazioni rapide ma introduce ritardo. L’isteresi usa due soglie: si accende sopra 650 e si spegne sotto 550; nella fascia intermedia conserva lo stato. Sono compiti diversi. La calibrazione richiede un riferimento noto e più punti: un valore ADC non diventa una misura affidabile soltanto perché è stato mediato.

Illustrazione: Sensori: filtro, isteresi e calibrazione
Illustrazione originale · tocca per aprire più grande.

Fai così

  1. Collega il potenziometro ad A0.
  2. Apri Monitor seriale a 115200; osserva valore grezzo, filtrato e stato.
  3. Muovi attorno a 600, poi oltre 650 e sotto 550.
Componenti e collegamenti

Potenziometro 10 kΩ su A0; LED integrato.

Programma commentato

#include <Arduino.h>
// Atlante: esempio originale per UNO R3.
// Verificare core, cablaggio e hardware prima dell’uso.
float filtrato = 0;
bool acceso = false;
unsigned long ultimo = 0;
void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  Serial.begin(115200);
  filtrato = analogRead(A0);
}
void loop() {
  unsigned long ora = millis();
  if (ora - ultimo < 100) return;
  ultimo = ora;
  int grezzo = analogRead(A0);
  filtrato += 0.2f * (grezzo - filtrato);
  if (filtrato >= 650) acceso = true;
  else if (filtrato <= 550) acceso = false;
  digitalWrite(LED_BUILTIN, acceso ? HIGH : LOW);
  Serial.print(grezzo); Serial.print(',');
  Serial.print(filtrato); Serial.print(','); Serial.println(acceso);
}
Scarica .ino

Il nuovo valore si avvicina del 20% alla lettura a ogni campione. return interrompe questa chiamata di loop, non ferma Arduino.

Adesso prova tu

Confronta coefficiente 0,2 e 0,5 con lo stesso gradino del potenziometro. Registra il tempo prima del cambio di stato.

Come verificare

Fra 550 e 650 lo stato dipende dalla storia precedente. Il filtro non elimina la necessità di verificare unità e sensore.

Se qualcosa non funziona

Soglie uguali annullano l’isteresi. Una misura piatta può indicare un collegamento interrotto: non considerarla automaticamente valida.

Approfondimento ufficiale ↗

10 / Avanzato

Comandi seriali e gestione degli errori

Definire un piccolo protocollo controllabile e non bloccante.

Un protocollo chiarisce i comandi accettati e le risposte. Questo esempio accetta un carattere alla volta: 1 accende, 0 spegne, ? legge lo stato. Non serve attendere un’intera frase o accumulare testo senza limite. I terminatori di riga vengono ignorati. Ogni altro carattere produce un errore esplicito; l’uscita mantiene il suo stato.

Fai così

  1. Collega solo USB e apri Monitor seriale a 115200.
  2. Invia 1, ?, 0 e infine X.
  3. Controlla che un comando sconosciuto non cambi il LED.
Componenti e collegamenti

Solo USB e LED integrato; UART via convertitore USB della UNO R3.

Programma commentato

#include <Arduino.h>
// Atlante: esempio originale per UNO R3.
// Verificare core, cablaggio e hardware prima dell’uso.
bool acceso = false;
void setup() {
  Serial.begin(115200);
  pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
  if (Serial.available() <= 0) return;
  char comando = Serial.read();
  if (comando == '\r' || comando == '\n') return;
  if (comando == '1') acceso = true;
  else if (comando == '0') acceso = false;
  else if (comando != '?') { Serial.println("ERR comando"); return; }
  digitalWrite(LED_BUILTIN, acceso ? HIGH : LOW);
  Serial.println(acceso ? "ON" : "OFF");
}
Scarica .ino

Le virgolette singole indicano un carattere; quelle doppie una stringa. available controlla i dati già presenti: loop non aspetta una risposta.

Adesso prova tu

Scrivi una tabella richiesta/risposta. Prova righe vuote, sequenze 10? e caratteri non previsti.

Come verificare

1? risponde ON due volte; X risponde ERR comando e non cambia lo stato. Il formato è documentato prima di collegare un altro programma.

Se qualcosa non funziona

Inviare parole intere a questo protocollo genera più comandi o errori: non è un parser di frasi. Per messaggi lunghi usa buffer limitati, scadenze e validazione.

Approfondimento ufficiale ↗

11 / Avanzato

I²C: trovare un dispositivo e usare una libreria

Separare collegamento elettrico, indirizzo e interpretazione dei dati.

I²C usa SDA e SCL con indirizzi. Su UNO R3 SDA corrisponde ad A4 e SCL ad A5. Uno scanner può rilevare una risposta ma non identifica con certezza modello o significato dei registri. Per un sensore serve la libreria corretta per la variante e un esempio del produttore. Pull-up e livelli devono essere compatibili: un chip a 3,3 V non è automaticamente compatibile con il bus a 5 V.

Fai così

  1. Prima prova senza sensori: devono comparire zero risposte.
  2. Scegli un breakout esplicitamente compatibile con UNO R3 e controlla alimentazione e pull-up nel suo manuale. Scollega USB durante il montaggio.
  3. Collega SDA, SCL e GND; alimenta come da manuale. Poi rileva l’indirizzo e confrontalo con quello documentato.
Componenti e collegamenti

UNO R3: A4/SDA e A5/SCL; GND comune. Alimentazione e adattamento dei livelli dipendono dal breakout scelto.

Programma commentato

#include <Arduino.h>
// Atlante: esempio originale per UNO R3.
// Verificare core, cablaggio e hardware prima dell’uso.
#include <Wire.h>
void setup() {
  Serial.begin(115200);
  Wire.begin();
  Wire.setWireTimeout(25000, true); // core AVR con timeout Wire
  byte trovati = 0;
  for (byte indirizzo = 8; indirizzo < 120; indirizzo++) {
    Wire.beginTransmission(indirizzo);
    byte esito = Wire.endTransmission();
    if (esito == 0) {
      Serial.print("Risposta 0x"); Serial.println(indirizzo, HEX);
      trovati++;
    }
    if (Wire.getWireTimeoutFlag()) {
      Serial.println("Timeout bus: controllare i collegamenti");
      Wire.clearWireTimeoutFlag();
      break;
    }
  }
  Serial.print("Totale: "); Serial.println(trovati);
}
void loop() {}
Scarica .ino

La scansione avviene una volta in setup. endTransmission restituisce un codice: zero indica un ACK. Le API di timeout sono specifiche del core: controlla che la tua versione le supporti.

Adesso prova tu

Annota indirizzo, codice esito, modello e versione libreria. Aggiungi una lettura solo dopo aver consultato l’esempio ufficiale del sensore.

Come verificare

Lo scanner senza dispositivi stampa Totale: 0. Un ACK non basta a dichiarare che temperatura o pressione siano corrette.

Se qualcosa non funziona

Due sensori con lo stesso indirizzo possono entrare in conflitto. Un bus bloccato o senza pull-up richiede verifica del cablaggio; ripetere all’infinito non è recupero degli errori.

Approfondimento ufficiale ↗

12 / Avanzato

Interrupt e dati condivisi

Contare eventi brevi mantenendo la routine di interrupt minima.

Un interrupt richiama una funzione quando accade un evento. Su UNO R3 D2 e D3 supportano gli interrupt esterni tramite digitalPinToInterrupt. La routine deve durare poco: aggiorna un contatore e torna. volatile indica che il valore può cambiare fuori dal flusso normale, ma non rende atomica una lettura a più byte su un processore a 8 bit.

Fai così

  1. Usa un generatore di impulsi compatibile 0–5 V su D2 con GND comune; non collegare tensioni negative o superiori ai limiti.
  2. In alternativa simula impulsi software nei test: un pulsante non filtrato produce conteggi da rimbalzo.
  3. Osserva il conteggio a intervalli di un secondo sul monitor.
Componenti e collegamenti

D2 ingresso impulsi; GND comune. Nessun carico controllato.

Programma commentato

#include <Arduino.h>
// Atlante: esempio originale per UNO R3.
// Verificare core, cablaggio e hardware prima dell’uso.
volatile unsigned long impulsi = 0;
unsigned long ultimo = 0;
void contaImpulso() { impulsi++; }
void setup() {
  Serial.begin(115200);
  pinMode(2, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(2), contaImpulso, FALLING);
}
void loop() {
  unsigned long ora = millis();
  if (ora - ultimo < 1000) return;
  ultimo = ora;
  noInterrupts();
  unsigned long copia = impulsi;
  interrupts();
  Serial.println(copia);
}
Scarica .ino

La sezione critica copia il contatore in poche istruzioni. La stampa avviene dopo aver riabilitato gli interrupt. Questo schema si usa qui nel normale loop, con interrupt inizialmente abilitati.

Adesso prova tu

Fornisci dieci impulsi puliti e verifica l’incremento. Documenta la frequenza provata, senza estendere il risultato a frequenze mai misurate.

Come verificare

La routine non contiene delay o Serial. Sai spiegare la differenza fra volatile e accesso atomico.

Se qualcosa non funziona

Un contatto meccanico non filtrato non genera un solo impulso per pressione. Disabilitare gli interrupt troppo a lungo può perdere eventi e interferire con altre funzioni.

Approfondimento ufficiale ↗

13 / Avanzato

Progetto completo: monitor con stati

Integrare ingresso, soglie, stato iniziale e ripristino manuale.

Una macchina a stati assegna significato alle situazioni. Questo monitor didattico parte disarmato. Il pulsante deve essere rilasciato, poi premuto stabilmente per armare. Una lettura almeno 700 porta in allarme; l’allarme resta memorizzato. Una pressione, con lettura non superiore a 600, riconosce l’allarme e torna disarmato. Il LED lampeggia quando armato e resta acceso in allarme. Non è un sistema di protezione.

Illustrazione: Progetto completo: monitor con stati
Illustrazione originale · tocca per aprire più grande.

Fai così

  1. Monta potenziometro A0 e pulsante D2–GND. Usa il LED integrato.
  2. Esegui le prove in ordine: avvio, rilascio/pressione, superamento soglia, diminuzione della lettura, riconoscimento.
  3. Prova anche a tenere premuto il pulsante mentre riavvii: non deve armarsi da solo.
Componenti e collegamenti

Potenziometro 10 kΩ: 5 V/GND e cursore A0. Pulsante D2–GND. Uscita LED integrato.

Programma commentato

#include <Arduino.h>
// Atlante: esempio originale per UNO R3.
// Verificare core, cablaggio e hardware prima dell’uso.
enum Stato { DISARMATO, ARMATO, ALLARME };
Stato stato = DISARMATO;
bool grezzo = HIGH, stabile = HIGH, rilascioVisto = false;
unsigned long cambiato = 0;
void setup() {
  pinMode(2, INPUT_PULLUP);
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW);
}
void loop() {
  unsigned long ora = millis();
  bool letturaPulsante = digitalRead(2);
  bool pressione = false;
  if (letturaPulsante != grezzo) { grezzo = letturaPulsante; cambiato = ora; }
  if (ora - cambiato >= 30) {
    if (grezzo == HIGH) rilascioVisto = true;
    if (stabile != grezzo) {
      stabile = grezzo;
      pressione = (stabile == LOW && rilascioVisto);
    }
  }
  int misura = analogRead(A0);
  switch (stato) {
    case DISARMATO: if (pressione) stato = ARMATO; break;
    case ARMATO: if (misura >= 700) stato = ALLARME; break;
    case ALLARME: if (pressione && misura <= 600) stato = DISARMATO; break;
  }
  bool led = stato == ALLARME || (stato == ARMATO && (ora / 300) % 2 == 0);
  digitalWrite(LED_BUILTIN, led ? HIGH : LOW);
}
Scarica .ino

enum assegna nomi agli stati. switch rende esplicite le transizioni consentite. Nessun comando deve avere effetti non descritti dalla tabella di stato.

Adesso prova tu

Disegna la tabella stato/evento/stato successivo. Verifica 699, 700, 601 e 600 conteggi. Registra il comportamento anche dopo reset.

Come verificare

La lettura bassa da sola non cancella l’allarme. Il pulsante mantenuto al riavvio non arma; dopo rilascio e nuova pressione può armare.

Se qualcosa non funziona

Il progetto non rileva affidabilmente il distacco di un sensore analogico: una futura funzione diagnostica richiede hardware e criteri specifici. Non usare per comandare impianti o protezioni.

Approfondimento ufficiale ↗

14 / Professionale

Test automatici, memoria e struttura del progetto

Dimostrare cosa funziona e conoscere i limiti della verifica.

Prima definisci i requisiti osservabili, poi separa la logica pura dall’hardware. La funzione decide non legge pin: riceve dati e restituisce una scelta. È più facile provarla con valori di confine. Un test che stampa OK non prova alimentazione, cablaggio o comportamento temporale. Su UNO R3 la memoria è limitata: controlla il rapporto di compilazione e evita allocazioni dinamiche ripetute in applicazioni lunghe.

Fai così

  1. Compila ed esegui lo sketch di test: il monitor deve riportare OK.
  2. Cambia volontariamente >= in > e verifica che venga segnalato KO. Poi correggi.
  3. Nel progetto finale separa configurazione pin, acquisizione, logica e uscita in funzioni; conserva una versione funzionante prima di modificare.
Componenti e collegamenti

Solo scheda USB; test della logica, non del sensore.

Programma commentato

#include <Arduino.h>
// Atlante: esempio originale per UNO R3.
// Verificare core, cablaggio e hardware prima dell’uso.
bool decide(bool precedente, int valore) {
  if (valore >= 650) return true;
  if (valore <= 550) return false;
  return precedente;
}
void setup() {
  Serial.begin(115200);
  bool ok = !decide(false, 550) && decide(false, 650)
    && decide(true, 600) && !decide(false, 600);
  Serial.println(ok ? "OK" : "KO");
}
void loop() {}
Scarica .ino

I quattro casi verificano soglia inferiore, superiore e memoria nella fascia intermedia. Il test di mutazione volontaria controlla che la prova sia capace di trovare un errore.

Adesso prova tu

Aggiungi casi 0, 549, 551, 649, 651 e 1023. Esporta tabella con ingresso, stato precedente, atteso e osservato.

Come verificare

Il difetto introdotto deve far fallire almeno una prova. Sai distinguere test logici, compilazione per la scheda e test hardware.

Se qualcosa non funziona

Non chiamare “validato” un progetto perché compila. La memoria libera stimata non dimostra assenza di errori nello stack o negli accessi agli array.

Approfondimento ufficiale ↗

15 / Professionale

Bus, librerie e portabilità: il passo successivo

Portare un progetto su un altro dispositivo senza ipotesi nascoste.

UART, I²C e SPI risolvono esigenze diverse. UART scambia flussi di byte; I²C indirizza periferiche su due segnali; SPI usa clock, dati e selezione del dispositivo. Il protocollo non garantisce compatibilità di tensione. Una libreria nasconde registri e sequenze, ma va scelta per chip e scheda esatti. Il porting da UNO R3 a ESP32 o UNO R4 richiede verifiche: numerazione pin, tensioni, ADC, PWM, timer, dimensioni dei tipi e API possono cambiare.

Fai così

  1. Scegli un solo modulo con datasheet, scheda breakout identificabile e libreria mantenuta. Registra versione, dipendenze e licenza.
  2. Compila prima l’esempio minimo del produttore per la scheda esatta. Controlla errori di inizializzazione e assenza del modulo.
  3. Integra una funzione alla volta nel progetto. Misura durata delle chiamate e comportamento quando il bus non risponde.
Componenti e collegamenti

Cablaggio solo dal datasheet della variante scelta. Nessun esempio universale di collegamento valido per tutti i moduli.

Per un driver robusto definisci almeno begin, acquisisci e statoErrore. Non riavviare indefinitamente senza una scadenza e un messaggio diagnostico.

Adesso prova tu

Prepara una matrice: scheda, core, libreria, pin, alimentazione, esito compilazione, esito hardware. Lascia “non provato” dove manca una misura.

Come verificare

Un’altra persona riesce a riprodurre la configurazione senza indovinare il modello del sensore. I moduli non provati restano dichiarati tali.

Se qualcosa non funziona

Non scambiare pin con etichetta simile per equivalenti. Wi-Fi e aggiornamenti remoti richiedono gestione credenziali, autenticazione, errori di rete e aggiornamenti verificabili.

Approfondimento ufficiale ↗

16 / Professionale

Consegna professionale: progetto riproducibile

Trasformare il prototipo in una consegna verificabile.

Un progetto professionale comprende requisiti, codice, schema elettrico, distinta materiali, versioni, piano di prova e limiti. Il fatto che un prototipo funzioni una volta non ne dimostra affidabilità. Definisci comportamento all’avvio, perdita alimentazione, ingresso fuori intervallo, comunicazione assente e ripristino. La breadboard è utile per imparare ma non equivale a un assemblaggio qualificato per esercizio continuo.

Fai così

  1. Usa il monitor della lezione 13 come progetto finale. Scrivi cinque requisiti misurabili e una tabella delle transizioni.
  2. Archivia sketch, schema e distinta con revisione. Registra scheda, core, IDE e strumenti di misura. Conserva il progetto in Git o in copie versionate.
  3. Esegui il piano di prova con risultati attesi/osservati. Usa il quaderno Academy per relazione e dati; documenta anche gli esiti negativi.
  4. Per impiego reale fai valutare alimentazione, driver, protezioni, EMC, ambiente e requisiti applicabili da competenze adeguate al prodotto.
Componenti e collegamenti

Il percorso usa solo USB e circuiti didattici a bassa tensione. Motori, relè e potenza richiedono driver e verifiche specifiche.

La competenza professionale si dimostra con progetti e prove. La percentuale del corso indica soltanto le tappe che hai segnato come completate; non è una certificazione.

Adesso prova tu

Consegna a un’altra persona il progetto completo. Chiedile di riprodurre configurazione, caricamento e prove senza spiegazioni aggiuntive; annota ciò che manca.

Come verificare

Consegna minima: requisiti, codice versionato, schema, distinta, istruzioni di compilazione, tabella prove, risultati, limiti e procedura di ripristino. Nessun campo critico lasciato implicito.

Se qualcosa non funziona

Una libreria aggiornata può cambiare il comportamento: ripeti i test coinvolti. Non pubblicare chiavi, password o dati personali nel repository.

Approfondimento ufficiale ↗

Le parole da conoscere

Sketch
Il programma che compili e carichi sulla scheda.
Ingresso / uscita
Un ingresso legge un segnale; un’uscita genera un comando.
GND
Riferimento comune del circuito: non è automaticamente la terra di protezione.
Variabile
Un nome associato a un valore che il programma usa o modifica.
ADC / PWM
ADC converte una tensione in un numero; PWM regola il rapporto fra tempo acceso e spento.
Compilazione / caricamento / simulazione
Trasformare il codice, trasferirlo alla scheda e modellarne un comportamento sono tre operazioni distinte.
Test di confine
Una prova subito sotto, sulla e subito sopra una soglia.

Dal corso al tuo progetto

Conserva obiettivi, versioni, misure e risultati. Il quaderno di Atlante ti aiuta a preparare una relazione riproducibile.

Apri il quaderno progetti →

Verifica del materiale: 15 ottobre 2026. Sketch controllati con compilatore C++ host e API Arduino simulate; non compilati per AVR e non provati su una scheda fisica. Le prove richieste nelle lezioni restano da eseguire dall’allievo. I contenuti non sostituiscono datasheet e istruzioni della variante hardware scelta.