SSD1680 e-paper display, 2.13 inch

A 2.13 inch 250x122 black and white e-paper panel on an SSD1680 over SPI. Aliases: 2.13 inch e-ink, WeAct e-paper, DEPG0213BN.

It is the display in name badges, shelf labels and weather panels that run on a coin cell for months: e-paper keeps its picture with no power at all, and only a refresh costs anything. The price is time. A full refresh takes about two seconds, and the panel flashes while it does it.

Pins

Pin What it does
VCC Supply, 3.3 V.
GND Ground.
SDA SPI data in (MOSI). It says SDA, but it is SPI.
SCL SPI clock.
CS Chip select, active low.
DC Command (low) or data (high).
RES Reset, active low. It is also the only way out of deep sleep.
BUSY High while the controller works. Wait for it to go low before the next command.

How it talks

SPI, most significant bit first, with DC marking commands. The controller has two one-bit RAMs: the black and white one (0x24, 1 is white) and the "red" one (0x26), which on this black and white panel holds the previous picture for a partial refresh. From the SSD1680 datasheet:

  • 0x12 software reset, 0x01 the gate count, 0x11 the data entry mode (which way the address counters walk), 0x44 and 0x45 the RAM window, 0x4E and 0x4F the counters.
  • 0x24 and 0x26 write RAM at the counters, eight pixels a byte.
  • 0x22 chooses the update sequence and 0x20 runs it. 0xF7 is a full refresh, 0xFC a partial one, and BUSY is high until it is done.
  • 0x10 puts it in deep sleep; only a reset on RES wakes it.

Nothing changes on the glass until a refresh finishes. Take the power away and the RAM is lost, but the glass keeps what it showed.

The library

GxEPD2_BW.h works as its tutorials use it on an Uno, drawing in pages because the panel is bigger than the board's RAM:

#include <GxEPD2_BW.h>

#define MAX_DISPLAY_BUFFER_SIZE 800
#define MAX_HEIGHT(EPD) (EPD::HEIGHT <= MAX_DISPLAY_BUFFER_SIZE / (EPD::WIDTH / 8) ? \
                         EPD::HEIGHT : MAX_DISPLAY_BUFFER_SIZE / (EPD::WIDTH / 8))

GxEPD2_BW<GxEPD2_213_BN, MAX_HEIGHT(GxEPD2_213_BN)>
    display(GxEPD2_213_BN(10, 9, 8, 7));  // CS, DC, RES, BUSY

void setup() {
  display.init(115200);
  display.setRotation(1);
  display.setTextColor(GxEPD_BLACK);
  display.setFullWindow();
  display.firstPage();
  do {
    display.fillScreen(GxEPD_WHITE);
    display.setCursor(10, 20);
    display.print("Hello World");
  } while (display.nextPage());
  display.hibernate();
}

void loop() {}

The do { } while (display.nextPage()) loop runs once for each page of 50 rows, and the last nextPage() refreshes the panel. setPartialWindow(x, y, w, h) redraws part of the picture with the quick partial refresh. hibernate() puts the controller to sleep, and the picture stays. The drawing calls are Adafruit GFX's; setFont() and the Fonts/ headers are not in Mokxi, so text is the 5x7 font, bigger with setTextSize().

What the model gets right

The SPI commands above, both RAMs, the RAM window and the data entry modes, BUSY high through a software reset, a refresh and a power sequence, deep sleep that only a reset ends, and a picture that changes only when a refresh finishes and stays with the power off, from the SSD1680 datasheet.

What it does not model

How long a refresh takes is in the panel's waveform, not the controller's datasheet: here it is 2 s for a full refresh and 0.4 s for a partial one, the panel's typical figures. The flashing of a full refresh, ghosting after many partial ones, the temperature's effect, and the red RAM's part in the waveform are not modeled. Reads are not supported.

Common mistakes

Sending commands while BUSY is high. The controller ignores what it cannot take; the library waits for BUSY for you.

Allocating a whole-panel buffer on an Uno. GxEPD2_BW<GxEPD2_213_BN, GxEPD2_213_BN::HEIGHT> needs 4000 bytes of RAM, twice what the Uno has. Use the MAX_HEIGHT pages.

Refreshing every second. E-paper is for pictures that change rarely.

See it in action

E-paper name badge draws a badge once and swaps its bottom line with a button. Open it at /templates.