Shelf label on an Arduino Uno
A 2.9 inch SSD1680 e-paper price tag driven with GxEPD2: drawn once with a full refresh, marked down with a partial one, and kept with the power off. The whole build, an Arduino Uno and 2 more parts, runs here in your browser on the firmware below; open it in the editor to change the wiring or the code and run it again.
Teaching? Assign it to your class in one click.
Intermediate Runs in your browser. Free, and no account needed.
The parts retail for about $44. On Mokxi they're free.
Step by step, with the wiring and the common mistakes: Arduino E-Paper Display: GxEPD2 on a 2.9 Inch Panel
The code
The firmware exactly as the editor opens it. Change a line there and press Run: it compiles in the browser.
// Shelf label: a 2.9 inch e-paper panel on an SSD1680, driven with GxEPD2,
// as the price tag on a shop shelf.
//
// e-paper SCL (CLK) -> 13 SDA (DIN) -> 11 CS -> 10 DC -> 9
// RES (RST) -> 8 BUSY -> 7 VCC -> 3.3 V GND -> GND
// button pin 2 to GND (the pin's pull-up holds it high)
//
// The label is drawn with a full refresh, about three seconds with BUSY
// high, and then the controller sleeps: e-paper keeps the picture with no
// power, which is why shelf labels run for years on a coin cell. The button
// marks the item down with a partial refresh of the price alone.
//
// The panel is 296 x 128 pixels; GxEPD2 draws it in pages that fit this
// 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_290_BS, MAX_HEIGHT(GxEPD2_290_BS)>
display(GxEPD2_290_BS(10, 9, 8, 7)); // CS, DC, RES, BUSY
const int BUTTON = 2;
bool sale = false;
void price() {
display.fillRect(150, 40, 146, 60, GxEPD_WHITE);
display.setTextColor(GxEPD_BLACK);
display.setTextSize(4);
display.setCursor(156, 52);
display.print(sale ? "$2.99" : "$4.99");
}
void drawLabel() {
display.setFullWindow();
display.firstPage();
do {
display.fillScreen(GxEPD_WHITE);
display.fillRect(0, 0, 296, 28, GxEPD_BLACK);
display.setTextColor(GxEPD_WHITE);
display.setTextSize(2);
display.setCursor(8, 6);
display.print("FRESH BREAD");
display.setTextColor(GxEPD_BLACK);
display.setTextSize(2);
display.setCursor(8, 52);
display.print("Sourdough");
display.setCursor(8, 76);
display.print("800 g");
display.drawFastHLine(8, 108, 280, GxEPD_BLACK);
price();
} while (display.nextPage());
}
void drawPrice() {
display.setPartialWindow(150, 40, 146, 60);
display.firstPage();
do {
price();
} while (display.nextPage());
}
void setup() {
Serial.begin(9600);
pinMode(BUTTON, INPUT_PULLUP);
display.init(115200);
display.setRotation(1);
drawLabel();
display.hibernate();
Serial.println("label drawn");
}
void loop() {
if (digitalRead(BUTTON) == LOW) {
sale = !sale;
drawPrice();
display.hibernate();
Serial.println(sale ? "marked down" : "full price");
delay(300);
}
}
Parts list
4 parts, plus the jumper wires. They retail for about $44; on Mokxi they're free.
- 1 × Arduino Uno R3
- 1 × Half breadboard
- 1 × E-paper display, 2.9 inch
- 1 × Pushbutton
How it is wired
10 connections, pin by pin, read from the circuit itself. Each line is one set of pins joined together, by a jumper wire or a breadboard strip.
- Ground: Arduino Uno R3 pin GND; E-paper display, 2.9 inch pin GND
- Arduino Uno R3 pin 13; E-paper display, 2.9 inch pin SCL
- Arduino Uno R3 pin 11; E-paper display, 2.9 inch pin SDA
- Arduino Uno R3 pin 10; E-paper display, 2.9 inch pin CS
- Arduino Uno R3 pin 9; E-paper display, 2.9 inch pin DC
- Arduino Uno R3 pin 8; E-paper display, 2.9 inch pin RES
- Arduino Uno R3 pin 7; E-paper display, 2.9 inch pin BUSY
- Arduino Uno R3 pin 2; Pushbutton pin 1a
- Arduino Uno R3 pin 3V3; E-paper display, 2.9 inch pin VCC
- Ground: Arduino Uno R3 pin GND; Pushbutton pin 2a
Change it and keep it
Open it in the editor, change the circuit or the code, and keep your version in a free account.