理系的な戯れ

理工学系とくにロボットやドローンに関する計算・プログラミング等の話題を扱って、そのようなことに興味がある人たちのお役に立てればと思っております。

【第1回】StampFlyのHAL作りにClaude Codeで挑む!〜AIとの協業で見えてきたもの〜

こんにちは、こうへいです。

今回から新しいシリーズを始めます。テーマは「Claude Codeを使ってStampFly HAL(Hardware Abstraction Layer)を作る」です。

このシリーズでは、私がM5Stack社と共同開発したドローン「StampFly」を題材に、最新のAIコーディングツール「Claude Code」と格闘する様子をリアルタイムでお伝えしていきます。うまくいく時も、うまくいかない時も、全部正直に書いていくつもりです。

なお、この記事自体もClaude Codeにインタビューを受けながら書いています。

StampFlyって何?

StampFlyは、私とM5Stack社が開発したオープンソースの教育用ドローンです。ESP32-S3をベースにしたクアッドコプターで、「日本で合法的に飛ばせて、ドローン制御の授業にも使える」ことを目標に作りました。

このプロジェクトのきっかけは面白くて、Xで私のドローンコントローラー開発記事を見た@necobutさんが「こうへいなら秒でAtomFlyをとばせる」とつぶやいたことから始まったんです。

その時は「秒は無理かと...」と返しましたが、実は内心燃えてました(笑)。実際には開発機をいただいてから4日で飛ばすことができました。

M5Stack社との共同開発体験

特に印象的だったのが、M5Stack社のJimmyさんとのやり取りでした。例えば「IMUのインターフェースがI2Cでは遅いからSPIにできないか」と話すと、1日くらいで新しい回路の提案が出てくるんです。そのスピード感には本当に驚かされました。

私は業務というより趣味の延長として楽しませていただくスタンスだったので、期待には応えたかったですが焦りはしませんでした。無理のない範囲でマイペースに進められたのがよかったですね。

なぜHALを作るのか?

StampFlyは発売後、多くの人たちに愛用していただいています。ただ、当初狙っていた「それを通じて飛行制御を勉強してもらう」というところにはまだ届いていません。

原因の一つは、ソフトウェアの構造が難しいことだと考えています。そこで抽象化を進めて、より使いやすく理解しやすいものにしたいと思ったんです。

AIコーディングへの挑戦

これまでChatGPTやClineを使ったAIコーディングを経験してきました。その中で気づいたのは、AIにプログラムを書かせる作業は「仕様を策定したり、仕様を決めさせたり、方針を作ってそれを守らせる」という作業が最初に必要だということです。

AIは前に指示したことを忘れたりして、手戻り作業の際にその指示が反映されずに、よかったところが改悪されたりします。だから仕様や作業方針をまずはドキュメントとして作ってもらい、それを確認しながら作業してもらうのがコツだと今は考えています。

実際のプロジェクト構造〜AIが作った膨大なファイル群〜

今回のプロジェクトの全体計画は、Claude Codeが作成したものです。まず、実際のプロジェクト構造を見てください:

stampfly_hal/
├── CLAUDE.md                           # Claude Code作業指針
├── STAMPFLY_HAL_WORK_PLAN.md          # 8週間開発計画
├── DEVELOPMENT_PROGRESS.md            # 進捗管理
├── CMakeLists.txt                     # プロジェクト設定
├── partitions.csv                     # フラッシュ分割設定
│
├── components/                        # HALコンポーネント群
│   ├── stampfly_hal/                  # コアHAL
│   │   ├── CMakeLists.txt
│   │   ├── include/
│   │   │   ├── stampfly_hal_base.h    # HAL基底クラス
│   │   │   ├── spi_hal.h              # SPI通信HAL
│   │   │   ├── i2c_hal.h              # I2C通信HAL
│   │   │   └── uart_hal.h             # UART HAL
│   │   └── src/
│   │       ├── stampfly_hal_base.cpp
│   │       ├── spi_hal.cpp
│   │       ├── i2c_hal.cpp
│   │       └── uart_hal.cpp
│   │
│   ├── stampfly_sensors/              # センサーHAL(準備中)
│   │   ├── CMakeLists.txt
│   │   ├── include/
│   │   └── src/
│   │
│   └── stampfly_utils/                # ユーティリティ(準備中)
│       ├── CMakeLists.txt
│       ├── include/
│       └── src/
│
├── debug_tests/                       # デバッグテスト群
│   ├── README.md
│   ├── hal/
│   │   ├── spi_debug_test.cpp
│   │   ├── i2c_debug_test.cpp
│   │   └── uart_debug_test.cpp
│   ├── integration/                   # 統合テスト(準備中)
│   ├── sensors/                       # センサーテスト(準備中)
│   └── unit/                          # 単体テスト(準備中)
│
└── main/                             # メインアプリケーション
    ├── CMakeLists.txt
    ├── main.cpp                      # HAL実証アプリ
    └── examples/
        └── README.md                 # 使用例(準備中)

現在のファイル数: 22個(buildディレクトリ除く) 予定されるファイル数: 8週間計画では100個以上!

実際の計画書を見てみましょう:

## StampFly HAL開発作業計画

### 開発期間: 8週間
### 開発環境: ESP-IDF v5.4.1, ESP32-S3
### 対象: M5Stack StampFly クアッドコプター

## フェーズ1: プロジェクト基盤構築(1週間)
## フェーズ2: センサー統合実装(3週間)
## フェーズ3: 制御システム実装(2週間)
## フェーズ4: 通信・高度なCLI実装(1週間)
## フェーズ5: 最終統合・最適化(1週間)

これだけ多くのファイル群を自分で作ることは大変な作業量です。プロジェクトの構造をすばやく合理的に決められることは大変驚くべきことです。

AIとの協業で決めた作業方針

これが重要なのですが、Claude Codeと一緒に決めた作業方針を文書化しました。CLAUDE.mdファイルの一部を紹介します:

### **作業方針(必須遵守)**
**全ての作業において以下を必ず実施:**

1. **StampFly仕様確認**
   - 作業開始前にStampFlyの実際のハードウェア構成を確認
   - Arduino版コードでの実装を参照
   - 推測や一般的な仕様に依存しない

2. **センサー仕様確認**
   - 各センサーの正確なモデル名、インターフェース、ピンアサインを確認
   - メーカー公式データシートの参照
   - StampFly固有の接続方法を優先

3. **API仕様確認**
   - ESP-IDF APIの正確なバージョン(v5.4.1)仕様を確認
   - メーカー純正センサーAPIの最新仕様確認
   - 非推奨APIや変更点の事前チェック

どうも別々に指示した時に言ったことを他のタスクでは反映させてくれないことが多いので、方針を明文化してそれを必ず適用するように指示しました。ただし、本当にやっているかはわかりません(笑)。

実際のコード〜AIが設計した基底クラス〜

具体的なコード例も見てみましょう。これはClaude Codeが設計したHAL基底クラスです:

/**
 * @brief HAL基底クラス
 * 全てのHAL実装クラスが継承する基底クラス
 */
class HALBase {
public:
    virtual esp_err_t init() = 0;
    virtual esp_err_t configure() = 0;
    
    bool is_initialized() const;
    bool is_enabled() const;
    virtual esp_err_t enable();
    virtual esp_err_t disable();
    virtual esp_err_t reset();

protected:
    const char* tag_;           ///< ログ用タグ
    bool initialized_;          ///< 初期化状態
    bool enabled_;              ///< 有効状態
    esp_err_t last_error_;      ///< 最後のエラー
};

この設計は完全にClaude Codeが提案したものです。オブジェクト指向の設計パターンを適切に適用できています。

現在の課題:SPI通信の壁

実は今、BMI270 IMUのChipID読み取りで苦戦しています。SPI通信がうまくいかず、デバイス固有の番号が読み取れないんです。

過去のプロジェクトでは、IMUのデータシートの手順を別のAIでまとめてもらい、Claude Codeに読み込ませてClaude Codeが書いたものを自分が確認して作っていました。ときどき間違いを指摘して修正をしてもらいます。その間違いの指摘自体が間違いのこともあり、若干苦労しますね。

今回は方針として、ハードの仕様、APIの仕様を必ず確認しながら作業を進めてもらっています。ただし、これではまだ足りないかなと思っています。

ハードウェア仕様の伝え方

Claude Codeにハードウェア仕様を伝える方法も試行錯誤しています:

  • GitHubのURLを示す
  • 作業ディレクトリに以前のコードをコピーしておく
  • 過去の自分のコードを見せる
  • Webサイトで確認させる

正解はまだわかっていませんが、いろいろと試しています。

実際のStampFlyのピン配置も、こうやって伝えました:

SPIConfig SpiHal::get_stampfly_default_config() 
{
    // StampFly SPI仕様(Arduino版から):
    // MISO: GPIO43, MOSI: GPIO14, SCLK: GPIO44
    SPIConfig config = {
        .host = SPI2_HOST,
        .miso_pin = GPIO_NUM_43,
        .mosi_pin = GPIO_NUM_14,
        .sclk_pin = GPIO_NUM_44,
        // ... 
    };
    return config;
}

AIコーディングの光と影

光の部分: - プロジェクト構造の迅速な立案 - 大量のボイラープレートコードの自動生成 - 設計パターンの適切な適用 - ドキュメントの自動生成

影の部分: - ハードウェアの微妙なタイミング問題は解決困難 - 指示したことを忘れる - 手戻り作業で改悪されることがある - 実際のデバイスとの相性問題は人間が解決する必要

期待外れについては「作業指示の仕方でどうにかなりそう」なので、そういうもんだと諦めています。できることできないことの見極めが今の段階なので、一喜一憂はしていません。

デバッグの工夫

便利なデバッガが使えないことも多いので、最低限のprintfデバッグはできないとと思っています。

デバッグ用のテストプログラムを作る際のコツですが、Claude Codeはカレントディレクトリに無造作にたくさんファイルを作ってしまう傾向があるので、専用のディレクトリを設けて見やすくしたり、後で整理しやすくしています。

AIコーディングのコツ

読者の皆さんに一番伝えたいのは、「たくさんやってみて失敗しながらコツを見つける」ことです。やればやるほど気づきがあるような気がします。

また、今は始まったばかりなので、AIも毎日進歩して今の悩みは明日は悩みでなくなるかもしれません。

この記事の作成過程

実は、この記事自体もClaude Codeとのインタビューで作成しています。「AIに質問してもらって答える」という形式で進めました。質問をしてもらうことで内容をまとめられるのはいいのですが、文章はまだ深みがないような気がします。これも今後の課題ですね。

次回予告

次回は、実際にSPI通信のChipID読み取りにClaude Codeと一緒に挑戦する様子をお伝えします。うまくいけばその解決方法を、うまくいかなければその格闘過程を正直にお見せします。

現実的には、まだ何も解決案がありません。でも、これこそがAIコーディングの現実なんです。

読者の皆さんへ

このシリーズは、これからどんどん発展する分野で「今何が起こっているか」を伝えて、皆さんがAIコーディングを始めるきっかけになればいいと思っています。

特にStampFlyを持っている方は、モチベーションが維持しやすいのではと思っています。一緒にこの新しい世界を探索していきましょう!


対象読者: - StampFlyユーザー - ドローンに興味がある方 - AIコーディングに興味がある方
- 組み込み開発にAIコーディングの活用を模索している方

次回: 「SPI通信でChipIDを読み取る」〜Claude Codeとのリアルタイム格闘記〜

github.com