WiFi ePaper

WiFi connected, solar powered, ePaper

Similar projects worth following
A solar powered ePaper with wireless communication and a magnet to stick it on a fridge, and a cloud app with which you can write and draw on it.

A while ago I bought an e-paper and displayed some images with my RasperryPi on it. See here for a video of it, with a link to full source code etc. in the description:

The amazing thing about e-papers is that the image lasts without power forever (I tested it for months), and the contrast is very good. So the idea is to build a small device with e-paper and solar cells, and then you can write or draw on the e-paper with your smartphone (maybe over BLE), or even remotely from anywhere over the internet to show a message (probably with WiFi, or a BLE relay). The case will have a magnet to stick it on a fridge. Of course, will use a low-power microcontroller instead of an RPi and some intelligent low-power polling mechanism.

This is a complete new dimension of the usual sticky notes on fridges, and it saves trees, too!

  • first working prototype

    Frank Buss04/15/2017 at 00:06 0 comments

    I finished the port of the Raspberry Pi source code for the ePaper, as a module for the nodemcu-firmware project. I forked the original repository and added it as the Lua module "epd", see here:

    Then I installed the Mosquitto MQTT broker and wrote a Lua script for the module, that subscribes to the topic "display". The messages are interpreted as links to binary files which are loaded from a webserver and then displayed on the display, see init2.lua for the details in the new github repository for this project:

    With the Mosquitto test client I can send messages to the module from the PC, for example to load the image wifi-epaper.bin:

    mosquitto_pub -t "display" -m "wifi-epaper.bin"

    See the instructions on this website for details how to setup your own MQTT broker and for some explanations how to use it from Lua. The bin files are located on the webserver and are created with the Python script from PNG images. The nodemcu_float_master_20170414-2230.bin file is the precompiled firmware image for the NodeMCU module, with the new epd Lua module.

    You can see the connecting scheme in the LibreOffice spreadsheet pins.ods on github. It gets quite complicated with all the different internal and external names. A spreadsheet is very useful for such a task so that you don't get lost.

    This is how it looks like when it is running:

    The current consumption in idle mode is still quite high with about 22 mA and some peaks from time to time, maybe I can find some sleep mode for the module, it doesn't need to react immediately. When receiving a new image and updating the display, it needs up to 80 mA (at 3V) for some seconds. But it is possible to run the NodeMCU module with less power, if you don't need immediate updates of the display, but poll it like every minute.

  • NodeMCU Lua string length limit

    Frank Buss04/14/2017 at 18:44 0 comments

    So I ported the C code from the Raspberry Pi library for the e-paper to the NodeMCU firmware. The source code didn't look very nice, I refactored and cleaned it a bit. I'm using strings for the binary image data, because this needs less memory than arrays in Lua. But I get "string length overflow" error.

    Turns out the default max string length in Lua for NodeMCU is 4096 bytes, and of course Murphy says I need 5808 bytes to store an image for my e-paper. But at least it can be changed with collectgarbage("setmemlimit", kilobytes) at runtime. Too bad there is only about 40 kB usable SRAM. I guess sooner or later I need to buy an ESP32, which has 520 kB.

  • collecting all the parts

    Frank Buss04/07/2017 at 16:56 0 comments

    So I dug up the display which I used 3 years ago, and the test image I uploaded with my Raspberry Pi project for another project I was planning, is still as clear as on the first day, and there was no power for these 3 years. That's amazing!

    Next for fast prototyping, I'll try to connect it to my NodeMcu module. This is a nice little ESP8266 WiFi module, which can execute Lua code, even over the internet. This makes development really easy and turnaround time fast, as I demonstrated here.

    Today I also listened to the podcast where Shulie Tornel and Elecia White talked about the 2017 Hackaday Prize, see here. This was a really inspiring talk and gave me some interesting ideas for more useful features for this project, which I will describe and test later.

View all 3 project logs

  • 1

    Build a new NodeMCU firmware

    NodeMcu has a lot of modules you can use, as you can see in the documentation:

    If you buy a NodeMcu module from eBay, chances are good that it comes with an old version and not with all modules you might need. So for the latest version and with all the goodies you need, it is best to compile your own firmware.

    The easiest way to do this is to use some cloud build service, as described on this page:

    You can stop reading now if you use this service.

    But you can compile it from source as well. You can do this with a Docker image:

    Docker is a nice system to create runtime environments with all the programs and libraries inside your OS. There are many different environments. To quote the webpage:

    Docker containers wrap up a piece of software in a complete filesystem that contains everything it needs to run: code, runtime, system tools, system libraries – anything you can install on a server. This guarantees that it will always run the same, regardless of the environment it is running in.

    If you've ever tried to setup a cross-compiler environment, you know how much work this can be, and chances are good that you break something other on your system. Docker solves all these problems.

    I'm using Debian Jessie as my main working operating system. Unfortunately it is not just "apt-get install docker" to install the Docker environment, and there is even another package named "docker", which makes it a bit confusing, but there is a manual at the Docker homepage how to install it and you need to to this only once:

    Obviously you don't want to do "apt-get remove docker", but the rest worked. This were my steps:

    sudo apt-get install apt-transport-https ca-certificates curl software-properties-common
    curl -fsSL | sudo apt-key add -
    sudo add-apt-repository "deb [arch=amd64] $(lsb_release -cs) stable"
    sudo apt-get update
    sudo apt-get install docker-ce
    "docker-ce" is the free community version of docker. There are instructions for Windows and Mac, too. After the installation you can check that it works with "sudo docker run hello-world" on Linux.

    Now you can install the NodeMcu Docker build environment:

    git clone
    sudo docker pull marcelstoer/nodemcu-build
    cd nodemcu-firmware
    docker run --rm -ti -v `pwd`:/opt/nodemcu-firmware marcelstoer/nodemcu-build

    If you want to enable different modules, change the file "app/include/user_modules.h" and recompile your image with the last "docker run" command. The result is in the "bin" directory. There are two version, one integer and one float version, which determines what number type Lua uses. I use the float version, because this is the default in Lua and makes programming easier. The image name in my case was "nodemcu_float_master_20170410-1703.bin".

  • 2

    Flash a NodeMCU firmware image

    For flashing a new image, I use esptool. Plugin your NodeMCU module to an USB port, clone the esptool project and flash your firmware. Usually a new device will appear, like /dev/ttyUSB0. Step by step:

    git clone
    cd esptool
    sudo python2 ./ --port /dev/ttyUSB0 write_flash 0x00000 ../nodemcu-firmware/bin/nodemcu_float_master_20170410-1703.bin

    (if there is an error "ImportError: No module named serial", then do a "sudo python2 -m pip install pyserial". If you have only Python 2.x installed, you can use "python" instead of "python2", this is just my system, where I have Python 3.x installed, too. Don't ask how long I needed to Google for all the errors and to have both versions of Python installed in parallel)

    Flashing needs less than a minute and the output should look something like this: v2.0-beta2
    Detecting chip type... ESP8266
    Uploading stub...
    Running stub...
    Stub running...
    Attaching SPI flash...
    Configuring flash size...
    Auto-detected Flash size: 4MB
    Flash params set to 0x0040
    Compressed 436208 bytes to 279594...
    Wrote 436208 bytes (279594 compressed) at 0x00000000 in 24.6 seconds (effective 141.8 kbit/s)...
    Hash of data verified.
    Hard resetting...
    You can test it with "minicom --device /dev/ttyUSB0 --baudrate 115200". You might need to disable hardware flow control (the usual Telix commands: ctrl-a, o, "Serial port setup", F and G for disabling hardware and software flow control). Hit the reset button on the module (small button near the USB connector) and you should see something like this:
    NodeMCU 2.0.0 build unspecified powered by Lua 5.1.4 on SDK 2.0.0(656edbf)
    lua: cannot open init.lua
    It has a Lua REPL, which means you can execute commands from the minicom terminal, which is nice for fast prototyping and testing things:
    > = 1+2
    > = wifi.sta.getip()
  • 3

    Install a Lua script

    If you want to install a Lua script, which is started when the module starts, you can write this in a file called "init.lua". With the you can upload it to the NodeMCU module:

    git clone
    python luatool/luatool/ --port /dev/ttyUSB0 --src init.lua --dest init.lua --restart
    You need the git clone only once. Sometimes the luatool script doesn't work. Reasons for this could be that you have still minicom open in another terminal, or you need to reset the module and start the script again. Note: if there is an error in init.lua, the module might get into an infinite reboot loop. To fix this, you can re-flash the firmware image, which deletes all scripts.

    This is an example script, which loads another script init2.lua from a webserver and executes it:

    function executeString(s)
        local fun = loadstring(s)
    function stripHeader(s)
        local pos = string.find(s, "\r\n\r\n")
        return s:sub(pos + 4)
    function runScript(host, url)
        receivedPage = ""
        conn = net.createConnection(net.TCP, 0) 
        conn:on("receive", function(conn, data) receivedPage = receivedPage .. data end)
        conn:on("disconnection", function(conn, data) pcall(function() executeString(stripHeader(receivedPage)) end) end)
        conn:connect(80, host)
        conn:send("GET /" .. url .. " HTTP/1.1\r\nHost: " .. host .. "\r\nConnection: close\r\n\r\n")
    wifi.sta.eventMonReg(wifi.STA_IDLE, function() print("IDLE") end)
    wifi.sta.eventMonReg(wifi.STA_CONNECTING, function() print("CONNECTING...") end)
    wifi.sta.eventMonReg(wifi.STA_WRONGPWD, function() print("WRONG PASSWORD!!!") end)
    wifi.sta.eventMonReg(wifi.STA_APNOTFOUND, function() print("NO SUCH SSID FOUND") end)
    wifi.sta.eventMonReg(wifi.STA_FAIL, function() print("FAILED TO CONNECT") end)
    wifi.sta.eventMonReg(wifi.STA_GOTIP, function() runScript("","init2.lua") end)
    Replace "SSID" and "PASSWORD" with your WiFi SSID and password and the address "" with your webserver address. For faster development it is nice to install a local webserver. Then you can edit the init2.lua file locally on your PC or Mac, and to test it just hit the reset button on the module, which reloads the script. This helps also if you have errors in your Lua script, because you don't need to re-flash the firmware in this case. Leave minicom open to the serial port and you will see the output of the script (with "print") and when it reboots. Once your script works, you can rename it to init.lua and permanently install it on the module with

    Note: the default max string length is 4096 bytes in Lua, which is the limit for your script. You can change this with 'collectgarbage("setmemlimit", 64)' in your init.lua to e.g. 64 kB. But when WiFi is connected etc., you have only about 40 kB available RAM. If you need more: the ESP32 has 520 kB RAM.

View all 4 instructions

Enjoy this project?



Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates