Updating an Arduino with resin.io

Micro-controllers are simple boards that can run C/C++ programs. They are easy to use and amazingly power efficient- but their simplicity typically makes them incompatible with resin.io [https://resin.io] since the resin service requires that a board can run Linux in order to manage Linux containers. A couple of weeks ago- however- one of our users…

Micro-controllers are simple boards that can run C/C++ programs. They are easy to use and amazingly power efficient, but their simplicity typically makes them incompatible with resin.io since the resin service requires that a board can run Linux in order to manage Linux containers. A couple of weeks ago, however, one of our users explained how they were using resin.io to update their Raspberry Pi and an attached Arduino.

I’ve expanded their explanation slightly to create this guide to an Arduino update mechanism within the resin.io ecosystem.

The basic workflows is this:

  • Connect your Arduino to a resin.io device via USB-serial.
    setup
  • Change some Arduino code.
    changecode
  • Push your your project to resin.io. This uses a Makefile to build your Arduino binary(from blink.ino) on our builders and ship everything to the resin device in container.
    push
  • When the container lands on the device check if there is a difference between the new version of Arduino code and previous version (which is stored in /data to persist through resin updates)
  • If there is a difference raise a flag to signal the uploading of the binary to the Arduino via the serial cable.
    logs
  • Arduino is updated with new code (a longer delay in the blink sequence).
    slow blink

Let’s take a look at some code

Because the Makefile and resin.io abstract all of the tricky stuff, the logic is actually very simple.

A Dockerfile is the basis for all resin projects, so lets start there. First we need to install some native dependencies in our Dockerfile:

“`bash

Dockerfile

RUN apt-get update && apt-get install -y –no-install-recommends \
arduino \
g++ \
gcc \
usbutils \
make
“`

Next, we trigger a build of our Ardiuno firmware from our Arduino source file using this “all-in-one” Makefile. It allows you to pass build configurations via environment variables. As you can see we are building for the leonardo board. Full documentation on the Makefile can be found here.

“`bash

Dockerfile

build the Arduino binary

WORKDIR /app

ENV ARDUINODIR /usr/share/arduino
ENV BOARD leonardo

RUN cd blink && make
“`

Once the container hits the device we’ll need to run a script to compare the code in blink.ino against the previous version. We declare our entry point like so:

“`bash

run start.sh when the container starts

CMD [“bash”,”start.sh”]
“`

In start.sh we have a flag PROGRAMMER which indicates whether there is an update for our Arduino. If the flag is raised we run make upload which uploads the binary via serial connection. We then store our new blink.ino in /data. This is important because resin.io treats /data similar to Docker sub-volumes, which means that the contents survive container updates – this is important when comparing new code to old code.

“`bash

start.sh

diff /app/blink/blink.ino /data/blink.ino || PROGRAMMER=1
if [ “${PROGRAMMER:-}” == “1” ]; then
echo $PROGRAMMER
pushd /app/blink
make upload && cp blink.ino /data/
popd
fi
“`

You can view the write progress from the resin logs:

** Note: I’ve stripped out a few extraneous details. **

12.01.16 13:04:58 [+0000] Connecting to programmer: .
12.01.16 13:04:58 [+0000] Programmer supports the following devices:
12.01.16 13:04:58 [+0000] Device code: 0x44
12.01.16 13:04:59 [+0000] avrdude: AVR device initialized and ready to accept instructions
12.01.16 13:04:59 [+0000] Reading | | 0% 0.00s Reading | ################################################## | 100% 0.01s
12.01.16 13:04:59 [+0000] avrdude: Device signature = 0x1e9587
12.01.16 13:04:59 [+0000] avrdude: reading input file "blink.hex"
12.01.16 13:04:59 [+0000] avrdude: writing flash (4756 bytes):
12.01.16 13:04:59 [+0000] Writing || ################################################## | 100% 0.59s
12.01.16 13:04:59 [+0000] avrdude: 4756 bytes of flash written
12.01.16 13:04:59 [+0000] avrdude done. Thank you.

And there you have it! Updating an Arduino using resin.io. You can find all the code here.

There are a ton of interesting use cases for this tutorial, such as using the Arduino as an ADC like Emonpi has done.
Let us know where you take this. Programming the Arduino via Bluetooth would be a great fork 😉

If you have any questions, the team will be hanging out in our gitter room.

Note

If you want to pin the programmer to specific port e.g /dev/ttyACM0 then you’d add another environment variable, like so: ENV SERIALDEV /dev/ttyACM0.


Posted

in

Tags: