Progettazione e Sviluppo con Arduino
Questa sezione copre la progettazione e lo sviluppo con Arduino, dalla lettura di sensori al controllo di attuatori, fino all’interfacciamento con Raspberry Pi via seriale e nRF24.
1. Cos’è Arduino
Section titled “1. Cos’è Arduino”Arduino è una piattaforma elettronica open-source basata su microcontrollori (ATmega328P su Arduino Uno). Serve per creare progetti interattivi che leggono dati da sensori e controllano attuatori.
Modelli principali
Section titled “Modelli principali”| Modello | MCU | Pin digitali | Pin analogici | Uso tipico |
|---|---|---|---|---|
| Uno R3 | ATmega328P (16 MHz) | 14 (6 PWM) | 6 | Progetti didattici e prototipi |
| Nano | ATmega328P (16 MHz) | 14 (6 PWM) | 8 | Progetti compatti |
| Mega 2560 | ATmega2560 (16 MHz) | 54 (15 PWM) | 16 | Progetti complessi |
| Leonardo | ATmega32U4 (16 MHz) | 20 (7 PWM) | 12 | HID (tastiera/mouse) |
Scheda Arduino Uno Rev3
Section titled “Scheda Arduino Uno Rev3”
Schema piedinatura Arduino Uno
Section titled “Schema piedinatura Arduino Uno”
Fonte: Arduino Store — UNO Rev3
Legenda:
~= pin con uscita PWMD0-D13= pin digitaliA0-A5= pin analogici (anche I²C su A4=SDA, A5=SCL)TX/RX= seriale hardware (collegata alla USB)
2. L’IDE di Arduino
Section titled “2. L’IDE di Arduino”Installazione
Section titled “Installazione”- Scarica l’IDE da arduino.cc
- Installa e avvia
- Collega Arduino via USB
- Seleziona la scheda: Strumenti → Scheda → Arduino Uno
- Seleziona la porta: Strumenti → Porta → COMx (Windows) o
/dev/ttyACMx(Linux)
Alternative: VS Code + PlatformIO
Section titled “Alternative: VS Code + PlatformIO”- Installa VS Code
- Installa l’estensione PlatformIO IDE
- Crea un nuovo progetto: PIO Home → New Project
- Seleziona scheda:
Arduino Uno - Scrivi il codice in
src/main.cpp - Compila: ✔️ (spunta in basso) o
Ctrl+Alt+B - Carica: → (freccia) o
Ctrl+Alt+U
Su Arduino non c’è un vero debugger hardware come GDB. Si usa Serial.print():
int valore = analogRead(A0);Serial.print("Valore sensore: ");Serial.println(valore);delay(100);Apri il Monitor Seriale (IDE: Ctrl+Shift+M, PlatformIO: icona plug) per vedere l’output.
3. Breadboard — costruire circuiti
Section titled “3. Breadboard — costruire circuiti”La breadboard permette di prototipare circuiti senza saldature.

┌─────────────┬───────┬───────┬─ ... ┬───────┐ (+) │ 1 │ 2 │ 3 │ ... │ 30 │ = binocoli orizzontali ├─────┼─────┼─────┼─────┼─────┤ │ │ │ │ │ │ ├─────┼─────┼─────┼─────┼─────┤ (-) │ 1 │ 2 │ 3 │ ... │ 30 │ └─────────────┴───────┴───────┴─ ... ┴───────┘
┌─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┐ │a│b│c│d│e│f│g│h│i│j│ ... │a│b│c│d│e│f│g│h│i│j│ ├─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┤ │ │ │ │ │ │ │ │ │ │ │ ... │ │ │ │ │ │ │ │ │ │ ← righe collegate ├─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┤ │ │ │ │ │ │ │ │ │ │ │ ... │ │ │ │ │ │ │ │ │ │ └─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┘ ───┴─── ───┴─── binocoli binocoli (+) / (-) (E / F)Regole base:
- I binocoli laterali (rosso/blu) sono collegati verticalmente: usali per alimentazione (rosso = 5V/Vcc, blu = GND)
- Le righe interne (a-j) sono collegate orizzontalmente in gruppi di 5
- Il ponticello centrale separa le due metà: nessuna connessione tra E e F
Collegamenti tipici:
┌─ LED ─────────────────────────────┐│ Anodo (+) → a1 Catodo (-) → a5 ││ Resistenza 220Ω da b1 a binocolo GND ││ Filo da D13 a a1 (LED+) │└────────────────────────────────────────┘4. Sensori — leggere l’ambiente
Section titled “4. Sensori — leggere l’ambiente”Sensore analogico: potenziometro
Section titled “Sensore analogico: potenziometro”const int PIN_POT = A0;
void setup() { Serial.begin(9600);}
void loop() { int valore = analogRead(PIN_POT); float tensione = valore * (5.0 / 1023.0);
Serial.print("Valore: "); Serial.print(valore); Serial.print(" Tensione: "); Serial.print(tensione); Serial.println(" V");
delay(200);}Schema di montaggio:

Circuito:
5V ──┐ │ ┌┴┐ │ │ Potenziometro 10kΩ │ │ └┬┘ ├── A0 (lettura analogica 0-1023) │ GND ─┘Sensore digitale: pulsante
Section titled “Sensore digitale: pulsante”const int PIN_BOTTONE = 7;
void setup() { pinMode(PIN_BOTTONE, INPUT_PULLUP); // Attiva resistenza interna di pull-up Serial.begin(9600);}
void loop() { int stato = digitalRead(PIN_BOTTONE);
if (stato == LOW) { // Premuto (LOW perché usiamo INPUT_PULLUP) Serial.println("Bottone premuto!"); delay(300); // Debounce semplice }}Schema di montaggio:

Circuito:
5V ──┐ │ ┌┤│ Pulsante │││ └┤│ │ └── D7 (con INPUT_PULLUP, non serve resistenza esterna) │ GND ─┘Sensore di temperatura: LM35 / TMP36
Section titled “Sensore di temperatura: LM35 / TMP36”const int PIN_TEMP = A1;
void setup() { Serial.begin(9600);}
void loop() { int valore = analogRead(PIN_TEMP); // TMP36: 10mV per °C, offset 0.5V = 50°C float tensione = valore * (5.0 / 1023.0); float temperatura = (tensione - 0.5) * 100.0;
Serial.print("Temperatura: "); Serial.print(temperatura); Serial.println(" °C");
delay(1000);}Schema di montaggio:

Circuito:
TMP36 ┌─┐ │ │ │ │ ─┬─ │ ┌─┼─┐ │ │ │ 5V A1 GNDSensore di distanza: HC-SR04 (ultrasuoni)
Section titled “Sensore di distanza: HC-SR04 (ultrasuoni)”const int PIN_TRIG = 9;const int PIN_ECHO = 10;
void setup() { pinMode(PIN_TRIG, OUTPUT); pinMode(PIN_ECHO, INPUT); Serial.begin(9600);}
void loop() { // Invia impulso ultrasonico digitalWrite(PIN_TRIG, LOW); delayMicroseconds(2); digitalWrite(PIN_TRIG, HIGH); delayMicroseconds(10); digitalWrite(PIN_TRIG, LOW);
// Misura il tempo di ritorno long durata = pulseIn(PIN_ECHO, HIGH);
// Calcola distanza: velocità suono ≈ 343 m/s = 0.0343 cm/μs // Distanza = durata / 2 * 0.0343 float distanza = durata * 0.0343 / 2.0;
Serial.print("Distanza: "); Serial.print(distanza); Serial.println(" cm");
delay(500);}Schema di montaggio:

Circuito HC-SR04:
HC-SR04 ┌──────────┐ │ VCC TRIG │ │ ECHO GND │ └──────────┘ │ │ │ │ 5V GND D9 D10 TRIG ECHORiepilogo sensori comuni
Section titled “Riepilogo sensori comuni”| Sensore | Tipo | Pin | Funzione |
|---|---|---|---|
| Potenziometro | Analogico | A0 | analogRead() → 0-1023 |
| LDR (fotoresistenza) | Analogico | A0 | analogRead() → luce/ombra |
| LM35 / TMP36 | Analogico | A1 | analogRead() → °C |
| Pulsante | Digitale | D7 | digitalRead() → LOW/HIGH |
| HC-SR04 | Digitale | D9, D10 | pulseIn() → cm |
| DHT11/DHT22 | Digitale | D2 | Libreria DHT → °C, umidità |
| PIR (movimento) | Digitale | D8 | digitalRead() → movimento |
5. Attuatori — agire sul mondo
Section titled “5. Attuatori — agire sul mondo”LED semplice
Section titled “LED semplice”Schema di montaggio:

const int PIN_LED = 13;
void setup() { pinMode(PIN_LED, OUTPUT);}
void loop() { digitalWrite(PIN_LED, HIGH); // Accendi delay(500); digitalWrite(PIN_LED, LOW); // Spegni delay(500);}LED con PWM (sfumatura)
Section titled “LED con PWM (sfumatura)”const int PIN_LED = 9; // Deve essere un pin ~PWM
void setup() { pinMode(PIN_LED, OUTPUT);}
void loop() { for (int luminosita = 0; luminosita <= 255; luminosita++) { analogWrite(PIN_LED, luminosita); delay(5); } for (int luminosita = 255; luminosita >= 0; luminosita--) { analogWrite(PIN_LED, luminosita); delay(5); }}Schema di montaggio:

Circuito con resistenza:
D9 (PWM) ──┬──┐ │ │ 220Ω │ │ │ └── Anodo (+) │ LED └────── Catodo (-) │ GNDServomotore SG90
Section titled “Servomotore SG90”Schema di montaggio:

#include <Servo.h>
Servo mioServo;const int PIN_SERVO = 9;
void setup() { mioServo.attach(PIN_SERVO);}
void loop() { mioServo.write(0); // 0 gradi delay(1000); mioServo.write(90); // 90 gradi delay(1000); mioServo.write(180); // 180 gradi delay(1000);}Collegamento servomotore:
SG90 ┌───┐ │ │ ╱ ╲ ╱ ╲ │ │ │ ────┬─── │ │ │ GND 5V Segnale │ D9 (PWM)Motor DC con driver L298N
Section titled “Motor DC con driver L298N”Schema di montaggio:

const int PIN_ENA = 9; // PWM velocitàconst int PIN_IN1 = 8;const int PIN_IN2 = 7;
void setup() { pinMode(PIN_ENA, OUTPUT); pinMode(PIN_IN1, OUTPUT); pinMode(PIN_IN2, OUTPUT);}
void loop() { // Avanti a 1/2 velocità digitalWrite(PIN_IN1, HIGH); digitalWrite(PIN_IN2, LOW); analogWrite(PIN_ENA, 128); delay(2000);
// Stop analogWrite(PIN_ENA, 0); delay(1000);
// Indietro a piena velocità digitalWrite(PIN_IN1, LOW); digitalWrite(PIN_IN2, HIGH); analogWrite(PIN_ENA, 255); delay(2000);
// Stop analogWrite(PIN_ENA, 0); delay(1000);}Schema L298N:
Arduino L298N ─────── ───── D9 ────────────────────────── ENA (PWM velocità A) D8 ────────────────────────── IN1 D7 ────────────────────────── IN2 5V ────────────────────────── +5V GND ────────────────────────── GND │ ┌────────┴────────┐ 12V (batteria) Motore DCRiepilogo attuatori
Section titled “Riepilogo attuatori”| Attuatore | Pin | Controllo |
|---|---|---|
| LED | D13 (o qualunque) | digitalWrite(LED, HIGH/LOW) |
| LED PWM | D3, D5, D6, D9, D10, D11 | analogWrite(pin, 0-255) |
| Servomotore | D9 | servo.write(0-180°) |
| Motor DC (L298N) | ENA+IN1+IN2 | digitalWrite(IN1, IN2), analogWrite(ENA) |
| Buzzer | D8 | tone(pin, frequenza) / noTone(pin) |
| Relay | D12 | digitalWrite(RELAY, HIGH/LOW) |
6. Comunicazione Seriale (UART)
Section titled “6. Comunicazione Seriale (UART)”La comunicazione seriale (UART) è il metodo più semplice e versatile per far comunicare Arduino con un PC, un Raspberry Pi, sensori seriali (GPS, RFID) o un secondo Arduino. Utilizza due linee dati (TX e RX) oltre alla massa comune (GND).
Principio di funzionamento
Section titled “Principio di funzionamento”L’UART (Universal Asynchronous Receiver-Transmitter) trasmette i dati un bit alla volta a una velocità concordata detta baud rate (es. 9600, 115200). La comunicazione è asincrona: non c’è un segnale di clock separato, quindi entrambi i dispositivi devono usare la stessa velocità.
┌─────────────────┐ ┌─────────────────┐│ │ TX ───→ RX ││ Arduino │ RX ←─── TX │ PC / Altro│ │ GND ──── GND │└─────────────────┘ └─────────────────┘ (D1=TX, D0=RX)
Frame di un byte (9600 baud, 8N1):┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐│START│ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │STOP ││ bit │ bit │ bit │ bit │ bit │ bit │ bit │ bit │ bit │└─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┘ 8 bit di dato (LSB first) ± eventuale paritàImportante:
- Il collegamento è incrociato (TX→RX, RX→TX)
- Con il cavo USB, la conversione seriale-USB è gestita dal chip FTDI/CH340G sulla scheda Arduino
- Massa comune (GND collegato) sempre necessaria
Baud rate: quale scegliere
Section titled “Baud rate: quale scegliere”| Baud rate | Utilizzo tipico | Max distanza (appross.) |
|---|---|---|
| 300 | GPS vecchi, dispositivi lenti | ~1000 m |
| 1200 | Modem, dispositivi industriali | ~500 m |
| 9600 | Default Arduino, debug, sensori | ~100 m |
| 57600 | Trasferimento dati veloce | ~10 m |
| 115200 | GPS moderni, Bluetooth HC-05/HC-06 | ~5 m |
| 250000 | Comunicazione rapida tra moduli | ~1 m |
Regola:
Serial.begin(9600)è il valore più sicuro per iniziare. Per aumentare la velocità, assicurati che entrambi i dispositivi supportino il baud rate scelto.
Il Monitor Seriale (IDE Arduino)
Section titled “Il Monitor Seriale (IDE Arduino)”
Il Monitor Seriale (Ctrl+Shift+M) permette di:
- Visualizzare i dati inviati da Arduino
- Inviare comandi da tastiera ad Arduino
- Selezionare il baud rate (in basso a destra)
- Scegliere terminazione riga (
\n,\r\n, ecc.)
Consiglio: usa lo Serial Plotter (
Ctrl+Shift+L) per visualizzare graficamente i dati numerici in tempo reale (es. andamento temperatura).
Caso d’uso 1 — Debug e logging
Section titled “Caso d’uso 1 — Debug e logging”Il caso più comune: stampare messaggi di debug per capire cosa sta succedendo nel programma.
#define DEBUG
void setup() { Serial.begin(9600); Serial.println("Sistema avviato!"); Serial.print("Timestamp (ms): "); Serial.println(millis());}
void loop() { int sensore = analogRead(A0);
#ifdef DEBUG Serial.print("[DEBUG] A0 = "); Serial.print(sensore); Serial.print(" Tensione = "); Serial.print(sensore * (5.0 / 1023.0)); Serial.println(" V");#endif
delay(500);}Caso d’uso 2 — Invio dati strutturati (CSV)
Section titled “Caso d’uso 2 — Invio dati strutturati (CSV)”Utile per registrare dati su PC e importarli in Excel o fogli di calcolo.
void setup() { Serial.begin(9600); // Intestazione CSV (stampata una volta sola) Serial.println("timestamp,temperatura,umidita,luminosita");}
void loop() { unsigned long t = millis(); float temp = 20.0 + random(-50, 50) / 10.0; // Simula TMP36 float hum = 50.0 + random(-20, 20) / 10.0; int luce = analogRead(A0);
// Dati in formato CSV Serial.print(t); Serial.print(","); Serial.print(temp, 1); Serial.print(","); Serial.print(hum, 1); Serial.print(","); Serial.println(luce);
delay(1000);}Su PC: un programma Python o Node.js può leggere la seriale e salvare i dati in un file CSV.
Caso d’uso 3 — Invio dati in formato JSON
Section titled “Caso d’uso 3 — Invio dati in formato JSON”Perfetto per interfacciarsi con applicazioni web o Node.js.
void setup() { Serial.begin(9600);}
void loop() { float temp = 20.0 + random(-50, 50) / 10.0; float hum = 50.0 + random(-20, 20) / 10.0;
// Output JSON compatto Serial.print("{\"t\":"); Serial.print(temp, 1); Serial.print(",\"h\":"); Serial.print(hum, 1); Serial.println("}");
delay(2000);}Output:
{"t":22.3,"h":48.7}{"t":22.1,"h":49.2}Caso d’uso 4 — Ricezione comandi (parsing)
Section titled “Caso d’uso 4 — Ricezione comandi (parsing)”Arduino ascolta comandi testuali dal PC e reagisce di conseguenza.
const int PIN_LED = 13;const int PIN_LED2 = 12;
void setup() { Serial.begin(9600); pinMode(PIN_LED, OUTPUT); pinMode(PIN_LED2, OUTPUT); Serial.println("Pronto. Comandi: LED1 ON, LED1 OFF, LED2 ON, LED2 OFF, STATO");}
void loop() { if (Serial.available() > 0) { String cmd = Serial.readStringUntil('\n'); cmd.trim(); cmd.toUpperCase();
if (cmd == "LED1 ON") { digitalWrite(PIN_LED, HIGH); Serial.println("LED1 acceso"); } else if (cmd == "LED1 OFF") { digitalWrite(PIN_LED, LOW); Serial.println("LED1 spento"); } else if (cmd == "LED2 ON") { digitalWrite(PIN_LED2, HIGH); Serial.println("LED2 acceso"); } else if (cmd == "LED2 OFF") { digitalWrite(PIN_LED2, LOW); Serial.println("LED2 spento"); } else if (cmd == "STATO") { Serial.print("LED1: "); Serial.println(digitalRead(PIN_LED) ? "ON" : "OFF"); Serial.print("LED2: "); Serial.println(digitalRead(PIN_LED2) ? "ON" : "OFF"); } else if (cmd == "HELP") { Serial.println("Comandi: LED1 ON, LED1 OFF, LED2 ON, LED2 OFF, STATO"); } else { Serial.print("Comando sconosciuto: "); Serial.println(cmd); } }}Caso d’uso 5 — Lettura sensore seriale (GPS NMEA)
Section titled “Caso d’uso 5 — Lettura sensore seriale (GPS NMEA)”Molti sensori comunicano direttamente via seriale, come i moduli GPS (Neo-6M, Neo-8M).
Collegamento:
┌───────────┐ ┌─────────────┐│ GPS │ TX ───→ RX (D2) ││ Neo-6M │ RX ←─── TX (D3) ││ │ GND ──── GND │└───────────┘ └─────────────┘ Arduino (SoftwareSerial)#include <SoftwareSerial.h>
// Crea una seconda porta seriale sui pin D2 (RX) e D3 (TX)SoftwareSerial gps(2, 3); // RX, TX
void setup() { Serial.begin(9600); // Seriale principale (USB → PC) gps.begin(9600); // Seriale software (GPS) Serial.println("Lettura GPS...");}
void loop() { if (gps.available() > 0) { char c = gps.read(); // Inoltra al PC per elaborazione Serial.write(c); }
// Invia comando al GPS (es. configurazione) if (Serial.available() > 0) { gps.write(Serial.read()); }}Nota: I moduli GPS inviano frasi NMEA (es.
$GPGGA,123519,4807.038,N,...) che possono essere parse per estrarre latitudine, longitudine, altitudine e orario.
Caso d’uso 6 — Comunicazione tra due Arduino (UART)
Section titled “Caso d’uso 6 — Comunicazione tra due Arduino (UART)”Due Arduino possono comunicare direttamente via seriale.
Schema collegamento:
┌─────────────────┐ ┌─────────────────┐│ Arduino #1 │ │ Arduino #2 ││ │ │ ││ TX (D1) ───────┼─────────┼── RX (D0) ││ RX (D0) ───────┼─────────┼── TX (D1) ││ GND ───────┼─────────┼── GND │└─────────────────┘ └─────────────────┘ (master) (slave)Arduino #1 (trasmettitore):
int contatore = 0;
void setup() { Serial.begin(9600);}
void loop() { Serial.print("CIAO_"); Serial.println(contatore); contatore++; delay(1000);}Arduino #2 (ricevitore):
void setup() { Serial.begin(9600); pinMode(LED_BUILTIN, OUTPUT);}
void loop() { if (Serial.available() > 0) { String msg = Serial.readStringUntil('\n'); msg.trim();
Serial.print("Ricevuto: "); Serial.println(msg);
// Accendi LED a ogni messaggio digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); }}Caso d’uso 7 — Serial Plotter: visualizzazione grafica
Section titled “Caso d’uso 7 — Serial Plotter: visualizzazione grafica”Lo Serial Plotter dell’IDE Arduino (Ctrl+Shift+L) permette di vedere i dati numerici in tempo reale.
void setup() { Serial.begin(9600);}
void loop() { int pot = analogRead(A0); // 0-1023 int luce = analogRead(A1); // LDR float temp = analogRead(A2) * (5.0 / 1023.0 - 0.5) * 100.0;
// Serial Plotter accetta valori separati da spazio o virgola Serial.print(pot); Serial.print(" "); Serial.print(luce); Serial.print(" "); Serial.println(temp);
delay(100);}Lo Serial Plotter disegna automaticamente una curva per ogni valore numerico stampato su una riga. Ideale per vedere l’andamento di sensori in tempo reale.
Riepilogo funzioni Serial
Section titled “Riepilogo funzioni Serial”| Funzione | Descrizione |
|---|---|
Serial.begin(speed) | Avvia la seriale con baud rate speed |
Serial.print(val) | Stampa il valore come testo |
Serial.println(val) | Stampa il valore con newline (\n) |
Serial.write(byte) | Invia un byte grezzo (0-255) |
Serial.available() | Restituisce il numero di byte in arrivo |
Serial.read() | Legge un byte (restituisce -1 se nessun dato) |
Serial.readString() | Legge tutti i byte disponibili come stringa |
Serial.readStringUntil(c) | Legge fino al carattere c |
Serial.parseInt() | Legge il prossimo intero |
Serial.parseFloat() | Legge il prossimo float |
Serial.flush() | Attende che tutti i dati in uscita siano trasmessi |
Serial.setTimeout(t) | Imposta il timeout in ms per le funzioni di parse |
Uso di SoftwareSerial (pin seriali aggiuntivi)
Section titled “Uso di SoftwareSerial (pin seriali aggiuntivi)”Arduino Uno ha una sola porta seriale hardware (D0=RX, D1=TX). La libreria SoftwareSerial permette di crearne altre su qualsiasi pin digitale.
#include <SoftwareSerial.h>
// Crea una seriale software su pin 10 (RX) e 11 (TX)SoftwareSerial mySerial(10, 11);
void setup() { Serial.begin(9600); // Seriale USB (PC) mySerial.begin(9600); // Seriale software (es. GPS, Bluetooth)
mySerial.println("Modulo connesso!");}
void loop() { // Bridge: inoltra dati tra PC e modulo if (mySerial.available()) { Serial.write(mySerial.read()); } if (Serial.available()) { mySerial.write(Serial.read()); }}Limitazione: SoftwareSerial non può inviare e ricevere contemporaneamente ad alta velocità. Per più porte seriali simultanee, usa Arduino Mega (ha 4 UART hardware).
Tabella comparativa: Seriale vs altre interfacce
Section titled “Tabella comparativa: Seriale vs altre interfacce”| Caratteristica | UART (Seriale) | I²C | SPI |
|---|---|---|---|
| Numero fili | 2 (+ GND) | 2 (SDA+SCL) | 4 (MOSI+MISO+SCK+SS) |
| Velocità | Fino a 2 Mbps | Fino a 3.4 MHz | Fino a 10 MHz |
| Dispositivi | Punto-punto | Multi-master | Multi-slave |
| Complessità | Molto semplice | Media | Media |
| Tipico uso | Debug, GPS, Bluetooth, PC | Sensori (LCD, BME280) | SD card, nRF24, display |
Errori comuni
Section titled “Errori comuni”| Errore | Causa | Soluzione |
|---|---|---|
| Caratteri strani sul monitor | Baud rate diverso tra Arduino e Monitor | Stessa velocità su entrambi |
| Niente sul monitor | Arduino in reset continuo o porta sbagliata | Verifica porta e alimentazione |
| Dati saltati o corrotti | Buffer overflow o baudrate troppo alto | Riduci baudrate o aumenta delay |
Serial non funziona se uso pin D0/D1 | Quei pin sono usati dalla seriale USB | Evita di usarli come I/O generico |
| SoftwareSerial non riceve bene | Interferenza con interrupt timer | Usa baudrate ≤ 57600 |
7. Interfacciamento via Seriale con Raspberry Pi
Section titled “7. Interfacciamento via Seriale con Raspberry Pi”Cablaggio
Section titled “Cablaggio”
┌──────────┐ ┌──────────────┐│ Arduino │ USB │ Raspberry ││ Uno │═══════════════════│ Pi 4/5 │└──────────┘ └──────────────┘Cavo USB-A → microUSB (o USB-C). Il Raspberry rileva Arduino come /dev/ttyACM0 o /dev/ttyUSB0.
Python su Raspberry — lettura dati
Section titled “Python su Raspberry — lettura dati”import serialimport time
# Configurazione porta serialeser = serial.Serial( port='/dev/ttyACM0', baudrate=9600, timeout=1)
time.sleep(2) # Attendi reset Arduino
try: while True: if ser.in_waiting > 0: linea = ser.readline().decode('utf-8').strip() print(f"Arduino dice: {linea}")except KeyboardInterrupt: print("Chiusura...") ser.close()Python su Raspberry — invio comandi
Section titled “Python su Raspberry — invio comandi”import serialimport time
ser = serial.Serial('/dev/ttyACM0', 9600, timeout=1)time.sleep(2)
while True: comando = input("Comando (ACCENDI/SPEGNI): ").strip() ser.write((comando + "\n").encode())
risposta = ser.readline().decode().strip() print(f"Risposta: {risposta}")Esempio completo: sensore + Python + logging
Section titled “Esempio completo: sensore + Python + logging”Arduino (lettura temperatura su richiesta):
const int PIN_TEMP = A1;
void setup() { Serial.begin(9600);}
void loop() { if (Serial.available() > 0) { String cmd = Serial.readStringUntil('\n'); cmd.trim();
if (cmd == "TEMPERATURA") { int valore = analogRead(PIN_TEMP); float tensione = valore * (5.0 / 1023.0); float temp = (tensione - 0.5) * 100.0;
Serial.print(temp); Serial.println(" C"); } }}Raspberry (Python con logging CSV):
import serialimport timeimport csvfrom datetime import datetime
ser = serial.Serial('/dev/ttyACM0', 9600, timeout=1)time.sleep(2)
with open('temperature.csv', 'w', newline='') as f: writer = csv.writer(f) writer.writerow(['timestamp', 'temperatura'])
try: while True: ser.write(b"TEMPERATURA\n") risposta = ser.readline().decode().strip()
if risposta: timestamp = datetime.now().isoformat() writer.writerow([timestamp, risposta]) f.flush() print(f"{timestamp} → {risposta}")
time.sleep(60) # Leggi ogni minuto except KeyboardInterrupt: ser.close() print("Logging terminato.")8. Interfacciamento via nRF24L01
Section titled “8. Interfacciamento via nRF24L01”Il modulo nRF24L01 permette comunicazione wireless tra Arduino e Raspberry (o tra due Arduino) a 2.4 GHz, con portata fino a 100m (modello +PA+LNA).
Pinout nRF24L01
Section titled “Pinout nRF24L01” nRF24L01 ┌───────────┐ │ 1 2 3 │ │ 4 5 6 │ │ 7 │ └───────────┘
1 = GND 5 = MOSI 2 = VCC (3.3V) 6 = SCK 3 = CE 7 = CSN 4 = CS (alcuni modelli: IRQ = 8)Collegamento ad Arduino
Section titled “Collegamento ad Arduino”| nRF24L01 | Arduino Uno |
|---|---|
| GND | GND |
| VCC | 3.3V (mai 5V!) |
| CE | D9 |
| CSN | D10 |
| MOSI | D11 |
| SCK | D13 |
| MISO | D12 |
Schema pratico:
nRF24L01 Arduino Uno ──────── ────────── VCC ───────────────────── 3.3V GND ───────────────────── GND CE ───────────────────── D9 CSN ───────────────────── D10 MOSI ──────────────────── D11 MISO ──────────────────── D12 SCK ───────────────────── D13
Aggiungi un condensatore 10µF tra 3.3V e GND (vicino al modulo) per stabilizzare l'alimentazione!Collegamento a Raspberry Pi
Section titled “Collegamento a Raspberry Pi”| nRF24L01 | Raspberry Pi (GPIO) |
|---|---|
| GND | GND (pin 6) |
| VCC | 3.3V (pin 1) |
| CE | GPIO22 (pin 15) |
| CSN | GPIO8 / CE0 (pin 24) |
| MOSI | GPIO10 / MOSI (pin 19) |
| MISO | GPIO9 / MISO (pin 21) |
| SCK | GPIO11 / SCLK (pin 23) |
┌─────────────────────────────────────┐ │ Raspberry Pi 40-pin │ ├─────────────────────────────────────┤ │ 1 3.3V ── nRF24 VCC 2 5V │ │ 3 SDA 4 5V │ │ 5 SCL 6 GND ←───┤ │ 7 GPIO4 8 GPIO14 │ │ 9 GND 10 GPIO15 │ │ 11 GPIO17 12 GPIO18 │ │ 13 GPIO27 │ 14 GND │ │ 15 GPIO22 ←── CE 16 GPIO23 │ │ 17 3.3V 18 GPIO24 │ │ 19 MOSI ←───────┐ 20 GND │ │ 21 MISO ←───────┤ 22 GPIO25 │ │ 23 SCK ←────────┤ 24 CE0 ←────┤ CSN │ 25 GND 26 CE1 │ └─────────────────────────────────────┘Installazione librerie
Section titled “Installazione librerie”Arduino (Library Manager):
- Apri Strumenti → Gestione librerie
- Cerca “RF24” di TMRh20
- Installa
Raspberry Pi:
# Abilita SPIsudo raspi-config# → Interface Options → SPI → Enable
# Installa libreriapip install pyrf24
# Verificapython3 -c "import pyrf24; print('OK')"Codice Arduino — trasmettitore (invia temperatura)
Section titled “Codice Arduino — trasmettitore (invia temperatura)”#include <SPI.h>#include <RF24.h>
RF24 radio(9, 10); // CE, CSNconst byte indirizzo[6] = "NODO1";
const int PIN_TEMP = A1;
void setup() { Serial.begin(9600);
if (!radio.begin()) { Serial.println("Modulo nRF24 non rilevato!"); while (1); }
radio.openWritingPipe(indirizzo); radio.setPALevel(RF24_PA_LOW); // Massima potenza: RF24_PA_MAX radio.setDataRate(RF24_250KBPS); // Bassa velocità = più portata radio.stopListening();
Serial.println("Trasmettitore nRF24 pronto");}
void loop() { int valore = analogRead(PIN_TEMP); float tensione = valore * (5.0 / 1023.0); float temperatura = (tensione - 0.5) * 100.0;
bool successo = radio.write(&temperatura, sizeof(temperatura));
if (successo) { Serial.print("Inviato: "); Serial.print(temperatura); Serial.println(" °C"); } else { Serial.println("Invio fallito!"); }
delay(2000);}Codice Raspberry — ricevitore (Python)
Section titled “Codice Raspberry — ricevitore (Python)”import pyrf24import time
# Configurazioneradio = pyrf24.RF24(22, 0) # CE = GPIO22, CSN = CE0 (SPI bus 0)indirizzo = b"NODO1"
if not radio.begin(): print("Modulo nRF24 non rilevato!") exit(1)
radio.setPALevel(pyrf24.RF24_PA_LOW)radio.setDataRate(pyrf24.RF24_250KBPS)radio.openReadingPipe(1, indirizzo)radio.startListening()
print("Ricevitore nRF24 pronto...")
try: while True: if radio.available(): buffer = radio.read(4) # float = 4 byte temperatura = float(buffer[0]) # Semplificato # Oppure con struct: # import struct # temperatura = struct.unpack('f', buffer)[0]
print(f"Temperatura ricevuta: {temperatura:.2f} °C")
time.sleep(0.1)except KeyboardInterrupt: print("Chiusura...") radio.stopListening()Esempio bidirezionale: comando + risposta
Section titled “Esempio bidirezionale: comando + risposta”Arduino (nodo sensore con comando LED):
#include <SPI.h>#include <RF24.h>
RF24 radio(9, 10);const byte indirizzo[6] = "NODO1";
const int PIN_LED = 5;
void setup() { Serial.begin(9600); pinMode(PIN_LED, OUTPUT);
if (!radio.begin()) { Serial.println("nRF24 non rilevato!"); while (1); }
radio.openReadingPipe(1, indirizzo); radio.setPALevel(RF24_PA_LOW); radio.setDataRate(RF24_250KBPS); radio.startListening();}
void loop() { if (radio.available()) { char comando[32] = ""; radio.read(&comando, sizeof(comando));
Serial.print("Comando ricevuto: "); Serial.println(comando);
radio.stopListening();
if (strcmp(comando, "ACCENDI") == 0) { digitalWrite(PIN_LED, HIGH); char risposta[] = "LED acceso"; radio.write(&risposta, sizeof(risposta)); } else if (strcmp(comando, "SPEGNI") == 0) { digitalWrite(PIN_LED, LOW); char risposta[] = "LED spento"; radio.write(&risposta, sizeof(risposta)); } else { char risposta[] = "Comando sconosciuto"; radio.write(&risposta, sizeof(risposta)); }
radio.startListening(); }}Raspberry (controllo remoto):
import pyrf24import time
radio = pyrf24.RF24(22, 0)indirizzo = b"NODO1"
radio.begin()radio.setPALevel(pyrf24.RF24_PA_LOW)radio.setDataRate(pyrf24.RF24_250KBPS)radio.openWritingPipe(indirizzo)
while True: comando = input("Comando (ACCENDI/SPEGNI): ").strip()
radio.stopListening() radio.write(comando.encode())
time.sleep(0.1) radio.startListening()
if radio.available(): buffer = radio.read(32) risposta = buffer.decode().strip().rstrip('\x00') print(f"Risposta: {risposta}")9. Schema riepilogativo delle interfacce di Arduino
Section titled “9. Schema riepilogativo delle interfacce di Arduino”┌─────────────────────────────────────────────────┐│ ARDUINO UNO │├─────────────────────────────────────────────────┤│ ││ ┌─────────────────────────────────────────────┐ ││ │ PIN DIGITALI (D0-D13) │ ││ │ D0/RX ── Comunicazione seriale (ricezione) │ ││ │ D1/TX ── Comunicazione seriale (invio) │ ││ │ D2-D13─ I/O digitale generico │ ││ │ ~D3,~D5,~D6,~D9,~D10,~D11 ── PWM (0-255) │ ││ │ D10/SS, D11/MOSI, D12/MISO, D13/SCK ── SPI │ ││ └─────────────────────────────────────────────┘ ││ ││ ┌─────────────────────────────────────────────┐ ││ │ PIN ANALOGICI (A0-A5) │ ││ │ A0-A5 ── Ingresso analogico 0-1023 (0-5V) │ ││ │ A4/SDA, A5/SCL ── I²C/TWI │ ││ └─────────────────────────────────────────────┘ ││ ││ ┌─────────────────────────────────────────────┐ ││ │ ALIMENTAZIONE │ ││ │ Vin ── Alimentazione esterna (7-12V) │ ││ │ 5V ── Uscita 5V (max ~500mA) │ ││ │ 3.3V ── Uscita 3.3V (max ~150mA) │ ││ │ GND ── Massa comune │ ││ └─────────────────────────────────────────────┘ ││ ││ ┌─────────────────────────────────────────────┐ ││ │ COMUNICAZIONE │ ││ │ USB ── Seriale con PC (alimenta + prog)│ ││ │ UART ── TX/RX (D0-D1) seriale hardware │ ││ │ SPI ── D10-D13 (per nRF24, SD, ecc.) │ ││ │ I²C/TWI ── A4(SDA), A5(SCL) (per sensori) │ ││ └─────────────────────────────────────────────┘ ││ │└─────────────────────────────────────────────────┘10. Guida alla scelta dei componenti
Section titled “10. Guida alla scelta dei componenti”Come riconoscere un componente
Section titled “Come riconoscere un componente”| Componente | Aspetto | Come si identifica |
|---|---|---|
| Resistenza | Cilindro con bande colorate | Bande = valore (es. rosso-rosso-marrone = 220Ω) |
| LED | Sfera trasparente/colorata con 2 gambe | Gamba lunga = anodo (+), gamba corta = catodo (-) |
| Condensatore | Cilindro (elettrolitico) o disco (ceramico) | Elettrolitico: striscia = negativo |
| Diodo | Cilindro con una striscia | Striscia = catodo |
| Pulsante | Piccolo blocco con 4 gambe | Gambe collegate a coppie |
| Potenziometro | Rotella con 3 gambe | Gambe laterali = 5V/GND, centrale = segnale |
| Transistor | Semidisco con 3 gambe | Lettera sul corpo (es. 2N2222, BC547) |
| Regolatore | Sembra un transistor, 3 gambe | 7805 = 5V output, 7812 = 12V output |
| IC (integrato) | Rettangolo nero con gambe (DIP) | Tacca = pin 1 |
Specifiche elettriche base
Section titled “Specifiche elettriche base”| Parametro | Valore |
|---|---|
| Tensione logica Arduino | 5V |
| Corrente max per pin I/O | 40 mA |
| Corrente totale Vcc/GND | ~200 mA |
| Tensione ingresso analogico | 0-5V |
| Resistenza pull-up interna | ~20 kΩ |
| Frequenza PWM | ~490 Hz (~980 Hz su D5/D6) |
11. Progetti guidati
Section titled “11. Progetti guidati”Progetto 1: Termostato con display seriale
Section titled “Progetto 1: Termostato con display seriale”Materiali: Arduino Uno, TMP36, potenziometro, LED
Circuito:
TMP36 Potenziometro LED ───── ───────────── ─── VCC-5V 5V-GND-A2 D13-GND (con 220Ω) A1Codice:
const int PIN_TEMP = A1;const int PIN_SOGLIA = A2;const int PIN_LED = 13;
void setup() { Serial.begin(9600); pinMode(PIN_LED, OUTPUT);}
void loop() { int valTemp = analogRead(PIN_TEMP); float temp = ((valTemp * 5.0 / 1023.0) - 0.5) * 100.0;
int valSoglia = analogRead(PIN_SOGLIA); float soglia = ((valSoglia * 5.0 / 1023.0) - 0.5) * 100.0;
Serial.print("Temperatura: "); Serial.print(temp); Serial.print(" °C Soglia: "); Serial.print(soglia); Serial.println(" °C");
if (temp > soglia) { digitalWrite(PIN_LED, HIGH); Serial.println(">> ALLARME: temperatura superata!"); } else { digitalWrite(PIN_LED, LOW); }
delay(500);}Progetto 2: Stazione meteo wireless (Arduino + nRF24 → Raspberry)
Section titled “Progetto 2: Stazione meteo wireless (Arduino + nRF24 → Raspberry)”Materiali:
- Arduino Uno + nRF24L01 + DHT11 (temperatura/umidità)
- Raspberry Pi + nRF24L01
- Breadboard, cavi, alimentatore
Architettura:
┌─────────┐ nRF24 ┌──────────┐ │ Arduino │ ─── 2.4GHz ──→│ Raspberry │ │ DHT11 │ wireless │ Python │ │ nRF24 │ │ nRF24 │ └─────────┘ │ CSV/DB │ │ Web? │ └──────────┘Codice Arduino (con DHT11):
#include <SPI.h>#include <RF24.h>#include <DHT.h>
RF24 radio(9, 10);const byte indirizzo[6] = "METEO";
#define PIN_DHT 4DHT dht(PIN_DHT, DHT11);
struct DatiMeteo { float temperatura; float umidita; unsigned long timestamp;};
void setup() { Serial.begin(9600); dht.begin();
if (!radio.begin()) { Serial.println("nRF24 non rilevato!"); while (1); }
radio.openWritingPipe(indirizzo); radio.setPALevel(RF24_PA_MAX); radio.setDataRate(RF24_250KBPS); radio.stopListening();}
void loop() { DatiMeteo dati; dati.temperatura = dht.readTemperature(); dati.umidita = dht.readHumidity(); dati.timestamp = millis();
if (isnan(dati.temperatura) || isnan(dati.umidita)) { Serial.println("Errore lettura DHT"); delay(2000); return; }
bool ok = radio.write(&dati, sizeof(dati));
if (ok) { Serial.print("Inviato: "); Serial.print(dati.temperatura); Serial.print("°C, "); Serial.print(dati.umidita); Serial.println("%"); } else { Serial.println("Invio fallito!"); }
delay(5000); // Invia ogni 5 secondi}Codice Raspberry (ricezione + logging CSV):
import pyrf24import structimport csvimport timefrom datetime import datetime
radio = pyrf24.RF24(22, 0)indirizzo = b"METEO"
radio.begin()radio.setPALevel(pyrf24.RF24_PA_MAX)radio.setDataRate(pyrf24.RF24_250KBPS)radio.openReadingPipe(1, indirizzo)radio.startListening()
print("Stazione meteo: in attesa di dati...")
with open('meteo_log.csv', 'a', newline='') as f: writer = csv.writer(f)
try: while True: if radio.available(): buffer = radio.read(16) # 4+4+4+4 byte (float+float+uint32) temperatura, umidita, timestamp = struct.unpack('ffI', buffer)
now = datetime.now().isoformat() writer.writerow([now, f"{temperatura:.1f}", f"{umidita:.1f}"]) f.flush()
print(f"[{now}] Temp: {temperatura:.1f}°C Umid: {umidita:.1f}%")
time.sleep(0.1) except KeyboardInterrupt: print("Logging terminato.")12. Debug e risoluzione problemi
Section titled “12. Debug e risoluzione problemi”Problemi comuni
Section titled “Problemi comuni”| Problema | Causa probabile | Soluzione |
|---|---|---|
| LED non si accende | Resistenza mancante o sbagliata | Usa 220Ω in serie al LED |
| nRF24 non comunica | Alimentazione insufficiente | Aggiungi condensatore 10µF vicino al modulo |
| Valori analogici ballerini | GND fluttuante | Controlla che GND sia comune |
| Sketch non carica | Porta sbagliata | Verifica Porta in Strumenti |
| Serial mostra caratteri strani | Baud rate diverso | Stessi baud su TX e RX |
| Servo vibra | PWM su pin sbagliato | Usa pin ~ (PWM) |
| Niente sul monitor seriale | Arduino in reset continuo | Controlla alimentazione |
Debug con Serial
Section titled “Debug con Serial”#define DEBUG
void setup() { Serial.begin(9600);}
void loop() { int valore = analogRead(A0);
#ifdef DEBUG Serial.print("DEBUG - A0: "); Serial.println(valore);#endif
// Resto del codice...}13. Riepilogo visivo
Section titled “13. Riepilogo visivo” ┌───────────────────────┐ │ COMPONENTI ARDUINO │ ├───────────────────────┤ │ │ SENSORI ───────┤ ARDUINO UNO ├─────── ATTUATORI (INPUT) │ (Microcontrollore) │ (OUTPUT) │ ATmega328P │ ┌─────────┐ │ 16 MHz, 32KB flash │ ┌──────────┐ │Potenziom.│ │ 2KB SRAM, 1KB EEPROM│ │ LED │ ├─────────┤ │ │ ├──────────┤ │TMP36 │────┤ Alimentazione: ├────│Servo │ ├─────────┤ │ • USB 5V │ ├──────────┤ │HC-SR04 │ │ • Vin 7-12V │ │Motor DC │ ├─────────┤ │ • 5V / 3.3V output │ ├──────────┤ │Pulsante │ │ │ │Relay │ ├─────────┤ │ Comunicazione: │ ├──────────┤ │LDR │ │ • Seriale (USB/UART) │ │Buzzer │ ├─────────┤ │ • SPI (nRF24, SD) │ └──────────┘ │DHT11 │ │ • I²C (LCD, sensori) │ └─────────┘ │ │ │ nRF24L01 ←────→ Raspberry Pi │ │ Seriale ←────→ Raspberry Pi │ └───────────────────────┘Riferimenti utili
Section titled “Riferimenti utili”- Arduino Reference — documentazione ufficiale delle funzioni
- RF24 Library docs — documentazione completa nRF24
- Arduino引脚说明 — mappa pin dettagliata
- Tinkercad Circuits — simulatore online di circuiti Arduino