Nerves is a framework for developing embedded software with Elixir on a minimal Linux system. I was introduced to it at Abstractions conf this year, and wanted to give it a try.
Nerves is meant for devices that can run Linux, such as Raspberry Pi, Intel Galileo, and Beaglebone Black. I’ll be trying it out on my Raspberry Pi Zero.
Getting Started with Nerves
Once Nerves is installed (check out the getting started page),
we can use mix
to create a new project. Here I’m calling the project flight_controller
(since I intend to use it
for my quadcopter), and targeting the Raspberry Pi.
$ mix nerves.new flight_controller --target rpi
* creating flight_controller/config/config.exs
* creating flight_controller/lib/flight_controller.ex
* creating flight_controller/test/test_helper.exs
* creating flight_controller/test/flight_controller_test.exs
* creating flight_controller/rel/vm.args
* creating flight_controller/rel/.gitignore
* creating flight_controller/.gitignore
* creating flight_controller/mix.exs
* creating flight_controller/README.md
Let’s quickly set things up to blink an LED so that we can see that our firmware is running.
I’ll use the Elixir Ale library to control IO,
so let’s add it to dependencies and start it in mix.exs
:15
def application do
[
mod: {FlightController, []},
applications: [
:logger,
:elixir_ale # <-- Added
]
]
end
def deps do
[
{:nerves, "~> 0.3.0"},
{:elixir_ale, "~> 0.5.6"} # <-- Added
]
end
Then, in flight_controller.ex
, I’ll add some logic to blink the LED:
defmodule FlightController do
use Application
@blink_duration 150 # ms
@led_pin 18
@gpio_on 1
@gpio_off 0
def start(_type, _args) do
{:ok, pid} = Gpio.start_link(@led_pin, :output)
spawn fn -> blink_forever(pid) end
{:ok, self}
end
def blink_forever(pid) do
Gpio.write(pid, @gpio_on)
:timer.sleep @blink_duration
Gpio.write(pid, @gpio_off)
:timer.sleep @blink_duration
blink_forever(pid)
end
end
After that, I can run some commands to get the dependencies, compile, and build the firmware:
$ mix deps.get
$ mix compile
$ mix firmware
With the firmware created, I can then insert the SD card and burn it:
$ mix firmware.burn
Discovered devices:
0) 14.98 GiB found at /dev/rdisk4
1) 0.75 GiB found at /dev/rdisk3
Which device do you want to burn to? 0
100%
And we have a blinking LED!
Accessing IEx over a serial cable
Instead of connecting a monitor and keyboard to my Pi, I just want to connect to the IEx console over a serial connection. Luckily I’ve got quite a few USB to Serial converters sitting around from working with Arduino, but if you don’t have one, you can get them on Ebay for ~$2.
As far as configuring the firmware to do this, the FAQ section of the docs covers this quite well.
We’ll need to override a config file in the filesystem. To do this, we’ll need to create some new directories:
$ mkdir -p config/rootfs-additions/etc
Then, we’ll copy the erlinit.config
file from our system library into our application so we can override it:
$ cp deps/rpi/nerves_system_rpi/rootfs-additions/etc/erlinit.config config/rootfs-additions/etc
And then edit it:
# -- snip --
# Specify the UART port that the shell should use.
# Access IEx via HDMI/keyboard (comment this out)
# -c tty1
# Access IEx via serial/UART (add this line)
-c ttyAMA0
# -- snip --
Finally, we tell Nerves to look for the new rootfs directory:
# ...
config :nerves, :firmware, rootfs_additions: "config/rootfs-additions"
# ...
As a side note, anything you add to this rootfs-additions
directory will be added
to the filesystem! This will come in handy later.
Now we can insert the SD card and run the familiar compile/build/burn commands:
mix compile
mix firmware
mix firmware.burn
Connecting the Serial converter
Once the serial converter is plugged into the Pi and computer, you can run:
screen /dev/tty.SLAB_USBtoUART 115200
And we’ve got IEx!
iex(1)> System.cmd("ls", ["/"]) |> elem(0) |> IO.puts
var
usr
tmp
...
Note that your device name may be different, you can figure it out by unplugging the converter,
running ls /dev/tty.*
, plugging it back in and then running the command again to see which
device has been added
Working Wirelessly with Nerves
In a future post, I’ll show how to connect to Wifi, and access IEx and upload firmware wirelessly. I’ll link to it here when it’s complete!
Thanks for reading!
If you have any questions or comments tweet me @bolandrm!
Be sure to follow me if you’re interested if you’re interested in more Nerves related posts!