Lezione 10 – Corso di Elettronica Creativa con Arduino Sensor Kit

Cenni teorici

Cos’è la pressione atmosferica?

La pressione atmosferica è la forza esercitata dall’aria su ogni unità di superficie. Viene misurata in pascal (Pa) o, più comunemente, in hectopascal (hPa) dove 1 hPa = 100 Pa.

Il sensore BMP280

Il BMP280 è un sensore barometrico assoluto prodotto da Bosch Sensortec. Le sue caratteristiche principali:

  • Campo di misura: 300 – 1100 hPa (≈ -500 m / +9000 m s.l.m.)
  • Accuratezza assoluta tip. ±1 hPa; accuratezza relativa ±0.12 hPa (≈ ±1 m)
  • Interfacce: I²C (fino a 3.4 MHz) e SPI
  • Consumo: 2.7 µA @ 1 Hz in modalità normale
  • Range termico: –40 … +85 °C

Collegamenti

Collegate il cavo Grove tra il connettore del sensore e la porta I²C (qualsiasi) sullo shield.

Installazione libreria

Sicuramente è un’operazione che avete già eseguito, in ogni caso lo ricordo:

  • Arduino IDE > Gestione librerie > cerca “Arduino_SensorKit”.
  • Installate la libreria (include automaticamente LPS22HB, HTS221, OLED, ecc.)

 Esempio 01: Sketch base – Lettura e stampa dati su Serial Monitor

/*
  Prof. Maffucci Michele
  02.10.2025
  LPS22HB del Sensor Kit
  Stampa valori su Serial Monitor
*/

#include <Arduino_SensorKit.h>   // include unico per tutti i sensori

void setup() {
  Serial.begin(9600);
  Pressure.begin();              // inizializza il barometro
}

void loop() {
  // La libreria restituisce:
  // - pressione in pascal
  // - temperatura in gradi Celsius
  // - altitudine in metri rispetto a 1013,25 hPa

float pressionePa  = Pressure.readPressure();
  float temperaturaC = Pressure.readTemperature();
  float altitudineM  = Pressure.readAltitude();

// conversione pa → hPa per leggibilità
  float pressioneHpa = pressionePa / 100.0;

Serial.print(F("Pressione: "));
  Serial.print(pressioneHpa, 2);
  Serial.print(F(" hPa\tTemperatura: "));
  Serial.print(temperaturaC, 2);
  Serial.print(F(" °C\tAltitudine: "));
  Serial.print(altitudineM, 1);
  Serial.println(F(" m"));

delay(1000);
}

Ricordo che, come già indicato nelle precedenti lezioni, la F(…) (maiuscola), inserita all’interno delle Serial.print(), è una macro di Arduino che serve a mettere una stringa letterale in memoria flash (PROGMEM) invece che copiarla nella SRAM al momento della stampa.

Perché è utile utilizzare F

  • Le board come Arduino UNO (AVR) hanno poca SRAM (2 KB).
  • Senza (), ogni stringa tra virgolette ("Pressione: ") viene copiata in SRAM prima di stamparla > spreco di RAM.
  • Con F("Pressione: "), la stringa resta in flash e Serial.print() la legge direttamente da lì > RAM risparmiata.

Come si usa

Funziona con tutte le funzioni che derivano da Print (es. Serial.print, Serial.println, spesso anche display che usano print in stile Arduino):

Serial.print(F("Pressione: "));
Serial.println(F(" hPa"));

Quando usarla

  • Frasi/titoli/menu costanti e ripetute (log su Serial, messaggi di errore, etichette).
  • Con progetti in cui si ha scarsa disponibilità di RAM (UNO/Nano classici) può fare la differenza.

Limiti

  • Non puoi concatenare direttamente elementi come F(“A”) + F(“B”).
  • Evitare di mescolarla con String in modo implicito (meglio stampare pezzi separati).
  • Funzioni come sprintf non leggono da flash; su AVR esistono versioni “_P” (es. sprintf_P) per farlo.

La struttura delle funzioni (Pressure.begin(), Pressure.readPressure(), ecc.) è la stessa mostrata negli esempi ufficiali di Arduino.

 Esempio 02: Lettura e stampa dati su Serial Monitor e display OLED

Abbiamo già visto l’uso del display OLED nella lezione: Lezione 9 – Corso di Elettronica Creativa con Arduino Sensor Kit vediamo ora come mostrare i valori di: pressione, temperatura e altitudine anche sul display OLED.

/*
  Prof. Maffucci Michele
  02.10.2025
  BMP280 - Arduino Sensor Kit
  Stampa valori su Serial Monitor e OLED
*/

#include <Arduino_SensorKit.h>  // include unico per tutti i sensori

void setup() {
  Serial.begin(9600);
  Pressure.begin();  // inizializza il barometro

Oled.begin();
  // Inizializza il display OLED.
  // Fa partire la comunicazione I2C e manda al display la sequenza di avvio.
  // Senza questa riga lo schermo non mostra nulla.

Oled.setFlipMode(true);
  // Ruota il contenuto di 180° (utile se lo vedi capovolto).
  // Se nel tuo caso appare già dritto, puoi mettere false: Oled.setFlipMode(false);

Oled.setFont(u8x8_font_chroma48medium8_r);
  // Sceglie il font (carattere) 8x8.
  // Con un font 8x8 il display 128x64 si comporta come una griglia 16 colonne × 8 righe.
  // Significa che setCursor(colonna, riga) userà numeri tra 0..15 (colonne) e 0..7 (righe).

Oled.clear();
  // Pulisce lo schermo (cancella tutto quello che c’era prima).
}

void loop() {
  // La libreria restituisce:
  // - pressione in pascal
  // - temperatura in gradi Celsius
  // - altitudine in metri rispetto a 1013,25 hPa

float pressionePa = Pressure.readPressure();
  float temperaturaC = Pressure.readTemperature();
  float altitudineM = Pressure.readAltitude();

// conversione pa → hPa per leggibilità
  float pressioneHpa = pressionePa / 100.0;

// --- Intestazione ---

Oled.setCursor(0, 0);             // colonna 0, riga 0
  Oled.println("STAZIONE METEO");   // stampa la stringa e va a capo
  Oled.println("P - Pressione");    // stampa la stringa e va a capo
  Oled.println("T - Temperatura");  // stampa la stringa e va a capo
  Oled.println("A - Altitudine");   // stampa la stringa e va a capo

Oled.setCursor(0, 5);         // colonna 0, riga 2
  Oled.print("P: ");            // stampa la stringa P:
  Oled.print(pressioneHpa, 2);  // stampa valore della pressione con 2 numeri decimali

Oled.setCursor(0, 6);         // colonna 0, riga 3
  Oled.print("T: ");            // stampa la stringa T:
  Oled.print(temperaturaC, 2);  // stampa valore della temperatura con 2 numeri decimali
  Oled.refreshDisplay();

Oled.setCursor(0, 7);        // colonna 0, riga 4
  Oled.print("A: ");           // stampa la stringa A:
  Oled.print(altitudineM, 2);  // stampa valore dell'altitudine con 2 numeri decimali
  Oled.refreshDisplay();

// Aggiorna fisicamente il display (altrimenti potresti non vedere le modifiche).
  delay(60);

Serial.print(F("Pressione: "));
  Serial.print(pressioneHpa, 2);
  Serial.print(F(" hPa\tTemperatura: "));
  Serial.print(temperaturaC, 2);
  Serial.print(F(" °C\tAltitudine: "));
  Serial.print(altitudineM, 1);
  Serial.println(F(" m"));

delay(1000);
}

Buon Coding a tutti 🙂

Progettare bene, programmare meglio: pseudocodice e diagrammi per sistemi elettronici – lezione 4/5


Ripasso di inizio anno – appunti per la classe.

Nella lezione precedente abbiamo capito che cos’è lo pseudocodice e perché ci aiuta a trasformare problemi della vita quotidiana in passi ordinati, fatti di input, decisioni e azioni. Lo abbiamo usato per pianificare una routine del mattino, un “pomodoro” di studio, uno “zaino intelligente”: esempi senza hardware, ma già con la testa da progettisti.

Oggi facciamo un passo in più: useremo lo stesso modo di pensare per progettare sistemi elettronici con Arduino. Tradurre “ciò che deve accadere” in uno pseudocodice chiaro e verificabile ci farà risparmiare tempo quando passeremo alla codifica in C/C++.

Vedremo in questa lezione come:

  • descrivere il comportamento di un sistema (sensori, attuatori, tempi, soglie) prima di scrivere codice;
  • organizzare lo pseudocodice in sezioni: costanti e pin, variabili di stato, inizializzazione, loop principale, funzioni;
  • riconoscere e usare pattern ricorrenti da laboratorio: lettura sensori, debounce, timer con millis(), macchina a stati semplici;
  • migliorare la qualità del vostro pseudocodice: nomi significativi, commenti utili, blocchi brevi, casi limite previsti;

L’obiettivo pratico è quello di fornire uno schema eseguibile del vostro sistema, uno pseudocodice che, riga per riga, si traduce in istruzioni Arduino.

Vediamo come fare.

Vi ricordo che in laboratorio non “giochiamo con led e fili”: impariamo a progettare sistemi.
Ogni sistema ha ingressi (sensori), uscite (attuatori), stati, soglie, tempi e condizioni di errore, pertanto mettere tutto in ordine prima di codificare significa:

  • sapere cosa misurare e quando;
  • chiarire quando intervenire (condizioni);
  • evitare loop confusi e delay() ovunque (inizio a dirvi che il delay è il male assoluto 🙂 );
  • testare in modo mirato (so quali valori provo e che output mi aspetto);

Quindi il risultato quale sarà?

  • Meno frustrazione;
  • meno “perché non va?”;
  • più tempo per capire.

Le fasi di lavoro saranno le seguenti:

  • progettazione: partiremo dal comportamento desiderato e lo scriveremo in pseudocodice, a blocchi.
  • traduzione: mapperemo ogni blocco in istruzioni Arduino (Serial, pinMode, digitalRead/Write, analogRead, map, millis, ecc.);
  • verifica: controlleremo che i casi limite siano previsti (pulsante che rimbalza, soglia ballerina, time-out, errori di misura);
  • codifica: solo alla fine andremo sull’IDE Arduino.

Per semplificare la fase di progettazione di seguito trovate alcune regole di base molto semplici che consiglio di trasformare in un foglio di riferimento da aggiungere all’inizio del quadernone.

Regole di base

  • scrivi una istruzione per riga;
  • usa i due punti dopo le parole chiave (SE:, PER:, MENTRE:, FUNZIONE:);
  • indenta (vai a capo e rientra) quello che sta “dentro” ad un blocco;
  • metti commenti con // per spiegare.

Esempio di forma di scrittura codice:

SE (condizione) ALLORA:
    fai questa cosa
ALTRIMENTI:
    fai quest’altra

Negli anni passati avete già programmato, ma poiché ho notato qualche disordine e dimenticanza di seguito vi elenco le strutture di base in pseudocodice che useremo come base di partenza, le scrivo io, le analizzeremo e poi userete questi blocchi come mattoncini lego per scrivere lo pseudocodice di un sistema.

Input / Output

LEGGI nome
SCRIVI "Ciao, " + nome

Variabili

imposta eta a 13
imposta temperatura a 21.5

Scelte (IF)

SE (eta >= 18) ALLORA:
    SCRIVI "Maggiorenne"
ALTRIMENTI:
    SCRIVI "Minorenne"

Ripetizioni (LOOP)
Per numero di volte:

PER i da 1 a 5:
    SCRIVI i

Finché una condizione è vera

imposta numero a 1
MENTRE (numero <= 10):
    SCRIVI numero
    numero = numero + 1

Funzioni (blocchi riutilizzabili)

FUNZIONE somma(a, b):
    RITORNA a + b

SCRIVI somma(3, 4)  // stampa 7

Liste (array) piccole

imposta voti a [7, 8, 6, 9]
per ogni v in voti:
    SCRIVI v

Nota sullo stile dei commenti

E’ importante commentare e saper commentare, ne abbiamo già parlato, ma credo sia meglio ribadirlo:

usare nomi chiari: “contaStudenti” è meglio di “c”, ricorda di usare la forma camelcase;
commenta le parti importanti:

// aggiorno il punteggio
punteggio = punteggio + 10

Usa un’idea per riga: corto e leggibile.

Errori comuni

3 errori che ritrovo sempre nelle correzioni delle esercitazioni, sia nello scrivere lo pseudocodice che il codice:

  • dimenticare di aggiornare le variabili nei cicli > il ciclo non finisce mai.
  • usare = invece di == nelle condizioni (in pseudocodice teneteli distinti);
  • non indentare: diventa confuso capire cosa sta dentro un IF o un ciclo.

Qualche esempio pratico

Pari o dispari

LEGGI n
SE (n % 2 == 0) ALLORA:
    SCRIVI "Pari"
ALTRIMENTI:
    SCRIVI "Dispari"

Massimo tra 3 numeri

LEGGI a, b, c
imposta max a a
SE (b > max) ALLORA: max = b
SE (c > max) ALLORA: max = c
SCRIVI "Massimo = " + max

Conta quanti voti ≥ 6

LEGGI N
imposta cont a 0

PER i da 1 a N:
    LEGGI voto
    SE (voto >= 6) ALLORA:
        cont = cont + 1

SCRIVI "Promossi: " + cont

Nella prossima lezione vedremo come passare dallo pseudocodice allo sketch Arduino.

Buon pseudocodice a tutti 🙂

Quick References per lo studio – Mini Gantt di progetto

Il mini-Gantt è il cruscotto dei lavori di gruppo: in una tabella unica vedi attività, responsabili, scadenze, stato e milestone. Non serve un software complesso: 5–8 attività ben definite, un responsabile (e un backup), date realistiche con buffer del 20% e codici semplici per lo stato (☐/▣/☑). È didatticamente prezioso perché rende visibile il processo, non solo il prodotto: chi fa cosa, quando, con quali dipendenze. Aiuta a prevenire il “tutto all’ultimo” e sostiene l’autovalutazione: se manca una definizione chiara di “fatto”, il blocco è dietro l’angolo. Chiusura imprescindibile: retrospettiva breve (“cosa tenere/cosa cambiare”) per migliorare il prossimo ciclo.

Perfetto per lavori di gruppo, PCTO e preparazione verifiche di lungo periodo. In una pagina ottieni il quadro d’insieme e la checklist operativa.

Scarica PDF A4 della guida operativaApri il sorgente Markdown su GitHub

Se non sai cos’è il Markdown segui il link

---
title: "QR - Mini‑Gantt di progetto"
version: "1.0"
autore: "<Classe/Team>"
licenza: "CC BY 4.0"
ultimo_aggiornamento: "31.08.2025"
---

| ID | Attività | Responsabile | Inizio | Fine | Stato | Note |
|----|----------|--------------|--------|------|-------|------|
| 1 | | | | | ☐/▣/☑ | |
| 2 | | | | | ☐/▣/☑ | |

## Milestone
- M1: 
- M2: 

Vediamo un esempio pratico su un’attività di laboratorio.

Mini-Gantt — “Stazione ambientale con Arduino Sensor Kit”

Setup progetto (premesse)

  • Team (4 studenti):
    PM (coordinamento), HW (cablaggi), SW (codice), DOCS (relazione/slide).
  • Durata: 2 settimane scolastiche (6 ore in laboratorio + 2 a casa).
  • Consegna: sketch .ino, demo funzionante, grafico dei dati, mini-report (2 pagine) o slide (6–8).

Tabella mini-Gantt (compilata)

Stati: ☐ non iniziato · ▣ in corso · ☑ completato

Versione PDF della tabella di esempio (ingrandita).

ID Attività Responsabile Inizio Fine Dipendenze Stato Definizione di “fatto”
1 Kick-off, ruoli, criteri di valutazione PM 02/10 02/10 Ruoli assegnati + checklist comune
2 Inventario kit e test IDE HW 02/10 02/10 1 IDE apre, board selezionata, cavo OK
3 Cablaggio sensori (Temp/Umid, Luce) HW 03/10 03/10 2 Wiring secondo schema + foto
4 Sketch base: lettura sensori + Serial SW 03/10 04/10 3 Serial.println() valori leggibili ogni 1s
5 Soglie e feedback (LED/Buzzer) SW 04/10 04/10 4 LED/Buzzer attivi se superate soglie
6 Logging dati (CSV) SW/DOCS 04/10 05/10 4 CSV con timestamp + 50 righe campione
7 Analisi rapida e grafico (foglio di calcolo) DOCS 05/10 05/10 6 Grafico linea luce/temp/umidità
8 Test integrato + bugfix PM+Tutti 06/10 06/10 5,6 10 min run stabile, nessun falso allarme
9 Slide/mini-report + foto schemi DOCS 06/10 07/10 7,8 6–8 slide/2 pagine, font leggibile
10 Prova demo e consegna PM 07/10 07/10 9 Repository/Drive ordinato + consegna docente

Milestone

  • M1 (03/10): Cablaggio completato e foto schema.
  • M2 (05/10): Dati registrati in CSV + grafico generato.
  • M3 (07/10): Demo + consegna finale.

Schema di lavoro (che cosa fare concretamente)

Wiring (HW):

  • Sensore temperatura/umidità → I²C o pin indicati dal Kit.
  • Sensore luce/Fotoresistenza → ingresso analogico A0.
  • LED + Buzzer → pin digitali (es. D5 buzzer, D6 LED).
  • Scatta foto del cablaggio finito (serve per la relazione).

Codice (SW):

  • setup(): Serial.begin(9600); test di lettura sensori; pinMode uscita LED/Buzzer.
  • loop(): leggi sensori → stampa timestamp,temp,umidità,luce → applica soglie (es. luce < 200 → LED rosso; temp > 28°C → buzzer breve).
  • File CSV: usa Serial + salvataggio lato PC (copiando dal monitor o con un logger semplice).

Documentazione (DOCS):

  • Tabella decisioni (soglie adottate e motivazione).
  • Grafico lineare (luce/temp/umidità) da CSV.
  • 1 pagina di “lezioni apprese” (cosa ha funzionato/cosa cambiare).

Coordinamento (PM):

  • Aggiorna stato ogni fine sessione (☐/▣/☑).
  • Verifica dipendenze (es. 6 parte solo dopo 4).
  • Mantiene lista bug e check pre-demo (vedi sotto).

Checklist tecnica rapida (per non perdere tempo)

  • IDE: scheda corretta (UNO/compatibile), porta seriale ok.
  • Librerie sensori installate (se necessarie).
  • Numeri pin nel codice = pin del wiring (evita errori “LED non va”).
  • delay() brevi; usa millis() per letture periodiche.
  • Stampa formato CSV coerente: ms,temperatura,umidità,luce.

Esempio di definizione soglie (adattabili)

  • Luce bassa: < 200 (scala 0–1023) → LED rosso acceso. Caldo eccessivo: temp > 28°C per > 5 s → beep corto ogni 2 s.
  • Umidità alta: umidità > 70% → messaggio su Serial.

Spiegate sempre perché avete scelto quelle soglie (es. classe luminosa, temperatura in aula, ecc.).

Rischi (da incollare vicino al Gantt)

  • Cavo/porta non riconosciuta → prova altro cavo/porta, riavvia IDE.
  • Rumore luce → media mobile su 5 letture.
  • Buzzer fastidioso → limita durata, usa segnale visivo in alternativa.
  • CSV confuso → intestazione time_ms,temp,hum,light e separatore coerente.

Buon lavoro 🙂

Lezione 9 – Corso di Elettronica Creativa con Arduino Sensor Kit

Sensore di temperatura ed umidità (DHT22)

Ho parlato in precedenti post dei sensori di temperatura ed umidità, nello specifico l’uso del diffusissimo DHT11. L’Arduino Sensor Kit li può usare entrambi, ma nel kit è presente il DHT22.

Caratteristiche tecniche del DHT22

Il DHT22 è un sensore digitale che integra:

  • un elemento capacitivo per l’umidità relativa (RH),
  • un sensore termico per la temperatura,
  • un microcontrollore che invia i dati su un’unica linea (single-wire digitale, non analogica).
  • Range tipici e specifiche:
    • Temperatura: –40…+80 °C (risoluzione 0,1 °C, tip. ±0,5 °C),
    • Umidità relativa: 0…100 % RH (risoluzione 0,1 % RH, tip. ±2 % RH, max ±5 %),
  • Alimentazione: 3,3–5 V,
  • Frequenza di campionamento: max 0,5 Hz (una misura ogni ~2 s).

Cos’è l’umidità relativa

L’umidità relativa (RH) indica quanta vapor d’acqua è presente nell’aria rispetto alla quantità massima che quell’aria potrebbe contenere alla stessa temperatura.

  • 50 % RH = l’aria contiene metà del vapore “possibile” a quella temperatura.
  • 100 % RH = saturazione (rischio di condensa).
    Poiché la capacità dell’aria di trattenere vapore cresce con la temperatura, la RH dipende dalla temperatura: per questo i sensori come il DHT22 misurano entrambe le grandezze.

Mi è capitato spesso rispondere alla domanda: “ma Prof. cosa è meglio usare il DHT11 o il DHT22”

Se si dispone di entrambi certamente scegliere il DHT22 è da preferire, ma perché?

  • Precisione e range migliori: DHT22 copre –40…+80 °C (vs 0…+50 °C del DHT11) con ±0,5 °C tipici; RH 0…100 % con ±2–5 % (DHT11 è meno preciso e più limitato).
  • Risoluzione più fine: 0,1 °C / 0,1 % RH (utile per realizzare grafici e verificare trend).

Un vantaggio derivante dall’uso dell’Arduino Sensor Kit è che il DHT22 viene connesso all’Arduino mediante connessione I²C pertanto per il suo utilizzo è possibile collegarlo ad una delle uscite I²C presenti sulla Base Shield.

Veniamo ora agli esempi pratici, ne indico 6 di base, come sempre nei commenti la spiegazione. In classe ne realizzerò altri in cui mostreremo ad esempio la rilevazione della temperatura a media mobile a 10 campioni, attivazione di allarmi e ventole e molto altro.

Connessioni usate in questa lezione:

  • Sensore di Temperatura ed Umidità: connesso ad una qualsiasi dei pin I²C della Base Shield.
  • Display OLED: connesso ad una qualsiasi dei pin I²C della Base Shield.
  • Diodo LED: connesso al D6.

Esempio 01: sensore ambiente – lettura base (temperatura – umidità)

/*
  Prof. Maffucci Michele
  01.10.2025
  Sensore Ambiente – Lettura base (Temperatura + Umidità)

  NOTE:
    - DHT20 (I2C): decommenta la define Environment_I2C e abilita Wire.begin()
    - DHT11 (pin D3 via Base Shield): commenta la define, la libreria gestisce il pin di default
*/

#include <Arduino_SensorKit.h>

// >>> Decommenta se il sensore è DHT20 (I2C) <<<
#define Environment Environment_I2C

void setup() {
  Serial.begin(9600);
  // Necessario per DHT20 (I2C); non influisce negativamente su DHT11
  Wire.begin();

  Environment.begin();  // inizializza il sensore ambiente (DHT11 o DHT20)
}

void loop() {
  float temperaturaC = Environment.readTemperature(); // °C
  float umiditaRH    = Environment.readHumidity();    // %RH

  // Stampa della temperatura e dell'umidità sulla Serial Monitor ogni secondo
  Serial.print("Temperatura: ");
  Serial.print(temperaturaC, 1);
  Serial.print(" °C   Umidità: ");
  Serial.print(umiditaRH, 1);
  Serial.println(" %");

  delay(1000);
}

Esempio 02: Lettura Temperatura e Umidità con allarme su D6 (LED)

In questo esempio utilizziamo il diodo LED connesso al D6 come allarme, pertanto verrà acceso se la temperatura supera un valore di soglia impostato.

/*
  Prof. Maffucci Michele
  01.10.2025
  Lettura Temperatura e Umidità con allarme su D6 (LED)

  - Allarme: LED su D6 si accende se T > soglia.
  - Messaggi su Serial Monitor: ALERT all'attivazione, DISATTIVATO allo spegnimento.
  - DHT20 (I2C): lascia attiva la define Environment_I2C.
  - DHT11: commenta la define sotto; la libreria gestisce il pin del Base Shield.
*/

#include "Arduino_SensorKit.h"

#define Environment Environment_I2C

// Configurazione allarme
const int pinLedAllarme = 6;            // LED collegato al pin D6
const float sogliaTemperaturaC = 25.0;  // soglia in °C

bool allarmeAttivo = false;  // stato attuale dell'allarme

void setup() {
  Serial.begin(9600);

  // Necessario per DHT20 e per eventuali altre periferiche I2C (OLED, ecc.)
  Wire.begin();

  // Inizializza il sensore ambiente (DHT11 o DHT20 a seconda della define)
  Environment.begin();

  // LED di allarme
  pinMode(pinLedAllarme, OUTPUT);
  digitalWrite(pinLedAllarme, LOW);

  Serial.println("== Avvio lettura Temperatura & Umidita' con allarme su D6 ==");
  Serial.print("Soglia T = ");
  Serial.print(sogliaTemperaturaC, 1);
  Serial.println(" C");
}

void loop() {
  // Letture dal sensore
  float temperaturaC = Environment.readTemperature();  // °C
  float umiditaRH = Environment.readHumidity();        // %RH

// --- Gestione allarme con isteresi ---
// Usiamo DUE soglie diverse per evitare ON/OFF continui vicino al limite.
//  - Soglia di ACCENSIONE  (T_on):  temperaturaC > sogliaTemperaturaC
//  - Soglia di SPEGNIMENTO (T_off): temperaturaC < sogliaTemperaturaC // Finché T resta tra T_off e T_on, manteniamo lo stato attuale (nessun cambiamento). if (!allarmeAttivo && temperaturaC > sogliaTemperaturaC) {
  // Caso 1: l'allarme è attualmente OFF e la temperatura SUPERA la soglia di ACCENSIONE.
  // Accendiamo l'allarme (LED ON) e stampiamo un messaggio di ALERT.
  allarmeAttivo = true;
  digitalWrite(pinLedAllarme, HIGH);

  Serial.print("!!! ALERT: Temperatura sopra soglia: ");
  Serial.print(temperaturaC, 1);
  Serial.println(" C");

} else if (allarmeAttivo && temperaturaC < sogliaTemperaturaC) { // Caso 2: l'allarme è attualmente ON e la temperatura SCENDE sotto la soglia di SPEGNIMENTO // Spegniamo l'allarme (LED OFF) e informiamo che è rientrato. allarmeAttivo = false; digitalWrite(pinLedAllarme, LOW); Serial.print("Allarme DISATTIVATO: Temperatura rientrata: "); Serial.print(temperaturaC, 1); Serial.println(" C"); } // Nota sui casi limite: // - Se temperaturaC == sogliaTemperaturaC, NON si accende (serve ">" strettamente).
// - Se temperaturaC == (sogliaTemperaturaC, NON si spegne (serve "<" strettamente).

  // Stampa della temperatura e dell'umidità sulla Serial Monitor
  Serial.print("T=");
  Serial.print(temperaturaC, 1);
  Serial.print(" C   RH=");
  Serial.print(umiditaRH, 1);
  Serial.print(" %   ALLARME=");
  if (allarmeAttivo) {
    Serial.println("ON");
  } else {
    Serial.println("OFF");
  }

  delay(1000);
}

Esempio 03: Lettura Temperatura e Umidità con allarme su D6 (LED) con isteresi

Premessa

In elettronica, isteresi è la presenza di due soglie diverse per il passaggio tra due stati, così l’uscita dipende non solo dal valore istantaneo dell’ingresso, ma anche dalla sua storia. Serve a evitare commutazioni rapide e instabili quando il segnale oscilla vicino a una soglia.

Come nell’esempio precedente utilizziamo il diodo LED connesso al D6 come allarme, inoltre useremo l’isteresi per evitare che il LED “sfarfalli” (ON/OFF ripetuti) quando la temperatura oscilla vicino alla soglia a causa di rumore o piccole variazioni.

Nello sketch che segue l’isteresi funziona in questo modo:

  • Soglia di attivazione: sogliaTemperaturaC = 26.0 °C
    L’allarme si accende appena T > 26.0 °C.
  • Isteresi: isteresiC = 0.5 °C
    L’allarme si spegne solo quando T < 26.0 − 0.5 = 25.5 °C.

Quindi usi due soglie:

  • T_on = 26.0 °C (accendo quando la supero)
  • T_off = 25.5 °C (spengo solo quando scendo sotto)

Senza isteresi, se la temperatura è nell’intorno di intorno a 26 °C (es. 25.9 ↔ 26.1 per il rumore), l’allarme continuerebbe ad accendersi e spegnersi rapidamente. Con l’isteresi, una volta acceso, resta acceso finché non rientra ben al di sotto della soglia, evitando lampeggi/ronzii fastidiosi e messaggi “ALERT” ripetuti.

Quindi come regola generale per i sensori DHT che utilizziamo in laboratorio valori tra 0,3 e 1°C sono di solito sufficienti. Se è presente ancora sfarfallio, aumentare leggermente; se la risposta è troppo lenta a spegnersi, ridurre.

Come schema logico si tenga in conto:

  • Se allarme OFF e T > T_on → accendere
  • Se allarme ON e T < T_off → spegnere
  • Altrimenti mantenere lo stato corrente

È la stessa logica usata nei termostati: due soglie (accensione/spegnimento) invece di una sola, per ottenere un comportamento stabile.

/*
  Prof. Maffucci Michele
  01.10.2025
  Lettura Temperatura e Umidità con allarme su D6 (LED) con isteresi

  - Allarme: LED su D6 si accende se T > soglia.
  - Messaggi su Serial Monitor: ALERT all'attivazione, DISATTIVATO allo spegnimento.
  - DHT20 (I2C): lascia attiva la define Environment_I2C.
  - DHT11: commenta la define sotto; la libreria gestisce il pin del Base Shield.
*/

#include <Arduino_SensorKit.h>

#define Environment Environment_I2C

// Configurazione allarme
const int pinLedAllarme = 6;            // LED collegato al pin D6
const float sogliaTemperaturaC = 25.0;  // soglia in °C
const float isteresiC = 0.5;            // isteresi per evitare lampeggi (spegnimento sotto soglia - isteresi)

bool allarmeAttivo = false;  // stato attuale dell'allarme

void setup() {
  Serial.begin(9600);

  // Necessario per DHT20 e per eventuali altre periferiche I2C (OLED, ecc.)
  Wire.begin();

  // Inizializza il sensore ambiente (DHT11 o DHT20 a seconda della define)
  Environment.begin();

  // LED di allarme
  pinMode(pinLedAllarme, OUTPUT);
  digitalWrite(pinLedAllarme, LOW);

  Serial.println("== Avvio lettura Temperatura & Umidita' con allarme su D6 ==");
  Serial.print("Soglia T = ");
  Serial.print(sogliaTemperaturaC, 1);
  Serial.println(" C");
}

void loop() {
  // Letture dal sensore
  float temperaturaC = Environment.readTemperature();  // °C
  float umiditaRH = Environment.readHumidity();        // %RH

// --- Gestione allarme con isteresi ---
// Usiamo DUE soglie diverse per evitare ON/OFF continui vicino al limite.
//  - Soglia di ACCENSIONE  (T_on):  temperaturaC > sogliaTemperaturaC
//  - Soglia di SPEGNIMENTO (T_off): temperaturaC < (sogliaTemperaturaC - isteresiC) // Finché T resta tra T_off e T_on, manteniamo lo stato attuale (nessun cambiamento). if (!allarmeAttivo && temperaturaC > sogliaTemperaturaC) {
  // Caso 1: l'allarme è attualmente OFF e la temperatura SUPERA la soglia di ACCENSIONE.
  // Accendiamo l'allarme (LED ON) e stampiamo un messaggio di ALERT.
  allarmeAttivo = true;
  digitalWrite(pinLedAllarme, HIGH);

  Serial.print("!!! ALERT: Temperatura sopra soglia: ");
  Serial.print(temperaturaC, 1);
  Serial.println(" C");

} else if (allarmeAttivo && temperaturaC < (sogliaTemperaturaC - isteresiC)) { // Caso 2: l'allarme è attualmente ON e la temperatura SCENDE sotto la soglia di SPEGNIMENTO // (cioè sotto la soglia di accensione meno l'isteresi). // Spegniamo l'allarme (LED OFF) e informiamo che è rientrato. allarmeAttivo = false; digitalWrite(pinLedAllarme, LOW); Serial.print("Allarme DISATTIVATO: Temperatura rientrata: "); Serial.print(temperaturaC, 1); Serial.println(" C"); } // Nota sui casi limite: // - Se temperaturaC == sogliaTemperaturaC, NON si accende (serve ">" strettamente).
// - Se temperaturaC == (sogliaTemperaturaC - isteresiC), NON si spegne (serve "<" strettamente).
// Questo evita cambi di stato ripetuti quando il valore oscilla esattamente sulla soglia.

  // Stampa della temperatura e dell'umidità sulla Serial Monitor
  Serial.print("T=");
  Serial.print(temperaturaC, 1);
  Serial.print(" C   RH=");
  Serial.print(umiditaRH, 1);
  Serial.print(" %   ALLARME=");
  if (allarmeAttivo) {
    Serial.println("ON");
  } else {
    Serial.println("OFF");
  }

  delay(1000);
}

Esempio 04: Lettura Temperatura e Umidità con stampa su OLED e Serial Monitor

Abbiamo visto nella precedente lezione l’uso del display OLED dell’Arduino Sensor Kit, utilizziamolo ora per mostrare temperatura ed umidità che stamperemo anche sulla Serial Monitor.

/*
  Prof. Maffucci Michele
  01.10.2025
  Lettura Temperatura e Umidità con stampa su OLED e Serial Monitor

  - DHT20 (I2C): lascia attiva la define Environment_I2C.
  - DHT11: commenta la define sotto; la libreria gestisce il pin del Base Shield.
*/

#include <Arduino_SensorKit.h>

#define Environment Environment_I2C

void setup() {
  Serial.begin(9600);
  Wire.begin();         // necessario con DHT20/OLED su I2C
  Environment.begin();  // DHT11 o DHT20 (in base alla define)
  Oled.begin();         // inizializza OLED

  // Orientamento e font leggibile
  Oled.setFlipMode(true);
  Oled.setFont(u8x8_font_chroma48medium8_r);

  // Pulisci UNA volta all’avvio
  Oled.clearDisplay();

  // Etichette fisse (non cambiano > non serve riscriverle)
  Oled.setCursor(0, 2);
  Oled.print("T=");
  Oled.setCursor(0, 4);
  Oled.print("RH=");
}

void loop() {

  float tC = Environment.readTemperature();  // °C
  float rH = Environment.readHumidity();     // %RH

  // --Stampa su OLED

  // Sovrascrivo soltanto il campo variabile, SENZA clearDisplay
  Oled.setCursor(2, 2);  // subito dopo "T="
  Oled.print(tC);

  Oled.setCursor(3, 4);  // subito dopo "RH="
  Oled.print(rH);

  // --Stampa su seriale
  Serial.print("T=");
  Serial.print(tC);
  Serial.print(" C   RH=");
  Serial.print(rH);
  Serial.println(" %");

  delay(500);  // aggiorna 2 volte al secondo (meno sfarfallio)
}

Esempio 05: Lettura Temperatura e Umidità con stampa su OLED e Serial Monitor ed accensione LED con isteresi

Aggiungiamo alla versione precedente l’allarme dato con il LED.

/*
  Prof. Maffucci Michele
  01.10.2025
  Lettura Temperatura e Umidità con stampa su OLED e Serial Monitor
  ed accensione LED con isteresi

  - DHT20 (I2C): lascia attiva la define Environment_I2C.
  - DHT11: commenta la define sotto; la libreria gestisce il pin del Base Shield.
*/

#include <Arduino_SensorKit.h>

#define Environment Environment_I2C

// Configurazione allarme
const int pinLedAllarme = 6;            // LED collegato al pin D6
const float sogliaTemperaturaC = 25.0;  // soglia in °C
const float isteresiC = 0.5;            // isteresi per evitare lampeggi (spegnimento sotto soglia - isteresi)

bool allarmeAttivo = false;  // stato attuale dell'allarme

void setup() {
  Serial.begin(9600);
  Wire.begin();         // necessario con DHT20/OLED su I2C
  Environment.begin();  // DHT11 o DHT20 (in base alla define)
  Oled.begin();         // inizializza OLED

  // Orientamento e font leggibile
  Oled.setFlipMode(true);
  Oled.setFont(u8x8_font_chroma48medium8_r);

  // Pulisci UNA volta all’avvio
  Oled.clearDisplay();

  // Etichette fisse (non cambiano → non serve riscriverle)
  Oled.setCursor(0, 2);
  Oled.print("T=");
  Oled.setCursor(0, 4);
  Oled.print("RH=");

  pinMode(pinLedAllarme, OUTPUT);
  digitalWrite(pinLedAllarme, LOW);

  Serial.println("== Avvio lettura Temperatura & Umidita' con allarme su D6 ==");
  Serial.print("Soglia T = ");
  Serial.print(sogliaTemperaturaC, 1);
  Serial.println(" C");
}

void loop() {

  float tC = Environment.readTemperature();  // °C
  float rH = Environment.readHumidity();     // %RH

// --- Gestione allarme con isteresi ---
// Usiamo DUE soglie diverse per evitare ON/OFF continui vicino al limite.
//  - Soglia di ACCENSIONE  (T_on):  temperaturaC > sogliaTemperaturaC
//  - Soglia di SPEGNIMENTO (T_off): temperaturaC < (sogliaTemperaturaC - isteresiC) // Finché T resta tra T_off e T_on, manteniamo lo stato attuale (nessun cambiamento). if (!allarmeAttivo && tC > sogliaTemperaturaC) {
  // Caso 1: l'allarme è attualmente OFF e la temperatura SUPERA la soglia di ACCENSIONE.
  // Accendiamo l'allarme (LED ON) e stampiamo un messaggio di ALERT.
  allarmeAttivo = true;
  digitalWrite(pinLedAllarme, HIGH);

  Serial.print("!!! ALERT: Temperatura sopra soglia: ");
  Serial.print(tC, 1);
  Serial.println(" C");

} else if (allarmeAttivo && tC < (sogliaTemperaturaC - isteresiC)) {
  // Caso 2: l'allarme è attualmente ON e la temperatura SCENDE sotto la soglia di SPEGNIMENTO
  // (cioè sotto la soglia di accensione meno l'isteresi).
  // Spegniamo l'allarme (LED OFF) e informiamo che è rientrato.
  allarmeAttivo = false;
  digitalWrite(pinLedAllarme, LOW);

  Serial.print("Allarme DISATTIVATO: Temperatura rientrata: ");
  Serial.print(tC, 1);
  Serial.println(" C");
}

  // -- Stampa su OLED --

  // Sovrascrivo soltanto il campo variabile, SENZA clearDisplay
  Oled.setCursor(2, 2);  // subito dopo "T="
  Oled.print(tC);

  Oled.setCursor(3, 4);  // subito dopo "RH="
  Oled.print(rH);

  // -- Stampa su seriale --
  Serial.print("T=");
  Serial.print(tC);
  Serial.print(" C   RH=");
  Serial.print(rH);
  Serial.println(" %");

  delay(500);  // aggiorna 2 volte al secondo (meno sfarfallio)
}

Esempio 06: lettura Temperatura & Umidità con stampa su OLED e Serial Monitor ed accensione LED – su OLED viene mostrato allarme

Aggiungiamo allo sketch precedente la visualizzazione del messaggio di alert sul display. Per semplicità di lettura ho tolto i commenti nella sezione: “Gestione allarme con isteresi”, lasciando solo quelli che si riferiscono alla stampa dell’alert sul display.

/*
  Prof. Maffucci Michele
  01.10.2025
  Lettura Temperatura & Umidità con stampa su OLED e Serial Monitor
  ed accensione LED - su OLED viene mostrato allarme

  - DHT20 (I2C): lascia attiva la define Environment_I2C.
  - DHT11: commenta la define sotto; la libreria gestisce il pin del Base Shield.
*/

#include <Arduino_SensorKit.h>

#define Environment Environment_I2C

// Configurazione allarme
const int pinLedAllarme = 6;            // LED collegato al pin D6
const float sogliaTemperaturaC = 25.0;  // soglia in °C
const float isteresiC = 0.5;            // isteresi per evitare lampeggi (spegnimento sotto soglia - isteresi)

bool allarmeAttivo = false;  // stato attuale dell'allarme

void setup() {
  Serial.begin(9600);
  Wire.begin();         // necessario con DHT20/OLED su I2C
  Environment.begin();  // DHT11 o DHT20 (in base alla define)
  Oled.begin();         // inizializza OLED

  // Orientamento e font leggibile
  Oled.setFlipMode(true);
  Oled.setFont(u8x8_font_chroma48medium8_r);

  // Pulisci UNA volta all’avvio
  Oled.clearDisplay();

  // Etichette fisse (non cambiano → non serve riscriverle)
  Oled.setCursor(0, 2);
  Oled.print("T=");
  Oled.setCursor(0, 4);
  Oled.print("RH=");

  pinMode(pinLedAllarme, OUTPUT);
  digitalWrite(pinLedAllarme, LOW);

  Serial.println("== Avvio lettura Temperatura & Umidita' con allarme su D6 ==");
  Serial.print("Soglia T = ");
  Serial.print(sogliaTemperaturaC, 1);
  Serial.println(" C");
}

void loop() {

  float tC = Environment.readTemperature();  // °C
  float rH = Environment.readHumidity();     // %RH

  // --- Gestione allarme con isteresi ---
  if (!allarmeAttivo && tC > sogliaTemperaturaC) {
    allarmeAttivo = true;
    digitalWrite(pinLedAllarme, HIGH);

    // cursore nell'angolo in alto a destra
    Oled.setCursor(0, 0);
    // stampa del messaggio di alert
    Oled.print("ALERT: t>tMax");
    Serial.print("!!! ALERT: Temperatura sopra soglia: ");
    Serial.print(tC, 1);
    Serial.println(" C");
  } else if (allarmeAttivo && tC < (sogliaTemperaturaC - isteresiC)) {
    allarmeAttivo = false;
    digitalWrite(pinLedAllarme, LOW);

    // cursore nell'angolo in alto a destra
    Oled.setCursor(0, 0);
    // cancellazione con spazi del messaggio di alert
    Oled.print("             ");
    Serial.print("Allarme DISATTIVATO: Temperatura rientrata: ");
    Serial.print(tC, 1);
    Serial.println(" C");
  }

  // -- Stampa su OLED --

  // Sovrascrivo soltanto il campo variabile, SENZA clearDisplay
  Oled.setCursor(2, 2);  // subito dopo "T="
  Oled.print(tC);

  Oled.setCursor(3, 4);  // subito dopo "RH="
  Oled.print(rH);

  // -- Stampa su seriale --
  Serial.print("T=");
  Serial.print(tC);
  Serial.print(" C   RH=");
  Serial.print(rH);
  Serial.println(" %");

  delay(500);  // aggiorna 2 volte al secondo (meno sfarfallio)
}

Buon Coding a tutti 🙂

Quick References per lo studio – Checklist pre-verifica

Questa checklist mi piace definirla “un paracadute cognitivo”: in 3 minuti aiuta a controllare ciò che conta davvero prima di una prova. Tocca quattro aree chiave: contenuti, materiali, strategia del tempo, benessere, in più ho inserito una parte logistica e regole per evitare dimenticanze che costano punti. Non sostituisce lo studio: lo rende verificabile in modo chiaro e tracciabile ed anche consapevole.

Scarica PDF A4 della guida operativaApri il sorgente Markdown su GitHub

Se non sai cos’è il Markdown segui il link

---
title: "QR – Checklist pre-verifica"
version: "1.1"
autore: "<Classe/Studente>"
licenza: "CC BY 4.0"
ultimo_aggiornamento: "2025-09-30"
---

## Contenuti (sapere e saper fare)
- [ ] Ho coperto tutti gli argomenti della griglia ufficiale
- [ ] Ho svolto ≥3 esercizi rappresentativi per **ogni** argomento
- [ ] Ho rivisto gli errori frequenti e scritto una **mini-spiegazione corretta**
- [ ] Ho 1 esempio **risolto e commentato** per l’orale (se previsto)

## Materiali (cosa porto)
- [ ] Penne + riserva / correttore / righello
- [ ] Calcolatrice **consentita** (modalità esame se richiesta)
- [ ] Formulari/schede **consentite** (nome e data in alto)
- [ ] Documento / tessera / fogli protocollo (se richiesti)

## Strategia tempo (piano di gara)
- [ ] Lettura consegna (2–3′) → sottolineo verbi d’azione e vincoli
- [ ] Ordino gli esercizi: **facili → medi → difficili**
- [ ] Stima minuti per esercizio: … / … / …  (buffer +20%)
- [ ] Ultimi 5–10′ per **ricontrollo** e intestazione

## Benessere (corpo + attenzione)
- [ ] Sonno ≥7 h
- [ ] Idratazione / snack leggero
- [ ] Smartphone **spento** e fuori vista
- [ ] 2′ di respirazione se sento ansia (4-4-6)

## Logistica & regole
- [ ] Aula/orario verificati – arrivo 10′ prima
- [ ] Postazione ordinata (niente fogli non autorizzati)
- [ ] Nome, classe e data su ogni foglio
- [ ] Riletta la **policy** su citazioni/uso strumenti

## Piano d’emergenza (se mi blocco)
- [ ] Passo al punto successivo (max 90″ di stallo)
- [ ] Scrivo i **passi logici** anche se non completo
- [ ] Torno indietro con la checklist di controllo

## Note personali
- Cose da ricordare: …
- Errori tipici da evitare: …

In genere consiglio di usarla in questo modo:

  • La sera prima (3 minuti): spuntare le voci, preparare ciò che manca, chiudere con 5 minuti di ripasso mirato sugli errori tipici.
  • Mattina della prova (2 minuti): rivedere strategia tempo, impostare l’ordine degli esercizi e decidere un tempo di riserva per rivedere/correggere.
  • Durante (ultimi 5–10 minuti): ricontrollo finale: intestazione, unità di misura, passaggi logici, ordine e pulizia.

Penso che una lista di questo genere possa ridurre l’ansia (sai cosa fare e quando), abbassa i “colli di bottiglia” (materiali, tempi, regole) e si allinea alle rubriche di valutazione: ciò che la checklist rende visibile è spesso ciò che fa la differenza nel giudizio finale.

Esempio concreto su un esercizio di un possibile compito
Compito sui diagrammi di flusso

Consegna per gli studenti

Scegli un problema reale della tua giornata e trasformalo in un diagramma di flusso che porti a una decisione chiara o a un risultato misurabile. Usa blocchi standard (Start/Stop, Azione, Decisione, Input/Output) e gestisci almeno due ramificazioni condizionali.

Possibile risposta

  • Problema: come scegliere il mezzo per arrivare puntuale a scuola?
  • Input disponibili: orario attuale, tempo residuo (min), meteo (pioggia sì/no), bici disponibile sì/no, orario bus (min).
  • Output: mezzo scelto (a piedi / bici / bus) + messaggio “parti ora” / “sei in ritardo”.

Flowchart (Mermaid)

flowchart TD
  A([Start]) --> B[Leggi orario e tempo residuo]
  B --> C{Tempo residuo >= 25 min?}
  C -- No --> D{Bus in arrivo entro 10 min?}
  D -- Sì --> E[Prendi BUS]
  D -- No --> F[Chiedi passaggio / Avvisa ritardo]
  C -- Sì --> G{Piove?}
  G -- Sì --> D
  G -- No --> H{Bici disponibile e gomme ok?}
  H -- Sì --> I[Prendi BICI]
  H -- No --> L[Vai A PIEDI]
  E --> Z([Stop])
  F --> Z
  I --> Z
  L --> Z

Flowchart

Cosa valuto (mini-rubrica 10pt)

  • Correttezza sintattica dei blocchi e delle frecce (2)
  • Chiarezza degli input/output e delle condizioni (2)
  • Completezza (almeno due decisioni, tutti i casi gestiti) (3)
  • Ordine e leggibilità (etichette brevi, layout pulito) (1)
  • Coerenza con il problema reale (2)

Suggerimenti pratici

  • Definisci prima variabili e soglie (es. “tempo residuo ≥ 25′”).
  • Scrivi le domande sì/no in forma chiara (“Piove?” “Bus in arrivo entro 10′?”).
  • Se un ramo diventa lungo, prova a modularizzare (sotto-diagramma “Controllo bici”).
  • Alla fine, ripassa con la checklist: blocchi chiusi, nessuna freccia sospesa, tutti i casi coperti.

Buon ripasso 🙂