WyoLum EReader Library

IMG_20130515_190044_194

If you have an E-Paper Display form Adafruit, this library will allow you to draw points, lines, circles, ellipses, ASCII text and Unicode text (thanks Roman Czyborra).  Oh, and display images (in the WyoLum Image Format).  Please consider this an alpha release and help us find the bugs.

Overview
Besides looking great in full sun, E-Paper requires very little power and can maintain an image for a very long time without any power at all.  It costs energy only to turn the “page”.  If low power is the reason you are considering E-Paper in your design, then you probably want to consider the power requirements of the whole system.  If you can get by with an ATMEGA328 (like what is in most Arduino’s) your power requirements are greatly relaxed when compared to the more capable processors out there.   My Arduino DUE running “blink.ino” uses 120 mA at 5V whereas my UNO uses six times less: only 20 mA.

The problem is that the ATMEGA328 does not have enough memory to display very much.  That is where the SD card comes in.   Even a small SD card by today’s standard has an unimaginable amount of space for an Arduino project.  We use the SD to store, pre-formatted images (WIF) of any size, font files, and as the frame buffer for the display.  The frame buffer allows you to configure the next image behind the scene and the update the display all at once.  This is because the underlying EPD library does not support partial updates.

IMG_20130516_062723_614

Build it.
Note: We will be using the AlaMode for this tutorial, but any Arduino compatible with an SD card connected should work.

1. Use spare male header pins to connect the AlaMode to the EPD display using the wiring bundle included with the EPD or use gender bender jumpers as pictured here. You can find the pin assignments here on the repaper.org site.
2. Create any images you’d like to be able to display using these instructions to WIF your images.
3. Store your images in the IMAGES/ directory on an SD card.

Software Installation.
Download the source code from GitHub and unzip it in a temporary location.  This will create a directory called “EPD-master”.  Move (or merge) the “libraries” directory to your “sketchbook location” which can be found in the “File->Preferences” dialog inside of the Arduino IDE.  I am using /home/justin/sketchbook.  The directory structure should look like this:Screenshot from 2013-05-16 07:22:37

[sketchbook]/
—AlaModeEPD/
—libraries/
——EReader/
———examples/
————EReader_demo/
————IMAGES/
————unifont.wff

Restart Arduino after setting up your directory structure.

AlaModeEPD — Displays all WIF files in the /IMAGES directory of the SD card.  This was the result of early experiments using the EPD.  It does not use the EPaper library.  You can safely ignore this sketch, but I left it as a reference.

EPaper_demo — This demonstrates some of the functionality in the EPaper library. It cycles through four screens displaying images, circles and text.  The AlaMode is compatible with the UNO board when run from a laptop.  Select “AlaMode” from the boards menu if you are programming from the Raspberry PI.

Screenshot from 2013-05-16 07:40:16

Copy the IMAGES/ directory to the root folder of your SD card.  Copy the file called “unifont.wff” to the root directory of your SD card.  Upload the program. The careful observer will notice that the “WyoLum ROCKS!!!” is at a new location each time the puzzle piece image comes up.  This highlights the fact that the display contents are dynamic.

Code walk through

Imports. All the libraries you need either come standard with Arduino, or are infcluded in the zip file download.

#include <inttypes.h>
#include <ctype.h>
#include <SPI.h>
#include <SD.h>
#include "EPD.h"
#include "S5813A.h"
#include "EReader.h"

A global variable to store unicode data

uint16_t UNICODE_MSG[10];

Setup is simple. Just call the setup() method on the global ereader variable with one of the three predefined sizes.

// I/O setup
void setup() {
  Serial.begin(115200);
  ereader.setup(EPD_2_7); // or EPD_2_0 or EPD_1_44
  ...

The remainder of setup() is self explanatory.

All of the action resides in the loop() function. Pasted here in its entirity.

// main loop
unsigned long int loop_count = 0;

void loop() {

  if(loop_count % 4 == 0){
    ereader.display_wif("/IMAGES/AANDJ.WIF", 0, 0);
  }
  else if(loop_count % 4 == 1){
    ereader.display_wif("/IMAGES/WYOLUM.WIF", 0, 0);
  }
  else if(loop_count % 4 == 2){
    ereader.display_wif("/IMAGES/LENA.WIF", -264/2, 0);
    ereader.display_wif("/IMAGES/LENA.WIF", 264/2, 0);
  }
  else{
    ereader.display_wif("/IMAGES/AANDJ.WIF", -264 / 2,  176 / 2);
    ereader.display_wif("/IMAGES/AANDJ.WIF",  264 / 2, -176 / 2);
    ereader.display_wif("/IMAGES/CAT_SM.WIF", 264 / 2, 176 / 2);
    ereader.display_wif("/IMAGES/APHRODIT.WIF", 0, 0);
    ereader.toggle_ellipse(random(0, 264), random(0, 176), 20, 20);
    ereader.put_ascii(random(0, 200), random(16, 150), "WyoLum ROCKS!!", true);
    ereader.setpix(128, 0, true);
    ereader.setpix(128, 2, true);
    ereader.setpix(128, 6, true);
    ereader.put_unicode(10, 140, UNICODE_MSG, true);
    ereader.toggle_line(70, 0, 120, 50);
  }

  loop_count++;
  ereader.show();
  ereader.sleep(1000); // allows EPD to power off gracefully
}

Function descriptions
The first call you need to make on the global epaper variable is the setup method. This call takes a single argument that indicates one of currently three possible sizes: (small)EPD_1_44, (medium)EPD_2_0, and (Large)EPD_2_7.

  void setup(EPD_size size);

Zero out the frame buffer to clear the display. You should not have to call this method explicitly. It is called after each show() in preparation for the next image. Each frame begins blank by default.

  void clear();

Display a WIF image at the indicated x,y location. Partial images will be displayed by using negative x and or y coordinates.  Path is the full path to the file, like “/IMAGES/AANDJ.WIF” for instance. Use the old 8.3 naming convention to save your self hassle.

  bool display_wif(char *path, int16_t x, int16_t y);

Set a pixel located at x, y to indicated val: true=black, false=white.

  void setpix(uint16_t x, uint16_t y, bool val);

Toggle the pixel located at x, y. If the pixel was white, it becomes black and vice versa.

  void togglepix(uint16_t x, uint16_t y);

Draw a line from staring x,y to stopping x,y in indicated color:true=black, false=white.

  void draw_line(int16_t startx, int16_t starty, int16_t stopx, 
                 int16_t stopy, bool color);

Draw a line from staring x,y to stopping x,y by toggling each pixel on the path.

  void toggle_line(int16_t startx, int16_t starty, int16_t stopx, 
                   int16_t stopy);

Draw an ellipse centered at cx,cy with x-radius rx and y-radius ry in the indicated color:true=black, false=white.

  void draw_ellipse(uint16_t cx, uint16_t cy, uint16_t rx, 
                    uint16_t ry, bool color);

Draw an ellipse centered at cx,cy with x-radius rx and y-radius ry by toggling each pixel on the path.

  void toggle_ellipse(uint16_t cx, uint16_t cy, uint16_t rx, 
                      uint16_t ry);

Draw a single unicode character at location x, y in the indicated color:true=black, false=white. Location is the upper left hand corner of the character bitmap.

  uint16_t put_char(uint16_t x, uint16_t y, uint16_t unic, bool color);

Put either an ASCII string (one byte per char) or a unicode string (two bytes per char) at the specified location and color:true=black, false=white.IMG_20130516_185849_504

  uint16_t put_ascii(uint16_t x, uint16_t y, char * ascii, bool color);
  uint16_t put_unicode(uint16_t x, uint16_t y, uint16_t * unic, 
                       bool color);

Read the width and height dimensions of a WIF image stored in the provided File using “pass by reference”.

  void SD_image_dims(File imgFile, unsigned short *h, 
                     unsigned short *w);

TODO:

  • Filled rectangles, ellipses
  • update EPD.h to handle partial updates
  • hack EPD.h for 4-bit grey scale.

 

Epoch: $10 Real Time for RaspberryPi

Epoch01_02

(This post is a re-write of the easy to follow instructions  and more instructions available from AdaFruit.com with some original added python stuff.  Thanks AdaFruit!)

If your RaspberryPi project needs to know the date and time without an internet connection you need a real time clock.  There are a few available.  The cheapest option is AdaFruit’s DS1307 kit at $9.00.  This kit works with Arduino and Raspberry pi if you are willing to put it together.

Epoch is a real-time clock designed just for the Raspberry Pi.  It attaches right to the GPIO, no assembly required.  We’ve priced it without a middleman markup so we could keep it as cheap as possible.

Here is how I got my Epoch Prototype up and running.  I started with a fresh raspian installation to be sure I did not miss any steps.  I’ve done this all form the command line.  Use LX terminal or SSH into your pi.

Screenshot from 2013-05-11 17:13:43

You can see that although the rtc is present, it is not yet available.  First we have to get the tools to talk to I2C.

> sudo apt-get update
> sudo apt-get install git
> sudo apt-get install python-smbus
> sudo apt-get install i2c-tools

Now let’s make sure the I2C is not blacklisted.  Edit the /etc/ /etc/modprobe.d/raspi-blacklist.conf file.  Comment out the last two lines if this file is present.

> sudo nano /etc/blacklist.confScreenshot from 2013-05-11 17:22:22

Next we have to enable I2C on the pi by editing the /etc/modules file. Add the following lines and reboot.

i2c-bcm2708
i2c-dev

> sudo nano /etc/modules

Screenshot from 2013-05-11 17:15:51

> sudo reboot

Now see what is on the I2C bus (bus 1 for newer raspberry pi models 0 for older ones)

> sudo i2cdetect -y 1           ## use -y 0 for revAScreenshot from 2013-05-11 17:23:49

And the is the DS3231 chip showing up at address 0x68!

Next let’s install the python interface to this chip (not required: skip to hwclock setup if you don’t need python interaction with the rtc)

I just created a directory called GIT on the pi to download the Epoch library into.  You can put it wherever you want.

> mkdir GIT
> cd GIT
> git clone https://github.com/wyolum/Epoch.git
> cd Epoch
Screenshot from 2013-05-11 19:36:18

It works!

hwclock setup (skip to here)

Most likely you will want to operating system to control the hardware clock.  This takes a few steps to set up.  Type the following from the command line.  The greater than symbol “>” represents the pi user, whereas the pound sign “#” represents the root user command prompt

> sudo bash
# modprobe rtc-ds1307
# echo ds1307 0x68 > /sys/class/i2c-adapter/i2c-1/new_device
# nano /etc/modules

(add the line “rtc-ds1307” and save the file)

Screenshot from 2013-05-11 18:09:01(while still root user add the following two lines to /etc/rc.local and save)
echo ds1307 0x68 > /sys/class/i2c-adapter/i2c-1/new_device
sudo hwclock -s

nano /etc/rc.local

Screenshot from 2013-05-11 18:10:20Now reboot and test it out

# reboot

(…after logging back in.  If you are not connected to the internets set the time manually)

> sudo date –set=”20130511 02:08:00″ 
> sudo hwclock -w
> date

Screenshot from 2013-05-11 22:15:33