Archivi tag: oled

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 🙂

Esercizio Arduino in 60 minuti – usare un display OLED

Avevo fatto una promessa ad un amico per un progetto ed ora è arrivato il tempo… 🙂

Qualche tempo fa feci una serie di acquisti elettronici da utilizzare in sperimentazioni che sto conducendo in queste settimane, tra questi un piccolo display OLED da utilizzare per dare espressione ad un piccolo robot didattico di cui sto progettando la struttura da stampare in 3D.
Come sempre questo breve articolo oltre ad essere un tutorial per quanti lo vorranno utilizzare, sarà la mia nota su cui svolgere lezioni con gli allievi.

Ciò che utilizzo è un piccolo display da 0,96 pollici OLED con risoluzione di 128×64 pixel, monocromatico bianco e quindi dalle dimensioni contenutissime solo 2.7 x 2.8 cm che utilizza il protocollo SPI, interessantissimo l’angolo di visione che è maggiore di di 160°. Acquistato su banggood ad un prezzo estremamente contenuto. Fate attenzione che le immagini riportate differiscono leggermente dal prodotto che vi verrà consegnato.
Le dimensioni del display sono tali che lo rendono ad esempio particolarmente adatto per realizzare ad orologi da polso, piccoli dispositivi medici elettronici, o sistemi wearable.
Per ora mostrerò come visualizzare caratteri e immagini, lascerò a voi gli ulteriori sviluppi.

Il driver che pilota il display è un SSD1306, tensione di alimentazione dai 3,3V ai 6V circa.
Il pilotaggio avviene utilizzando solo due pin I/O

oled

oled01

Ma cosa è il protocollo SPI?

Come probabilmente saprete per rendere semplice il trasferimento di informazioni tra sensori e microcontrollori sono stati realizzati due tipologie di protocolli: I2C (Inter-Integrated Circuit) e SPI (Serial Peripheral Interface). Le librerie di arduinio permettono di utilizzare questi protocolli con estrema facilità.
In fase progettuale la scelta del protocollo dipende dal tipo di dispositivo che si vuole utilizzare. Sicuramente potrete trovare in commercio dispositivi che permettono di utilizzare entrambi i protocolli ma è più comune trovare dispositivi che supportano un solo standard.

Non mi dilungherò in questa fase sui pregi e difetti dell’uno o dell’altro protocollo, sarà oggetto di un futuro articolo (già in cantiere) vi dico solamente che il vantaggio principale di I2C e che richiede solamente due linee, una di clock e una linea unica per i dati utilizzata sia come input che come output, per tutti i dispositivi I2C collegati al microcontrollore in cascata, quindi solo due linee a cui collegherete tutti i dispositivi I2C, però la velocità di trasmissione dei dati è inferiore a quella del protocollo SPI, nell’I2C i dati possono viaggiare solo in una direzione alla volta, ciò che non accade nell’SPI.
Nell’SPI i dati possono viaggiare ad una velocità maggiore le linee di input e di output sono separate per cui potrete inviare e ricevere dati contemporaneamente, per contro l’utilizzo di dispositivi SPI richiede una linea di connessione in più che permette di selezionare da parte del master SPI, nel nostro caso Arduino, il dispositivo che si desidera utilizzare.

Vedremo più avanti, con specifici tutorial, la differenza precisa tra questi due protocolli di comunicazione.

SPI dispone di due linee separate per l’input identificata con la sigla MOSI e per l’output identificata con la sigla MISO ed una linea per il clock. A queste tre linee vengono collegati uno o più slave e questi vengono selezionati dal master SPI attraverso la linea Slave Select (SS). Il disegno che segue chiarisce meglio quanto appena detto.

collegamenti-master-slave-spi

Partiamo con la sperimentazione

Schema di collegamento

schema-collegamento01

schema-collegamento02

schema-collegamento03

la corrispondenza di collegamento display -> Arduino è la seguente:

GND -> GND
Vcc -> 3.3V
MOSI -> 11
CLK -> 12
DC -> 9
CS -> 8

Passo 1

E’ indispensabile effettuare il download della libreria da GitHub della libreria Adafruit_SSD1306, fate click sul pulsante “Download ZIP”

github01

Nella pagina di riferimento, su GitHub trovate il link alla libreria Adafruit-GFX che deve essere anch’essa prelevata, anche in questo caso click su “Download Zip” per scaricare la libreria

Nella pagina di riferimento della libreria GFX trovate due risorse utili per la conversione di un immagine BMP in codice esadecimale, saranno utilizzeremo durante questo tutorial.

github02

Passo 2

Rinominiamo le librerie:

Adafruit_SSD1306-master -> Adafruit_SSD1306
Adafruit-GFX-Library-master -> Adafruit-GFX-Library

librerie01

librerie02

Passo 3

Spostiamo le librerie nella cartella “libraries” di Arduino e riavviamo l’IDE

librerie03

Se non ricordate dove è allocata la vostra libraries di Arduino, aprite l’IDE: File -> Preferences
Il percorso della cartella in cui sono memorizzati i vostri sketch è indicata in “Sketchbook location” in essa troverete anche la cartella libraries

librerie04

librerie05

Passo 4

Nella cartella Adafruit_SSD1306 trovate la cartella examples

librerie06

Passo 5

Selezionate l’esempio corrispondente al vostro display, nel mio caso ssd1306_128x64_spi

Il codice che segue vi permetterà di visualizzare a centro display il testo “Salve mondo”:

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

// visualizzazione di un testo su display OLED
// Prof. Michele Maffucci
// 02.10.15

// utilizzo di dispositivo SPI
// dispositivo -> Arduino

#define OLED_MOSI   11
#define OLED_CLK   12
#define OLED_DC    9
#define OLED_CS    8
#define OLED_RESET 10

Adafruit_SSD1306 display(OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);

// viene controllato se stiamo utilizzando esattamente un display a 64 righe
#if (SSD1306_LCDHEIGHT != 64)
#error("Assolutamente non corretto! Per favore correggi Adafruit_SSD1306.h!");
#endif

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

  // per default by default viene impostata una tensione ionterna di 3.3V
  display.begin(SSD1306_SWITCHCAPVCC);

  // cancelliamo lo schermo
  display.clearDisplay();

  // impostiamo il colore a bianco (in questo tipo di dsiplay possimo impostare solo bianco e nero)
  display.setTextColor(WHITE);

  // fissiamo la dimensione del testo
  display.setTextSize(1);

  // posizioniamo il cursore nella posizione x: 35; y: 32
  display.setCursor(32,32);

  // stampiamo su display il messaggio
  display.print("Salve mondo");

  // abilitiamo il display alla visualizzazione
  display.display();
}


void loop() {
// loop vuoto
}

Passo 6

Vediamo ora come muovere un testo sullo schermo, faremo oscillare il testo “Salve mondo” dall’alto verso il basso”

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

// visualizzazione di un testo in movimento su display OLED
// Prof. Michele Maffucci
// 02.10.15

// utilizzo di dispositivo SPI
// dispositivo -> Arduino

#define OLED_MOSI   11
#define OLED_CLK   12
#define OLED_DC    9
#define OLED_CS    8
#define OLED_RESET 10

Adafruit_SSD1306 display(OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);

// viene controllato se stiamo utilizzando esattamente un display a 64 righe
#if (SSD1306_LCDHEIGHT != 64)
#error("Assolutamente non corretto! Per favore correggi Adafruit_SSD1306.h!");
#endif

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

  // per default by default viene impostata una tensione ionterna di 3.3V
  display.begin(SSD1306_SWITCHCAPVCC);

  // cancelliamo lo schermo
  display.clearDisplay();

  // impostiamo il colore a bianco (in questo tipo di dsiplay possimo impostare solo bianco e nero)
  display.setTextColor(WHITE);

  // fissiamo la dimensione del testo
  display.setTextSize(1);
}


void loop() {
  // movimento verso il basso
  for (int i = 0; i < 56; i++) {
    // incrementiamo la coordinata i (coordinata y)
    // fino a quando i < 56
    // Viene fissata la coordinata x
    // per far scorrere il testo sulla stessa colonna

    display.setCursor(32, i);
    display.print("Salve mondo");
    display.display();
    display.clearDisplay();
  }
  // movimento verso l'alto
  for (int i = 56; i > 0; i--) {
    // decrementiamo la coordinata i (coordinata y)
    // fino a quando i > 0
    // Viene fissata la coordinata x
    // per far scorrere il testo sulla stessa colonna

    display.setCursor(32, i);
    display.print("Salve mondo");
    display.display();
    display.clearDisplay();
  }
}

Come specificato nei commenti per consentire il movimento sulla verticale incrementiamo e decrementiamo la coordinata y della funzione display.setCursor(x, y);

Passo 7

Vediamo ora come visualizzare un’immagine sul display.
Per effettuare questa conversione, come detto in precedenza è necessario convertire un’immagine bitmap in un array di codici esadecimali che verranno inseriti come matrice all’interno dello sketch Arduino, questo tipo di conversione potete effettuarla in diversi modi, per gli utenti Windows esiste l’utilissimo programma: LCD Assistant che vi permetterà di convertire immagini adatte per un gran numero di tipi di display.
Il programma genera un file che può essere utilizzato con qualsiasi compilatore C per AVR, ARM, PIC, 8051 e molti altri.

Poiché sono utente Mac ho utilizzato l’applicazione Java Img2Code che trovate seguendo il link da cui avete prelevato Adafruit-GFX-Library

Al fondo della pagina trovate il link al programma java Img2Code
(Per chi volesse provate trovate sempre nella stessa pagina trovate un link ad un plug-in di GIMP)

scaricate sul vostro computer e fate doppio click su: Image2Code.jar

image2code

Create la vostra immagine, che ovviamente deve essere di dimensione non superiore a 128×64

faccina-uno

Dal programma Image2Code.jar click sul pulsante “Choose file”

image2code02

image2code03

image2code04

image2code05

Selezionate il codice esadecimale generato e inseritelo all’interno dell’array a cui abbiamo dato il nome faccinaUno così come potete visualizzare nel codice

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

// visualizzazione di un bitmap su display OLED
// Prof. Michele Maffucci
// 02.10.15

// utilizzo di dispositivo SPI
// dispositivo -> Arduino

#define OLED_MOSI   11
#define OLED_CLK   12
#define OLED_DC    9
#define OLED_CS    8
#define OLED_RESET 10

Adafruit_SSD1306 display(OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);

// array dell'immagine convertita
const unsigned char PROGMEM faccinaUno [] =
{
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x1,0xc0,0x0,0x0,0x1,0xc0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x7,0xf0,0x0,0x0,0x7,0xf0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0xf,0xf8,0x0,0x0,0xf,0xf8,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0xf,0xf8,0x0,0x0,0xf,0xf8,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x1f,0xfc,0x0,0x0,0x1f,0xfc,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x1f,0xfc,0x0,0x0,0x1f,0xfc,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x3c,0x1e,0x0,0x0,0x3c,0x1e,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x38,0xe,0x0,0x0,0x38,0xe,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x38,0xe,0x0,0x0,0x38,0xe,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x70,0x6,0x0,0x0,0x30,0x7,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x70,0x7,0x0,0x0,0x70,0x7,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x70,0x7,0x0,0x0,0x70,0x7,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x70,0x7,0x0,0x0,0x70,0x7,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x70,0x7,0x0,0x0,0x70,0x7,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x70,0x6,0x0,0x0,0x30,0x7,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x30,0x6,0x0,0x0,0x30,0x6,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x38,0xe,0x0,0x0,0x38,0xe,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x38,0xe,0x0,0x0,0x38,0xe,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x1c,0x1c,0x0,0x0,0x1c,0x1c,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x1f,0xfc,0x0,0x0,0x1f,0xfc,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0xf,0xf8,0x0,0x0,0xf,0xf8,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0xf,0xf8,0x0,0x0,0xf,0xf8,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x7,0xf0,0x0,0x0,0x7,0xf0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x1,0xc0,0x0,0x0,0x1,0xc0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x18,0x0,0x0,0x0,0x0,0x0,0x0,0xc,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0xe,0x0,0x0,0x0,0x0,0x0,0x0,0x38,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x7,0x80,0x0,0x0,0x0,0x0,0x0,0xf0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x3,0xe0,0x0,0x0,0x0,0x0,0x3,0xe0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0xfc,0x0,0x0,0x0,0x0,0x1f,0x80,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x7f,0xc0,0x0,0x0,0x1,0xff,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x1f,0xfe,0x0,0x0,0x3f,0xfc,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x3,0xff,0xff,0xff,0xff,0xe0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x7f,0xff,0xff,0xff,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x7,0xff,0xff,0xf0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf,0xf8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0
};

// viene controllato se stiamo utilizzando esattamente un display a 64 righe
#if (SSD1306_LCDHEIGHT != 64)
#error("Assolutamente non corretto! Per favore correggi Adafruit_SSD1306.h!");
#endif

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

  // per default by default viene impostata una tensione ionterna di 3.3V
  display.begin(SSD1306_SWITCHCAPVCC);
}


void loop() {
  // cancelliamo lo schermo
  display.clearDisplay();

  // visualizziamo il bitmap di dimensione 128x64 px con nome: faccinaUno nella posizione (0,0) impostando il colore a bianco
  display.drawBitmap(0, 0, faccinaUno, 128, 64, WHITE);

  // attiviamo il display
  display.display();
}

Passo 8

Nell’esempio ho utilizzato una immagine di dimensioni 128×64 ma ovviamente avrei potuto utilizzare immagini più piccole, come mostrato nel codice seguente in cui utilizzo il bitmap di dimensioni 48×48 px:

faccina-uno

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

// visualizzazione di un bitmap su display OLED
// Prof. Michele Maffucci
// 02.10.15

// utilizzo di dispositivo SPI
// dispositivo -> Arduino

#define OLED_MOSI   11
#define OLED_CLK   12
#define OLED_DC    9
#define OLED_CS    8
#define OLED_RESET 10

Adafruit_SSD1306 display(OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);

// array dell'immagine convertita
const unsigned char PROGMEM faccinaUno [] =
{
0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x3f,0xfc,0x0,0x0,
0x0,0x1,0xff,0xff,0x80,0x0,
0x0,0x7,0xff,0xff,0xe0,0x0,
0x0,0x1f,0xff,0xff,0xf8,0x0,
0x0,0x3f,0xff,0xff,0xfc,0x0,
0x0,0x7f,0xff,0xff,0xfe,0x0,
0x0,0xff,0xff,0xff,0xff,0x0,
0x1,0xff,0xff,0xff,0xff,0x80,
0x3,0xff,0xff,0xff,0xff,0xc0,
0x7,0xff,0x3f,0xfc,0xff,0xc0,
0x7,0xfe,0x1f,0xf8,0x7f,0xe0,
0xf,0xfc,0xf,0xf0,0x3f,0xf0,
0xf,0xfc,0xf,0xf0,0x3f,0xf0,
0x1f,0xfc,0xf,0xf0,0x3f,0xf8,
0x1f,0xfc,0xf,0xf0,0x3f,0xf8,
0x1f,0xfc,0xf,0xf0,0x3f,0xf8,
0x3f,0xfc,0xf,0xf0,0x3f,0xfc,
0x3f,0xfe,0x1f,0xf8,0x7f,0xfc,
0x3f,0xff,0x3f,0xfc,0xff,0xfc,
0x3f,0xff,0xff,0xff,0xff,0xfc,
0x3f,0xff,0xff,0xff,0xff,0xfc,
0x3f,0xff,0xff,0xff,0xff,0xfc,
0x3f,0xff,0xff,0xff,0xff,0xfc,
0x3f,0xff,0xff,0xff,0xff,0xfc,
0x3f,0xff,0xff,0xff,0xff,0xfc,
0x3f,0xe7,0xff,0xff,0xe7,0xfc,
0x3f,0xcf,0xff,0xff,0xf3,0xfc,
0x3f,0x9f,0xff,0xff,0xf9,0xfc,
0x1e,0xf,0xff,0xff,0xf0,0x78,
0x1f,0xcf,0xff,0xff,0xf3,0xf8,
0x1f,0xe7,0xff,0xff,0xe7,0xf8,
0xf,0xf3,0xff,0xff,0xcf,0xf0,
0xf,0xf9,0xff,0xff,0x9f,0xf0,
0x7,0xfc,0x7f,0xfe,0x1f,0xe0,
0x3,0xfe,0x1f,0xf8,0x7f,0xc0,
0x3,0xff,0x0,0x0,0xff,0xc0,
0x1,0xff,0xc0,0x3,0xff,0x80,
0x0,0xff,0xfc,0x3f,0xff,0x0,
0x0,0x7f,0xff,0xff,0xfe,0x0,
0x0,0x3f,0xff,0xff,0xfc,0x0,
0x0,0x1f,0xff,0xff,0xf8,0x0,
0x0,0x7,0xff,0xff,0xe0,0x0,
0x0,0x1,0xff,0xff,0x80,0x0,
0x0,0x0,0x3f,0xfc,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0
};

// viene controllato se stiamo utilizzando esattamente un display a 64 righe
#if (SSD1306_LCDHEIGHT != 64)
#error("Assolutamente non corretto! Per favore correggi Adafruit_SSD1306.h!");
#endif

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

  // per default by default viene impostata una tensione ionterna di 3.3V
  display.begin(SSD1306_SWITCHCAPVCC);
}


void loop() {
  // cancelliamo lo schermo
  display.clearDisplay();

  // visualizziamo il bitmap di dimensione 128x64 px con nome: faccinaUno nella posizione (40,8) impostando il colore a bianco
  display.drawBitmap(40, 8, faccinaUno, 48, 48, WHITE);

  // attiviamo il display
  display.display();
}

Passo 9

Vediamo ora come visualizzare in sequenza tre immagini differenti.
Il procedimento è molto semplice, e sufficiente inserire gli array corrispondenti al bitmap che si intendono utilizzare.
Nell’esempio che segue ho utilizzato tre immagini:

faccina-uno

faccina-due

faccina-tre

Ho utilizzato i tre array con nome: faccinaUno, faccinaDue, faccinaTre

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

// visualizzazione tre bitmap in sequenza su display OLED
// Prof. Michele Maffucci
// 02.10.15

// utilizzo di dispositivo SPI
// dispositivo -> Arduino

#define OLED_MOSI  11
#define OLED_CLK   12
#define OLED_DC    9
#define OLED_CS    8
#define OLED_RESET 10

Adafruit_SSD1306 display(OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);

// array dell'immagine convertita
const unsigned char PROGMEM faccinaUno [] =
{
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x1,0xc0,0x0,0x0,0x1,0xc0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x7,0xf0,0x0,0x0,0x7,0xf0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0xf,0xf8,0x0,0x0,0xf,0xf8,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0xf,0xf8,0x0,0x0,0xf,0xf8,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x1f,0xfc,0x0,0x0,0x1f,0xfc,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x1f,0xfc,0x0,0x0,0x1f,0xfc,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x3c,0x1e,0x0,0x0,0x3c,0x1e,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x38,0xe,0x0,0x0,0x38,0xe,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x38,0xe,0x0,0x0,0x38,0xe,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x70,0x6,0x0,0x0,0x30,0x7,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x70,0x7,0x0,0x0,0x70,0x7,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x70,0x7,0x0,0x0,0x70,0x7,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x70,0x7,0x0,0x0,0x70,0x7,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x70,0x7,0x0,0x0,0x70,0x7,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x70,0x6,0x0,0x0,0x30,0x7,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x30,0x6,0x0,0x0,0x30,0x6,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x38,0xe,0x0,0x0,0x38,0xe,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x38,0xe,0x0,0x0,0x38,0xe,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x1c,0x1c,0x0,0x0,0x1c,0x1c,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x1f,0xfc,0x0,0x0,0x1f,0xfc,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0xf,0xf8,0x0,0x0,0xf,0xf8,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0xf,0xf8,0x0,0x0,0xf,0xf8,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x7,0xf0,0x0,0x0,0x7,0xf0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x1,0xc0,0x0,0x0,0x1,0xc0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x18,0x0,0x0,0x0,0x0,0x0,0x0,0xc,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0xe,0x0,0x0,0x0,0x0,0x0,0x0,0x38,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x7,0x80,0x0,0x0,0x0,0x0,0x0,0xf0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x3,0xe0,0x0,0x0,0x0,0x0,0x3,0xe0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0xfc,0x0,0x0,0x0,0x0,0x1f,0x80,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x7f,0xc0,0x0,0x0,0x1,0xff,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x1f,0xfe,0x0,0x0,0x3f,0xfc,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x3,0xff,0xff,0xff,0xff,0xe0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x7f,0xff,0xff,0xff,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x7,0xff,0xff,0xf0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf,0xf8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0
};

const unsigned char PROGMEM faccinaDue [] =
{
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0xc0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7,0xf0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf,0xf8,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf,0xf8,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1f,0xfc,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1f,0xfc,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3c,0x1e,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x38,0xe,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x1c,0x0,0x0,0x0,0x38,0xe,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x3e,0x0,0x0,0x0,0x30,0x7,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x3f,0x80,0x0,0x0,0x70,0x7,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x3f,0xc0,0x0,0x0,0x70,0x7,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0xf,0xf0,0x0,0x0,0x70,0x7,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x7,0xf8,0x0,0x0,0x70,0x7,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x1,0xfe,0x0,0x0,0x30,0x7,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0xff,0x0,0x0,0x30,0x6,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x7f,0x80,0x0,0x38,0xe,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x1f,0x0,0x0,0x38,0xe,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0xe,0x0,0x0,0x1c,0x1c,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1f,0xfc,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf,0xf8,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf,0xf8,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7,0xf0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0xc0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x1c,0x0,0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0xe,0x0,0x0,0x0,0x0,0x0,0x0,0xc,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x7,0x0,0x0,0x0,0x0,0x0,0x0,0x38,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x3,0xc0,0x0,0x0,0x0,0x0,0x0,0xf0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x1,0xf0,0x0,0x0,0x0,0x0,0x3,0xe0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x7e,0x0,0x0,0x0,0x0,0x1f,0x80,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x3f,0xe0,0x0,0x0,0x1,0xff,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0xf,0xfe,0x0,0x0,0x3f,0xf8,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x3,0xff,0xff,0xff,0xff,0xe0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x7f,0xff,0xff,0xff,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x7,0xff,0xff,0xf0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf,0xf8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0
};

const unsigned char PROGMEM faccinaTre [] =
{
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x1,0xc0,0x0,0x0,0x1,0xc0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x7,0xf0,0x0,0x0,0x7,0xf0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0xf,0xf8,0x0,0x0,0xf,0xf8,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0xf,0xf8,0x0,0x0,0xf,0xf8,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x1f,0xfc,0x0,0x0,0x1f,0xfc,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x1f,0xfc,0x0,0x0,0x1f,0xfc,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x3c,0x1e,0x0,0x0,0x3c,0x1e,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x38,0xe,0x0,0x0,0x38,0xe,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x38,0xe,0x0,0x0,0x38,0xe,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x70,0x6,0x0,0x0,0x30,0x7,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x70,0x7,0x0,0x0,0x70,0x7,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x70,0x7,0x0,0x0,0x70,0x7,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x70,0x7,0x0,0x0,0x70,0x7,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x70,0x7,0x0,0x0,0x70,0x7,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x70,0x6,0x0,0x0,0x30,0x7,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x30,0x6,0x0,0x0,0x30,0x6,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x38,0xe,0x0,0x0,0x38,0xe,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x38,0xe,0x0,0x0,0x38,0xe,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x1c,0x1c,0x0,0x0,0x1c,0x1c,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x1f,0xfc,0x0,0x0,0x1f,0xfc,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0xf,0xf8,0x0,0x0,0xf,0xf8,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0xf,0xf8,0x0,0x0,0xf,0xf8,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x7,0xf0,0x0,0x0,0x7,0xf0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x1,0xc0,0x0,0x0,0x1,0xc0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x18,0x0,0x0,0x0,0x0,0x0,0x0,0xc,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0xe,0x0,0x0,0x0,0x0,0x0,0x0,0x38,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x7,0x80,0x0,0x0,0x0,0x0,0x0,0xf0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x3,0xe0,0x0,0x0,0x0,0x0,0x3,0xe0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0xfc,0x0,0x0,0x0,0x0,0x1f,0x80,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x7f,0xe0,0x0,0x0,0x3,0xff,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x1f,0xff,0xc0,0x1,0xff,0xfc,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x3,0xff,0xff,0xff,0xff,0xe0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x7f,0xff,0xff,0xff,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x1f,0xff,0xff,0xfc,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x1f,0xff,0xff,0xf8,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0xf,0xff,0xff,0xf0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x7,0xff,0xff,0xe0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x7,0xff,0xff,0xe0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x3,0xff,0xff,0xc0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xff,0xff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7f,0xfe,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1f,0xf8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3,0xc0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0
};

// viene controllato se stiamo utilizzando esattamente un display a 64 righe
#if (SSD1306_LCDHEIGHT != 64)
#error("Assolutamente non corretto! Per favore correggi Adafruit_SSD1306.h!");
#endif

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

  // per default by default viene impostata una tensione ionterna di 3.3V
  display.begin(SSD1306_SWITCHCAPVCC);
}

void loop() {
  // cancelliamo lo schermo
  display.clearDisplay();

  // visualizziamo il bitmap di dimensione 128x64 px con nome: faccinaUno nella posizione (0,0) impostando il colore a bianco
  display.drawBitmap(0, 0, faccinaUno, 128, 64, WHITE);

  // attiviamo il display
  display.display();

  //Manteniamo persistente l'immagine per 1 secondo
  delay(1000);

  // cancelliamo lo schermo
  display.clearDisplay();

  // visualizziamo il bitmap di dimensione 128x64 px con nome: faccinaDue nella posizione (0,0) impostando il colore a bianco
  display.drawBitmap(0, 0, faccinaDue, 128, 64, WHITE);
  display.display();

  //Manteniamo persistente l'immagine per 1 secondo
  delay(1000);

  // cancelliamo lo schermo
  display.clearDisplay();

  // visualizziamo il bitmap di dimensione 128x64 px con nome: faccinaTre nella posizione (0,0) impostando il colore a bianco
  display.drawBitmap(0, 0, faccinaTre, 128, 64, WHITE);
  display.display();

  //Manteniamo persistente l'immagine per 1 secondo
  delay(1000);
}

Passo 10

Vediamo ora come muovere un’immagine su schermo, utilizzeremo una tecnica simile a quanto visto nel secondo sketch di questo tutorial.
Muoviamo da sinistra verso destra l’immagine:

faccina-uno

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

// movimento di un bitmap su display OLED
// Prof. Michele Maffucci
// 02.10.15

// utilizzo di dispositivo SPI
// dispositivo -> Arduino

#define OLED_MOSI  11
#define OLED_CLK   12
#define OLED_DC    9
#define OLED_CS    8
#define OLED_RESET 10

Adafruit_SSD1306 display(OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);

// array dell'immagine convertita
const unsigned char PROGMEM faccinaUno [] =
{
0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x3f,0xfc,0x0,0x0,
0x0,0x1,0xff,0xff,0x80,0x0,
0x0,0x7,0xff,0xff,0xe0,0x0,
0x0,0x1f,0xff,0xff,0xf8,0x0,
0x0,0x3f,0xff,0xff,0xfc,0x0,
0x0,0x7f,0xff,0xff,0xfe,0x0,
0x0,0xff,0xff,0xff,0xff,0x0,
0x1,0xff,0xff,0xff,0xff,0x80,
0x3,0xff,0xff,0xff,0xff,0xc0,
0x7,0xff,0x3f,0xfc,0xff,0xc0,
0x7,0xfe,0x1f,0xf8,0x7f,0xe0,
0xf,0xfc,0xf,0xf0,0x3f,0xf0,
0xf,0xfc,0xf,0xf0,0x3f,0xf0,
0x1f,0xfc,0xf,0xf0,0x3f,0xf8,
0x1f,0xfc,0xf,0xf0,0x3f,0xf8,
0x1f,0xfc,0xf,0xf0,0x3f,0xf8,
0x3f,0xfc,0xf,0xf0,0x3f,0xfc,
0x3f,0xfe,0x1f,0xf8,0x7f,0xfc,
0x3f,0xff,0x3f,0xfc,0xff,0xfc,
0x3f,0xff,0xff,0xff,0xff,0xfc,
0x3f,0xff,0xff,0xff,0xff,0xfc,
0x3f,0xff,0xff,0xff,0xff,0xfc,
0x3f,0xff,0xff,0xff,0xff,0xfc,
0x3f,0xff,0xff,0xff,0xff,0xfc,
0x3f,0xff,0xff,0xff,0xff,0xfc,
0x3f,0xe7,0xff,0xff,0xe7,0xfc,
0x3f,0xcf,0xff,0xff,0xf3,0xfc,
0x3f,0x9f,0xff,0xff,0xf9,0xfc,
0x1e,0xf,0xff,0xff,0xf0,0x78,
0x1f,0xcf,0xff,0xff,0xf3,0xf8,
0x1f,0xe7,0xff,0xff,0xe7,0xf8,
0xf,0xf3,0xff,0xff,0xcf,0xf0,
0xf,0xf9,0xff,0xff,0x9f,0xf0,
0x7,0xfc,0x7f,0xfe,0x1f,0xe0,
0x3,0xfe,0x1f,0xf8,0x7f,0xc0,
0x3,0xff,0x0,0x0,0xff,0xc0,
0x1,0xff,0xc0,0x3,0xff,0x80,
0x0,0xff,0xfc,0x3f,0xff,0x0,
0x0,0x7f,0xff,0xff,0xfe,0x0,
0x0,0x3f,0xff,0xff,0xfc,0x0,
0x0,0x1f,0xff,0xff,0xf8,0x0,
0x0,0x7,0xff,0xff,0xe0,0x0,
0x0,0x1,0xff,0xff,0x80,0x0,
0x0,0x0,0x3f,0xfc,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0
};

// viene controllato se stiamo utilizzando esattamente un display a 64 righe
#if (SSD1306_LCDHEIGHT != 64)
#error("Assolutamente non corretto! Per favore correggi Adafruit_SSD1306.h!");
#endif

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

  // per default by default viene impostata una tensione ionterna di 3.3V
  display.begin(SSD1306_SWITCHCAPVCC);
}


void loop() {
  // cancelliamo lo schermo
  display.clearDisplay();

  // partendo dalla posizione (0,8) spostiamo da sinistra verso destra
  // l'immagine di dimensione 48x48 px con nome: faccinaUno fino alla coordinata (48,8)

  // movimento da SX a DX
  for (int i = 0; i < 80; i++){
    display.drawBitmap(i, 8, faccinaUno, 48, 48, WHITE);
    // attiviamo il display
    display.display();
    // cancelliamo lo schermo
    display.clearDisplay();
  }

  // movimento da DX a SX
  for (int i = 80; i > 0 ; i--){
    display.drawBitmap(i, 8, faccinaUno, 48, 48, WHITE);
    // attiviamo il display
    display.display();
    // cancelliamo lo schermo
    display.clearDisplay();
  }
}

Grazie per aver sperimentato insieme a me 🙂