One day in September 2020, I suddenly felt like exploring remote programming meetups in Japan, my home country after having been in the US for about 9 years. Since I was interested in Elixir programming language, I was focused on Elixir in my searching for meetups. I realized that Japan's Elixir community so active and enthusiastic. First one I found was fukuoka.ex/kokura.ex - Fukuoka Elixir community, which is probably the largest one as far as I know. After visiting a few remote online events, I started participating in Nerves JP (Nerves community in Japan), where I learned Nerves IoT framework. I was a total beginner in hardware or physics but really enjoy playing with Nerves and Raspberry Pi thanks to the communities around the world.
I decided to write up so that more people can get started and have fun with Nerves.
Install necessary tools
For the setup, I just followed the Installation doc.
# Quick check
elixir --version
Once installation is done, I studied the basics reading the Getting Started doc.
Although the above doc talks about how to create a new Nerves app, I would recommend fellow beginners to try running the official "Blinky" example in nerves-project/nerves_examples first. I found it helpful because I actually see an LED blinking on my device without writing any code. I got a sense of accomplishment after being confused what I was supposed to do.
It took me a while to understand and get used to the Nerves development, but you'll be fine. If you get stuck, your friends from around the world including me will help you at these places:
- Slack elixir-lang #nerves invite
-
Elixir Forum - make sure you add
Nerves
tag to your questions - Your local Elixir community
Download Blinky example project
Blinky is a Nerves official example app that blinks a green on-board LED of your target device.
First I cloned nerves_examples from Github.
cd path/to/some/folder
git clone git@github.com:nerves-project/nerves_examples.git
Move to the blinky
project directory.
cd nerves_examples/blinky
Connect to a target device
One thing we need to think about is how to connect to our target device, such as Raspberry Pi. According to the doc, we can make a network connection to our target device, using:
- Ethernet cable
- USB cable
- WIFI
I personally use WIFI. All I needed was just to edit one section of config/target.exs
file and to provide my WIFI id and password.
--- a/blinky/config/target.exs
+++ b/blinky/config/target.exs
@@ -58,7 +58,20 @@ config :vintage_net,
type: VintageNetEthernet,
ipv4: %{method: :dhcp}
}},
- {"wlan0", %{type: VintageNetWiFi}}
+ {"wlan0",
+ %{
+ type: VintageNetWiFi,
+ vintage_net_wifi: %{
+ networks: [
+ %{
+ key_mgmt: :wpa_psk,
+ ssid: System.get_env("WIFI_SSID") || raise "Environment variable WIFI_SSID is missing.",
+ psk: System.get_env("WIFI_PSK") || raise "Environment variable WIFI_PSK is missing.",
+ }
+ ]
+ },
+ ipv4: %{method: :dhcp}
+ }}
]
config :mdns_lite,
The WIFI ID and password can be hardcoded in that file, but I did not want to so I decided to pass them through environment variables.
export WIFI_SSID=xxxxxxxx
export WIFI_PSK=xxxxxxxx
Alternatively you could manage your environment variables using utility programs like direnv.
Create the firmware bundle
Before running any firmware
command, we need to tell Nerves what our target device is. Here is the list of supported targets.
For example, my target is "Raspberry Pi 4", so I run export MIX_TARGET=rpi4
export MIX_TARGET=<your-target>
FYI
# List some commands related to firmware
mix help | grep firmware
# Check currently-set target tag
echo $MIX_TARGET
Get dependencies
mix deps.get
Build a firmware bundle
mix firmware
Write a firmware image to an SDCard
Insert an SD card to your host machine (not the target), then run mix burn
.
mix burn
Use 119.38 GiB memory card found at /dev/rdisk2? [Yn] y # Type y then hit enter
Check the connection
- Insert the SD card to your target device
- Turn on the target device
- Count 30 in your head and
- Verify the connection by running
ping nerves.local
❯ ping nerves.local
PING nerves.local (10.0.0.179): 56 data bytes
64 bytes from 10.0.0.179: icmp_seq=0 ttl=64 time=111.131 ms
64 bytes from 10.0.0.179: icmp_seq=1 ttl=64 time=5.939 ms
64 bytes from 10.0.0.179: icmp_seq=2 ttl=64 time=6.247 ms
...
Verify the blinking
Once the connection is established, you should see an LED on your target device blinking.
SSH into the target
If you have used SSH before, probably you can SSH into your target device without doing anything. If not, you need to set it up.
ssh nerves.local
Interactive Elixir (1.11.2) - press Ctrl+C to exit (type h() ENTER for help)
Toolshed imported. Run h(Toolshed) for more info.
RingLogger is collecting log messages from Elixir and Linux. To see the
messages, either attach the current IEx session to the logger:
RingLogger.attach
or print the next messages in the log:
RingLogger.next
iex(1)> ls
lib releases
iex(2)> top
Total processes: 201
Application Name or PID Reds/Δ Mbox/Δ Total/Δ Heap/Δ Stack/Δ
blinky <0.1165.0> 1670K/1670K 0/0 1375/1375 987/987 9/9
kernel file_server_2 672K/672K 0/0 2208/2208 1598/1598 12/12
undefined <0.3.0> 306K/306K 0/0 233/233 233/233 3/3
undefined application_controller 262K/262K 0/0 56K/56K 28K/28K 8/8
undefined erl_prim_loader 209K/209K 0/0 136K/136K 17K/17K 7/7
vintage_net <0.1179.0>=Elixir.VintageNet 192K/192K 0/0 32K/32K 4185/4185 13/13
vintage_net <0.1181.0>=Elixir.VintageNet 104K/104K 0/0 5172/5172 2586/2586 13/13
kernel code_server 102K/102K 0/0 310K/310K 118K/118K 5/5
nerves_runti Elixir.Nerves.Runtime.Log.Km 81K/81K 0/0 32K/32K 4185/4185 12/12
vintage_net <0.1110.0>=Elixir.VintageNet 68K/68K 0/0 3585/3585 2586/2586 11/11
iex(3)>
Instead of Linux shell, we use interactive Elixir shell (iex) to interact with our target device.
Because it is not a Linux shell, we cannot use Linux commands there but we can run something similar that is powered by fhunleth/toolshed library that is automatically imported into our IEX shell.
Run exit
command to close the IEX shell.
Next steps
I googled around what else I could do for learning about my Raspberry Pi and physics. Right now, I've been blinking LEDs in various ways on my breadboard. There are infinite amount of things to do. Whenever I have a question, I ask somebody in the Elixir/Nerves communities. The other day I was lucky, I got an answer from a co-authors of Nerves framework!
Elixir Forum - Can I add an LED to /sys/class/leds and control it using nerves_leds?
When I see some question that I can answer, I am tring to answer to contribute back to the community.
That's it. I hope this will help somebody start Nerves. Happy coding!
P.S. I am still learning. If I have something wrong, please feel free to correct me :)
Top comments (0)