Interfacing Raspberry Pi 3 and Arduino (with remote monitoring and upgradeability)

Tomás Migone
7 min readAug 7, 2019

Raspberry Pi and Arduino are undoubtedly two of the most popular hardware & software platforms in the world. Nearly every DIY project, tutorial or guide on the maker community uses one or the other. There are tons of articles that explain the differences between them and when to use one over the other, so we are not going to dive into that. The focus of this article will be on a fully fledged solution that involves combining both platforms with remote monitoring and upgradeability.

To understand the use case I’m going to base this guide on a real client project I developed some time ago. For this project, we turned a shoe rack wall from a retail shop into an interactive experience for customers. Picking up a shoe triggered animations and content on a huge video wall. To achieve this we had:

  • Over 100 sensor modules: Consisting of an Arduino Nano board with an analog infrared sensor.
  • 6 Raspberry Pi “hubs”
  • Intel NUC: Central unit controlling the video wall output.

Besides logistics and construction issues, the most interesting challenges revolved around what happened after the installation was completed. How can we provide adequate support without interfering with the shop’s day to day? What happens if we find a bug and need to re-flash 100 arduinos? The technology stack used to answer these questions is the motivation behind this article, the solution turned out to be quite interesting so I want to share it with you.

Let’s go over the different pieces of the puzzle:

Meet the tech stack!

Arduino + StandardFirmataPlus

StandardFirmataPlus is an arduino firmware that talks the firmata protocol. It enables you to run a program on a host machine that transmits basic IO instructions to the arduino via usb serial. This allows us to remotely update arduino functionality without having to reprogram it, instead we will be updating the code on the host machine.

Raspberry Pi 3 + balenaOS + Johnny Five

Johnny Five (J5) is a javascript platform (an NPM module really) that conveniently also talks the firmata protocol. We will use balenaOS to run a containerized solution on a Raspberry Pi. Thanks to balenaCloud we will be able to remotely manage our hardware.

I’ll walk you through the process step by step, here is what you will need:

  • A Raspberry Pi 3
  • Know how to deploy a solution to balenaOS
  • An arduino with some kind of sensor attached to it
  • USB cable
  • The sample project code

Step 1: Building the Arduino module

What module you build will entirely depend on what your application is. You can use any type of sensor or hardware that works with an arduino. Some examples include infrared or ultrasonic sensors, photoresistors or just a couple of LEDs. For this guide, I will be using the sensor module I built for the shoe rack project. The module consists of a very simple infrared sensor circuit, you can check out the schematics for a perfboard version of it below:

The module measures the distance to an object by reading the reflection of an infrared signal on said object. You can test it using the following arduino code (also included on the project under the test/arduino folder):

If everything works you should see the values on the serial console change based on the distance between the module and an object in front of it:

Serial Monitor on the left; Serial plotter on the right.

Step 2: Flashing Arduino with Firmata firmware

Now that we have a working module we need to reprogram the Arduino with Firmata. The Firmata firmware is an arduino program like any other, to ‘flash’ it you just upload it using the Arduino IDE.

You can check the source code on the official firmata repo; a very TLDR would be that the program is a thin client that interprets commands it receives via serial port, it won’t do anything unless there is a host machine attached sending instructions.

  1. Install Arduino IDE
  2. Open Arduino IDE, and make sure you have the firmata plugin installed. To do this go to Sketch > Include Library > Manage Libraries … and search for the package called Firmata by Firmata Developers.
  3. To open the firmata program, go to File > Examples > Firmata > StandardFirmataPlus. Some Arduino boards are not compatible with the “StandardPlus” version of firmata, if in doubt you can search for your platform on the J5 platform support page.
  4. Plug your arduino board and make sure you have the correct port (Tools > Port) and board (Tools > Board) selected.
  5. Upload the sketch with the upload button. That’s it!

Step 3: Writing a Johnny-Five script

Let’s run the Hello World example for the Johnny Five library to verify firmata was correctly flashed. Again you can find the code under the test/j5:

Follow the install and run instructions on the gist, and you should now see the built-in led blinking every second.

As you can see, J5 provides abstractions to easily handle arduino IO and it even adds very useful functionality (the sensor class for example provides the data and change events or the scale method to name a few). You should check the API documentation for more usage details. J5 supports almost every arduino feature but not all of them. Be sure to check the platform support page before starting a new project.

We are going to build a simplified version of the algorithm I used for the shoe rack; but first we need to experiment a bit with the module. We need to take notes on the values we observe for two distinctive cases:

  1. With an object (shoe) very close to the sensor.
  2. With nothing near the sensor.

The following code (raw.js) will help us out by printing the raw values the sensor reads. To do this we use the ‘data’ event from the sensor class:

The closer the shoe is to the sensor the higher the sensor value is, typically I’m seeing values over 200 for a reasonably close distance. On the contrary, when I completely remove the shoe the values are always below 30.

From this data we can build a very basic algorithm to detect when the shoe is lifted: we will consider that the ‘shoe was lifted’ whenever the sensor value changes at least by 50 (200 to 30) and the resulting value is less than 30. While this seems reasonable and will work most of the time, a better solution would be to include some sort of calibration mechanism to obtain these values automatically rather than empirically (I leave that as an exercise for the reader :D).

Our final solution (arduino.js) looks like this (make sure to update the values to what you observed earlier):

Place a shoe or another object close to the sensor and run the script. When you remove it you will see that a message appears on the console and the built-in led blinks for a few seconds. On the production code instead of doing this I would notify the central unit in charge of the video wall application to react accordingly.

Step 4: Integration with balena

The last step is to integrate our solution with balenaOS/balenaCloud. Balena is the crucial piece that ties everything together by providing the means to remotely access your device and also remotely update them. We need to add just two more files to complete our solution: Dockerfile and docker-compose.yml :

If you have any questions on balena usage I suggest you check out their getting started guide. Both the Dockerfile and the docker-compose.yml file are derived from that guide.

The only thing worth noting is that you need to enable UDEV on your Dockerfile and run the container as privileged for it to see the arduino device. If you are interested in learning more about dynamically plugged devices on linux and balena check out this other article I wrote.

You should now be able to manage your device remotely via the balena cloud and command line.

Conclusion

It might seem a little bit tricky to pull it off but combining all these technologies results in a very powerful and versatile solution. Going back to the shoe rack project, we had literally thousands of devices deployed and were able to manage them remotely with very little trouble. We had to do an emergency update to fix a silly bug and it was as easy as running a shell command from the office with maybe 5 minutes of downtime.

Some pictures from the modules (custom PCBs unfortunately didn’t make it in time).

--

--

Tomás Migone

Electronic engineer. Software & hardware enthusiast 🇦🇷.