SDD1306 OLED display: cablaggio nozioni di base con l’esp8266, esp32 e Arduino – 1
L’IC SSD1306 viene utilizzato per i display OLED più comuni, è un driver CMOS OLED/PLED a chip singolo con controller per sistema di visualizzazione grafica a matrice di punti a diodi emettitori di luce organici/polimerici. E’ formatp da 128 segmenti e 64 comuni.
L’SSD1306 integra il controllo del contrasto, la RAM del display e l’oscillatore, il che riduce il numero di componenti esterni e il consumo energetico. Ha un controllo della luminosità a 256 stadi. I dati/i comandi vengono inviati dall’MCU generale tramite l’interfaccia parallela compatibile con la serie 6800/8000 selezionabile tramite hardware, l’interfaccia I2C o SPI.
Il display OLED ssd1306 su AliExpress I2C SPI SSD1306 0.91 0.96 inch OLED
Caratteristiche
- Risoluzione: pannello a matrice di punti 128 x 64 o 128 x 32
- Alimentazione elettrica
- VDD = da 1,65 V a 3,3 V per logica IC
- VCC = da 7V a 15V per il pilotaggio del pannello
- Per display a matrice
- Tensione di uscita di pilotaggio OLED, massimo 15 V
- Segmento di corrente massima della sorgente: 100uA
- Corrente massima del dissipatore comune: 15 mA
- Controllo corrente della luminosità del contrasto a 256 passaggi
- Buffer di visualizzazione SRAM 128 x 64 bit integrato
- Interfacce MCU selezionabili tramite pin:
- Interfaccia parallela a 8 bit serie 6800/8080
- Interfaccia periferica seriale a 3/4 fili
- Interfaccia I2C
- Funzione di scorrimento continuo salvaschermo sia in direzione orizzontale che verticale
- Segnale di sincronizzazione scrittura RAM
- Frame rate programmabile e rapporto di multiplexing
- Rimappatura righe e Rimappatura colonne
- Oscillatore su chip
- Layout del chip per COG e COF
- Temperatura di esercizio: da -40°C a 85°C
Cablaggio i2c
Arduino
Ricorda che Arduino funziona a 5v, quindi se la tua versione di Oled non supporta la logica a 5v devi inserire nel mezzo un convertitore di livello logico.
Qui il convertitore di livello logico Aliexpress
Il costruttore è abbastanza semplice:
/*
* Arduino UNO <--> Oled
* 3.3v VCC
* GND GND
* A4 SDA
* A5 SCL
*/
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
[...]
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
esp8266
Per ESP32 ed esp8266 è più semplice, perché il lavoro a 3.3v. Quindi non c’è bisogno di convertitore.
Il codice è lo stesso di Arduino, cambia solo il cablaggio (con standard i2c):
/*
* WeMos D1 <--> Oled
* 3.3v VCC
* GND GND
* D2 SDA
* D1 SCL
*/
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
[...]
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
esp32
/*
* ESP32 <--> Oled
* 3.3v VCC
* GND GND
* 21 SDA
* 22 SCL
*/
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
[...]
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
Cablaggio SPI
Arduino
Per SPI è necessario collegare più fili, non solo quello SPI ma anche RST e pin DC. Ricorda che Arduino ha un livello logico a 5v, quindi devi verificare che il tuo display supporti quella tensione.
// Declaration for SSD1306 display connected using software SPI (default case):
#define OLED_MOSI 12
#define OLED_CLK 13
#define OLED_DC 9
#define OLED_CS 10
#define OLED_RESET 6
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);
[...]
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if(!display.begin(SSD1306_SWITCHCAPVCC)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
esp8266
Per l’esp8266 ed esp32 è più semplice perché hanno una logica nativa a 3.3v.
// Declaration for SSD1306 display connected using software SPI (default case):
#define OLED_MOSI D7
#define OLED_CLK D5
#define OLED_DC D2
#define OLED_CS D8
#define OLED_RESET D1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);
[...]
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if(!display.begin(SSD1306_SWITCHCAPVCC)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
esp32
// Declaration for SSD1306 display connected using software SPI (default case):
#define OLED_MOSI 22
#define OLED_CLK 18
#define OLED_DC 16
#define OLED_CS 5
#define OLED_RESET 17
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);
[...]
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if(!display.begin(SSD1306_SWITCHCAPVCC)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
Libreria Adafruit
Tra le migliori librerie ci sono sempre quelle di Adafruit, gli obiettivi di Adafruit sono sempre semplicità e completezza.
Puoi trovarla su GitHub o scaricarla tramite il gestore di librerie dell’IDE di Arduino.
Questa libreria ha 2 dipendenze Adafruit BusIO
e la libreria Adafruit GFX.
Nozioni di base sul display
Puoi trovare le seguenti informazioni sul sito di Adafruit con molte altre cose, copio qui un sottoinsieme per dare semplici informazione di base e integro con alcuni altri suggerimenti.
Sistema di coordinate e unità
I pixel (elementi dell’immagine, i blocchi che costituiscono un’immagine digitale) sono indirizzati dalle coordinate orizzontali (X) e verticali (Y). Il sistema di coordinate posiziona l’origine (0,0) nell’angolo in alto a sinistra, con X positivo che aumenta a destra e Y positivo che aumenta verso il basso. Per utilizzare un layout “portrait” alto piuttosto che un formato “landscape” ampio è possibile applicare delle quattro impostazioni di rotazione, indicando quale angolo del display rappresenta l’angolo superiore sinistro .
I colori sono 1 (impostato) o 0 (trasparente). La semantica di un display OLED set/clear è “set” illuminato “clear” no.
Primitive grafiche
Qui una serie di comandi standard e cross display.
Disegnare pixels (punti)
The first is the drawing of an elementary pixel. Puoi chiamarlo con le coordinate X, Y e un colore e creerà un singolo punto:
void drawPixel(uint16_t x, uint16_t y, uint16_t color);
Disegnare linee
Puoi anche disegnare linee, con un punto iniziale e finale e un colore:
void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t color);
Per le linee orizzontali o verticali, sono disponibili funzioni di disegno delle linee ottimizzate che evitano i calcoli angolari:
void drawFastVLine(uint16_t x0, uint16_t y0, uint16_t length, uint16_t color);
void drawFastHLine(uint8_t x0, uint8_t y0, uint8_t length, uint16_t color);
Rettangoli
Poi, rettangoli e quadrati possono essere disegnati e riempiti utilizzando le seguenti procedure. Ciascuno accetta una coppia X, Y per l’angolo superiore sinistro del rettangolo, una larghezza e un’altezza (in pixel) e un colore. drawRect() disegna solo la cornice (contorno) del rettangolo mentre fillRect() riempie l’intera area con un dato colore:
void drawRect(uint16_t x0, uint16_t y0, uint16_t w, uint16_t h, uint16_t color);void fillRect(uint16_t x0, uint16_t y0, uint16_t w, uint16_t h, uint16_t color);
Per creare un rettangolo solido con un contorno, usa prima fillRect(), quindi drawRect() su di esso.
Cerchi
Allo stesso modo, per i cerchi, puoi disegnare e riempire. Ogni funzione accetta una coppia X, Y per il punto centrale, un raggio in pixel e un colore:
void drawCircle(uint16_t x0, uint16_t y0, uint16_t r, uint16_t color);
void fillCircle(uint16_t x0, uint16_t y0, uint16_t r, uint16_t color);
Rettangoli arrotondati
Per i rettangoli con angoli arrotondati, sono nuovamente disponibili sia le funzioni di disegno che di riempimento. Ognuno inizia con X, Y, larghezza e altezza (proprio come i normali rettangoli), quindi c’è un raggio d’angolo (in pixel) e infine il valore del colore:
void drawRoundRect(uint16_t x0, uint16_t y0, uint16_t w, uint16_t h, uint16_t radius, uint16_t color);
void fillRoundRect(uint16_t x0, uint16_t y0, uint16_t w, uint16_t h, uint16_t radius, uint16_t color);
Ecco un ulteriore trucco: poiché le funzioni del cerchio sono sempre disegnate rispetto a un pixel centrale, il diametro del cerchio risultante sarà sempre un numero dispari di pixel.
Triangoli
Con i triangoli, ancora una volta ci sono le funzioni di disegno e riempimento. Ciascuno richiede ben sette parametri: le coordinate X, Y per tre punti d’angolo che definiscono il triangolo, seguite da un colore:
void drawTriangle(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color);
void fillTriangle(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color);
Caratteri e testo
Ci sono due procedure di base per disegnare le stringhe e per aggiungere testo.
Puoi posizionare un singolo carattere in qualsiasi luogo e con qualsiasi colore. C’è solo un carattere (per risparmiare spazio) ed è pensato per essere 5×8 pixel, ma può essere passato un parametro di dimensione opzionale che ridimensiona il carattere di questo fattore (ad esempio size=2 renderà il testo a 10×16 pixel per carattere). È un po’ pixelato, ma avere un solo carattere aiuta a ridurre le dimensioni del programma.
void drawChar(uint16_t x, uint16_t y, char c, uint16_t color, uint16_t bg, uint8_t size);
Il testo è molto flessibile ma funziona in modo leggermente diverso. Invece di una procedura, la dimensione del testo, il colore e la posizione sono impostati in funzioni separate e quindi viene utilizzata la funzione print(), questo lo rende facile e fornisce tutte le stesse capacità di formattazione di stringhe e numeri del familiare Serial.print( )!
void setCursor(uint16_t x0, uint16_t y0);
void setTextColor(uint16_t color);
void setTextColor(uint16_t color, uint16_t backgroundcolor);
void setTextSize(uint8_t size);
void setTextWrap(boolean w);
Per impostazione predefinita, le righe di testo lunghe sono impostate per “andare a capo” automaticamente nella colonna più a sinistra. Per ignorare questo comportamento (in modo che il testo scorra sul lato destro del display, utile per gli effetti di selezione scorrevole), utilizzare setTextWrap(false). Il normale comportamento di wrapping viene ripristinato con setTextWrap(true).
Bitmaps
Puoi disegnare piccole bitmap monocromatiche (a un colore), utili per sprite e altre mini-animazioni o icone:
void drawBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h, uint16_t color);
Questo invia un blocco contiguo di bit al display, dove ogni bit “1” imposta il pixel corrispondente su “colore”, mentre ogni bit “0” viene saltato. x, y è l’angolo in alto a sinistra in cui viene disegnata la bitmap, w, h sono la larghezza e l’altezza in pixel.
Cancellazione o riempimento dello schermo
La funzione fillScreen() imposterà l’intero display su un dato colore, cancellando qualsiasi contenuto esistente:
void fillScreen(uint16_t color);
Puoi anche usare clearDisplay() per disattivare tutti i pixel.
void clearDisplay(void)
Per invertire la matrice (abilitare o disabilitare la modalità di inversione del display: bianco su nero vs nero su bianco) puoi usare invertDisplay
.
void invertDisplay(bool i)
Per gestire la luminosità istantaneamente hai la funzione dim
, che con true
abilita la modalità di luminosità minima, false
per la massima luminosità.
void dim(bool dim)
Per aggiornare la visualizzazione è possibile utilizzare.
void display(void)
Rotazione del display
Puoi anche ruotare il disegno. Possiamo ruotare solo di 0, 90, 180 o 270 gradi: qualsiasi altra cosa non è possibile.
void setRotation(uint8_t rotazione);
Scrollare la schermata
Sono presenti, inoltre, alcune funzioni per scorrere il contenuto dello schermo:
- startcrollright: scorrimento destro per tutto o parte del display;
- startcrollleft: scorrimento a sinistra per tutto o parte del display;
- startcrolldiagright: scorrimento diagonale per tutto o parte del display;
- startcrolldiagleft: scorrimento diagonale per tutto o parte del display;
- stopscroll: interrompe un’azione di scorrimento iniziata in precedenza.
Utilizzo dei caratteri
Le versioni più recenti della libreria Adafruit GFX offrono la possibilità di utilizzare caratteri alternativi. Sono inclusi diversi caratteri alternativi, oltre alla possibilità di aggiungerne di nuovi.
Dopo aver #incluso Adafruit_GFX e le librerie specifiche per il display, includi i file di font che prevedi di utilizzare nel tuo schizzo. Per esempio:
#include <Adafruit_GFX.h> // Core graphics library
#include <Adafruit_SSD1306.h> // Hardware-specific library
#include <Fonts/FreeMonoBoldOblique12pt7b.h>
All’interno di questi file .h ci sono diverse strutture di dati, inclusa una struttura di caratteri principale che di solito avrà lo stesso nome del file di caratteri (meno .h). Per selezionare un font per successive operazioni grafiche, utilizzare la funzione setFont(), passando l’indirizzo di questa struttura, come ad esempio:
tft.setFont(&FreeMonoBoldOblique12pt7b);
Per le chiamate successive a tft.print() ora utilizzeranno questo carattere. La maggior parte degli altri attributi che in precedenza funzionavano con il carattere integrato (colore, dimensione, ecc.) funzionano in modo simile qui.
Per tornare al carattere standard a dimensione fissa, chiama setFont(), passando NULL o nessun argomento:
tft.setFont();
Semplici sketch
Ora qualche sketch completo per mostrare le funzioni di base.
Scrivere testo
Ecco un semplice sketch che scrive un testo sullo schermo in una posizione specifica.
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
void setup() {
Serial.begin(115200);
delay(2000);
Serial.println(F("Starting!"));
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
Serial.println(F("Initialized!"));
// Show initial display buffer contents on the screen --
// the library initializes this with an Adafruit splash screen.
display.display();
delay(2000); // Pause for 2 seconds
// Clear the buffer
display.clearDisplay();
// Refresh (apply command)
display.display();
// Set color of the text
display.setTextColor(SSD1306_WHITE);
// Set position of cursor
display.setCursor(10, 20);
// Set text size multiplier (x1 standard size)
display.setTextSize(1);
// print text like Serial
display.print(F("www.mischianti.org"));
display.setCursor(10, 50);
// Set color of the text and color of the background
display.setTextColor(SSD1306_BLACK, SSD1306_WHITE);
display.setTextSize(1);
display.print(F("www.mischianti.org"));
// Refresh (apply command)
display.display();
}
void loop() {
}
Il risultato è:
Disegna pixel e linee
Ora disegneremo un singolo pixel e una linea.
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
void setup() {
Serial.begin(115200);
delay(2000);
Serial.println(F("Starting!"));
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
Serial.println(F("Initialized!"));
// Show initial display buffer contents on the screen --
// the library initializes this with an Adafruit splash screen.
display.display();
delay(2000); // Pause for 2 seconds
// Clear the buffer
display.clearDisplay();
// Refresh (apply command)
display.display();
// Draw a single pixel
display.drawPixel(10, 10, SSD1306_WHITE);
// Draw line
display.drawLine(10, 35, 114, 54, WHITE);
// Refresh (apply command)
display.display();
}
void loop() {
}
E il risultato:
Disegna rettangoli normali, arrotondati e quadrati
Qui lo sketch.
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
void setup() {
Serial.begin(115200);
delay(2000);
Serial.println(F("Starting!"));
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
Serial.println(F("Initialized!"));
// Show initial display buffer contents on the screen --
// the library initializes this with an Adafruit splash screen.
display.display();
delay(2000); // Pause for 2 seconds
// Clear the buffer
display.clearDisplay();
// Refresh (apply command)
display.display();
// Draw a rectangle perimeter
display.drawRect(25, 10, 30, 20, WHITE);
// Draw a filled rectangle
display.fillRect(25, 40, 30, 20, WHITE);
// Draw a round rectangle perimeter
display.drawRoundRect(75, 10, 30, 20, 5, WHITE);
// Draw a round rectangle perimeter
display.fillRoundRect(75, 40, 30, 20, 5, WHITE);
// Refresh (apply command)
display.display();
}
void loop() {
}
E qui il risultato
Disegnare cerchio e triangolo
Le ultime forme sono cerchio e triangolo, qui lo sketch.
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
void setup() {
Serial.begin(115200);
delay(2000);
Serial.println(F("Starting!"));
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
Serial.println(F("Initialized!"));
// Show initial display buffer contents on the screen --
// the library initializes this with an Adafruit splash screen.
display.display();
delay(2000); // Pause for 2 seconds
// Clear the buffer
display.clearDisplay();
// Refresh (apply command)
display.display();
// Draw a circle perimeter
display.drawCircle(40, 20, 10, WHITE);
// Draw a filled circle
display.fillCircle(40, 50, 10, WHITE);
// Draw a triangle perimeter
display.drawTriangle(75, 10, 105, 20, 80, 30, WHITE);
// Draw a filled triangle
display.fillTriangle(75, 40, 105, 50, 80, 60, WHITE);
// Refresh (apply command)
display.display();
}
void loop() {
}
E qui il risultato.
Grazie
- Display OLED SDD1306: utilizzo di base con esp8266, esp32 e Arduino
- Display OLED SDD1306: immagini, splash e animazioni
- SDD1306 e PCF8574: gestisci più dispositivi su singolo i2c con interrupt
Bravo, articolo bellissimo ed utilissimo, fatto molto bene
Grazie Brno,
è un incentivo a continuare a scrivere.