Finally using your Raspberry Pi & Elixir

Underjord is a tiny, wholesome team doing Elixir consulting and contract work. If you like the writing you should really try the code. See our services for more information.

How many Raspberry Pi do you have sitting in a drawer. I think I still have about 4? And at least 2 on a shelf. I may be over the average there but the story itself is common. “Oh! This is neat, I can automate X with this! And learn Y tech doing it!” And yet it never gets quite done. For reasons.

No one needs to feel too bad about this. Not all projects pan out. But I’ve recently found my footing on putting these devices to use and figured I’d share some thoughts. The idea of Pis gathering dust in a drawer along with all your ambitions is a bit of a meme. As the introduction might have intimated I have a worse Raspberry Pi habit than many others. Going from memory this is my idle inventory right now:

  • Pi 1, some revision
  • Pi 3, at least 2 of them
  • Pi 3 A+
  • Pi Zero WH with OLED Bonnet
  • Pi 400, swedish layout
  • Pi Zero 2 W

Currently in use:

  • Pi 4, handed off to the inlaws to provide a computer for their TV, straight Raspbian
  • Pi Zero WH with Inky eInk Phat running the calendar_gadget
  • Pi Zero WH with Keybow 12-key, running the lightswitch

Let’s not talk about the Arduinos and compatibles. I swear I’ll get to them any day now.

To give myself some additional points I’ll note that both the Pi0 OLED Bonnet and Pi 400 have been frequently featured in recent livestream experiments. They are seeing some use in that way but they are not in service as production devices yet. The Pi Zero 2 W just arrived.

The two Pi Zero I’ve recently put into service for showing my calendar and controlling my workstation camera lights respectively are both set up with the Elixir/Erlang-based Nerves project (less markety Github) instead of your typical Raspbian. Why? Because I prefer it. Why do I prefer it? A few things come to mind. For one thing it makes doing hardware on Linux in Elixir a darned delight. It turns the whole project into a single repo for generating firmware that doesn’t depend on setting up an OS, installing language runtimes or compiling anything on-device. It makes shipping code updates to the device comfortable and flexible.

Nerves has great ergonomics for development and it also has the useful property of constraining your possible approaches a bit. It needs an Erlang language, so you don’t have to decide between all languages you could run on a Pi. It has a way to deploy firmware so you do not have to think about Ansible, Docker or any other deployment approach. It comes with an OS set up to let you make the device an IoT style device, you don’t have to rummage through Raspbian making all of the choices. The world is no longer your oyster so you might get some actual stuff done.

So what is the OS? The Nerves project is built on Buildroot which is a bunch of tooling for building embedded Linux systems. So for kernel, drivers, OS-level packages we get all of that via Buildroot. Sort of like a compile-time apt you get a repository of packages to choose from to include in your OS. Typically I don’t have to touch Buildroot but I’ve customized it when needed. Once a Nerves system has booted Linux it will start the Erlang virtual machine, the BEAM, to start your project. And everything you want to do, you typically implement in, or orchestrate from Erlang or Elixir. So Nerves runs a much leaner install than Raspbian would and you build your project and install on your dev machine, burn the entire thing to SD card or ship it over SSH, its a very nice workflow. You can mock out hardware and iterate quickly on your dev host, or you can paste a bunch of code into your machine over SSH just to try it. Lots of workflow options.

Nerves does a lot of neat stuff for you, such as keeping most of your SD card read-only, protecting you from the dangers of corruption. And if your SD-card craps out, setting up a new environment is just burning the firmware to a new card. No need to set up deployment infrastructure to be able to repeat the build. I think that’s one place where Pi projects go to die. Reproducing the builds or recovering from a screw-up. The Getting Started guide is pretty good.

The Pi Zero W or Pi 3 A+ are ideal devices for all of this since they have everything you need to work conveniently. WiFi, USB Gadget mode, easy to power off of your computer USB. But any WiFi Pi is easy enough and any Pi at all should work.

So once you’ve burned a Nerves system firmware to an SD card you can just plug the device into your computer, it should start up and present itself as nerves.local over mDNS and you can SSH to it. All across the USB umbilical, power and data, the glory of gadget mode. If you gave it WiFi credentials it’ll also announce itself there. If you want the fatest way to try it out you can download and flash Nerves Livebook which will give you a Nerves device which provides the Livebook web UI for trying out code, has lots of examples of fun stuff you can do with the device and shows how to get started with a ton of examples. Livebook is a pretty wild Elixir take on Jupyter Notebooks and Nerves really makes good use of it as an introduction.

Now, for additional hardware.. Most hobbyist RPi hardware comes with Python libraries which is convenient on Raspbian but less useful for us here. Hardware support will vary wildly. But if the device does SPI/I2C/GPIO the Circuits library provides the foundation you need. I’ve ported some stuff, just implemented a subset for some others. There is a list on the Circuits site, I don’t expect that’s exhaustive.

Anyway. I’d suggest starting with something that is known to work. Either something with inputs, buttons or sensors or some output, lights, a motor, a relay.

Make it mostly use skills you already have and let the hardware be the new thing if that is unfamiliar. If you already know web dev for example you could have a device with buttons that talks to an API on the web somewhere to make things happen.

So for example, I had the Pi with an eInk display already. It doesn’t have any fun hardware input connected so I made a Web UI for setting up a calendar URL to import and made pulling that calendar the input. The Web UI was easy enough to make and Phoenix LiveView made it a pleasure. The novel part was rendering a nice visual of the next calendar event to the device and I did do a bit of yak shaving in the form of a live web preview.

Pi Zero with Inky Phat on it showing some calendar information with sensitive information redacted

Look for controllable things in what you use. Your computer itself, remote servers, simple devices on your network. My other project I got working controls my Elgato Keylights which are normal Web API endpoints. The tricky new part there was mostly around discovery via mDNS and there are good Nerves libraries for that.

Keybow keypad on a desk, looks absolutely inert but can actually control lights

You can follow some of the process of me getting familiar with different parts of using these devices from my livestreams where I’ve done both exploration and implementation work on these projects. There is a playlist here on YouTube or you can find them on this blog if you’d rather feel indie.

So what has been the key in making these Pis stop gathering dust for me? I’ve chosen tools I like and care about. I know that if I want to set up these projects in 2 years it should all just work. The work doesn’t feel ephemeral, it feels finished now and trivial to continue if I want to. These kinds of projects can easily turn into unwieldy yak shaves where I make no progress. I feel like Nerves constrains me and saves me from that sprawling complexity by providing solutions I like and don’t have to pour energy into. I also set aside time to do it, mostly around the livestream. That’s an important non-technical aspect, know when you are planning on actually doing it, if you care about it getting done.

If you are curious about Nerves I suggest signing up for the Nerves Newsletter which is bi-weekly and updates you on what is happening in the project as well as neat projects people have put together with it. It is hand-typed by a human (me) that is active in and excited about the project. The entire archive is available here.

I’ve also experimented a fair bit. Some of the most fun stuff I’ve done with these things is to set up Erlang clustering where all of my Pi devices can detect each other on the network as they start and connect up to form and Erlang cluster. This would allow easy communication between the devices if I want to integrate them with each other. I’m not using it for anything currently but it is an interesting piece. I’m considering setting up the OLED Bonnet to be a blinking reminder of meetings that are about to start as it has buttons that would let me also dismiss the meeting. If I set up a node that runs on my desktop computer as well I could even have the button presses trigger opening the calendar event information on the desktop over the cluster. There are a lot of fun possibilities when your devices can connect to each other and communicate via message passing.

Unused Pi Zero with OLED Bonnet, looks like a small game console

The next thing I would want to get started on is a radio thing. I have a number of Arduino-style boards with RFM69 transceivers on them. I also have a transceiver with an RPi-friendly breakout. I’ve had them talking in the past but I want to revisit it with a new approach. I want the Arduinos on battery, reading sensors or operating relays and I want an Rpi on my network being the hub for collecting sensor data and controlling the devices. That’s a bit more involved to do right but it should be a fun project.

If you have projects with Pis that you think are cool or plans that you would like to share, don’t hesitate to reach out over email ( or on Twitter (@lawik).

Underjord is a 4 people team doing Elixir consulting and contract work. If you like the writing you should really try the code. See our services for more information.

Note: Or try the videos on the YouTube channel.