IoT development using Raspberry Pi, Elixir and Nerves
Tags: elixir, raspberrypi, iot, nerves
Published: 2021-04-02 13:53:50

Today I am going to be talking about [IoT (Internet of Things)](https://en.wikipedia.org/wiki/Internet_of_things) development using Raspberry Pi and [Elixir](https://en.wikipedia.org/wiki/Erlang_(programming_language)), using [Nerves](https://www.nerves-project.org/) IoT platform.

I usually work on web applications, but I started learning about embedded devices development to expand my expertise.

After studying the basics of electronics components, I built a real-time temperature and humidity monitoring system for my living room. 

The [Nerves](https://www.nerves-project.org/) IoT platform allows us to build a custom Linux-based firmware easily as well as enabling IoT development using modern programming language Elixir. It is a huge plus for developer experience and device performance.

## Feature

Here is what I do:

- The target device reads a measurement from the sensor and sends it to the web server every second.
- The web server broadcast a measurement to a real-time monitoring dashboard.
- The host machine can update the firmware over the WIFI anytime.

![hello-nerves-2](https://user-images.githubusercontent.com/7563926/113411295-6508b380-9383-11eb-81ef-942e0999d0cd.gif)

![pi_and_bme680](https://user-images.githubusercontent.com/7563926/113063889-04f7ee80-9184-11eb-8213-90fe7fbb39b8.jpg)

## System Components

### Host machine (My laptop)

- develop a firmware (Elixir progmamming)
- burn a firmware into a micro SD card (only one time)
- upload a firmware over the wifi
- ssh into the target device over the wifi

### Target device (Raspberry Pi Zero W)

- a small general purpose computer
- has WIFI capability
- has Micro SD card slot

### Firmware (device-specific software)

- burned into a micro SD card that is inserted into a target device
- contains Linux, Erlang VM, Elixir and my business logic

### Sensor (Bosch BME680)

- Environmental sensor
- I2C and SPI are among the most common serial communication protocols for transporting data between devices
- Elixir library: https://github.com/fhunleth/bmp280

### Web server

- accepts a sensor measurement from the target device
- broadcasts a new measurement to a dashboard

### Software

- Elixir - programming language
- Nerves - platform for developing IoT devices
- Phoenix - web framework
- Phoenix LiveView - enables rich, real-time user experiences with server-rendered HTML

## Embedded systems

Technically what I am doing is not a traditional embedded system development.

Generally the embedded systems engineers deal with microcontrollers, which are good at doing dedicated tasks efficiently. They do not have an operating system. Typically C/C++ are used for programming.

On the other hand, most Raspberry Pis are a general purpose computer just like my laptop despite being tiny. So I can let it do various tasks out of the box.

I chose the latter because computers is more powerful than microcontrollers and I want to build things quickly taking advantage of modern development tools, using my favorite programming language Elixir.

## Elixir

- functional programming language built on top of Erlang
- particularly built-in support for process supervision and concurrency is great
- Erlang is battle-tested in telecommunication systems since 1980's; recent years, Erlang is used for a number of messaging apps, like whats app, Slack, Discord etc.

## Nerves

- platform for embedded device development
- builds firmware with lightweight Linux + Erlang VM (~20MB)

## Difference between IoT development and web development

### physics

I am more aware of physics than usual when I am dealing with IoT devices.

- each electronics components comes with a data sheet, which looks like a physics textbook
- data is transmitted as high or low voltage through electric wires
- I've seen smoke coming out of a circuit; probably I made a mistake in wiring

### bit operations

In embedded system programming, we express the high voltage as 1, low voltage as 0. So we need to encode/decode sequence of 0s and 1s frequently. Usually a peripheral has physical addresses called registers we read data from and write data to.

Speaking of bit operations, in many programming languages, bit operations can look complicated despite simply handling 0s and 1s. Thankfully Elixir's pattern matching makes it so easy.

For example, where C++ does something like this,

[![Screen Shot 2021-04-01 at 4 57 32 PM](https://user-images.githubusercontent.com/7563926/113353477-b70df280-930b-11eb-8ae5-e21b93d34042.png)](https://github.com/adafruit/Adafruit_AHTX0/blob/master/Adafruit_AHTX0.cpp)

Elixir can express the same logic in a lot more human-readable ways. Elixir's pattern matching is so powerful.

```elixir
<<_state::8, h::20, t::20>> = data       # 6 bytes (48 bits) that is read from the sensor
humiduty_rh   = h * 100 / 0x100000       # 15.079402923583984
temperature_c = t * 200 / 0x100000 - 50  # 28.26671600341797
```

## Conclusion

So my IoT development using Raspberry Pi and Elixir has been successful and fun. I just wanted to share it with you.

Thank you for listening!

## Resources

- [Nerves IoT platform](https://www.nerves-project.org/)
- [Erlang | wikipedia](https://en.wikipedia.org/wiki/Erlang_(programming_language))
- [Elixir | wikipedia](https://en.wikipedia.org/wiki/Elixir_(programming_language))
- [AHT20で温度湿度を取得して全世界に惜しげもなくあたい（値）を公開する(Elixir/Nerves/Phoenix)](https://qiita.com/torifukukaiou/items/5876bc4576e7b7991347)