
I like electronic paper, it appears more natural and less intrusive than other types of electronic display. It doesn't have the blockiness of LCD displays, it doesn't glow, and is more easily visible in natural light. All this makes it ideal for showing slowly updating information in an unobtrusive way. I've never tried using an e-paper display before, so armed with an Ardunio, here's how I got it to work.
E-paper (also electronic ink, or e-ink) is a great choice for low power applications, so combining one with a low-power microcontroller makes perfect sense. Unfortunately a lot of the instructions I found seemed to miss out various steps, meaning this took longer than I expected. Hopefully I've gathered all the information needed for anyone else trying to get it to work here.
The Screen
I'm using a 2.9" e-paper screen from Waveshares, which are reasonably priced and relatively easy to find. Many other sizes exist, but all the examples below will be on getting this model to work. It is 296x128 pixels, black and white, and the version 2, which can be identified by a silvery "V2" sticker on the back. It comes complete with a header that you can plug into the back of the board, and then connect the wires to the Arduino with.
Waveshares have a good wiki with information about all their screens, including this one. The section "User Guides for Arduino" contains the wiring and an overview of the various functions in the demo code.
Waveshare Demo
The first thing is to get the manufacturer's demo to work. For this I'll be using the Arduino IDE running on MacOS 10.15 (Catalina), but the instructions should work anywhere you can get the Arduino IDE to work.
Waveshares have a git repository with example code, for this screen we want the folder Arduino/epd2in9, which you can download and copy into your Arduino sketch folder, and the then open the .ino
file.
To connect the screen with the Arduino, wire them together as the Waveshares wiki suggests:
Display | Wire Colour | Arduino Pin |
---|---|---|
BUSY | Purple | D7 |
RST | White | D8 |
DC | Green | D9 |
CS | Orange | D10 |
DIN | Blue | D11 |
CLK | Yellow | D13 |
VCC | Grey | 3.3V |
GND | Brown | GND |
I used the wired header included with the screen, which slots easily into the back of the screen. The colours above are the colours of the wires as they match my header, and correspond to the pins labelled on the display. I'm not sure if there wire colours are always the same, so double-check them against how the pins are labelled on the back of the display.
Once it's wired together you can upload the sketch to the Arduino and hopefully watch the screen come to life, display a few primitive shapes, the Waveshare logo, and then start a counter.
GxEPD2 Library and Demo
While the waveshare demo is nice, and uses code that you could also use to draw things on the display, I found the GxEPD2 Library to be easier to understand and use. It's based on the more generic Adafruit GFX Library, which you can use for other displays, but wraps and extends it so it can be used with Waveshares and Dalian Good Display e-paper displays.
You can install both of these libraries through the Arduino Library manager.
Before we load one of the GxEPD2 demos and look at it in more detail, we have to switch two wires between the display and the Arduino. The GxEPD2 library expects the wiring to be as follows, with pins D9 and D8 switched compared to that of the Waveshares demo.
Display | Colour | Arduino |
---|---|---|
BUSY | Purple | D7 |
RST | White | D9 |
DC | Green | D8 |
CS | Orange | D10 |
DIN | Blue | D11 |
CLK | Yellow | D13 |
VCC | Grey | 3.3V |
GND | Brown | GND |
You can also edit the code to change the pin mapping, but I found it easier just to switch the wires, that way all the demos work with less adjustment.
The best demo to open and learn from (via File > Examples > GxEPD2) is GxEPD2_Example. Before you can upload it and get it to run you need to make two minor adjustments. The first is in the file "GxEPD2_display_selection_new_style.h" (open in a tab in the Arduino IDE), where you need to uncomment (remove the //
at the start of the line) the entry, on line 17.
#define GxEPD2_DISPLAY_CLASS GxEPD2_BW
This selects a black & white e-paper display type, the alternatives being 3 and 7 colour displays. Additionally you need to uncomment line 40 for the 2.9" Waveshare board we're using (if you're using a different board, you will have to uncomment a different line).
#define GxEPD2_DRIVER_CLASS GxEPD2_290_T94_V2 // GDEM029T94 128x296, SSD1680, Waveshare 2.9" V2 variant
Once you've saved these changes you can upload the file to the Arduino and it should work.
The GxEPD2_Example file is large, and the most useful simple example function helloWorldForDummies()
is hidden starting on line 205. This gives us a great step-by-step example of how to write text onto the screen. It's easy to miss though, as it's not even used in the actual setup()
or loop()
functions that the code works through. There are additional other examples not triggered further down the file too. But if you read only one function in detail, read this one.
Simple e-paper Example with Two Fonts
To test out a couple of things to make sure I'd understood them I created the GxEPD2_with_two_fonts sketch, which adapts the included examples. The wiring is the same as the previous GxEPD2 examples.
The main difference is that I'm using two fonts on different parts of the display,, but you can't use them with the same call to display
, you have to use setPartialWindow()
again and draw it separately. This is because you can't attache a font to a specific peice of text, only all the text drawn in one call.
The fonts use up a lot of space in the Arduino's memory, especially larger fonts, as they literally take up one byte per pixel, and the more pixels the font covers, the more bytes is uses. The 24 point font uses 8815 bytes, which is about 3 times the size of the 12 point font.
Given the large amount of memory used by the fonts it's also worth noting that while the string formatting function snprintf()
1 is OK here, if the program grows much more such a memory hungry function should be avoided, and it might be necessary to start using strcpy()
, strcat()
and itoa() to create text strings with lower memory use.
There is a great article on formatting strings on the Arduino that you should read. ↩