mruby が組み込まれたマイコンボード GR-CITRUS を使ってみた

この記事は、[Fujitsu Advent Calender](http://qiita.com/advent-calendar/2016/fujitsu)の 19 日目の記事です。

# はじめに

@GORO_Nekoです。ご存知の方ご無沙汰してます。初めての方お初にお目にかかります。

えーっと、先にお断りをば一言。

自分、仕事では一切 mruby 扱っておりません。

以下は、自分が所属する会社の意向を反映したものでもスタンスを示すものでもなく、単なる一個人の趣味の活動から産まれた記述です。

# GR-CITRUS ってご存知ですか？

唐突に自分語りしますが、自分、昔っからの [Ruby](https://www.ruby-lang.org/ja/)大好き、電子工作大好き人間です。

当然のように組込用途に向け開発された軽量 Ruby こと [mruby](http://forum.mruby.org/doc/mruby-141121135812-conversion-gate01.pdf)大好きです。

で、そんな人間が目の前に、こんなマイコンボードぶら下げられちゃったら、触らずにはおられんでしょ？

● GR-CITRUS
![GR-CITRUS.png](https://qiita-image-store.s3.amazonaws.com/0/89832/a68200ee-04ba-cfab-95f9-90b41e00b746.png)

- [Renesas Electronics Corporation 製マイコンボード](http://gadget.renesas.com/ja/product/citrus.html)
- 組込み向け軽量 Ruby の mruby を搭載したマイコンボード
- ルネサス32ビットマイコン RX631 グループ MCU を搭載
- Arduino 互換（Arduino Pro Miniと互換性のあるピン配置
- mruby 製アプリケーションに加え、Arduino 言語製アプリケーションも動作可能（・・・私はまだ試してません）
- ESP8266 を搭載したボード「WA-MIKAN」（この試行では使っていません）と組み合わせることで WiFi 通信やマイクロ SD カードの使用が可能
- Chrome App の [Rubic](https://chrome.google.com/webstore/detail/rubic/mgbcgagfggopcpbbfgididddbnhhnhjp?hl=ja)を使うことで、プログラムの作成から実行までスムーズに実行可能

ってな訳で、買ってきたらすぐに mruby が使える（と言っても開発母機として、Linux なり Windows なり Mac なりの OS が乗っかった、所謂アプリケーション開発用 PC は必要ですが）マイコンボードが目の前に出てきちゃ試すしかないですか！

で、良くありがちな電子工作例になりますが「 GR-CITRUS ＋ mruby ＋ 温度センサ」で「電子気温計」なるものを作ってみました。

# 用意したハードウェア

● 一覧

- GR-CITRUS（マイコンボード。詳細は上記参照）
- 温度センサ（ LM61CIZ 。気温に対応した電圧を出力する）
- ブレッドボード（電子回路の試作・実験用の基板)
- 接続用ジャンパ線 × 5

とまぁ、開発用 PC 以外に上記のようなものをかき集めてまいりました。

部品を以下のように配置し、GR-CITRUS 上のアナログピン経由で LM61CIZ から 繰り返しデータ（出力電圧）を受け取り、得られたデータをシリアル接続で PC 上に転送し、約 1 秒間隔で、気温として表示することにしました。

え？　なんでわざわざデータを PC 上に転送して表示させてるかって？

組込ボードには汎用の PC みたいに、モニタをぽんとつなげたらそのままデータを出力できる所謂標準出力機能のような機能は、普通ついていないからです。

標準出力も標準エラー出力も無い世界では、puts も p も無力です。

Ruby 文法を使ってプログラムが組めるといっても、puts や p の引数として、表示対象データを記述すれば、それがどこかに表示されると言う世界は、ここにはありません。

[配置図]
![配線図_2.png](https://qiita-image-store.s3.amazonaws.com/0/89832/9de7d40d-5a2e-15e3-9d03-707e08ba7325.png)


[実際のマイコンボード等]
![IMG_5469.JPG](https://qiita-image-store.s3.amazonaws.com/0/89832/25273564-7d08-ff23-30f1-bd0851f97be4.jpeg)


GR-CITRUS のアナログピンの入力値は 10Bit 分解能なので 0 ～ 1023 の値となります。

よって、5V（ 5000mV ）駆動しているこのボードのアナログピンから、ピンに入力された電圧情報（ 0mV ～ 5000mV ）を、0～1023 の範囲にマッピングした値の形で得ることができます。

また LM61CIZ は周囲の温度（ -30 ℃ ～ +100 ℃ ）に合わせて、リニアに電圧を出力（ +300mV ～ +1600ｍV ）する性質を持った IC です。

故に、LM61CIZ からアナログピン経由で得たデータは、以下の 2 段変換を行ったデータを PC に転送する必要があります。

1. アナログピンが受け取った値（ 0 ～ 1023 ）を電圧値（ 0 ～ 5000 ）に変換
1. 電圧値（ 300 ～ 1600 ）を温度（ -30 ～ +100 ）に変換

このため、以下の 3 つの働きを GR-CITRUS にさせる必要があります。

1. アナログピン経由で LM61CIZ からデータを読み取る
1. 読み取ったデータを温度に変換する
1. 温度データを PC に転送する

今回はそれを GR-CITRUS 上に配備した mruby によるプログラムで実現させます。

# 作成した mruby のコード

今回作成したコードは以下の通り。

```
def mapping_data(conversion_targetfloat,in_min,in_max,out_min,out_max)

  # conversion_targetfloat を in_min ～ in_max のレンジから、in_max,out_min ～ out_max のレンジに変換する
  return (conversion_targetfloat - in_min) * (out_max - out_min) / (in_max - in_min) + out_min

end

# 各機器等が返しうる最小・最大値
PIN_NUMBER_OF_A0               =   14
DELAY_TIME                     = 1000
MIN_INPUT_VALUE_OF_ANALOGPIN   =    0
MAX_INPUT_VALUE_OF_ANALOGPIN   = 1023
MIN_VOLTAGE_VALUE_OF_ANALOGPIN =    0
MAX_VOLTAGE_VALUE_OF_ANALOGPIN = 5000
MIN_VOLTAGE_VALUE_OF_SENSOR    =  300.0
MAX_VOLTAGE_VALUE_OF_SENSOR    = 1600.0
MIN_TEMP_VALUE_OF_SENSOR       =  -30.0
MAX_TEMP_VALUE_OF_SENSOR       =  100.0

# USB 経由で PC とシリアル通信を行う準備
usb_serial = Serial.new(0)

# 無限ループ中で、以下を繰り返す
#  1. センサーからデータを読み出す
#  2. 読み出したデータを気温に変換する
#  3. PC へ転送する
#  4. 1000ms(1s) 休む
while true

  # センサー（ A0 → 14Pin ）からデータを読み出す
  sensor_data = analogRead(PIN_NUMBER_OF_A0)

  # 読み出したデータを、電圧値に変換する
  voltage_data = mapping_data(sensor_data,MIN_INPUT_VALUE_OF_ANALOGPIN,MAX_INPUT_VALUE_OF_ANALOGPIN,MIN_VOLTAGE_VALUE_OF_ANALOGPIN,MAX_VOLTAGE_VALUE_OF_ANALOGPIN)

  # 電圧値を気温に変換する
  temperature_data = mapping_data(voltage_data.to_f,MIN_VOLTAGE_VALUE_OF_SENSOR,MAX_VOLTAGE_VALUE_OF_SENSOR,MIN_TEMP_VALUE_OF_SENSOR,MAX_TEMP_VALUE_OF_SENSOR)

  # 気温データを、PC に転送する
  usb_serial.println(temperature_data.to_s)

  # 1000ms(1s) 休む
  delay(DELAY_TIME)

end
```

※ 2018/11/16 追記: 上記スクリプト（コメントは英語化）を [GitHub](https://github.com/YoshihikoHara/get-temperature-data-from-LM61CIZ/tree/master) で公開しました。

これを開発PC上に用意した開発環境（Rubic）上で編集し、コンパイルし、GR-CITRUS に書き込みます。

[ PC 上で出力された温度情報]
![IMG_5471.JPG](https://qiita-image-store.s3.amazonaws.com/0/89832/5fba2183-e36b-ee48-ed8a-5e31535cbd8b.jpeg)


アプリケーションを動作させると・・・をを、動いた！　こんな感じで気温が PC 上に表示されます。

若干、値の取り出しと補正のやり方が面倒くさくはありますが、あっさりそれっぽい値が読み取れました。

因みに、上の写真で PC 上に表示されるデータの値（気温）が段々あがっていっている理由は、LM61CIZ を指でつまんで、一生懸命体温で暖めて、感知温度がちゃんと上昇することを確認しながら、写真撮影したためです。

# おわりに

mruby（と言うかプログラミング言語 Ruby ）は汎用言語です。

構造化プログラミング（順次、反復、分岐）出来るのはもちろん、オブジェクト指向なプログラミングも書けてしまう、立派なプログラミング言語です。

が、ruby 本体が持っている機能はここまで。

Ruby の標準化（ [ISO/IEC 30170](http://kikakurui.com/x3/X3017-2013-01.html)等参照）で定められているのも、ほぼここまでのはず。

それ以外の「 Ruby から使える」機能は、公式開発陣が用意した「組込みクラス及び組込みモジュール」だったり、善意のコントリビュータが提供してくれた所謂「ライブラリ」だったりが実現してくれているものです。

GR-CITRUS 上の色々な機能や、GR-CITRUS 経由で様々なセンサに実装された機能を使えるのも同じ理屈。これら機能を提供してくれた方々には、本当に頭が下がります。

今回 GR-CITRUS 上のアナログ入出力ピン経由で LM61CIZ からあっさりデータを得られたのも、PC 上に USB シリアル通信機能経由でデータを送信できたのも、これら提供機能あっての話です。

今回の試行では、この[ドキュメント](http://www.slideshare.net/MinaoYamamoto/grcitrusruby)等を参考にさせて頂きました。

その恩寵で、利用するマイコンボードとして GR-CITRUS を選択するのであれば、Ruby 文法で、ボードやセンサの制御も含め、組み込みアプリケーションがあっさり書けてしまうと言う「自分にとってはまさに願ったり叶ったりな結果を得られました」と言う結末で、試行で幕を閉じることができました（いやぁ、良かった良かった）。

今回はアナログピン経由でセンサーから値を得たり、所謂 USB シリアル通信機能を使って PC へのデータ送信を行ったりしてみましたが、I2C 等各種シリアル通信インターフェースを利用したデータの授受も、どうやら容易に利用できそうです。

次は、I2C でデータの受信が可能な GPS レシーバーユニットでも追加して、緯度経度的に何処で得た気温か一目でわかる、進化型の「測定位置情報付き気温計」でも作ってみようかなと思っています。

また、買ったら即 mruby が使えるマイコンボードとしては、 Manycolors, Inc. 製の [enzi board](http://enzi.cc/)も存在する（ & 実は所持している）ので、これを使って同様のデジタル温度計を作るのもやってみたいですね。

[enzi board]
![enziboard.png](https://qiita-image-store.s3.amazonaws.com/0/89832/e23c7ef6-308f-44ab-7521-2e011849a023.png)

では、また。