Wio LTEでmruby/cを動かすArduinoライブラリを作った

2018-06-04Project, TechArduino, c, Embedded, Japanese, mruby/c, Ruby, Wio LTE

英語版はこちら

先日、第60回 kawasaki.rbで↓のようなLTしてきました。
https://docs.google.com/presentation/d/15-78GUJtlWsIcS6HThrWswXMGcyIbfPntIaUzqqXSvU/edit?usp=sharing
その内容をブログにもまとめておきます。

要約

モチベーション

 
最近電子工作が趣味になっていて、ここでひとつ何か役に立つデバイス作りたいと思ってアイデアを考えていました。

年のせいか、最近自分で自分を見失うことが増えてきたので、自分で自分をトラッキングするデバイスがあると少し幸せになるのではないか。
→自分専用常時モバイルネットワーク接続のGPSトラッカ―を作ろう。
(スマホアプリ作ればいいのでは?)
(そもそも飲みすぎないようにすればよいのでは?)

モデム搭載のデバイスといえば

 
IoTブームで色々デバイスがあるのかなと思って調べてみると、意外と趣味の範囲で使えそうなのが見つからないです。
いくつか使えそうなものを上げてみました。

Particle Electron

アメリカのベンチャーの製品。回線契約とセットになっている。最低限必要な機能がコンパクトにまとまっていて良さそう。
日本でもローミングで動くようだけど、デバイスが技適(工事設計認証)を取っていないようなので、残念ながら使えないっぽい。
https://www.particle.io/products/hardware/electron-cellular-2g-3g-lte

さくらの通信モジュール

さくらのIoTプラットフォームと連携する前提のモジュール。モデムを専用のプロトコルで通信して制御する。Arduinoのライブラリもあります。モジュールは専用のブレイクアウトボードやシールドで接続する前提なので、ちょっと準備が面倒そう。
https://sakura.io/product/module_lte.html

Wio LTE JP version

Wio LTE and GPS module
Wio LTE and GPS module

中国深センのSeeed Studio製。制御マイコンがSTM32で回路図も公開されていてハックしやすい。ちゃんと日本でも使えます。インタフェースとして同社製品用のGroveコネクタ搭載。
個人で遊ぶにはちょうど良さそうなので、これを採用。SIMはソラコムのものを利用することにしました。

その他

USB接続のドングルなどは比較的安いのがあるけれど、WindowsやLinuxが前提になるので、今回はパス。RaspberryPiでも良いときには使えそうです。

完成図

開発用のボードで待機時もそれなりに電流が流れてしまうようなので、RTCで大本の電源を制御できるようにしようと思っています。
モデムが電力食うようなので、2A程度の容量が必要みたいです。モバイルバッテリーだとスリープ時の制御が難しいので、大きめのLiPoバッテリ必要かと思っていますが未検証。

GPS tracker system for me
GPS tracker system for me

開発言語は?

WioLTEは日本向けにArduinoのライブラリが公開されていて、説明も手厚いです。
https://github.com/SeeedJP/WioLTEforArduino/wiki/Home-ja
個人的にはそれで十分なのだけど、それだけだとちょっとつまらなかったので、mrubyを動かしてみることにしました。
STM32F405RGT6 のRAMは200KB程度なので、通常のmrubyをそのまま動かすのはかなり大変。
最近動向を追っていなかったのでしらなかったのですが、よりリソースが少ないマイコン向けに、mruby/cというのがあるらしいです。今回それを試してみることにした。

http://www.s-itoc.jp/activity/research/mrubyc/
https://github.com/mrubyc/mrubyc

試した結果

mruby/cのソースコード一式をライブラリとしてあっさりArduinoIDE上でビルドできました。(多少の修正は必要でしたが)
ソースは下記にアップしています。通常のArduinoライブラリとして利用できる形になっています。ダウンロードしてlibrariesフォルダにコピーすれば使えると思います。サンプルのinoファイルもあります。
https://github.com/kishima/libmrubycForWioLTEArduino

Arduino側のソース

‘mrbc_define_wiolte_methods()’ という関数の中で、WioLTEのAPIをRubyのメソッドとして定義しています。(今はLEDにだけ)

#include 
#include 
extern const uint8_t code[];

// mrubyでバイトコンパイルしたRubyのスクリプト
const uint8_t code[] = {
0x52,0x49,0x54,0x45,0x30,0x30,0x30,0x34,0x7e,0x45,0x00,0x00,0x01,0x4d,0x4d,0x41,
---中略---
};

#define MEMSIZE (1024*30)
static uint8_t mempool[MEMSIZE];

void setup() {
  delay(1000);

  SerialUSB.println("--- begin setup"); 
  mrbc_init(mempool, MEMSIZE);
  mrbc_define_wiolte_methods();
  if(NULL == mrbc_create_task( code, 0 )){
    SerialUSB.println("mrbc_create_task error");
    return;
  }
  SerialUSB.println("--- run mruby script"); 
  mrbc_run();
}

void loop() {
  delay(1000);
}

バイトコンパイル前のRubyスクリプト

r=0
g=0
b=0
while true
    r=b/2
    g=b/3
    puts "mruby/c example: control LED B="+b.to_s
    Wio.control_led(r,g,b)
    sleep(1)
    b=b+10
    b=0 if b>60
end

mruby/cの良いところ

言語としての機能がかなり制限されていますが、その分とてもコンパクトです。
デフォルト設定の実行環境としての規模は↓程度です。

  • ROM:100K+バイトコード分
  • RAM:5KB+ヒープ用

vm_config.h の定数を書き換えると最大オブジェクト数などの上限を増やすことができます。
使用するメモリの上限をコントロール可能なのはよいと思います。

規模が小さいので、各処理の動きの見当が付きやすく、ポーティングが非常にやりやすいと感じました。

mruby/cであることの意義

毎回、バイトコンパイルして、結果をコピペするのでは面倒すぎるので、mrubyだけで完結できるようにしたいです。
余裕があれば、ArduinoのC/C++の実装をセカンドブートローダのような扱いとして、バイトコードの転送機能とあわよくばインターネット経由の更新機能も試してみたいな、と思っていますが、時間が掛かりそうです。

思ったこと

  • 早く完成させたい。
    • 最近modemの起動時の応答がなく、起動に失敗している…。原因調査中ですが、致命的な故障でないとよいのですが…。
  • 必要なAPIを一通りメソッド定義すれば、mruby/cを使って十分開発できそう
    • よく電子工作で使われるESP32では、mrubyをポーティングしたPoCがある。こちらはAPIもポーテイングしてあるが、メジャーではない。
    • ESP32やその他の開発環境として、最近MicroPythonが広まってる気がする。
    • WioLTEの場合、公式がJavascriptベースの開発環境(Espruino)をサポートしてるのでLLで開発したいひとはこちらをつかえばいいのでは(本末転倒)
      http://www.espruino.com/WioLTE
    • 小規模な工作レベルであれば、個人的には、Cで書いた方が気楽。
    • mruby/cを使うのは、Cを使わない人向けへの導入として有効だと思う。
    • ArduinoAPIとWioLTE用API一式のメソッド移植!
  • mruby/cはポーティングが非常に楽なので、他でも使ってみたい。

mruby/cについては、また別の記事で触れてみようと思います。