はじめに:Arduinoという「心地よいぬるま湯」からの脱却

世の中のガジェット製作や電子工作の入り口として、Arduino環境はあまりにも圧倒的で、そしてあまりにも「生ぬるい」。 面倒なレジスタ設定も、クロックツリーの計算も、ハードウェアの泥臭い仕様も、すべて分厚い抽象化レイヤーの向こう側に隠蔽され、digitalWrite()やanalogRead()といったお仕着せの関数を並べるだけで、誰でも簡単に「動かした気」になれる。

しかし、その便利さと引き換えに、私たちは何を見失っているだろうか。 背後で肥大化したランタイムライブラリがCPUサイクルを食いつぶし、ブラックボックス化された割り込み処理が予期せぬジッター(時間ゆらぎ)を生み出す。ほんの数マイクロ秒の遅延が致命傷になるシビアなリアルタイム制御の世界において、その「ぬるま湯」は文字通り命取りになる。

「ボタン一つ、ライブラリの関数一つで動く」という黒魔術から一線を画し、マイコンの足回りからレジスタ、そしてハードウェアの挙動の隅々までをすべて手中に収めること。 それこそが、本記事でいざなう「ハードでスパルタンなベアメタルの世界」への扉である。

数あるマイコンの中でも、近年のトレンドとして第一候補に挙がるのがESP32シリーズだ。だが、数あるバリエーションの中から、あえて無駄な機能をそぎ落とした「ESP32-C3」を選んだのには、明確な必然性がある。

  • WiFiを使え、サーバーとしてふるまえること=それなりのメモリ搭載量
  • Bluetoothは使わない=高額なSIG登録が必要で、事実上一般への配布はできない
  • アンテナ内蔵で工事認証、技適取得済、SoCを使うメーカーの手続き不要
  • float演算は軽い制御計算のみで、FPU不要、シングルコアで可
  • RCサーボ制御のためのPWM出力
  • ジャイロセンサーのインターフェースに、I2C、またはSPI通信機能
  • 何より値段が安いもの
  • 国内在庫が豊富ですぐ手に入る
  • VSCodeによる開発環境を手軽に使える
  • 癖の強いXtensaではなく、素直なRISC-Vがベター

これらの条件を突き詰めた結果たどり着いたのが、「ESP32-C3」である。

倒立振子・自転車ロボットにおける「スピードの呪縛」

ROBOBIKEは自転車ロボットである。その実態は、世にあふれる「倒立振子」の血を引く極めてダイナミックな兄弟たちだ。

ジャイロセンサー(IMU)で左右方向の傾きを検知し、倒れそうになったら素早く舵を切る――この制御を、短い時間で何回も繰り返す「リアルタイム演算」が不可欠となる。 ROBOBIKEが叩き出している演算周期は、200〜250Hz(すなわち4ms〜5ms周期)。この圧倒的なハイペースで計算ループが回っている。

ここで、現実の厳しさに直面する。 自転車という乗り物は、ぼやぼやしているとあっという間に倒れる。特に室内で走らせることができる小型・低速のロボットにおいては、人間が目で見て傾きを察知した瞬間には、すでに手遅れで立て直すことは不可能だ。

つまり、「いかに早く傾きを検知し、素早く舵を切れるか」が、転倒せずに走り続けるための唯一にして絶対の生命線となる。

世の中には「高速制御にはデュアルコアが必須だ」「メインCPUと制御用CPUを分けるべきだ」という風潮がある。 だが、それはマイコンのハードウェアの引き出しを開けられず、リソースの暴力に頼るだけの「勉強不足」でしかない。

FPUを持たず、シングルコアで、命令セットに素直なRISC-Vを積んだ安価なESP32-C3であっても、ハードウェアの仕様を隅々まで読み込み、とことん突き詰めれば、世界最先端のリアルタイム制御マシンに対応可能なのだ。

ここから先は、Arduinoの生ぬるい抽象化を捨て、レジスタを直接叩き、タイマーとセンサーの位相を極限まで調律する、スパルタンなベアメタル・ハックの真髄を明かしていこう。

「デュアルコア必須」という思い込みを覆す

高速なリアルタイム制御やモータ制御の話題になると、「マルチコアやデュアルコアの処理能力が不可欠だ」という意見を耳にする。メインの処理と制御の処理をCPUごとに分けるべきだ、という設計論も根強い。

しかし、それはマイコンが持つハードウェアのポテンシャルを引き出すアプローチをしていないケースが多い。

FPUを持たず、シングルコアでありながら命令セットに素直なRISC-Vを積んだ「ESP32-C3」であっても、ハードウェアの仕様を隅々まで読み込み、とことん突き詰めれば話は違ってくる。

タイマー割り込みと周辺回路の制御を極限まで調律し、一つのコアの性能を完全に引き出し切ることで、外部の高級プロセッサに頼らずとも俊敏なリアルタイム制御は十分に実現できる。

マルチコアでなければ制御できないのではない。一つのコアが持つリソースと可能性をどこまで絞り出せるか――それこそが、ベアメタル制御が真価を発揮するところである。

IMUのODRを飼い慣らす!ソフト制御PLLとFSYNCの極意

センサー同期という幻想と泥臭い現実

「センサーがデータを用意した瞬間に割り込みをかける(DRDY)」――一見すると王道に思えるこのアプローチは、マルチタスク環境や複雑なシステムにおいては必ず綻びを見せる。フリーランで走るマイコンのタイマーと、IMU内部の出力データレート(ODR)のクロックは厳密には一致せず、放置すれば必ずビート現象やジッターが蓄積していく。

リアルタイム制御の命である「等間隔のサンプリング」を維持するためには、センサー側の呼吸とマイコン側のタイマーを完全に調律しなければならない。ここで登場するのが、ESP32-C3のシングルコアを極限までしゃぶりつくす、「ソフトウェアPLL(位相同期ループ)」という泥臭くも洗練されたアプローチだ。

FSYNCタイムデルタを吸い上げる

採用したIMU(ICM-42670-L)には、外部同期やタイムスタンプを管理する強力な機能が備わっている。MREG1の TMST_CONFIG1 レジスタ(0x00)に 0x07 を書き込んでタイムスタンプおよびFSYNC関連の機能を有効化し、IMU内部の計測タイミングと外部信号のズレを数値化する。

実際のコード(icm426xxSPI.c)を見てみよう。センサーからのバーストリード(加速度・角速度の12バイトに続く2バイト)により、「FSYNCから最初のサンプル取得までのタイムデルタ(fsync_time_delta)」を毎周期リアルタイムに吸い上げている。