7
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Raspberry Pi Pico (RP2040) をSmTで動かした

7
Last updated at Posted at 2025-12-23

この記事は mrubyファミリ (組み込み向け軽量Ruby) Advent Calendar 2025 23日目の記事です。

はじめに

mruby/cはmrubyから派生した小型のRuby実行環境であり、Rubyの書きやすさ・読みやすさをマイコン開発に持ち込めます。

しかしGitHubにあるmruby/cをそのまま使うと少々クセがあり、実際は「Rubyを書いてそのまま実行できる環境」(本記事内では「mruby/c処理系」と呼びます)を使うことが多いと思います。

本記事では、プログラミング初学者向けのmruby/c処理系であるSmT(シント)にRaspberry Pi Pico(RP2040)ボードを対応させた際に学んだことを共有します。

もし「既存のmruby/c処理系でマイコン特有の機能が欲しいけど、Rubyコードより先の仕組みが分からない…」という方がいらっしゃったときに参考になれば幸いです。

mruby/cをマイコンで動かすには

mruby/cにおいて、Rubyコードをマイコンで動かすまでにはいくつかの手続きを踏む必要があります。
例えばRP2040用のGPIOクラスを実装し、それを利用したRubyコードでマイコン上のLEDを光らせる場合、下記のようなLチカのRubyコードがあるとします。

Rubyコード
gpio = GPIO.new(25, GPIO::OUT) # ボード上にあるLEDを使う
gpio.write(0)                  # 消灯
sleep(1)                       # 1秒待って…
gpio.write(1)                  # 点灯!

これをそのままmruby/c VM上で動かしたいところですが、mruby/cはRubyコードを直接実行できません。

素朴に実装すると、まず上のフローの「バイトコード」セクションを目指してRubyコード、組み込みライブラリ、および独自のライブラリの3つを mrbc コマンドでバイトコードにコンパイルします。
それらをファームウェア(C言語のメインプログラム)に渡してビルド→マイコンに書き込む、という流れになります。

つまり、Rubyコードの変更のたびにCコンパイルが発生します。つらい

Cコード(バイトコードの変更のたびにビルド→書き込みが必要)
void main() {
  mrbc_init(memory_pool, MEMORY_SIZE);   // (内部で下記が呼ばれます)
    // hal_init();                       //   - HAL : ボード固有の実装…メモリ確保など
    // mrbc_run_mrblib(mrblib_bytecode); //   - Ruby組み込みクラス

                                         // (GPIOなどのRubyライブラリは処理系が独自に決められる)
  mrbc_pico_gpio_gem_init(0);            //   - C拡張
  mrbc_run_mrblib(myclass_bytecode);     //   - Rubyのクラス

  mrbc_create_task(master_bytecode, 0);  // - Rubyコード(★上記プログラム★)
  mrbc_run();                            // - mruby/c VM : 各クラスなどを含むプログラム実行
}

mruby/c処理系

そもそもGPIOやPWMなどの汎用的なライブラリの中身を変えることは少なく、基本的に開発中はRubyコード(というかGPIOクラスなどを利用して実際に使うセンサーなどに特化した実装)の試行錯誤が多くなるかと思います。

そのため最近はPicoRuby+R2P2などの「Rubyを書いてそのまま実行できる環境」がよく使われるようになりました。

今回はmruby/c処理系のひとつである、ビジュアルプログラミングツール「SmT」でRP2040が使えるようにしました。

SmTについて

SmTはScratchフォークのスモウルビーをさらにフォークしたプログラミングツールです。SmTは松江高専1さんが中心となって開発されています。

スモウルビーではScratchのブロックとRubyコードを相互変換でき、SmTではさらにRubyコードのバイトコード変換および(WebブラウザからUSB接続された)マイコンへのRubyバイトコードの書き込みが可能です。

これにより、キーボード操作の経験が少ないプログラミング初学者でも、ビジュアルプログラミングから入ってコーディングまで体験できるようになっています。

さて、前述のフローからSmTが担当する部分を分けると下図はになります。
事前にファームウェアを書き込んでおけば、Rubyコードはブラウザからコンパイル・書き込み可能になるわけです。

RP2040のSmT対応

前述の通りSmTは環境構築もほぼ不要なのでとても便利…なのですが、現在はRBoard(PIC32)およびESP32マイコンのみ対応している状況でした。

  • 書き込みツール「kaniwriter」はSmTのフラグボタンから起動
    image.png

幸いRBoard用のボーレート(PC-マイコン間の転送速度)がRP2040で対応している速度だったため、SmT側はそのままで問題ありませんでした。また、mruby/cにはすでにRP2040用のHAL(Ruby組み込みクラスがRP2040上で動作するためのC実装)がありました。

そのため今回は、Ruby組み込みクラスの実装を除く下記2点を組み込んだファームウェアを実装しました。

  1. Raspberry Pi Pico SDKを用いたRubyライブラリ(GPIO、PWM、ADC、I2Cクラス)の実装
  2. SmTからマイコンへバイトコードを転送するために利用されるmrbwriteプロトコルの実装

実装方針

最初のCコードから変わるのは、mruby/c VMが実行するバイトコードがファームウェアの外から与えられる点です。

RP2040ではフラッシュROMにプログラムからデータを書き込むことができるため、mrbwriteプロトコルで送信されたバイトコードをフラッシュへ書き込むようにしています(実行時はそれを読み込んでVMへ渡す)。

  void main() {
+   while (mrbwrite_request_detected()) {  // mrbwriteのコマンドモードの処理
+     mrbwrite_cmd_mode();                 // フラッシュへのバイトコード(Rubyコード相当)の書き込みなど
+   }
+                                          // バイトコード(Rubyコード相当)をフラッシュから読み込み
+   uint8_t *master_bytecode = vfs_read("master.mrbc");
+
    mrbc_init(memory_pool, MEMORY_SIZE);   // (内部で下記が呼ばれます)
      // hal_init();                       //   - HAL : ボード固有の実装…メモリ確保など
      // mrbc_run_mrblib(mrblib_bytecode); //   - Ruby組み込みクラス

                                           // (GPIOなどのRubyライブラリは処理系が独自に決められる)
    mrbc_pico_gpio_gem_init(0);            //   - C拡張
    mrbc_run_mrblib(myclass_bytecode);     //   - Rubyのクラス

    mrbc_create_task(master_bytecode, 0);  // - Rubyコード(★上記プログラム★)
    mrbc_run();                            // - mruby/c VM : 各クラスなどを含むプログラム実行
  }

実装したもの

前述の実装方針をもとにCコードを作成し、公式のSDKであるpico-sdkをもとにCMakeLists.txtなどのターゲットを定義したリポジトリです。

※ まだ動作確認しただけなので、Forkもとにマージいただいた場合はリンクを差し替えます。

makeコマンドでビルドされたファームウェアをボードに書き込むことでSmTで開発するための準備ができます。

# 1. 本リポジトリのclone
git clone https://github.com/matsudai/mrubyc-pico
git checkout feature/support-smt # 本ブランチ

# 2. Submoduleの取得
git submodule update --init --recursive

# 3. 環境構築
# 3.1 必要なパッケージの取得
# refs https://github.com/raspberrypi/pico-sdk?tab=readme-ov-file#unix-command-line
sudo apt install cmake python3 build-essential gcc-arm-none-eabi libnewlib-arm-none-eabi libstdc++-arm-none-eabi-newlib

# 3.2 mrubyのインストール ※要rbenv
rbenv install mruby-3.4.0
rbenv local mruby-3.4.0

# 4. ファームウェアのビルド
make

# 5. ボードへの書き込み
# 5.1 Raspberry Pi PicoのBOOTSELボタンを押しながら、PCにUSBケーブルで接続します。
# → USBフラッシュドライブとして開きます。
# 5.2 build/main.uf2をD&Dなどで書き込みます。

# 6. Rubyプログラムの書き込み
# 6.1 SmT (https://ceres.epi.it.matsue-ct.ac.jp/smt/) で汎用ブロック・デバッグでプログラムを作成します。
# 6.2 kaniwriterでRBoardとして書き込みます。

動作確認

実際にSmTでLチカプログラムを作成し、動かしてみた結果は次の通りです。

SmTで書くプログラム例
gpio25 = GPIO.new( 25, GPIO::OUT )
gpio25.write( 0 )
puts( "Hello World" )
loop do
  sleep(1)
  gpio25.write( 1 )
  puts( gpio25.read )
  sleep(1)
  gpio25.write( 0 )
  puts( gpio25.read )
end
  1. Rubyコードの作成と書き込み
    output.gif
  2. RP2040での実行
    output2.gif
  1. 独立行政法人 国立高等専門学校機構 松江工業高等専門学校

7
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?