Archivi tag: elettronica

Meditazione da Maker: un supporto DIN per prototipare in fretta (e con ordine)

5 minuti da Maker del fine settimana.

In queste settimane devo prototipare velocemente e rispondere ai dubbi di studenti di classi diverse: c’è chi inizia a “giocare” con l’elettronica e chi, più grande, pensa già ai progetti per la maturità. Risultato? Un continuo montare e smontare circuiti… e l’ordine che vacilla.

Per la mia attività di making del weekend ho deciso di dare forma a un supporto di prototipazione basato su guide DIN (guide omega), utilissime in elettronica e automazione. Chi mi segue sa che in passato ho realizzato vari supporti, trovate esempi sul mio sito e su Thingiverse, soprattutto per esercitazioni con PLC e microcontrollori.

Oggi pomeriggio, stanco dei moduli sparsi sul banco, ho sfruttato solo materiale di recupero per costruire una base pratica che mi permetta di passare da un’esercitazione all’altra in pochi minuti. Ho trattato l’attività come una piccola “Meditazione da Maker”: due ore di musica in sottofondo, progettazione e realizzazione. Missione compiuta nei tempi.

Il progetto è ancora migliorabile, quindi per ora non condivido i sorgenti: li pubblicherò a breve. Dalle immagini si capisce comunque quanto sia semplice replicarlo. La base misura 22×22 cm, una scelta dettata dal pannello già a disposizione e la struttura che ospita le barre DIN riprende i miei progetti precedenti, con qualche variazione mirata.

Nei prossimi giorni arriveranno sorgenti e dettagli, tornate a trovarmi. 🙂

Arduino – istruzione “do…while” – soluzione esercizi proposti

In riferimento alla lezione: Arduino – istruzione “do…while”: eseguire almeno una volta, poi verificare pubblico una possibile soluzione agli esercizi proposti.

Esercizio 01 – Attendi pulsante

  • Consegna: attendere che un pulsante su D2 venga premuto; durante l’attesa far lampeggiare il LED integrato.
  • Vincoli: usare while come attesa in ingresso (while(digitalRead(…)==HIGH)).
  • Extra: al termine, stampare “OK” e fermarsi.

Soluzione

/*
  Prof. Maffucci Michele
  data: 27.10.25

  Soluzione esercizio 01 - Attendi pulsante
  Hardware:
    - Pulsante su D2 con INPUT_PULLUP (un capo a D2, l'altro a GND)
    - LED integrato (pin 13)
  Obiettivo:
    - Lampeggiare il LED mentre si attende la pressione del pulsante
    - Usare while(digitalRead(PIN_BTN) == HIGH) come attesa
    - Quando il pulsante viene premuto -> stampare "OK" e fermarsi
*/

// PIN_BTN dichiarato come byte e non come int per occupare meno spazio di memoria
// collegare il pulsante a GND (INPUT_PULLUP)

const byte PIN_BTN = 2;

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(PIN_BTN, INPUT_PULLUP);
  Serial.begin(9600);
  Serial.println("Premi il pulsante per continuare...");
}

void loop() {
  // Attesa attiva: finché il pulsante NON è premuto (HIGH con pull-up)
  // il LED_BUILTIN (13) lampeggia
  while (digitalRead(PIN_BTN) == HIGH) {
    digitalWrite(LED_BUILTIN, HIGH);
    delay(150);
    digitalWrite(LED_BUILTIN, LOW);
    delay(150);
  }

  // Debounce semplice per elimina rimbalzi meccanici
  // realizzato con piccolo ritardo
  delay(30);
  
  while (digitalRead(PIN_BTN) == LOW) {  // resta qui finché è tenuto premuto
  }

  Serial.println("OK");
  digitalWrite(LED_BUILTIN, HIGH);      // lascia il LED acceso come conferma
  while (true) {}                       // ferma la demo
}

Esercizio 02 – Svuota buffer seriale

  • Consegna: quando l’utente invia testo, fare echo e svuotare tutti i caratteri residui.
  • Vincoli: usare while(Serial.available()>0).
  • Extra: contare quanti byte sono stati letti e mostrarli.

Soluzione

/*
  Prof. Maffucci Michele
  data: 27.10.25

  Soluzione esercizio 02 — Svuota buffer seriale
  Obiettivo:
    - Appena arriva del testo, fare echo di TUTTI i caratteri presenti nel buffer
    - Usare while(Serial.available() > 0) per svuotare il buffer
    - Contare i byte letti e mostrarli
  Ricordare:
    - Impostare il Serial Monitor a 9600 baud
*/

void setup() {
  Serial.begin(9600);
  Serial.println("Scrivi una riga di testo e premi invio...");
}

void loop() {
  if (Serial.available() > 0) {
    int conteggioByte = 0;

    Serial.print("Echo: ");
    // Legge TUTTO ciò che è attualmente in buffer
    while (Serial.available() > 0) {
      char c = Serial.read();     // leggi un byte
      Serial.write(c);            // echo (stampa il carattere così com'è)
      conteggioByte++;            // conta i byte letti
      // piccola attesa facoltativa per dare tempo al buffer di riempirsi
      delay(1);
    }
    Serial.println();
    Serial.print("Byte letti: ");
    Serial.println(conteggioByte);
    Serial.println("----");
  }
  // Se serve introdurre qui altro codice non bloccante
}

Attenzione!

Può capitare che vengano contati due byte in più, ciò accade perché la Serial Monitor (in basso a destra)
aggiunge automaticamente i caratteri di fine riga quando premete invio.

  • entrambi NL & CR (Both NL & CR) > aggiunge due byte: \r (CR, 13) e \n (LF, 10) → ecco il tuo +2 costante;
  • a capo NL (Newline) > aggiunge un byte: \n > +1;
  • ritorno carrello (CR) (Carriage return) > aggiunge un byte: \r > +1;
  • nessuna fine riga (No line ending) > +0 (il conteggio coincide con i caratteri digitati, salvo caratteri non ASCII).

Esercizio 03 – Timer regressivo

  • Consegna: da un valore t letto da Serial (es. 5..20), eseguire un countdown finché t>0.
  • Vincoli: usare while(t>0) con t– e stampa del tempo.
  • Extra: beep finale + messaggio “Decollo!”.

Soluzione

/*
  Prof. Maffucci Michele
  data: 27.10.25

  Soluzione esercizio 03 — Timer regressivo
  Obiettivo:
    - Leggere un intero t (5..20) dal Serial Monitor
    - Eseguire while(t > 0) con stampa del tempo e t--
    - Al termine: beep su D5 e messaggio "Decollo!"
  Note:
    - Usa Serial.parseInt() per semplicità (attende un numero)
    - Per maggior informazioni sull'uso di parseInt() consultare il link:
      https://wp.me/p4kwmk-4Ah
*/

const int PIN_BUZ = 5;  // collegare un buzzer piezo (se disponibile)

void setup() {
  Serial.begin(9600);
  pinMode(PIN_BUZ, OUTPUT);
  Serial.println("Inserisci un numero intero t tra 5 e 20 e premi invio:");
}

void loop() {
  int t = 0;

  // Attendi un numero valido nell'intervallo [5..20]
  while (t < 5 || t > 20) {
    if (Serial.available() > 0) {
      t = Serial.parseInt();  // legge il primo intero disponibile
      // Svuota residui (ad es. '\n')
      while (Serial.available() > 0) Serial.read();

      if (t < 5 || t > 20) {
        Serial.println("Valore non valido. Inserisci un numero tra 5 e 20:");
      }
    }
  }

  // Countdown con while(t > 0)
  while (t > 0) {
    Serial.print("T-");
    Serial.println(t);
    delay(1000);  // 1 secondo
    t--;
  }

  // Fine: beep + messaggio
  tone(PIN_BUZ, 880, 350);  // beep di 350 ms
  Serial.println("Decollo!");

  while (true) {}  // ferma la demo
}

Buon lavoro.

Quick References per lo studio – Prototipi hardware: sicurezza & ordine

 

In laboratorio sicurezza = metodo + ordine. Un prototipo ben organizzato non è solo più “bello”: è più sicuro, più facile da testare e più veloce da riparare. Lavoriamo con alimentazioni, correnti, componenti sensibili: le buone abitudini proteggono persone, strumenti e risultati.

  1. Preparazione dell’area
  • Banco pulito: via oggetti non necessari, liquidi lontani, cavi non incrociati.
  • Illuminazione adeguata, seduta stabile, spazio per notebook/strumenti.
  • Documenti a portata: schema, pinout, datasheet; cartellina con buste (evita “pezzi sparsi”).
  1. Alimentazione: scelte e verifiche
  • Parti sempre disalimentato: cabla a cavo staccato.
  • Tensione e corrente: verifica che la sorgente regga (es. 5 V/2 A per moduli + motori).
  • Polaritá corretta: segna rosso = +, nero = GND; no fili volanti senza colore.
  • Protezione: preferisci alimentatori con limite di corrente o fusibili rapidi; imposta limiti sul banco di alimentazione.
  • GND comune: con più sorgenti, i riferimenti di massa vanno uniti (salvo isolamenti voluti).
  1. Cablaggio e componenti
  • Cavi corti e fissati (fascette/nastro): riduce falsi contatti.
  • Breadboard: limiti (resistenza di contatto, cadute, correnti basse). Per correnti > 200–300 mA, evita breadboard → morsetti/stripboard.
  • Sezione dei fili adeguata (motori ≠ jumper sottili).
  • Polarità di LED, elettrolitici, moduli. Diodo di ricircolo con carichi induttivi (relè/motori).
  • ESD (sensori e IC): tocca massa prima di maneggiare, se possibile usa bracciale ESD.
  1. Strumentazione e misure
  • Multimetro: inizia sul fondo scala più alto; controlla sonde e modalità (V, A, Ω).
  • Misure “prima di accendere”: continuità su alimentazione (niente corto), verifica resistenze sospette.
  • Misure “dopo”: V su pin chiave, I assorbita dal sistema, calore (dito/misuratore IR).
  • Log: annota valori e condizioni (tensione di alimentazione, carico, ambiente).
  1. Procedura di test (incrementale)
  • Un passo alla volta: prima l’alimentazione, poi un sensore, poi un attuatore…
  • Stato noto ad ogni passaggio: se qualcosa “salta”, sai dove guardare.
  • Rollback: se peggiori, torna alla versione stabile precedente.
  1. Chiusura lavori (safety & ordine)
  • Spegni/disalimenta, scollega, lascia un post-it con lo stato del prototipo (“sensore X instabile; rifare cablaggio domani”).
  • Rimetti a posto componenti (sacchetti etichettati), attrezzi, cavi avvolti.
  • Backup: foto cablaggi, schema aggiornato, commit del codice con messaggio chiaro.
  1. Rischi tipici & prevenzione
  • Surriscaldamento: dissipatori/pad termici, correnti entro specifiche.
  • Corto accidentale: fili spelati, breadboard usurate, stagnature “a goccia” → isola e rifinisci.
  • Rumore elettrico: twist dei cavi segnale, condensatori di bypass (0.1 µF vicino ai Vcc), massa stellare.
  • Batterie Li-ion/LiPo: carica solo con circuiti dedicati, non perforare o piegare, mai cortocircuitare, storage a ~3.8 V.
  • Meccanica: bordi vivi, parti in movimento: occhiali protettivi se c’è rischio.

Scarica PDF A4 della guida operativaApri il sorgente Markdown su GitHub

Se non sai cos’è il Markdown segui il link

---
title: "QR – Prototipi hardware: sicurezza & ordine"
version: "1.2"
autore: "<Classe/Studente>"
licenza: "CC BY 4.0"
ultimo_aggiornamento: "2025-10-05"
---

## 1) Preparazione dell’area
- [ ] **Banco pulito** (via liquidi/oggetti inutili), **luce buona**, sedia stabile.
- [ ] **Documenti a vista**: schema, pinout, datasheet (cartella o busta trasparente).
- [ ] PC/Notebook con IDE aperto e cavo **funzionante**.
- [ ] Foto “prima” del banco (torna utile per confronto e relazione).

## 2) Alimentazione (scelte & verifiche)
- [ ] Cabla **a cavo staccato**; alimenta **solo a fine controllo**.
- [ ] Tensione/ corrente **coerenti** con il carico (es. 5 V/2 A).
- [ ] **Polaritá marcata**: rosso = +V, nero = GND; niente fili volanti non isolati.
- [ ] Se possibile, **limite di corrente** sull’alimentatore o fusibile rapido.
- [ ] Con più sorgenti, **GND comune** (salvo isolamenti voluti).

## 3) Cablaggio e componenti
- [ ] **Cavi corti e fissati** (fascette/nastro); evitare anelli e incroci inutili.
- [ ] Breadboard ok per segnali/ piccole correnti; per >300 mA usa morsetti/stripboard.
- [ ] Sezione fili adeguata (motori ≠ jumper sottili).
- [ ] **Polarità**: LED/elettr. corretta; **diodo di ricircolo** con relè/motori.
- [ ] **ESD**: tocca GND prima di maneggiare IC/sensori; se possibile usa bracciale.

## 4) Strumentazione & misure
- [ ] Multimetro: scala corretta (V, A, Ω) e **sonde ben inserite**.
- [ ] **Prima di accendere**: continuità tra +V e GND (no corto).
- [ ] **Dopo**: misura V su pin chiave, **corrente assorbita**, temperatura (dito/IR).
- [ ] Logga dati e condizioni (V aliment., carico, ambiente).

## 5) Procedura di test (incrementale)
1. **Alimenta** → verifica solo la parte di potenza.
2. **Aggiungi** un modulo alla volta (sensore → attuatore).
3. **Stato noto** a ogni passo; se peggiori, **rollback** alla versione stabile.
4. Una modifica per volta (HW *o* SW), poi test.

## 6) Chiusura lavori
- [ ] **Spegni e scollega**.
- [ ] **Post-it** di stato: “sensore X instabile; rifare cablaggio domani”.
- [ ] Riponi componenti/attrezzi; avvolgi cavi.
- [ ] **Backup**: foto cablaggio, schema aggiornato, commit codice con messaggio chiaro.

## 7) Rischi tipici & prevenzione
- **Surriscaldamento** → dissipatori/pad; rispetta correnti massime; ventilazione.
- **Corto** → rifinisci stagnature; isola punti nudi; sostituisci breadboard usurate.
- **Rumore elettrico** → twist cavi segnale, **bypass 0.1 µF** vicino a Vcc, massa a stella.
- **Batterie Li-ion/LiPo** → carica **solo** con circuiti dedicati; non perforare/piegare; mai in corto; storage ~3.8 V.

Esempio – “Il motore non parte e il driver scotta”

Setup

  • Alimentazione 12 V (banco da laboratorio, limite corrente 1.5 A).
  • Driver ponte H (es. L298N o similare), motore DC 6–12 V, Arduino UNO.
  • Cavi: alimentazione 0.5–0.75 mm², segnale jumper corti.

Sintomi

  • A “start”, motore fermo o vibra; driver caldo dopo pochi secondi; LED di alimentazione ok.

Procedura di diagnosi

01. Isola blocchi

    • Scollega Arduino → alimenta solo il driver e il motore in manuale: ponticella IN1=HIGH, IN2=LOW (o usa enable).
    • Se ancora fermo, il problema è driver/motore (non il codice).

02. Verifica alimentazione

    • Misura V_motore a vuoto: ~12 V?
    • Cala a 5–6 V quando provi a muoverlo? → alimentatore in current limit (motore richiede più spunto).
    • Soluzione: alimentatore con corrente di picco più alta o soft-start (PWM graduale).

03. Controlla cablaggio e polarità

    • GND comune tra Arduino e driver.
    • Sezione fili verso motore sufficiente (evita jumper sottili).
    • Diodi di ricircolo: presenti/integrati? Se driver ne è privo, aggiungili.

04. Assorbimento & termica

    • Misura corrente di spunto (metti multimetro in serie): >1.5–2 A? Il L298N satura e scalda.
    • Opzioni: driver più efficiente (MOSFET, es. BTS7960 o ponte H moderno), abbassa tensione o usa PWM limitato all’avvio.

05. Test incrementale

    • Motore scollegato > misura V ai morsetti del driver con PWM 30/60/100%.
    • Se V è stabile e driver non scalda → il problema è carico (motore duro/ingranaggi).
    • Lubrifica/controlla meccanica; prova con un motore “buono”.

Checklist “fatto”

  • Motore avvia fluido a PWM 30→60→100%.
  • Driver < 70 °C dopo 2′ di lavoro (dito o termometro IR).
  • Alimentatore non entra in limit; cavi non scaldano.
  • GND comune, fili fissati, schema aggiornato con modello driver.

Note didattiche

Mostrare agli studenti foto prima/dopo del cablaggio, la tabella di misure (V/I a step di PWM) e un grafico corrente-tempo allo spunto: è evidente perché alcuni driver scaldano.

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 &lt;Arduino_SensorKit.h&gt;   // 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 🙂

Lezione 8 – Corso di Elettronica Creativa con Arduino Sensor Kit

Lo schermo OLED

Questo modulo è un display OLED monocromatico 128×64 con interfaccia Grove a 4 pin I²C, adatto a mostrare testi e semplici indicatori grafici direttamente dall’Arduino Sensor Kit. Rispetto agli LCD, gli OLED offrono autoluminescenza, alto contrasto, ampio angolo di visione e basso consumo, perché non richiedono retroilluminazione.

L’OLED (Organic Light-Emitting Diode) usa materiali organici che emettono luce quando attraversati da corrente; non avendo una retroilluminazione, ogni pixel deve essere acceso/aggiornato dal controller. Nel Sensor Kit l’OLED 0,96″ (famiglia SSD1306/SSD1315) si controlla in modo semplificato tramite la libreria Arduino_SensorKit, che fornisce la classe Oled con metodi pronti per inizializzazione, posizionamento del cursore e stampa del testo.

Collegamento

  • Inserire il modulo/display sul connettore I2C del Grove Base Shield, monta lo shield su Arduino UNO e collega via USB.
  • Impostare l’interruttore del Base Shield su 5V (necessario per alimentare correttamente il display).
  • Su Arduino UNO i pin I²C sono SDA=A4 e SCL=A5; l’indirizzo I²C tipico dei moduli SSD1306 è 0x3C (alcuni esemplari possono usare 0x3D). Se non risponde, esegui uno scanner I²C per verificarlo.
  • Sull’Arduino Sensor Kit collegare il display al connettore I2C come mostrato nell’immagine che segue.

Librerie da utilizzare

  • Oled.begin() inizializza il controller con l’indirizzo corretto e imposta modalità/parametri base di comunicazione I²C.
  • Oled.setCursor(x,y) posiziona il cursore: con l’API U8x8 esposta dal kit lavori in celle di carattere 8×8 (circa 16 colonne × 8 righe su 128×64).
  • Oled.print(...) scrive testo/valori;
  • Oled.refreshDisplay() aggiorna lo schermo.

L’API U8x8 è “testo-only” e non richiede buffer RAM; per disegni pixel-level bisogna usare l’API grafica U8g2 (con font e funzioni grafiche più ricche).

Le differenze tra le due API:

  • U8x8 = velocità e semplicità e solo per testo;
  • U8g2 = grafica avanzata con e richiede più memoria.

Per i più curiosi

Il controller SSD1306 gestisce la RAM del display per pagine e supporta vari modi di indirizzamento (orizzontale/verticale/pagina). Le librerie si occupano dei dettagli, ma sapere che l’aggiornamento avviene “a blocchi” aiuta a capire perché alcune operazioni grafiche richiedono più tempo/buffer.

Specifiche del display

  • Alimentazione: 3,3–5 V (compatibile con UNO).
  • Interfaccia: I²C (Grove 4 pin).
  • Indirizzo: 0x3C (varianti 0x3D).
  • Caratteristiche d’uso: alto contrasto, basso consumo, ampia temperatura operativa (fino a –40…+85 °C su molte versioni).

Qualche consiglio da tenere a mente durante le sperimentazioni

  • Non lasciare per ore la stessa immagine ad alto contrasto; meglio aggiornare periodicamente o usare una schermata di riposo.
  • Stabilità del contenuto: se il testo “sfarfalla”, stampare prima su Serial Monitor per verificare i valori e ridurre la frequenza di refresh (es. ogni 100–200 ms).
  • Differenza tra griglia di caratteri (U8x8) e coordinate in pixel (U8g2): una “barra” fatta di caratteri ha 16 step, mentre a pixel può averne 128.

Esempi pratici

Versione con commenti per gli studenti in cui viene dettagliato il funzionamento di ogni parte del codice.

Esempio 1 (semplice)

/*
Prof. Maffucci Michele
25/09/2025
OLED – Scrivere nome e cognome - versione 1
Inizializzare il display OLED del Sensor Kit e mostrare
"Allievo:" su una riga, poi Nome e Cognome sulla riga sotto.
*/

#include <Arduino_SensorKit.h>  // Include la libreria del Sensor Kit.
// Questa libreria mette a disposizione l’oggetto 'Oled' (già pronto)
// per usare facilmente il display senza dover scrivere codice di basso livello (I2C).

void setup() {
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).

Oled.setCursor(0, 2);
// Posiziona il cursore alla colonna 0, riga 2 (terza riga dall’alto).
// Le coordinate sono "a caratteri" (non in pixel).

Oled.print("Allievo:");
// Stampa il testo "Allievo:" nella posizione corrente.

Oled.setCursor(0, 4);
// Sposta il cursore alla riga 4 (quinta riga), colonna 0.
// Qui stamperemo nome e cognome.

Oled.print("Michele");
// Stampa il nome.

Oled.print(" ");
// Stampa uno spazio tra nome e cognome.

Oled.print("Maffucci");
// Stampa il cognome.

Oled.refreshDisplay();
// Aggiorna fisicamente lo schermo.
// Finché non richiami refreshDisplay(), il display potrebbe non mostrare i nuovi testi.
}

void loop() {
// Vuoto: non dobbiamo aggiornare nulla in continuazione.
// Il display mantiene il testo finché non lo cambiamo nel codice.
}

Esempio 1 – senza commenti

Nel caso servisse copiare ed incollare solamente il codice per poi inserire i propri commenti vi lascio anche la versione senza commenti:

#include <Arduino_SensorKit.h> 

void setup() {
Oled.begin();
Oled.setFlipMode(true);
Oled.setFont(u8x8_font_chroma48medium8_r);
Oled.clear();
Oled.setCursor(0, 2);
Oled.print("Allievo:");
Oled.setCursor(0, 4);
Oled.print("Michele");
Oled.print(" ");
Oled.print("Maffucci");
Oled.refreshDisplay();
}

void loop() {
}

Esempio 1 – avanzato

Versione con commenti per gli studenti in cui viene dettagliato il funzionamento di ogni parte del codice.

/*
Prof. Maffucci Michele
25/09/2025
Scrive nome e cognome dell’allievo sul display OLED del Sensor Kit.
- Usa la libreria Arduino_SensorKit (oggetto Oled).
- Dimostrazione uso di: const char*, Oled.begin(), setFlipMode, setFont, setCursor, print, clear, refreshDisplay.
*/
#include <Arduino_SensorKit.h>  // Include la libreria che espone l’oggetto 'Oled'.

// -----------------------------------------------------------------------------
// DICHIARAZIONE DELLE STRINGHE
// 'const char*' = puntatore a caratteri costanti (stringa C in sola lettura).
// Puntano a letterali con terminatore '\0' (durata statica, non vanno modificati).
// -----------------------------------------------------------------------------
const char* nomeAllievo = "Michele"; // sostituisci con il nome reale (es. "Luca")
const char* cognomeAllievo = "Maffucci"; // sostituisci con il cognome (es. "Rossi")

void setup() {
// ---------------------------------------------------------------------------
// INIZIALIZZAZIONE DEL DISPLAY
// Oled.begin() avvia l'I2C e programma il controller del display (SSD1306/1315).
// Senza questa chiamata, il display non mostrerà nulla.
// ---------------------------------------------------------------------------
Oled.begin();

// setFlipMode(true) ruota il contenuto di 180°.
// Usarlo se il testo appare "capovolto" a causa dell’orientamento fisico.
// Mettere false se già si vede diritto.
Oled.setFlipMode(true);

// Seleziona il font 8x8 "chroma48medium8_r".
// Con font 8x8, lo schermo 128x64 si comporta come una griglia 16 colonne × 8 righe.
Oled.setFont(u8x8_font_chroma48medium8_r);

// ---------------------------------------------------------------------------
// PULIZIA E STAMPA DEL CONTENUTO
// ---------------------------------------------------------------------------

// Cancella tutto il contenuto precedente del display.
Oled.clear();

// Posiziona il cursore (colonna=0, riga=2) in coordinate "a caratteri" (non pixel).
// (0,2) significa: prima colonna, terza riga della griglia 16x8.
Oled.setCursor(0, 2);

// Stampa un’etichetta. Con la macro F("...") il testo resta in flash (serve per risparmiare RAM).
Oled.print(F("Allievo:"));

// Vai a riga 4, colonna 0, e stampa nome + cognome separati da spazio.
Oled.setCursor(0, 4);
Oled.print(nomeAllievo); // stampa la stringa puntata da 'nomeAllievo'
Oled.print(" "); // spazio tra nome e cognome
Oled.print(cognomeAllievo);

// Aggiorna fisicamente lo schermo: senza refresh, la nuova scritta potrebbe non apparire.
Oled.refreshDisplay();
}

void loop() {
// Nessuna azione periodica: il display mantiene il contenuto finché non lo cambiate.
// (Se volete far lampeggiare o scorrere il testo, lo fareste nel loop)
}

Esempio 1 – avanzato – senza commenti

#include <Arduino_SensorKit.h> 

const char* nomeAllievo = "Michele";
const char* cognomeAllievo = "Maffucci";

void setup() {
Oled.begin();
Oled.setFlipMode(true);
Oled.setFont(u8x8_font_chroma48medium8_r);
Oled.clear();
Oled.setCursor(0, 2);
Oled.print(F("Allievo:"));
Oled.setCursor(0, 4);
Oled.print(nomeAllievo);
Oled.print(" ");
Oled.print(cognomeAllievo);
Oled.refreshDisplay();
}

void loop() {
}

Che cosa significa char*? Perché const char* qui?

  • char è il tipo carattere in C/C++ (1 byte).
  • char* è un puntatore a char: invece di contenere direttamente un carattere, contiene l’indirizzo di memoria dove si trova una sequenza di caratteri (una stringa in stile C).
  • Le stringhe letterali scritte tra virgolette, es. "Nome", sono array di char terminati da \0 (null terminator). Hanno durata statica: esistono per tutta l’esecuzione del programma e sono solitamente in sola lettura.

Per questo si usa:

const char* nomeAllievo = "Nome";
  • const indica che non vogliamo (e non dobbiamo) modificare quei caratteri (sono un letterale costante).
  • Il tipo completo si legge: “puntatore a char costanti“. Potete cambiare il puntatore (farlo puntare ad un’altra stringa), ma non i caratteri a cui punta.

Alternative possibili

  • const char nomeAllievo[] = "Nome";
    (array di char costanti: il compilatore conosce la lunghezza e non potete riassegnare il nome dell’array).
  • String nomeAllievo = "Nome";
    (classe Arduino String: comoda ma usa più RAM dinamica; in progetti grandi può frammentare l’heap).

Nota su Arduino/AVR: i letterali come "testo" possono occupare SRAM a runtime se non si usa la macro F("testo") o PROGMEM. Nel nostro sketch la dimensione è minuscola, ma per testi lunghi conviene Oled.print(F("Allievo:")) per risparmiare RAM.

A cosa serve Oled.begin()

Oled.begin() inizializza il display OLED del Sensor Kit. In pratica:

  • Avvia la comunicazione I²C verso il controller del display (SSD1306/SSD1315) all’indirizzo corretto.
  • Manda la sequenza di setup al controller (accensione, modalità, contrasto di base, orientamento di default, ecc.).
  • Prepara l’oggetto Oled a ricevere comandi come setCursor, print, clear, refreshDisplay.

Senza Oled.begin() il display non risponde ai comandi, quindi va chiamato una volta nel setup().

Esempio 2

Lettura del valore analogico del potenziometro, visualizza il valore numerico grezzo dell’ADC e del valore percentuale sul display con barra (a carattere) di avanzamento.

Collegare il potenziometro all’ingresso A0.

/*
Prof. Maffucci Michele
25/09/2025
OLED
- Leggere il valore analogico dal potenziometro (0..1023 su Arduino UNO).
- Converte il valore in percentuale (0..100%).
- Visualizza il valore grezzo (ADC), la percentuale e una barra orizzontale su OLED.

Note:
- Usiamo la libreria Arduino_SensorKit che fornisce l'oggetto 'Oled' (display SSD1306/1315 via I2C).
- La barra è disegnata come sequenza di caratteri ASCII ('#').
*/

#include <Arduino_SensorKit.h>  // Include l'API semplificata per i sensori e l'OLED del Sensor Kit

// --------------------- CONFIGURAZIONE INGRESSO ANALOGICO ---------------------
// PIN del potenziometro: collega il cursore del pot al pin A0 (e gli altri due capi a +5V e GND).
const int PIN_POT = A0;

// Variabili per memorizzare il valore letto (grezzo) e la percentuale calcolata.
int valoreADC = 0; // Gamma tipica su UNO: 0..1023 (10 bit)
int percento = 0; // 0..100 (%)

// L'OLED in modalità font 8x8 ha circa 16 colonne: la barra avrà da 0 a 16 "blocchi" pieni.
const uint8_t LARGHEZZA_BAR = 16;

// -----------------------------------------------------------------------------
// Funzione di utilità: disegna una barra percentuale su una riga 'y' del display.
// Parametri:
// - y: indice riga (0..7 se font 8x8; 0 è la prima riga in alto).
// - percent: valore 0..100 che determina la lunghezza della barra.
// -----------------------------------------------------------------------------
void disegnaBarraPercento(uint8_t y, uint8_t percent) {
// Converte la percentuale 0..100 nel numero di "blocchi" (0..16)
// (uint32_t) evita overflow nella moltiplicazione su microcontrollori a 16 bit.
uint8_t pieni = (uint32_t)percent * LARGHEZZA_BAR / 100;

// 1) Pulisce la riga della barra: stampa 16 spazi per "cancellare" ciò che c'era prima.
Oled.setCursor(0, y); // posiziona il cursore all'inizio riga
for (uint8_t i = 0; i < LARGHEZZA_BAR; i++) {
Oled.print(' '); // spazio = cella vuota
}

// 2) Ridisegna i "blocchi" pieni (da sinistra verso destra) usando un carattere visibile e portabile ('#').
Oled.setCursor(0, y); // torna all'inizio riga
for (uint8_t i = 0; i < pieni; i++) {
Oled.print('#'); // carattere della barra
}
}

void setup() {
// ------------------------ INIZIALIZZAZIONE OLED ----------------------------
Oled.begin(); // inizializza I2C e il controller del display
Oled.setFlipMode(true); // ruota 180° se il testo appare capovolto (mettere false se OK)
Oled.setFont(u8x8_font_chroma48medium8_r); // font 8x8: griglia circa 16 colonne × 8 righe

// Pulizia e titolo
Oled.clear(); // cancella lo schermo
Oled.setCursor(0, 0); // colonna 0, riga 0 (prima riga)
Oled.print("Potenziometro"); // titolo
Oled.refreshDisplay(); // aggiorna la visualizzazione
}

void loop() {
// ----------------------------- LETTURA ADC --------------------------------
// Per stabilizzare il valore (ridurre rumore), facciamo una media di 4 campioni.
long somma = 0;
for (int i = 0; i < 4; i++) { somma += analogRead(PIN_POT); // legge l'ingresso analogico A0: 0..1023 delay(2); // piccola pausa per lasciare stabilizzare } valoreADC = somma / 4; // media semplice dei 4 campioni // ----------------------- SCALATURA IN PERCENTUALE ------------------------- // 'map' converte da una scala a un'altra: qui 0..1023 > 0..100.
// Nota: 'map' restituisce un intero; per scale diverse potresti usare una formula float.
percento = map(valoreADC, 0, 1023, 0, 100);

// ----------------------------- STAMPA TESTO -------------------------------
// Riga 2: mostriamo il valore ADC grezzo.
Oled.setCursor(0, 2); // colonna 0, riga 2
Oled.print("ADC: "); // spazi finali per "coprire" cifre residue
Oled.setCursor(5, 2); // posiziona circa a metà riga
Oled.print(valoreADC); // valore numerico 0..1023

// Riga 3: mostriamo la percentuale.
Oled.setCursor(0, 3);
Oled.print("Perc: ");
Oled.setCursor(6, 3);
Oled.print(percento); // 0..100
Oled.print("%");

// ------------------------------ BARRA GRAFICA -----------------------------
// Disegna la barra percentuale alla riga 5 (sesta riga).
disegnaBarraPercento(5, percento);

// Aggiorna fisicamente il display (altrimenti potresti non vedere le modifiche).
Oled.refreshDisplay();

// Piccolo delay per fluidità; valori troppo bassi aumentano il "flicker",
// valori troppo alti rendono meno reattivo l'aggiornamento.
delay(60);
}

Buon Coding a tutti 🙂