注意:
本記事は2019年6月に執筆したものなので,最新版のNervesとは異なるところがあるかもしれません(なにか差分を見つけたらコメントでお知らせくださいm(_ _)m
少なくとも開発環境の構築については 『ElixirでIoT#4.1』をご参照ください.こちらの記事は常に最新版に追従するようにしています.
この記事は「Elixir or Phoenix Advent Calendar 2017」の22日目です.
昨日は@zacky1972さんの「ZEAM開発ログv0.1.3 AI/MLを爆速にしたい! Flow のコードを OpenCL で書いてみる〜GPU編」でした.
お知らせ
**「fukuoka.ex#11:DB/データサイエンスにコネクトするElixir」を6/22(金) 19時に開催します
私も『ElixirでIoTやってみた』**ネタで発表します!是非ともご参加下さい!!
はじめに
こんにちは.
組込み界隈の"Hello, World!"はLチカ(LEDの点滅制御)と謂われています.
えぇーっ!?たった4日間で組込みビギナーを卒業できる開発合宿があるんだって!??
さてステマはさておき,先日の勉強会「fukuoka.ex#8(福岡Elixir会):2018年 春のElixir入学式」にて発表した内容を加筆編集しながら,**ElixirをIoTボードで動かしたらどうなんの?**という異色ネタをお届けしています.
これまでの連載記事では,IoTボード上でElixirが実行できる環境を構築し,それぞれの性能をベンチマークアプリで評価してきました.
|> ElixirでIoT#1.0:IoTボードへのLinux環境の準備
|> ElixirでIoT#1.1:IoTボードへのElixir環境の構築とEEloTツールキットの紹介
|> ElixirでIoT#1.2:いろいろ分かるベンチマークを整備してみる
|> ElixirでIoT#1.3:IoTボードで動いた!Phoenixが立った!性能評価と考察
残念ながらボード/アーキテクチャの性能評価までに留まり,IoT屋さんには物足りないところかもしれません.
今回から新章に突入します!
ElixirでIoTボードのデバイスプログラミング可能な環境を提供しているNervesというのを調査してみて,まずはIoTの醍醐味?であるLチカをしてみましょう!!
Nervesって何者?
HPのTopでは,
「Craft and deploy bulletproof embedded software in Elixir」
と謳われています.bulletproofをどう解釈するか悩ましいところですが,
堅牢な組込みソフトウェアをElixirでお手軽に開発!
を目指しているようです.
- Platform: たったの12MBでLinuxブートローダとErlang VM/Elixir実行環境を実現!
- Framework: ネットワーク,I/Oなどのデバドラ機能を提供!
- Tooling:
mix new
対応ですぐにプロジェクト開発を開始!
要するにNervesとは,IoTボード上で動作する最小構成のLinuxブートローダ+Elixir実行環境+各種デバドラのパッケージセットと理解してよいかと思います.
このプロジェクト,v1.0.0の正式リリースが2018年5月3日と新しめでありつつ,initial commitは2013年10月と,長期的かつ活発に活動されているようです.素晴らしい!!
現状の対応ボードは,歴代のラズパイに加えて,BeagleBone familyのボードやLEGO Mindstorms EV3も使えるようです.Linuxブート可能なものなら他のIoTボードへの移植もできるのかも.(EV3のサポートは終了したようですT T;
この辺りもそのうちいろいろ試してみたいところです.
環境設定
それではNervesを試してみるにあたって,まずはInstallationのページを参考にしてホスト側の開発環境を整えてみたいと思います.
Elixirアプリ/mixプロジェクトの開発はクロス開発1を前提にしています.このため本記事で解説する操作はホストPC上で行います.私はMacとUbuntuの両方で動くことを確認しています.
なお,Erlang/OTPとElixirはインストール済みを前提とします.
$ elixir --version
Erlang/OTP 20 [erts-9.3] [source] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false]
パッケージの導入
Nervesのツール内ではfwup
,squashfs
,ssh-askpass
辺りのパッケージを使っています.それぞれインストールしていきましょう.
- Macの場合
$ brew install fwup squashfs coreutils
- Ubuntuの場合
$ sudo apt install build-essential automake autoconf git squashfs-tools ssh-askpass
$ wget https://github.com/fhunleth/fwup/releases/download/v1.1.0/fwup_1.1.0_amd64.deb
$ sudo dpkg -i fwup_1.1.0_amd64.deb
以降の操作はMac/Ubuntuで同じになります.
ライブラリアップデート
hex
とrebar
は最新版にアップデートしといてほしいそうです.
$ mix local.hex
$ mix local.rebar
環境のインストール
nerves_bootstrap
という名前でHexパッケージとして公開されています.
もちろんコマンドラインから環境をインストールすることができます.
$ mix archive.install hex nerves_bootstrap
これでNervesアプリの開発環境が整いました!
使い方
次は,Nervesの使い方を説明していきます.
プロジェクトの作成
mix
で作成できます.途中のFetch and install dependencies? [Yn]
では気にせずY
を打ち込んで良いです.
以下はhello_nerves
という名前のプロジェクトの作成例です.出力も掲載します.
$ mix nerves.new hello_nerves
* creating hello_nerves/config/config.exs
* creating hello_nerves/lib/hello_nerves.ex
* creating hello_nerves/lib/hello_nerves/application.ex
* creating hello_nerves/test/test_helper.exs
* creating hello_nerves/test/hello_nerves_test.exs
* creating hello_nerves/rel/vm.args
* creating hello_nerves/rootfs_overlay/etc/iex.exs
* creating hello_nerves/.gitignore
* creating hello_nerves/.formatter.exs
* creating hello_nerves/mix.exs
* creating hello_nerves/README.md
Fetch and install dependencies? [Yn] Y
* running mix deps.get
* running mix nerves.release.init
Your Nerves project was created successfully.
You should now pick a target. See https://hexdocs.pm/nerves/targets.html#content
for supported targets. If your target is on the list, set `MIX_TARGET`
to its tag name:
For example, for the Raspberry Pi 3 you can either
$ export MIX_TARGET=rpi3
Or prefix `mix` commands like the following:
$ MIX_TARGET=rpi3 mix firmware
If you will be using a custom system, update the `mix.exs`
dependencies to point to desired system's package.
Now download the dependencies and build a firmware archive:
$ cd hello_nerves
$ mix deps.get
$ mix firmware
If your target boots up using an SDCard (like the Raspberry Pi 3),
then insert an SDCard into a reader on your computer and run:
$ mix firmware.burn
Plug the SDCard into the target and power it up. See target documentation
above for more information and other targets.
もうみなまで説明が書かれていて親切ですね.
テンプレートとして出力されるElixirコードを見てみましょう.
defmodule HelloNerves do
@moduledoc """
Documentation for HelloNerves.
"""
@doc """
Hello world.
## Examples
iex> HelloNerves.hello
:world
"""
def hello do
:world
end
end
これをベースとして色々なIoTアプリを開発できそうです.
プロジェクトのビルド
まずは,ターゲットのボードを環境変数の設定によって指定します.
選択肢はTargetsのページにある表のTAG列になります.今回はRaspberry Pi 3 Model Bのrpi3
を使っています.
$ export MIX_TARGET=rpi3
あとはいつも通りのmixプロジェクトのビルドと同じですね.
イメージファイル生成のためのmixタスクfirmware
が用意されています.
$ cd hello_nerves
$ mix deps.get
$ mix firmware
これで,ラズパイ3B上で動作するアプリが含まれたイメージファイル(最小構成のLinuxブートローダ+Elixir実行環境+各種デバドラ)が生成されました.
なお初回のmix deps.get
時には,おそらくブートローダとErlang VMをビルドするためのクロスコンパイラ環境が~/.nerves/artifacts/
にインストールされます.
何が生成されたの?
ちなみに生成されるイメージファイルの実態は_build/rpi3/dev/nerves/images/hello_nerves.fw
です.
$ ls -l _build/rpi3/dev/nerves/images/hello_nerves.fw
-rw-r--r-- 1 takase staff 24M 5 13 18:01 _build/rpi3/dev/nerves/images/hello_nerves.fw
確かに24MBと驚くべき小ささです!!
$ file _build/rpi3/dev/nerves/images/hello_nerves.fw
_build/rpi3/dev/nerves/images/hello_nerves.fw: Zip archive data, at least v2.0 to extract
ということは,,,??
$ unzip _build/rpi3/dev/nerves/images/hello_nerves.fw
$ ls meta.conf data/
meta.conf
data/:
bcm2710-rpi-3-b.dtb config.txt start.elf
bcm2710-rpi-cm3.dtb fixup.dat w1-gpio-pullup.dtbo
bootcode.bin pi3-miniuart-bt.dtbo zImage
cmdline.txt rootfs.img
なるほどなるほど,確かにいろいろ入っていますね
TIPS: SSH公開鍵の作成
$ mix deps.get
** (Mix.Config.LoadError) could not load config config/config.exs
** (File.Error) could not read file "/Users/takase/.ssh/id_rsa.pub": no such file or directory
と言われる場合は,SSH公開鍵を以下のように作ってあげてください.
$ ssh-keygen -t rsa -f ~/.ssh/id_rsa
microSDへの書き込み
これも簡単です.microSDカードをホストPCに繋いで$ mix firmware.burn
を実行します.
microSDの接続先は自動認識されますので,接続先が正しければY
を打ち込みます.なお,イメージ書き込み時には管理者パスワードを求められます.
$ mix firmware.burn
Nerves environment
MIX_TARGET: rpi3
MIX_ENV: dev
Use 59.8 GiB memory card found at /dev/rdisk2? [Yn] Y
|====================================| 100% (27.50 / 27.50) MB
Success!
Elapsed time: 4.330 s
ラズパイでの実行
イメージファイルを焼いたmicroSDカードをラズパイ3Bに差し込み,HDMIディスプレイとUSBキーボードを接続して電源を投下しました.
そして数秒経つと,,,おーiex
が立ち上がってきています!
普通のインタラクティブなコードはもちろんのこと,テンプレートのコードhello_nerves.ex
に入っていたHelloNerves.hello
だってもちろん動きます!!
ちなみにCtrl+C x2をしてもiex
が落ちることはありません^^;
さあLチカしてみよう!
Nerves Projectが幾つかのサンプルを提供しています.
その中のBlinky
を使ってみました.
$ git clone https://github.com/nerves-project/nerves_examples.git
$ cd nerves_examples/blinky
$ export MIX_TARGET=rpi3
$ mix deps.get
$ mix firmware
$ mix firmware.burn
おーなんとなんと!お分かりになりますでしょうか??
ボード左下にある緑色のLEDが見事にチカチカしています!!!
hello_gpio
やhello_phoenix
などなど,GPIOやPhoenixフレームワークを使ったサンプルも提供されています.また,各種センサ/アクチュエータをお手軽に繋げるGroveモジュールのライブラリもあるようです.
この辺りを使えばIoTアプリの構築もお手のもの!?これからぜひ触ってみたいと思います.
使ってみた感想
Elixir環境でここまでお手軽にさくっとIoTデバイスのアプリ開発を始められるとは,非常に驚きでした.IoTワールドでElixirの生産性の良さや並列性能を活かすことができますので,新たなアプリ創出の機運が高まってきていますね.
ただ,クロス開発なのはちょっと面倒だと感じました.
いちいちmicroSDに焼くのも面倒ですし,いちいち電源を投下して数秒経たないと結果が分からないのはストレスに感じます.複数ボードへの本番環境へのデプロイならお手軽になる状況とも考えられます.調査が及んでいないので提供されているかもですが,ホスト開発2の方法やリモートデバッグの方法が無いとツラいところです.
イメージファイルのサイズの小ささは魅力ではあります.しかしながら,ラズパイのようなLinuxがきびきび動くIoTボードは,そもそもメモリ量が潤沢ですので,メモリサイズはそこまで重視する要素にはなりません.それであれば,Linuxを載せちゃって生のelixir/iex環境でホスト開発したほうが手っ取り早いよなぁと感じました.(なお,Linuxが動かせないクラスのボードを目指すなら,12MBでも全然大きかったりします)
ホスト開発だと「elixir_ale - Elixir Actor Library for Embedded」というのが使えるらしいという情報もあります.王道としてはNIF/BIFに飛び込むのもアリでしょう.
IoTアプリのためのElixir実行環境/開発環境,うーん研究材料としてとっても面白そうだ!!
まとめ
- ElixirでIoT開発ができます!!
- Nervesを使ってお手軽に組込みソフトウェアを開発!
- IoTボード上で動作する最小構成のLinuxブートローダ+Elixir実行環境+各種デバドラのパッケージセット
- ホストPC上の
mix
システムでクロス開発を実現 - テンプレートのアプリ込みでもイメージファイルはたったの24MB!
皆さんもElixirを片手にIoTワールドへ飛び込んでみませんか!??
次回の発表駆動開発の機会である**「fukuoka.ex#11:DB/データサイエンスにコネクトするElixir」**までに,さらなる調査や開発を進めたいと思います!私の発表もお楽しみに!!
明日のAdvent Calendarは@piacere_exさんによる
「Excelから関数型言語マスター5回目:Webにグラフ表示」
です.