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