I was lucky enough to get a preview of repaper.org‘s new Electronic Paper Display (also available here) with a breakout board. It is pretty cool that e-paper has finally made its way to makers with a few other products coming out too, like the E-ink shield from Seeed Studio.
In case you don’t know, e-ink technology is enables a low-power display that can maintain its image without power indefinitely. My Dad described it well as “like an electronic etch-a-sketch?” If your project needs a fast refresh rate, e-ink will not do what you want. The setup below refreshes once every couple of seconds.
The hardware is specifically designed for the TI 430 Launchpad project board, but it turned out to be easy enough wire it up to our own AlaMode with the pin assignment table provided. It even worked the first try (a rare event for me).
The open source software works with Launchpad and Arduino. It is in its early stages so programming is a bit of a challenge at this point. The example code includes a demo for displaying images from EEPROM (external chip) or PROGMEM (limted space). But I think SD really seems like the way to go here and AlaMode already has an SD slot on board so I wanted to see if I could get them working together. It turned out to be more of a challenge than I was expecting (story of my life).
Displaying on an E-ink requires four steps: two to erase the old image and two two draw the new image. The extra steps are designed to avoid and eliminate image ghosting. A ghost image is the remnants of an old image after a new image is displayed. This might be made easier in the future with a nice library that hides all of the details. In the mean time, I just wanted to get the details out there.
I started poking around the header file EPD.h and found a generic reader template which turned out to be the key. The comment is my own.
/*
* A generic reader template
*
* buffer -- write buffer for outgoing bytes
* address -- byte index, 0 to display height
* length -- number of bytes to read
*/
typedef void EPD_reader(void *buffer, uint32_t address, uint16_t length);
I wrote a function new_SD_reader() which complied with the EPD_reader template.
/*
* SD card reader Comply with EPD_reader template
*
* buffer -- write buffer for outgoing bytes
* address -- byte index, 0 to display height
* length -- number of bytes to read
*/
void new_SD_reader(void *buffer, uint32_t address, uint16_t length){
byte *my_buffer = (byte *)buffer;
for(int i=0; i < length; i++){
newFile.seek(address + i + 4);
*(my_buffer + i) = newFile.read();
}
}
The variable newFile is a File object opened elsewhere. What would be handy here is an extra argument in the EPD_reader template to specify a filename. Maybe in the next release. As it is, I just made two similar functions for reading the new and old images.
Now can swap newFile and oldFile around in loop to change the image.
File newFile, oldFile;
char *datfilenames[2] = {"IMAGES/VENUS2.dat", "IMAGES/CAT2.dat"};
void next_image(char* fn){
oldFile.close();
oldFile = newFile;
newFile = SD.open(fn);
if(!newFile){
Serial.println("new image not found");
while(1){
delay(1000);
}
}
}
// main loop
unsigned long int loop_count = 0;
void loop(){
...
case 6: // swap old image for new image
EPD.frame_cb_repeat(0, old_SD_reader, EPD_compensate);
EPD.frame_cb_repeat(0, old_SD_reader, EPD_white);
EPD.frame_cb_repeat(0, new_SD_reader, EPD_inverse);
EPD.frame_cb_repeat(0, new_SD_reader, EPD_normal);
// swap files
next_image(datfilenames[loop_count++ % 2]);
state = 6; // backe to picture nex time
break;
...
The complete code can be found here. Before you can run it, you will need to covert the xbm format to a simple byte format. I’ve written this quick and dirty python code to do the trick.