

This document provides a detailed overview of a circuit designed to interface an ESP32-S3 microcontroller with a 2.9" Tri-Color E-Ink display. The circuit utilizes SPI communication to control the display, allowing for the rendering of graphics and text. The ESP32-S3 serves as the main processing unit, while the E-Ink display provides a low-power solution for visual output.
3V3 connected to 3.3V on the E-Ink display.
GND connected to GND on the E-Ink display.
16 connected to RESET on the E-Ink display.
17 connected to DC on the E-Ink display.
10 connected to DISPCS on the E-Ink display.
11 connected to MOSI on the E-Ink display.
12 connected to SCLK on the E-Ink display.
13 connected to MISO on the E-Ink display.
#include <SPI.h>
#include "Adafruit_ThinkInk.h"
// -------- SPI pins (your wiring)
static const int EPD_SCK = 12;
static const int EPD_MOSI = 11;
static const int EPD_MISO = 13;
// -------- Control pins (your wiring)
static const int EPD_CS = 10; // DISPCS
static const int EPD_DC = 17; // DC
static const int EPD_RST = 16; // RESET
// IMPORTANT: disable BUSY to avoid hanging in busy_wait()
static const int EPD_BUSY = -1;
// If you wired SRAMCS, put that GPIO here. Otherwise -1.
static const int SRAM_CS = -1;
// 2.9" Tri-Color 296x128 with SSD1680 chipset:
ThinkInk_290_Tricolor_Z94 display(EPD_DC, EPD_RST, EPD_CS, SRAM_CS, EPD_BUSY, &SPI);
static const int W = 296;
static const int H = 128;
void drawHeartRED(int cx, int cy, int size) {
int r = size / 3;
display.fillCircle(cx - r, cy - r, r, EPD_RED);
display.fillCircle(cx + r, cy - r, r, EPD_RED);
for (int y = 0; y < size; y++) {
int yy = (cy - r) + y;
int half = (size - y) / 2;
int x0 = cx - (r + half);
int x1 = cx + (r + half);
display.drawFastHLine(x0, yy, x1 - x0 + 1, EPD_RED);
}
}
void makeDemoArtwork() {
display.fillScreen(EPD_WHITE);
// BW checkerboard
for (int y = 0; y < H; y += 8) {
for (int x = 0; x < W; x += 8) {
if (((x ^ y) & 8) == 0) display.fillRect(x, y, 8, 8, EPD_BLACK);
}
}
// white badge + border
display.fillRect(10, 10, W - 20, H - 20, EPD_WHITE);
display.drawRect(10, 10, W - 20, H - 20, EPD_BLACK);
// left info card
display.drawRect(18, 20, 184, 88, EPD_BLACK);
display.drawLine(18, 54, 201, 54, EPD_BLACK);
display.drawLine(110, 20, 110, 107, EPD_BLACK);
display.setTextWrap(false);
display.setTextSize(1);
display.setTextColor(EPD_BLACK);
display.setCursor(26, 28); display.print(F("TRI-COLOR"));
display.setCursor(26, 40); display.print(F("SSD1680 DEMO"));
display.setCursor(26, 62); display.print(F("296x128"));
display.setCursor(26, 74); display.print(F("BLACK + RED"));
// RED sun + rays
int sunX = 238, sunY = 40;
display.fillCircle(sunX, sunY, 14, EPD_RED);
static const int dx[12] = { 0, 6, 10, 12, 10, 6, 0, -6, -10, -12, -10, -6 };
static const int dy[12] = { -12, -10, -6, 0, 6, 10, 12, 10, 6, 0, -6, -10 };
for (int a = 0; a < 12; a++) {
display.drawLine(sunX + dx[a], sunY + dy[a],
sunX + 2 * dx[a], sunY + 2 * dy[a],
EPD_RED);
}
// RED heart
drawHeartRED(238, 92, 34);
// RED stripes
for (int i = 0; i < 3; i++) display.fillRect(26, 88 + i * 6, 166, 3, EPD_RED);
}
void setup() {
Serial.begin(115200);
delay(50);
// ESP32-S3 pin-mapped SPI
SPI.begin(EPD_SCK, EPD_MISO, EPD_MOSI, EPD_CS);
Serial.println(F("Init display..."));
display.begin(THINKINK_TRICOLOR);
// Fix “rotated counterclockwise”
display.setRotation(0);
// Fix “red background” for panels where 0-bit means red ink
display.setColorBuffer(1, true);
// Clear AFTER changing buffer polarity
display.clearBuffer();
makeDemoArtwork();
Serial.println(F("Calling display.display()..."));
display.display();
Serial.println(F("display.display() done."));
display.powerDown();
}
void loop() {}
// This section is reserved for documentation purposes and does not contain executable code.
This concludes the documentation for the circuit. Please refer to the code section for implementation details and the wiring section for connection specifics.