inSmartBank

AI家計簿アプリ「ワンバンク」を開発・運営する株式会社スマートバンクの Tech Blog です。より幅広いテーマはnoteで発信中です https://note.com/smartbankinc

Inside #Board43: ソフトウェア・パッケージデザイン編 #rubykaigi

こんにちは。スマートバンクの kaoru です。RubyKaigi 2026 で実施した PicoRuby ワークショップについての連載第 2 回目として、masawada さんの基板編に続き、ソフトウェア(ブラウザー上で動く Board43 Playground および基板のファームウェア)とパッケージのデザインについてお届けします。

blog.smartbank.co.jp

Board43 Playground とは

Board43 Playground は Board43 用のブラウザー版 PicoRuby IDE です。TryRuby playground にならって命名し、R2P2 Web Terminal (ソース) を参考に実装しました。本来であれば UI も含めて全体を Ruby で書きたかったところですが、RubyKaigi までのスケジュール都合から TypeScript / React を採用しています。

汎用のオンライン Ruby IDE を目指すと、ファイル管理 / Gem 管理 / デバッガー / LSP 対応 / 実行の構成……と無限に機能が必要になっていきますが、Board43 Playground は割り切って開発しています。ワークショップの手順 (USB 接続 → LED を光らせるコードの実行 → アニメーション → 自分の画像をアイコン化してデバイスに転送・インストール → 共有リンク作成のステップ) を 30 分以内に終えられることを目標にエディタの機能やボタンの配置を選択しました。

Board43 Playground

例えばエディタはファイルツリーを置かずタブのみの構成にしています。開発当初はファイルツリーも実装していましたが、PicoRuby のファイルシステムが FAT から LittleFS に切り替わった (picoruby/picoruby#367) のを契機に、Playground 側で使っていたファイル列挙の API が想定通りに動かなくなり、ツリー表示の維持コストが見合わなくなって外しました。また、当初はダークテーマで威圧感のある見た目(=なんか黒い画面)だったのですが、目的を考えてワンバンクアプリのデザイントークンを利用したライトな見た目に変更しました*1

デバイスとシミュレータで同じコードを動かすために PicoRuby.WASM を利用

シミュレーターでの実行には @picoruby/wasm-wasi を使いました。LED マトリクスを薄い shim 経由で Canvas に描画するようにしており、Board43 の実機とシミュレーターで同じコードが動作するようにしています。私は残念ながら聞きに行けなかったのですが、PicoRuby 作者の @hasumikin さんの PicoRuby.WASM に関するセッションがワークショップ初回の開催直前に行われたのはすごい偶然でした。

ブラウザのメインスレッドで動かすと UI をブロックすることがありそうだったので Web Worker に分離しアニメーションのような長時間ループを実行しています。シミュレータ側の表示が実機の点滅速度に近づくようにするため、Worker 側で busy-wait して 30 fps 程度のフレームレートになるようにしています。このあたりは厳密な計測ではなく実機と比べて違和感の無い程度に勘でやりました。

画像のアップロードとピクセル化もブラウザで完結

写真を 16×16 LED で表示するのは Board43 で特に盛り上がるユースケースです。画像から 16×16 のピクセルへの変換は Rust で書いた board43-image-transformerwasm-pack で WASM にして行いました。変換するサーバーを用意しようとするとちょっと手間がかかるのでブラウザで完結できるようにしています。WS2812C-2020-V1 に合わせてガンマ値を調整していますが、フレームレートと同様に勘でやっていますのでもう少し改善できる部分がありそうです。Canvas + JavaScript あるいは PicoRuby で書く選択肢もあったかもしれませんが、私の好みで Rust を使っています(とはいっても外部ライブラリを使っているのでたいしたことはしていません)。

ネイティブアプリやドライバーを不要にするために Web Serial API を利用

デバイス書き込みは Chromium 系のブラウザが実装している Web Serial API を使いました。Web ページ上から USB シリアル経由で Board43 に直接通信できるため、ユーザーはブラウザのみでワークショップを完結させられます。

ターミナルに ghostty-web を採用

その Web Serial 経由でデバイスと繋がった先に R2P2 シェルを表示するターミナル UI には、ターミナルエミュレータ Ghostty の Web 版である ghostty-web を利用しました。ブラウザでターミナルを動かす場合 xterm.js が定番かと思いますし、前述の R2P2 Web Terminal でも採用されていますが、単純に面白そうだと思ったことが採用の理由です。

公開版限定: 共有機能とプレビュー画像 (og:image) を動的に生成

公開版にはツールバーに共有 URL を生成する共有ボタンを置いており、押した瞬間の LED マトリクスの状態を Cloudflare D1 に保存しておいて、og:image のリクエストが来た時に Cloudflare Workers でそのスナップショットから画像を組み立てて返すという流れを実装しました*2。X を #Board43 で検索するとみなさんが作ってくださったものをタイムラインでプレビューできてとても楽しいです。Cloudflare 大変便利ですね。

ファームウェア

Board43 には PicoRuby 3.4.2 に小さなパッチを適用したものを書き込んでいます。動作検証のスケジュールの都合でこのバージョンを選択しました。Board43 に固有の変更ですので、PicoRuby 本体を fork するのではなく Git の submodule として取り込み、その上に小さなパッチを当てています。以下のような変更を加えました。

picoruby-ws2812-plus / picoruby-lsm6ds3 を有効化

Board43 に搭載されている 256 個の LED (WS2812C-2020-V1) と 6 軸モーションセンサー (LSM6DS3TR) のドライバは PicoRuby 本体には標準で含まれていません。そこで、今回のワークショップのメンバーでドライバを実装し、mrbgem として公開、build_config に追加してビルド時に有効になるようにしました。

これらの mrbgem は Board43 以外の基板やプロジェクトでも便利に利用いただけますので、開発したメンバーそれぞれの GitHub アカウントで公開しています。

ステータス LED を起動直後に点灯

電源が接続された際にステータス LED が点灯するように main.c を変更しました。GPIO 初期化のタイミングで GPIO25 を出力モードにして HIGH に設定しています。回路側で吸収できる挙動ですが、基板の発注が終わった後に気付いたためファームウェアで対応しました。

SW3 ホールドで app.rb の自動起動をスキップし、ステータス LED で状態を通知

PicoRuby には、起動時に /home/app.rb (または /home/app.mrb) が存在すると自動でロードして実行してくれる仕組みがあります。Board43 Playground の「デバイスにインストールする」機能は、単純に編集中のファイルを app.rb として保存しているという仕組みですね。Board43 では、電源投入時に SW3 ボタンを押し続けていると、この自動実行をスキップして R2P2 シェルに進むという挙動を実装しました。

app.rb は起動時に実行されますので、これを変更したくなった場合は、まずその実行をスキップする必要があります。PicoRuby 標準では起動時に s キーを押すという手段が用意されていますが、キーを押すタイミングがややシビアなこともあり、物理ボタンでも同じことができると便利だろう、と考えて追加しました。ついでに app.rb がエラーになった場合も R2P2 シェルにフォールバックするようにしています。

ステータス LED は app.rb の自動実行時は高速点滅、SW3 ボタンでスキップした時はダブル点滅 × 3 で状況を通知するようにしています。

Board43::GPIO_* 定数を定義

ブザー / スイッチ / 6 軸センサー / LED マトリックス / ステータス LED のピン番号を Board43 モジュールとして定義しました。サンプルコードを見た時に番号を覚えていなくてもどのようなデバイスを触ろうとしているのか分かりやすくなります。

# 番号を覚えていなくても対象としているデバイス (SW3) が類推できる
sw3 = GPIO.new(Board43::GPIO_SW3, GPIO::IN | GPIO::PULL_UP)
buzzer = PWM.new(Board43::GPIO_BUZZER)

ビルドバージョンを秒精度に、SB サフィックスを付与

細かいところですが upstream とスマートバンク版を見分けるための SB サフィックスを、lib/picoruby/build.rb (mruby ビルド時の version.c 生成) と mrbgems/picoruby-r2p2/cmake/CMakeLists.txt (CMake project 名) の 2 箇所に足しました。バージョン文字列はこの 2 系統で別々に組み立てられているので、片側だけだと表示が一致しません。ついでにビルド日時を秒単位に変更したのは、デフォルトの日付精度だけだと焼き直しを繰り返しながら試行錯誤している時にファイルの区別が少し不便だったためです。

パッケージデザイン

プラモデルや IKEA の説明書のようなものを一度作ってみたいと思っていましたが、今回チャンスと思い封筒・マニュアル・額装のデザインにもこだわってみました。実は私の担当箇所では一番時間をかけてしまった部分です。

封筒

ワークショップ参加者へ 1 ページのガイドと Board43 を同封した封筒をお届けしました。これはワンバンクカードがユーザーの手元に届くパッケージをイメージしています。

封筒

同封した 1 枚もの。ワンバンクカードが届く際の台紙と同様に外三つ折りです。封筒にはパーツ名をあえて記載せず、基板を取り出し、三つ折りのガイドを広げていくにしたがって詳細を開示していくような構造にしています。

同封のガイド (裏表)

額装

同じビジュアルを元に、試作機の額装もデザインしました。お気に入りです。

額装した試作品

リファレンスマニュアル

時間とコストの関係で封筒に入れられませんでしたが、ワークショップの後にも便利なリファレンスマニュアルも作成しました。このマニュアルはオープンソースの組み版システムである Typst をベースにしたコンパイラで生成しました。ドキュメントおよびコンパイラもソースを公開していますのでご興味ある方はご覧ください(これも私の趣味で Rust を利用)。いくつかのページをご紹介します。

リファレンスマニュアル (抜粋)

爆発図と正面図の作り方

各所で使用している爆発図 (Exploded-view drawing や Exploded diagram と呼ばれます) と正面図は以下のように KiCad のプロジェクトから生成しました。Claude Code + Blender MCP addon に大変お世話になりました。

爆発図

Board43 爆発図

  1. pcb2blender で KiCad のプロジェクトを Blender へインポート
  2. 部品をカテゴリ別に Z 軸方向へ分離
  3. はんだパッド (SOLDER_* オブジェクト)を非表示
  4. 斜め上から正投影アイソメトリックカメラを設定
  5. EEVEE レンダラ + Freestyle レンダラを使って線画としてレンダリング
  6. 全マテリアルを white Emission に変更して線のみに変更
  7. Freestyle で SVG としてエクスポート
  8. Adobe Illustrator で微調整

正面図

Board43 正面図

  1. KiCad に同梱されている kicad-cli を使用して PCB の主要なレイヤーを SVG として出力
    • F.Cu / B.Cu: 銅箔 (表・裏)
    • F.SilkS / B.SilkS: シルクスクリーン (表・裏)
    • Edge.Cuts: 基板外形
  2. はんだパッド (SOLDER_* オブジェクト)を非表示
  3. 残ったパーツのうち、以下の主要パーツ以外を非表示
    • RP2350A
    • フラッシュメモリ
    • 加速度センサー・ジャイロスコープ・温度センサー (LSM6DS3TR)
    • LED (WS2812C-2020-V1)
    • BOOT / RUN ボタン
    • ユーザーボタン
    • ブザー
    • デバッグヘッダー
    • パブリックヘッダー
    • USB-C コネクタ
    • ステータス LED
  4. 真上から正投影カメラを設定
  5. 爆発物と同様にレンダリングし SVG としてエクスポート
  6. 1 と 4 の SVG をマージして Adobe Illustrator で微調整

おわりに

あらためて、ワークショップに参加してくださったみなさん、本当にありがとうございました。準備大変でしたが、封筒を開けるときのみなさんの笑顔やアイコンを光らせた時の歓声であっという間に報われました。来年の宮崎でも何かおもしろいことやれるといいなと思っています。

次回は koshiba さんによる PicoRuby ワークショップそのものの舞台裏の紹介です。お楽しみに!

*1:OSS として公開しているバージョンではワンバンクのデザイントークンは外しています。

*2:Cloudflare の無料プランで十分にカバーできるとは思いましたが、OSS 版では誰でも動かせることを優先しこれらの機能は削除しました。

We create the new normal of easy budgeting, easy banking, and easy living.
In this tech blog, engineers and other members will share their insights.