Erlang
RaspberryPi
Elixir
IoT
Grove

ElixirでIoT#2.2:関数型言語からGroveモジュールを使ってみた

この記事は「fukuoka.ex(その2) Elixir Advent Calendar 2017」の25日目,および
「Raspberry Pi Advent Calendar 2017」の20日目です.

昨日は,@twinbeeさんの
Google DatalabコンテナにElixirを入れてTensorflexを動かそう」でした.

本記事では,ラズパイのGrovePi+に接続した各種Groveを関数型言語Elixirから扱えるGrovePiライブラリを紹介します.

:camping: :camping: :camping: お知らせ!新たなElixir Advent Calendar、来週6/18(月)から始まります :camping: :camping: :camping:

fukuoka.exアドバイザーズのざっきーさん率いる山崎研究室、通称「ザキ研」の有志と、fukuoka.exアドバイザーズ/キャスト数名が、合同で新たな季節外れのElixir Advent Calendarを始めます:star2:

来週6/18(月)からスタートで、「季節外れのfukuoka.ex(その2) Elixir Advent Calender」で連載途中だったシリーズも、「fukuoka.ex x ザキ研 Advent Calendar」で、続きが見れます:gem:

どうぞ、来週6/18(月)以降の新たなカレンダーをお楽しみに!:rocket:

image.png

はじめに

どうもこんにちは.
fukuoka.exという福岡のElixir/PhoenixコミュニティにてIoT芸を披露している者です.
巷を賑わせている新しめの関数型言語であるElixirでIoTできるんじゃね!?と喧伝しております.

これまでの連載記事はこちら.
 |> ElixirでIoT#1.0:IoTボードへのLinux環境の準備
 |> ElixirでIoT#1.1:IoTボードへのElixir環境の構築とEEloTツールキットの紹介
 |> ElixirでIoT#1.2:いろいろ分かるベンチマークを整備してみる
 |> ElixirでIoT#1.3:IoTボードで動いた!Phoenixが立った!性能評価と考察
 |> ElixirでIoT#2.1:Nervesって何者?ラズパイでLチカできんの!?

Elixirユーザの皆さまにはいろいろそこそこ反響をいただいて感謝の限りです.
ラズパイユーザな皆さまにも,ラズパイでElixir使えるよ!?ということを知っていただきたく,やはり季節外れですが「Raspberry Pi Advent Calendar 2017」の空き日に投下しております.
なお,ラズパイカレンダーに前回投下した記事はこちらです.
 |> ElixirでIoT#1.1.1:ラズパイへのErlang/Elixir環境の構築

今回は,Elixirから各種Groveを扱えるGrovePiライブラリを紹介します.

Elixirとは?

RaspberryPiタグで来た方への説明です.

Elixirは2012年に登場した新しい関数型言語です.ErlangのVM上で走ります.次に来る大物Web言語と言われています.

Elixirには以下の特徴があります.

  • 読み書きしやすく,生産性が高い.
  • 並行処理(並列処理)のプログラミングが簡単に実現できる.
  • 分散システム対応/スケールしやすい.
  • 軽量で耐障害性が高い.

あれっ?これってIoTでも使えるんじゃね!??

Groveとは?

ElixirErlangのタグで来た方への説明です.

Groveは,各種センサなどのIoTデバイスを画一パッケージ化したモジュール群です.中国深センにある気鋭のスタートアップであるSeeed社が開発・販売しています.
入出力ピンが4ピンのGroveコネクタで統一されており,簡単に付け替えできるのが特徴です.また,Arduinoやラズパイに96Boardsなどの主要なIoTボードに適合する各種シールドも提供されています.このため,様々なIoTシステムの開発をラピッドに試すことができます:bullettrain_side::bullettrain_side::bullettrain_side:

Elixirのラズパイ/Groveへの対応状況

Elixir界隈では,前回の記事でも紹介したとおり,Nervesというプロジェクトにてラズパイへの対応が進んでいます.
Grove対応は,Nerves.Groveというライブラリが提供されており,GitHubでもソースが公開されています.最初はこれを使おうかと思ったのですが,ドキュメントやサンプルアプリが乏しく,扱い方がよく分かりませんでした.開発が2016年8月で止まっているのも気がかりです.

今回は,上記のNerves.Groveを発展させてGrovePiに対応した下記のライブラリを使いました.

GrovePi+とGrovePi Zeroに対応していて,examples/以下に幾つかサンプルも提供されていて分かりやすいです.Groveモジュールの対応状況はHexDocsをご参照ください.

GrovePiライブラリでは,Erlang VMのNIF経由でラズパイのGPIO,I2C,SPIの各種デバドラにアクセスできるelixir_aleが使われています.

用意した環境

筆者が試してみた環境をまとめてみます.

今回の記事では,以下のGroveモジュールを使いました.

IMG_9936.JPG

GrovePi+の環境構築

まずはこちらを参考にして,GrovePi+を使えるように環境をインストールします.
インストール後は再起動が必要です.

$ sudo curl -kL dexterindustries.com/update_grovepi | bash
$ sudo reboot

再起動後にGrovePi+をラズパイに刺して,i2cdetectコマンドで正常にシールド接続が検出できることを確認してください.

 sudo i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- 04 -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --                   

GrovePiライブラリの使用方法

それではGrovePiライブラリを使っていきましょう.
まずはmixプロジェクトの作成ですが,この辺りはいつものElixirと同じです.

$ mix new grovepi_test 
* creating README.md
* creating .formatter.exs
* creating .gitignore
* creating mix.exs
* creating config
* creating config/config.exs
* creating lib
* creating lib/grovepi_test.ex
* creating test
* creating test/test_helper.exs
* creating test/grovepi_test_test.exs

Your Mix project was created successfully.
You can use "mix" to compile it, test it, and more:

    cd grovepi_test
    mix test

Run "mix help" for more commands.
$ cd grovepi_test/

mix.exsにGrovePiライブラリを使うための依存関係を書いてやります.
releaseタグじゃなく最新のmasterブランチを明示的に指定してやらないと動かないサンプルがありました.

mix.exs
  defp deps do
    [{:grovepi, github: "adkron/grovepi", branch: "master"}]
  end

あとは,lib/grovepi_test.exにプログラミングしていくだけです.

コンパイルと実行はこんな感じです.
elixir_aleの都合でMIX_ENV=prodを明示指定する必要があるようです.

$ mix deps.get
$ MIX_ENV=prod mix compile
$ MIX_ENV=prod iex -S mix

examples/の紹介

最後に,GitHubに挙がっているexamplesを使ってみたので紹介します.
とりまgit cloneして移動しましょう.

$ git clone https://github.com/adkron/grovepi
$ cd grovepi/examples
$ ls
alarm  demo_pivotpi  demo_rgblcd  
home_weather_display  led_fade

alarm

GrovePi+のA0にButtonを,D3にBuzzerを接続します.
ボタンを押したらAlert!!!!と表示されて1秒間ブザーが鳴ります.Buzzer音がすっごく大きいので,周りの方々をビックリさせないようにご注意ください:rage::rage::rage:
(Buzzerに養生テープ等を貼り付けとくと音量が抑制できます)

$ cd alarm/
$ mix deps.get
$ MIX_ENV=prod mix compile
$ MIX_ENV=prod iex -S mix
Erlang/OTP 20 [erts-9.3] [source] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false]

Interactive Elixir (1.6.5) - press Ctrl+C to exit (type h() ENTER for help)
# ボタンを押したら,,,??
iex(1)> Alert!!!!

ちなみに,コネクタの配置はlib/alarm.exの6-7行目で変更できます.

lib/alarm.ex
  # Pick ports that work on both the GrovePi+ and GrovePi Zero
  @button_pin 14 # Port A0
  @buzzer_pin 3  # Port D3

demo_pivotpi

シリアルモータを制御できるPivotPi用のサンプルです.
手元に持っていなかったんでカッツアイ.

demo_rbglcd

LCDモジュールを使ったサンプルです.今回のLCD RGB Backlightは,名前の通りRBGのバックライトが付いています.
GrovePi+のI2C-1に接続します.

$ cd demo_rgblcd/
$ mix deps.get
$ MIX_ENV=prod mix compile
$ MIX_ENV=prod iex -S mix

LCDの表示を制御するデモが幾つか用意されています.
無限ループで動きますので,その都度Erlangを終了させる必要があります.

iex(1)> DemoRGBLCD.autoscroll()
%GrovePi.RGBLCD.Config{display_control: 12, entry_mode: 6, function: 56}
0
1
2
3
4
5
6
7
8
9
%GrovePi.RGBLCD.Config{display_control: 12, entry_mode: 7, function: 56}
0
1
2
3
4
5
6
7

BREAK: (a)bort (c)ontinue (p)roc info (i)nfo (l)oaded
       (v)ersion (k)ill (D)b-tables (d)istribution

実際に動いている様子です.0-9の数字が右から左へ受け流されます.

lcd_autoscroll.gif

iex(4)> DemoRGBLCD.colors()

バックライトがRGBWで点灯します.
動画だともっと綺麗なんですが,GIFだとコレが限界ですかね.

lcd_rgb.gif

その他のデモの解説はさらっといきますかね.

iex(3)> DemoRGBLCD.blink()
  # Say "Hello World!" and toggles cursor blinking on and off every 3000ms
iex(4)> DemoRGBLCD.cursor()
  # Say "Hello World!" and toggles the cursor on and off every 1500ms
iex(5)> DemoRGBLCD.display()
  # Toggles the display on and off every 1500ms
iex(6)> DemoRGBLCD.text_direction()
  # Demonstrates text direction both ways
iex(7)> DemoRGBLCD.set_cursor()
  # Demonstrates moving the cursor to the second line

home_weather_display

温湿度センサ(Temperature&Humidity Sensor)の値をLCDに表示します.

ただこれはなぜかNerves環境下で動作するクロス開発のアプリになっています.使用されているNervesや他ツールのバージョンが古いようで,最新環境を構築している筆者の母艦Macではコンパイルすらできませんでした.
そのうちセルフ開発で扱えるように本サンプルを作り変えたいと思っています.

led_fade

GrovePi+のA2にRotary Angle Sensorを,D3にLED Socketを接続します.
ロータリの角度に応じてLEDの点灯量が変化します.

$ cd led_fade/
$ mix deps.get
$ MIX_ENV=prod mix compile
$ MIX_ENV=prod iex -S mix

実際の動作はこんな感じ.
細かくて分かりにくい上に汚い指ですみません,,,

led_fade.gif

ラズパイはデジタルピンしか出ていないのですが,Groveを使用することでアナログ制御も簡単に実現できるようになります.

まとめ

  • ElixirでGrove使えるよ!IoTラピッドプロトタイピングできちゃうよ!!
  • Groveモジュールを扱えるGrovePiライブラリとそのサンプルを紹介しました

お知らせ

:alarm_clock::alarm_clock::alarm_clock::alarm_clock: 満員御礼!Elixir MeetUpを6月末に開催します :alarm_clock::alarm_clock::alarm_clock::alarm_clock:
※応募多数により、増枠しました
「fukuoka.ex#11:DB/データサイエンスにコネクトするElixir」を6/22(金) 19時に開催します.

image.png

私も「ElixirでIoTやってみた」芸を披露する予定です.
実は今回の記事は,このfukuoka.ex#11に向けたネタ仕込みの先出しだったりするのです.
温湿度センサをセルフで扱えるようにして,環境データをセンシングしてさくっとWeb表示できたらおもろいかな?と思っていたりしています.

そして,ネタ仕込みの開発状況は下記のGitHubで逐次公開していきます.

まだ今回のサンプルを移しただけなのですが,,,ちゃんと準備が進んでいるのかリポジトリをWatchしてたら面白いかもしれませんw

どうぞfukuoka.ex#11での発表にご期待ください!!