In questo tutorial imparerai come eseguire un ridisegno a pagine di un display E-Paper con un Arduino e perché è spesso necessario quando si usano microcontrollori con poca memoria.
Rispetto a computer personali o telefoni cellulari, i microcontrollori come Arduino hanno una memoria molto più limitata. Questa memoria ridotta può rendere difficile gestire immagini grandi o grafiche complesse. I display E-Paper spesso richiedono una quantità significativa di memoria per memorizzare l’intero contenuto dello schermo. Quando vuoi aggiornare il display, potresti non avere abbastanza RAM per contenere l’immagine completa.
Il ridisegno a pagine aiuta a risolvere questo problema. Invece di caricare tutto il contenuto del display in memoria contemporaneamente, dividi lo schermo in sezioni più piccole o “pagine”. Puoi quindi caricare e aggiornare una pagina alla volta. Questo metodo riduce l’uso della memoria e permette aggiornamenti più fluidi.
Nelle sezioni seguenti imparerai come eseguire un ridisegno a pagine per un display E-Paper usando un Arduino Uno.
Componenti necessari
Ti servirà un display E-Paper. Per questo tutorial ho scelto un display monocromatico da 2,9 pollici con risoluzione 296×128 pixel. Tuttavia, potresti usare anche un E-Paper di dimensioni diverse.
Per quanto riguarda il microcontrollore, qualsiasi Arduino o ESP32/ESP8266 andrà bene, ma per apprezzare davvero la necessità del ridisegno a pagine, ti consiglio di usare un Arduino Uno. La sua memoria limitata rende il ridisegno a pagine essenziale, anche per piccoli display E-Paper.

Display E-Paper 2,9″

Arduino Uno

Cavo USB per Arduino UNO

Set di fili Dupont

Breadboard
Makerguides is a participant in affiliate advertising programs designed to provide a means for sites to earn advertising fees by linking to Amazon, AliExpress, Elecrow, and other sites. As an Affiliate we may earn from qualifying purchases.
Cos’è un Ridisegno a Pagine
Il ridisegno a pagine è una tecnica usata nella programmazione grafica, specialmente in ambienti a bassa memoria come i microcontrollori. Permette di aggiornare un display disegnando il contenuto in “pagine” o sezioni separate.
Vediamo un esempio concreto. Il display E-Paper da 2,9″ che useremo in questo tutorial ha una risoluzione di 128×296 pixel. Assumendo che ogni pixel sia 1-bit per un display monocromatico (bianco e nero), questo significa che servono (128×296)/8 = 4736 byte per contenere l’intera matrice di pixel (immagine, frame) in RAM.
Tipicamente, l’immagine da visualizzare viene prima scritta in un buffer di display nella RAM del microcontrollore e poi inviata al controller E-Paper per aggiornare il contenuto mostrato. Tuttavia, un Arduino Uno ha solo 2KB di SRAM = 2048 byte, il che significa che non potremmo preparare un’immagine completa in RAM. In altre parole, su un Arduino Uno non possiamo creare un buffer di display abbastanza grande da contenere un’immagine 128×296.
Ridisegno a Pagine
Qui entra in gioco il Ridisegno a Pagine. Invece di preparare e inviare l’intera immagine in una volta, dividiamo l’immagine in sezioni più piccole chiamate “pagine” che si adattano alla RAM del microcontrollore. Elaboriamo quindi una pagina alla volta, le inviamo al controller E-Paper, che assembla l’immagine e aggiorna il display quando l’immagine è completa. Vedi l’immagine seguente per illustrazione:

Se usi la libreria GxEPD2, puoi vedere questo processo riflesso nel codice. Per un ridisegno a pagine, chiami prima firstPage() per iniziare il ridisegno. Poi chiami ripetutamente nextPage() in un ciclo finché tutte le pagine non sono state trasferite al display.
epd.firstPage();
do {
... // Graphics code
} while (epd.nextPage());
Nel ciclo definisci le operazioni grafiche che vuoi eseguire per creare il contenuto/immagine da visualizzare. Il ridisegno a pagine è ovviamente inefficiente, poiché devi creare lo stesso contenuto più volte, ma gli E-Paper sono lenti ad aggiornarsi, anche per un aggiornamento parziale (< 0,3 secondi), quindi questo non è un problema.
Altezza del buffer
Anche se una pagina potrebbe essere una sezione rettangolare arbitraria, la libreria GxEPD2 usa pagine a forma di strisce. La lunghezza della striscia è uguale alla larghezza del display e l’altezza dipende dalla memoria disponibile. Nel caso di un display monocromatico, puoi calcolare l’altezza h di una striscia o del buffer del display come segue,
h = buff / (width / 8)
dove buff è la dimensione in byte del buffer del display che puoi permetterti e width è la larghezza del display.
Per E-Paper con 4 livelli di grigio, o 3 o 4 colori, servono 2 bit per pixel e la formula diventa:
h = (buff / 2) / (width / 8)
Un Arduino ha 2048 byte di RAM, quindi l’altezza massima h per il display in modalità verticale sarebbe
h = 2048 / (128 / 8) = 128 pixel
Tuttavia, il buffer del display e il codice condividono la stessa memoria e non possiamo usare tutti i 2048 byte. Se usi metà della memoria per il buffer del display, otteniamo
h = 1024 / (128 / 8) = 64 pixel,
il che significa che con un’altezza del display di 296 pixel, avremmo 296 / 64 = 5 pagine.
A seconda della dimensione del codice e della RAM disponibile del tuo microcontrollore, dovrai regolare la dimensione del buffer. Se ricevi il seguente messaggio di errore durante la compilazione, significa che la dimensione del buffer è troppo grande:
Not enough memory; see https://support.arduino.cc/hc/en-us/articles/360013825179 for tips on reducing your footprint. data section exceeds available space in board. Compilation error: data section exceeds available space in board
Nelle sezioni successive collegheremo il display E-Paper all’Arduino e scriveremo del codice per dimostrare come si implementa un ridisegno a pagine.
Installazione della libreria GxEPD2 per E-Paper
Prima di poter disegnare o scrivere sull’E-Paper dobbiamo installare due librerie. La libreria Adafruit_GFX è una libreria grafica di base che fornisce un set comune di primitive grafiche (testo, punti, linee, cerchi, ecc.). E la libreria GxEPD2 fornisce il driver grafico per controllare un E-Paper via SPI.
Apri il Library Manager, cerca “Adafruit_GFX” e “GxEPD2” e premi “INSTALL”. Dopo l’installazione le librerie dovrebbero apparire nel Library Manager come segue.

Collegamento del display E-Paper all’Arduino
Lo schema di collegamento qui sotto mostra come connettere l’interfaccia SPI del display E-Paper a un Arduino. La maggior parte dei pin può essere configurata liberamente, ma per le linee DIN e CLK dobbiamo usare i pin specifici SPI. Nel caso di un Arduino Uno, DIN è al pin 11 e CLK al pin 13.

La tabella seguente elenca tutte le altre connessioni da effettuare.
| Display E-Paper | Arduino UNO |
|---|---|
| CS/SS | 4 |
| SCL/SCK/CLK | 13 |
| SDA/DIN/MOSI | 11 |
| BUSY | 7 |
| RES/RST | 6 |
| DC | 5 |
| VCC | 3.3V |
| GND | G |
Ridisegno a Pagine per E-Paper con Arduino Uno
Disegneremo la seguente immagine di test sul display E-Paper:

Qui sotto trovi il codice corrispondente. Dagli un’occhiata veloce prima, poi ne discuteremo i dettagli.
#include "GxEPD2_BW.h"
#define EPD_CS 4
#define EPD_DC 5
#define EPD_RST 6
#define EPD_BUSY 7
// CLK = 13
// DIN = 11
#define BUFF 1024
#define HEIGHT(EPD) ((BUFF / 1) / (EPD::WIDTH / 8))
GxEPD2_BW<GxEPD2_290_BS, HEIGHT(GxEPD2_290_BS)>
epd(GxEPD2_290_BS(EPD_CS, EPD_DC, EPD_RST, EPD_BUSY));
void setup() {
epd.init(115200);
epd.setRotation(1);
epd.setTextSize(2);
epd.setTextColor(GxEPD_BLACK);
epd.setFullWindow();
epd.firstPage();
do {
epd.fillScreen(GxEPD_WHITE);
epd.fillRect(30, 30, 60, 60, GxEPD_BLACK);
epd.fillTriangle (100, 120, 180, 120, 140, 60, GxEPD_BLACK);
epd.setCursor(200, 60); epd.print("TEST");
} while (epd.nextPage());
epd.hibernate();
}
void loop() {}
Iniziamo includendo la libreria grafica richiesta e definendo alcune costanti per i pin SPI. Ricorda che i pin DIN e CLK sono fissi e specifici per il tuo microcontrollore, mentre gli altri possono essere cambiati.
#include "GxEPD2_BW.h" #define EPD_CS 4 #define EPD_DC 5 #define EPD_RST 6 #define EPD_BUSY 7 // CLK = 13 // DIN = 11
Poi definiamo la dimensione del buffer del display BUFF e l’altezza della pagina HIGHT. L’altezza è calcolata tramite una macro che prende come parametro l’oggetto display EPD e usa la sua proprietà larghezza (EPD::WIDTH) per determinare l’altezza della pagina.
#define BUFF 1024 #define HEIGHT(EPD) ((BUFF / 1) / (EPD::WIDTH / 8))
Il calcolo segue la formula che abbiamo discusso prima. Per un display a tre colori useresti invece la seguente formula:
#define HEIGHT(EPD) ((BUFF / 2) / (EPD::WIDTH / 8))
Ora possiamo usare la macro HIGHT per creare l’oggetto display epd. Questo sembra complesso ma semplicemente prende le costanti dei pin, l’altezza e un tipo di display come parametri template per creare il display.
GxEPD2_BW<GxEPD2_290_BS, HEIGHT(GxEPD2_290_BS)> epd(GxEPD2_290_BS(EPD_CS, EPD_DC, EPD_RST, EPD_BUSY));
Se il tuo display non mostra nulla o mostra testo/immagini corrotte, probabilmente il display non è cablato correttamente o è stato scelto il tipo di display sbagliato.
La libreria Readme for GxEPD2 elenca tutti i display supportati e puoi trovare i dettagli nei file header, ad esempio GxEPD2.h. Trova il driver specifico per il tuo display. E magari dai un’occhiata al tutorial Interfacing Arduino with E-ink Display, dove colleghiamo un E-Paper a tre colori a un Arduino e a un ESP32.
Funzione Setup
Nella funzione setup, impostiamo prima alcuni parametri grafici come l’orientamento (verticale), la dimensione del testo, il colore del testo e la modalità di aggiornamento (finestra completa).
epd.init(115200); epd.setRotation(1); epd.setTextSize(2); epd.setTextColor(GxEPD_BLACK); epd.setFullWindow();
Esiste anche un “aggiornamento parziale”, ma qui non lo useremo. Se vuoi saperne di più, dai un’occhiata al tutorial Partial Refresh of e-Paper Display.
Infine arriviamo alla parte in cui si esegue il ridisegno a pagine. Iniziamo chiamando firstPage() per avviare il ridisegno. Poi disegniamo ripetutamente il rettangolo, il triangolo e il testo in un ciclo do-while loop finché nextPage() restituisce false.
epd.firstPage();
do {
epd.fillScreen(GxEPD_WHITE);
epd.fillRect(30, 30, 60, 60, GxEPD_BLACK);
epd.fillTriangle (100, 120, 180, 120, 140, 60, GxEPD_BLACK);
epd.setCursor(200, 60); epd.print("TEST");
} while (epd.nextPage());
Questo ciclo riempie essenzialmente il buffer del display con il contenuto di una pagina, invia quella pagina al display E-Paper, dove il controller unisce le pagine fino a completare l’immagine.
Non vedrai il display aggiornarsi pagina per pagina. Invece il controller del display aspetta che tutte le pagine siano ricevute e poi esegue un aggiornamento completo del display. Guarda il breve video qui sotto:

A proposito, se vuoi sapere l’altezza reale della pagina che il display sta usando, puoi chiamare la seguente funzione nella funzione setup per scoprirlo:
Serial.println(epd.pageHeight());
Funzione Loop
La funzione loop in questo esempio è vuota, dato che non c’è un aggiornamento periodico del contenuto.
void loop() {}
Ma supponiamo che tu voglia implementare un Digital Clock on e-Paper Display, la funzione loop conterrebbe il codice per il ridisegno a pagine invece della funzione setup.
Funzione di Disegno
Se hai applicazioni più complesse, è meglio usare una funzione di disegno invece di do-while loop per il ridisegno a pagine. La libreria GxEPD2 ti permette di definire una funzione di disegno e poi chiamare epd.drawPaged(...) per il disegno a pagine. Ecco lo schema del codice:
void draw(const void* pv) {
... // Graphics code
}
void setup() {
...
epd.drawPaged(draw, 0);
epd.hibernate();
}
void loop() {}
La funzione di disegno draw() prende un puntatore pv, che ti permette di passare parametri quando chiami epd.drawPaged(draw, 0). Ma puoi semplicemente passare 0 come puntatore parametro, se non ti serve.
L’uso di funzioni di disegno per i ridisegni a pagine rende il codice più leggibile ed estendibile. Ecco di nuovo il nostro codice di test ma ora usando una funzione di disegno invece di do-while loop:
#include "GxEPD2_BW.h"
#define EPD_CS 4
#define EPD_DC 5
#define EPD_RST 6
#define EPD_BUSY 7
// SCL(SCK)=13,
// SDA(MOSI)=11
#define BUFF 1024
#define HEIGHT(EPD) ((BUFF / 1) / (EPD::WIDTH / 8))
GxEPD2_BW<GxEPD2_290_BS, HEIGHT(GxEPD2_290_BS)>
epd(GxEPD2_290_BS(EPD_CS, EPD_DC, EPD_RST, EPD_BUSY));
void draw(const void* pv) {
epd.fillScreen(GxEPD_WHITE);
epd.fillRect(30, 30, 60, 60, GxEPD_BLACK);
epd.fillTriangle(100, 120, 180, 120, 140, 60, GxEPD_BLACK);
epd.setCursor(200, 60); epd.print("TEST");
}
void setup() {
epd.init(115200);
epd.setRotation(1);
epd.setTextSize(2);
epd.setTextColor(GxEPD_BLACK);
epd.setFullWindow();
epd.drawPaged(draw, 0);
epd.hibernate();
}
void loop() {}
E questo è tutto! Ora sai cos’è un Ridisegno a Pagine e come implementarlo.
Conclusioni
In questo tutorial hai imparato come eseguire un ridisegno a pagine di un display E-Paper monocromatico con un Arduino Uno. Se hai un E-Paper a tre colori invece che monocromatico o un ESP32, dai un’occhiata al Interfacing Arduino with E-ink Display.
Se vuoi saperne di più su aggiornamenti parziali vs completi, ti suggerisco il nostro tutorial Partial Refresh of e-Paper Display.
Inoltre, una combinazione di ridisegno a pagine, aggiornamenti parziali e completi di display E-Paper di diverse dimensioni è usata nei tutorial Temperature Plotter on e-Paper Display, Digital Clock on e-Paper Display e Analog Clock on e-Paper Display. Se ti servono esempi applicativi, li troverai lì.
Se hai altre domande, sentiti libero di chiedere nella sezione commenti.
Buon divertimento con il tinkering ; )

