Adafruit Repaper 2.0″ Display

E-ink is a great technology. Its the display technology behind the Amazon Kindle. The display is very easy on the eye because the display is not a light source. The display works in bright lights. And the display maintains its image when power is removed. All great!

There are a few downsides: generally they are only two tones, they are relatively expensive, and they have a very low refresh rate.

But if you need a ultra low power display that is readable in sunlight these are great. And the prices are coming down significantly for developer kits. And I have heard that there are color prototypes.

Here is what the 2.7″ version looks like hooked up to a Raspi:

2015-12-13 15.11.38.jpg

Notice that the Raspi is unplugged from power.

You can order this part here.

Here is a video showing the screen refreshing:

The instructions on Adafruit are pretty well written. However, there are few issues I ran into.

First Issue: Pin Mapping

Pin mapping to the Raspi doesn’t match the pins on the Raspi or the Adafruit Pi Cobbler Plus. (At least I couldn’t figure it out.) Save yourself a lot of trouble by not using the Pi Cobbler Plus as a guide and instead go to the Raspi reference material here.  I like my Pi Cobbler Plus for connecting the GPIO to a breadboard but the GPIO labels silk-screened on it do not help here.

Second Issue: Missing parameter on Make command

The documentation on Adafruit will say to run a make command like this:
>make rpi
However, the output I received was:
>make[1]: Entering directory ‘/home/pi/repaper/gratis/PlatformWithOS’
>please set to one of:


The error is telling you that you need to pass in a parameter. The PANEL_VERSION parameters meaning is as follows:

V110_G1 is for 1.44″ displays.

V230_G2 is for 2.0″ displays.

V231_G2 is for 2.7″ displays.

So if you have a 2.0″ Repaper display you would run the make command like this:
>make rpi PANEL_VERSION=V231_G2
Same applies to the next build command…
>sudo make rpi-install PANEL_VERSION=V231_G2

Third Issue: SPI port Disabled and Configuration Change Required

When I ran the service start command…
>sudo service epd-fuse start
I received the following error:
>[….] Starting EPD: epd_fuseERROR: could not insert ‘spi_bcm2708’: No such device
It turns out that my Raspi did not have SPI enabled. You can verify this using this command:
> lsmod | grep spi
If the result is empty you don’t have SPI enabled (below I’ll explain how to enable it).
If the result is something like:
>spi_bcm2835 7948 0
then you might have spi enabled but the EPD is looking for spi-bcm2708 (see the error message from above and notice the last 4 digits might be different). To change the EPD to look for the correct spi module change the epd-fuse configuration by opening the file:
>sudo nano /etc/init.d/epd-fuse
In the file editor, find the modprobe setting line and changing the line from:
>modprobe spi-bcm2708
>modprobe spi-bcm2835
To enable SPI open the Raspberry Pi’s built in configuration tool:
> sudo raspi-config
and navigate to the “Advanced Options” (using the down arrow) and select it (hit enter) and navigate down to “A6 SPI” and enable it. Reboot..
>sudo reboot
After reboot reconnect (assuming SSH) and try to start the service again:
>sudo service epd-fuse start
It should work now. You can proceed to the Python demos listed in the documentation on Adafruit’s site.

Adding an Accelerometer to the Windows 8 Simulator

I have been busy developing for Windows 8 for a while now. Until Microsoft releases a WinRT “Surface” device (October?) I thought it would be nice to be able to test my apps transitions between ApplicationViewState.

I have an accelerometer in my .Net Gadgeteer kit…and a wifi module…hmm.

What I built is a gadget that exposes JSON formatted accelerometer data via a web service. Any Windows 8 (WinRT) applications can consume this service. There are a few details to getting this to work. I will briefly go over the main things to be aware of here. I will post the entire project later.

Here is what it looks like tacked on my laptop:


Across the top (from left to right): OLED Display, SEEED Studio Accelerometer, GHI Spider board, Wifi module
Across the Bottom: power module, battery pack.
On the table is a ClearWire wifi router.

Here are some of the main things to be aware of:

Time Series Graph
I added a OLED Display because it was very handy to have a time series graph to display the x,y,z axis’ for troubleshooting.

Time Series Graph

Here is the code for the graph:

 public class GraphHelper
        uint currentX;
        uint MaxX;
        uint _y;
        uint _GraphHeight = 10;
        Gadgeteer.Modules.Seeed.OledDisplay _display;

        public GraphHelper(uint y, Gadgeteer.Modules.Seeed.OledDisplay display )
            _y = y;
            _display = display;
            currentX = 0;
            MaxX = _display.Width;
        private void Clear()
            _display.SimpleGraphics.DisplayRectangle(Gadgeteer.Color.Gray, 1, Gadgeteer.Color.White, 0, _y, _display.Width, _GraphHeight);
        float _maxG=1;
        public void AddDataPoint(float range)
            //check if new values are larger than we expected.
            //I assume the range is between 1 and -1.
            //If the range is larger then we need to adjust.
            if (System.Math.Abs((int)System.Math.Ceiling(range)) > _maxG)
                _maxG = range;
            //shift all values to positive range.
            //TODO: fix variable names...
            float rangeNorm = range + _maxG;
            float integral = _GraphHeight / _maxG;
            rangeNorm = rangeNorm * integral;
            rangeNorm -= _GraphHeight;
            rangeNorm += _y +  (float)(_GraphHeight * 0.5);
            if ( rangeNorm < _y)
                rangeNorm = _y;
            if(rangeNorm > (_y + _GraphHeight))
                rangeNorm = _y + _GraphHeight;
            if (currentX <= MaxX)
                _display.SimpleGraphics.SetPixel(Gadgeteer.Color.Green, currentX++, (uint)System.Math.Ceiling((uint)System.Math.Ceiling(rangeNorm)));
                currentX = 0;

Here is how you would call its c’tor to put a graph halfway down the screen (display_height/2=64)and plot a point :

this.graphX = new GraphHelper(64, _display );
graphX.AddDataPoint( (float) averagedAcceleration.X );

Windows 8 Capabilities Panel in Visual Studio 12
Pay attention to the Capabilites tab in the Package.appxmanifest. I had enabled “Internet(Client)” and thought I was good to go. No so. There is also a “Home or Work Networking” capability. For connections to resources on a LAN you need to enable this.

Reactive Extensions for .Net are Very Cool
In my Win8 application I needed to call the sensor service on a timer. There are many ways I could have done this. I wanted a quick and easy solution that would work with the async nature of WinRT development and I knew for certain that this code would be not in a production system…ever. This isn’t to say RX .Net isn’t production worthy, just that this usage of a timer is probably not optimal for production but is great for demo code.

             var fivePerSecond = Observable.Interval(TimeSpan.FromMilliseconds(200))
                .Subscribe(num =>

Every 200 ms this will call Get_Sensor_Data()…which then calls MoveCube() here:

    HttpResponseMessage response = await rootPage.httpClient.GetAsync("");
    await Helpers.MoveCube(response, renderer);
    Page.NotifyUser.Text = "Completed";

And finally, we get to the MoveCube()…

internal static class Helpers
        internal static async Task MoveCube(HttpResponseMessage response, DxRenderer.Cube cube)
            string responseBodyAsText;
            responseBodyAsText = await response.Content.ReadAsStringAsync();

            JsonValue value = JsonValue.Parse(responseBodyAsText);
            var c = value.GetObject();
            string sx = (c["Accel"] as JsonValue).GetObject()["x"].GetString();
            string sy = (c["Accel"] as JsonValue).GetObject()["y"].GetString();

            float.TryParse(sx, out cube.X);
            float.TryParse(sy, out cube.Y);

SharpDX is DirectX for C#
Finally, Jose Fajardo, who has published some very useful demos of SharpDX, provided the starting point for the Win8 cube rotation via accelerometer. I wasn’t able to get the SharpDX demos that come with SharpDX to run. But I was able to get Jose’s samples working. So thanks Jose! SharpDX is the only way I know of to do DirectX in WinRT apps using C#.

GHI Electronics: New GHI NETMF v4.1 and .NET Gadgeteer Package

There are some significant updates including drivers for WiFi and other modules, and bug fixes for Ethernet and Button.

This release requires reflashing the mainboard. The tool at Start->GHI Electronics->GHI NETMF v4.1 SDK->Firmware Update->Fez Spider Updater makes this easier than otherwise.
It requires going into serial mode to reflash the bootloader, which means flipping little switches on the mainboard. Be aware that the updater does not update the MAC address so you have to update that manually if you want to use Ethernet, using the MFDeploy tool (Start->Microsoft .NET Micro Framework v4.1->Tools->MFDeploy.exe) then choose USB then choose Target->Configuration->Network then change the field MAC Address to the text written on the mainboard sticker but with dashes between each pair of characters (e.g. if your mac is 123456789012 then you should use 12-34-56-78-90-12 in the MAC Address box).

You can download the updater here: or directly here.

I will try to post more on this later.

.Net Gadeteer: Display speed test

There are currently two display options available for .Net Gadgeteer…that I know of. You can always create your own too. But of the two for sale currently which is faster at displaying graphics?

The contenders are:

To find out I created a simple test. The code below starts a stopwatch timer, then draws a bunch of elipses, and then stops the stopwatch and checks the time difference. I am assuming that rendering elipses is the same as rendering other objects but I should test other things like text just to see. We will have to come back to this later.

Here is code for testing the speed of the Seeed Studio OLED display. To test the GHI 3.5″ touch display just swap out the OLED display with the GHI display. I just used the visual designer to do this and the only code change was to rename oledDisplay with “display” (the default name for the GHI display in the designer).

        void ProgramStarted()
            Debug.Print("Program Started");
            DateTime start;
            TimeSpan end;
            oledDisplay.DebugPrintEnabled = false;
            start = DateTime.Now;
            for (uint i = 0; i < 128; ++i)
                oledDisplay.SimpleGraphics.DisplayEllipse(GT.Color.FromRGB((byte)(i << 0), (byte)(i << 1), (byte)(i << 2)), i + 50, i + 20, (uint)System.Math.Floor(i * .1), (uint)System.Math.Floor(i * .6));
            for (uint i = 128; i > 0; --i)
                oledDisplay.SimpleGraphics.DisplayEllipse(GT.Color.FromRGB((byte)(i << 0), (byte)(i << 1), (byte)(i << 2)), i + 50, i + 20, (uint)System.Math.Floor(i * .1), (uint)System.Math.Floor(i * .6));
            end = DateTime.Now - start;
            Debug.Print("Test1: " + end);
            oledDisplay.SimpleGraphics.DisplayText("Test1: " + end, Resources.GetFont(Resources.FontResources.NinaB), GT.Color.White, 50, 50); 

Here are the results and I was surprised by the results.
The GHI display was twice as fast as the smaller Seeed Studio display.
I’ll post exact numbers if someone requests it. But twice as fast is convincing. For anything requiring fast display updates, like testing new modules, I would recommend the 3.5″. Once you have things figured out move to the OLED if the form factor requires it. For instance, I was playing with the gyro module and the accelerometer module and the 3.5″ display was very handy in getting a sense of the modules behavior.

That said, I really like the Seeed Studio display. It is perfect for small form factors (its tiny at 26.8mmx26.8mm) and the colors are very bright. Both displays have their purposes. Just be aware of the speed advantage the 3.5″ display offers.