mruby on IoT devices.
by
Y_uuu
Link
Embed
Share
Beginning
This slide
Copy link URL
Copy link URL
Copy iframe embed code
Copy iframe embed code
Copy javascript embed code
Copy javascript embed code
Share
Tweet
Share
Tweet
Slide 1
Slide 1 text
2023-02-18(Sat) 岡嵜雄平 mruby on IoT devices.
Slide 2
Slide 2 text
自己紹介
Slide 3
Slide 3 text
岡嵜雄平 @Y_uuu 株式会社Fusic IoTクラウドエンジニア フィヨルドブートキャンプ メンター
Slide 4
Slide 4 text
本日のお話 • mrubyとIoT • mruby-esp32 • 課題1: ESP-IDFの最新バージョン(v5.0)に追従できていない • 課題2: MQTT通信クライアントがない • まとめ 4
Slide 5
Slide 5 text
mrubyとIoT
Slide 6
Slide 6 text
mruby • 組込みシステムをターゲットに開発されたRubyの処理系 • 現在もMatzを中心に開発が続けられている • mrubyをさらに軽量化したmruby/cというOSSも存在する 6
Slide 7
Slide 7 text
• IoT開発(特にPoCフェーズ)で頻発するチューニングに柔軟に対応しやすい • Web/クラウドと同じRubyで開発ができる IoT開発におけるmrubyの可能性 7 クラウド デバイス センサー 収集 加工 分析 可視化 インターネット センサーの値を送信 7 別のセンサーを 使いたい 送信データの 形を変えたい 送信周期を 変えたい 機能を拡張 したい
Slide 8
Slide 8 text
mruby-esp32
Slide 9
Slide 9 text
ESP32 • Espressif Systems社によって開発されたマイクロコントローラ(マイコン) • 低消費電力かつWi-Fi・Bluetoothも内蔵しているためIoTとの親和性が高い • M5Stackに搭載されているマイコンもESP32 9 https://ja.wikipedia.org/wiki/ESP32
Slide 10
Slide 10 text
ESP32-DevKitC • ESP32を搭載した評価基盤 • 1600円で買える(送料・手数料は別) • mrubyを動かすために十分なスペック(RAM: 512KB, ROM: 4MB) 10
Slide 11
Slide 11 text
mruby-esp32 • ESP32上でmrubyを動かすためのOSSプロジェクト • ESP-IDFというフレームワークを使ってmrubyをコンパイル・リンクしている 11 ESP-IDF Project Component Main Component mruby Toolchain mruby-esp32.bin コンパイル・リンク
Slide 12
Slide 12 text
mruby-esp32 • binファイルをROMに書き込むことで起動 • FreeRTOS(組込み向けのリアルタイムOS)上でmrubyが動作 12 ESP-IDF Project Component Main Component mruby Toolchain mruby-esp32.bin ESP32-DevKitC FreeRTOS アプリケーション mruby MrubyTask コンパイル・リンク アップロード (ROMに書き込み) Library
Slide 13
Slide 13 text
使い方1. ESP-IDFをインストール • インストール手順はESP-IDF Programming Guide > Get Startedを参照 13 https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/index.html
Slide 14
Slide 14 text
使い方2. mruby-esp32をgit clone • mrubyがSubmoduleとなっているので注意 14 https://github.com/mruby-esp32/mruby-esp32
Slide 15
Slide 15 text
使い方3. Rubyのプログラムを書く • main/spiffs/main.rb に任意のプログラムを記述します 15
Slide 16
Slide 16 text
使い方4. ビルド • Idf.py build コマンドでビルドします(初回は1分ほどかかります) 16
Slide 17
Slide 17 text
使い方5. デバイスとPCを接続 • /dev/tty.usbserial-xxx のようなデバイスファイル(PORT)を確認 17
Slide 18
Slide 18 text
使い方6. 書き込み・起動 • idf.py -p (PORT) flash monitor コマンドで書き込み・起動します 18 LEDと反対側のボタンを押して、 モードを切り替える 実機での出力を シリアル通信で確認
Slide 19
Slide 19 text
応用編: AWS IoT CoreにMQTTSでPublish • わずか10行のコードでAWSにデータを送信できます 19
Slide 20
Slide 20 text
簡単にデバイス上でmrubyを動かせる🎉 • 「簡単に」というイメージを、今日はぜひ持ち帰ってください • ここから先は諸々の課題が解決する前(2ヶ月前)に時を戻します… 20
Slide 21
Slide 21 text
IoTでの活用を想定したとき、2つの課題に直面 1. mruby-esp32がESP-IDFの最新バージョン(v5.0)に追従できていない • デバイスのライフタイムを考えると、最新バージョンに対応したい 2. mruby-esp32で使用できるMQTT通信クライアントがない • IoTシステムにおいてよく使われるプロトコルであり、必要不可欠 21
Slide 22
Slide 22 text
2つの課題をどう解決したか? • これからお話していきます 22
Slide 23
Slide 23 text
課題1: ESP-IDFの最新バージョン(v5.0)に 追従できていない
Slide 24
Slide 24 text
プロジェクトの構成を理解する • 2つのコンポーネント、それぞれにcomponent.mk (Makefile)が配置 • Mrubyのコンポーネントの中にmrubyのソース一式がある 24 mruby_component main_component mrubyのソースコード一式 (サブモジュール)
Slide 25
Slide 25 text
ESP-IDF v5.0を使ってビルドしてみる • いろいろな問題が起こる💣 25
Slide 26
Slide 26 text
• project.mkがない、というエラーが出力される 問題1: ビルドが始まらない 26
Slide 27
Slide 27 text
• ビルドシステムがMake→cmakeに変わっている • v4.4のドキュメントでは存在していたMakeへの言及がv5.0では消滅 問題1: ビルドが始まらない 27 https://docs.espressif.com/projects/esp-idf/en/v4.4.4/esp32/api-guides/build-system.html https://docs.espressif.com/projects/esp-idf/en/v5.0/esp32/api-guides/build-system.html v5.0のドキュメントには Makeへの言及がない
Slide 28
Slide 28 text
問題1: ビルドが始まらない • ESP-IDFの他OSSやドキュメントを参考にCMakeLists.txtを記述 • Mrubyのビルドはカスタムコマンドとしてrakeを実行 28 https://github.com/mruby-esp32/mruby-esp32/pull/27 カスタムコマンドとして mrubyのrakeを実行
Slide 29
Slide 29 text
問題2: Legacy event loopでコンパイルエラー • mruby-esp32-wifiでコンパイルエラーが発生 29
Slide 30
Slide 30 text
問題2: Legacy event loopでコンパイルエラー • Wi-Fi接続やIP取得といったイベントを検知するために使用 • v5.0ではLegacy event loopが消滅している 30 V5.0にLegacy event loopの ドキュメントは存在しない https://docs.espressif.com/projects/esp-idf/en/release-v4.4/esp32/api-reference/system/esp_event_legacy.html
Slide 31
Slide 31 text
問題2: Legacy event loopでコンパイルエラー • 後継のEvent Loop Libraryを使って処理を置き換える 31 https://github.com/mruby-esp32/mruby-esp32-wifi/pull/3
Slide 32
Slide 32 text
問題3: mrubyのコンパイルでたくさんエラーが起こる • mrbgemでincludeしている、ESP-IDFが提供するヘッダファイルでエラー 32
Slide 33
Slide 33 text
問題3: mrubyのコンパイルでたくさんエラーが起こる • ESP-IDFの通常のプロジェクトをコンパイルするときとの オプションの違いを見比べる • 通常のプロジェクトでは-std=gnu17というオプションが付いている 33 Project Component Main Component mruby Toolchain ESP-IDFでビルド C17 Rakeでビルド C99 Toolchain内のソースコードが C17を前提としている esp_macros.h
Slide 34
Slide 34 text
問題3: mrubyのコンパイルでたくさんエラーが起こる • mrubyもC17でビルドするよう、オプションを付けることで解決 34 https://github.com/mruby-esp32/mruby-esp32/pull/27 オプションを追加
Slide 35
Slide 35 text
問題4: Error: app partition is too small for 〜 が出る • ビルドの終盤でエラーが発生 35
Slide 36
Slide 36 text
問題4: Error: app partition is too small for 〜 が出る • パーティション=ROMの構成情報 36 ブートローダー パーティションテーブル nvs: 24KB phy_init: 4KB factory: 1MB 空き 0x00000000 0x00001000 0x00009000 0x0000f000 0x00010000 0x00110000
Slide 37
Slide 37 text
問題4: Error: app partition is too small for 〜 が出る • デフォルトのパーティションテーブルではapp領域は1MBしかない 37 ブートローダー パーティションテーブル nvs: 24KB phy_init: 4KB factory: 1MB 空き ここがapp領域 0x00000000 0x00001000 0x00009000 0x0000f000 0x00010000 0x00110000
Slide 38
Slide 38 text
問題4: Error: app partition is too small for 〜 が出る • パーティションテーブルをカスタマイズして1.5MBまで拡げて対策 38 ブートローダー パーティションテーブル nvs: 24KB phy_init: 4KB factory: 1.5MB 空き 0x00000000 0x00001000 0x00009000 0x0000f000 0x00010000 0x00180000 ここには後々 ファイルシステムを構築予定 一部のESP32はROMが2MBしか ないため、全体を2MB以内としたい https://github.com/mruby-esp32/mruby-esp32/pull/30
Slide 39
Slide 39 text
ESP-IDF v5.0でビルド→起動までこぎ着けた🎉 • 実際には1つの問題に数日を要することもあり、それなりに大変だった 39
Slide 40
Slide 40 text
ポーティングのポイント • 組込みソフトウェアがどういった仕組みで動作するか前提知識をつけること • MCU/ROM/RAMといったH/W構成要素を理解する • リアルタイムOS(ex: FreeRTOS)について知る • エラーメッセージから何が起こっているのか正しく理解すること • Webとは違い、H/Wが関連するエラーもしばしば起こるので注意 40
Slide 41
Slide 41 text
ポーティングのポイント • 開発環境(ex: ESP-IDF)のドキュメントをよく読むこと • バージョンごとの変遷を追う • カスタマイズできること・できないことを把握する • 情報が集まるコミュニティ(ex: ESP-IDFのissues)を見つける • Webの世界に比べて、情報は少ない • 類似する問題を探す・質問する 41
Slide 42
Slide 42 text
課題2: MQTT通信クライアントがない
Slide 43
Slide 43 text
MQTT • TCP/IPによるPub/Sub型データ配信を行う、軽量データ配信プロトコル • ヘッダーサイズが最小2byte、プロトコルシーケンスがシンプル • 1つのクライアントがPublisherとSubscriberを兼ねることもできる 43 Broker Publisher Publisher Subscriber Subscriber
Slide 44
Slide 44 text
ESP-MQTT • ESP32上で動作するMQTTクライアント • これをラッピングしたmrbgemを作れば良い 44 https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/protocols/mqtt.html
Slide 45
Slide 45 text
参考: mrbgem • RubyでいうところのRubygemにあたる、mrubyの拡張ライブラリ • RubyまたはC言語を用いて実装できる • 今回はESP-IDFが提供するAPIを利用したいのでC言語で実装 45 アプリケーション mruby MrubyTask wifi mqtt .c ・・・ FreeRTOS Library .c mrbgems
Slide 46
Slide 46 text
クラス設計(mruby-mqttを参考) • 当初、mruby-mqttを元に検討した • 全体的に非同期的であり、コールバックを多用する仕様に懸念 46 https://github.com/hiroeorz/mruby-mqtt 接続時や送受信時に yieldされる
Slide 47
Slide 47 text
• on_connect等によるコールバックが別タスク(別コンテキスト)となる • mruby VMはシングルタスクでの動作が前提のため、避けたい クラス設計(mruby-mqttを参考) 47 Rubyアプリケーション connect mruby-esp32-mqtt on_connect ESP-MQTT mruby VM connect Main Task MQTT Task block event handler 別のタスク (別コンテキスト)
Slide 48
Slide 48 text
クラス設計(ruby-mqttを参考) • ruby-mqttの設計を参考にした • いずれのメソッドも同期的であり、処理が完了してから次の処理へ進む 48 https://github.com/njh/ruby-mqtt connect, getどちらも 同期的
Slide 49
Slide 49 text
• シングルタスクでmruby VMを動かす • 別タスクからのイベントを受信後、元のメソッドをreturn クラス設計(ruby-mqttを参考) 49 Rubyアプリケーション connect mruby-esp32-mqtt ESP-MQTT queue connect Main Task MQTT Task event handler wait_for_event イベントの情報を エンキュー 同期的にreturn
Slide 50
Slide 50 text
mrb_mruby_esp32_mqtt_gem_init 50 • mrbgemのお作法に則って実装 https://github.com/mruby-esp32/mruby-esp32-mqtt/blob/master/src/mrb_esp32_mqtt.c MQTTクラスを定義 各種メソッドを定義
Slide 51
Slide 51 text
mrb_mqtt_client_connect • 接続後に mqtt_wait_for_event で接続完了を待っている 51 https://github.com/mruby-esp32/mruby-esp32-mqtt/blob/master/src/mrb_esp32_mqtt.c Queueにイベントが 来るまで待つ MQTT接続開始
Slide 52
Slide 52 text
Rubyアプリケーション • わずか10行足らずで、MQTT Publish可能に🎉 52 https://github.com/mruby-esp32/mruby-esp32/blob/master/main/examples/mqtt_publish.rb
Slide 53
Slide 53 text
mruby-esp32/mruby-esp32-mqtt として公開中 • mruby-esp32のOrganization配下で公開 🎉 53 https://github.com/mruby-esp32/mruby-esp32-mqtt
Slide 54
Slide 54 text
まとめ
Slide 55
Slide 55 text
所感 • デバイス上でmrubyを動かすのは一苦労 • 一度動いてしまえば使い慣れた言語でデバイスを制御できる • 比較的コントリビュートしやすい • UART通信, SPI通信, タイマー, RTCといったAPIをmrbgem化 • ドキュメントの整備 55
Slide 56
Slide 56 text
おわりに • 今日の話を聞いて「デバイス難しそう…」と感じた人がいるかもしれません • 実際、Webシステムの開発とは別のハードルがたくさんあります 56
Slide 57
Slide 57 text
おわりに • 少なくとも、今日話した内容は全て解決済みなのでご安心ください • ぜひお手元にESP32-DevKitCをご用意の上、mrubyを動かしてみてください 57
Slide 58
Slide 58 text
ご清聴ありがとうございました
Slide 59
Slide 59 text
Appendix
Slide 60
Slide 60 text
参考: IoTシステム • モノのインターネット • よくある事例: センサーの値をクラウドに送信して可視化・分析 60 クラウド デバイス センサー 収集 加工 分析 可視化 インターネット センサーの値を送信
Slide 61
Slide 61 text
参考: リアルタイム性とmruby • IoTシステムで求められるリアルタイム性がそこまで高くない • 組込みシステムの中でも、mrubyが敬遠される要素が少ない 61 時間の流れ タスクA タスクB イベントが発生 レイテンシ タスクA イベントが発生 レイテンシ タスクB ハードリアルタイム 例: 自動車のブレーキ、緊急停止装置 ソフトリアルタイム 例: GUI、環境測定、データ配信 mrubyはソフトリアルタイム 処理期限
Slide 62
Slide 62 text
• FreeRTOSにおけるタスク間でのデータ送受信や同期を行う仕組みの一つ • 別タスクに対してデータを送信できる • 送受信が完了するまで、タスクを待ち状態にできる 参考: FreeRTOS Queue API 62 queue sender_task reveiver_task Queueにメッセージが 来るまで待ち状態に
Slide 63
Slide 63 text
参考: MQTT Publishの動作確認 • mosquittoというツールでSubscribeし、Publishできていることを確認 63