Alternative Architecture DOJO

オルターブースのクラウドネイティブ特化型ブログです。

arduino-cliとGitHub Actions self hosted runnerを使ってマイコン開発でもCI/CDを実現する

こんにちは、先日娘とおやつでクッキーを食べていたら、ハート型のクッキーを食べながら「これから心臓バイパス手術を始めます!」と言い出してどこで覚えたのかと聞いたところ、妻が好きで見ている医療もののドラマを一緒に見ていたそうで、よく覚えてるなと感心した木村です。

本記事はオルターブースアドベントカレンダー2024の22日目の記事になります。ちなみにアイキャッチ画像はブログの内容からX(旧Twitter)のAIである「grok2」に作ってもらいました。

今回は、ArduinoのCLIツールであるarduino-cliを使って、マイコン開発でもCI/CDを実現する方法を紹介します。

arduino-cliとは

arduino-cliは、ArduinoのCLIツールです。Arduino IDEを使わずに、コマンドラインからArduinoのスケッチをビルドしたり、アップロードしたり、ライブラリを管理したりできます。
GitHubのリリースページから、自身の環境にあったバイナリをインストールして利用します。

Wio BG770Aでやってみる

先日発売が開始された、Seeed社のWio BG770Aを使って、実際にarduino-cliを使って開発してみました。Arduino IDEで環境をセットアップし、センサーデータを読み取るところまでは私の別ブログ記事をご覧下さい。

BG770AのFQBNはSeeedJP:nrf52:wio_bg770aになりますので、サンプルのスケッチをsampleディレクトリに置いた状態で以下のコマンドを実行します。

# スケッチのコンパイル
% arduino-cli compile --fqbn SeeedJP:nrf52:wio_bg770a sample
# プログラムのアップロード
% arduino-cli -p com4 upload --fqbn SeeedJP:nrf52:wio_bg770a sample
# シリアルモニタを開いて動作を確認する
% arduino-cli monitor -p com3 --fqbn SeeedJP:nrf52:wio_bg770a

BG770Aにプログラムをアップロードする際は、ボードをDFUモードにする必要があります。
そのため、uploadコマンドを実行する前に、リセットボタンをダブルクリックします。環境にもよりますが、DFUモードに入るとCOM4ポートで接続が待機されるのでアップロードし、そして自動的にボードがリセットされてプログラムが動き出すと今度はCOM3ポートで接続を待機するようになるので、COM3ポートを指定してシリアルモニタを開きます。

開発時はアップロードしてシリアルモニタをチェックしてという作業を何度も繰り返すことになりますが、この際に都度ボードに触れないでもできるといいんだけど・・という話を先日Seeed社の松岡さんにお話したところ、「BG770Aは、シリアルにボーレート1200で繋ぐとDFUモードに入りますよ」と教えていただきました。
現在はドキュメントにも記載があるとのことでしたので、早速こちらを試してみました。

Windowsの場合はシリアルを設定するmodeコマンドがありますので、それを使う前後でのボードの一覧を確認してみます。Linuxであればsttyコマンドなどで設定できると思います。
以下は、Windows11のPowershellで実行した例です。プログラムが起動していて、シリアルモニターを使うときはCOM3に繋ぐ状態からスタートします。

PS C:> arduino-cli board list
シリアルポート Protocol タイプ               Board Name       FQBN                     Core
COM1    serial   Serial Port       Unknown
COM3    serial   Serial Port (USB) Seeed Wio BG770A SeeedJP:nrf52:wio_bg770a SeeedJP:nrf52

PS C:> mode COM3: BAUD=1200
既定値は、7 データ ビットです。
既定値は、偶数パリティです。

デバイス状態 COM3:
------------
    ボー レート:        1200
    パリティ:           Even
    データ ビット:      7
    ストップ ビット:    1
    タイムアウト:       OFF
    XON/XOFF:           OFF
    CTS ハンドシェイク: OFF
    DSR ハンドシェイク: OFF
    DSR の検知:         OFF
    DTR サーキット:     ON
    RTS サーキット:     ON

PS C:> arduino-cli board list
シリアルポート Protocol タイプ               Board Name       FQBN                     Core
COM1    serial   Serial Port       Unknown
COM4    serial   Serial Port (USB) Seeed Wio BG770A SeeedJP:nrf52:wio_bg770a SeeedJP:nrf52

COM3ポートだったのがCOM4ポートに変わってますね。実際にこれでアップロードしてみると、DFUモードに入っていて、アップロードができました。

modeコマンドを使わずにarduino-cliだけで行う事もできます。まずは、シリアルモニタで繋いでみる方法です。

arduino-cli monitor -p com3 --config baudrate=1200

この場合、Ctrl-Cを押してモニターを停止する必要があります。

もう1つはボードの定義を変更する方法です。例えば私のWindows環境ですと、該当のボードの設定はC:\Users\{ユーザ名}\AppData\Local\Arduino15\packages\SeeedJP\hardware\nrf52\1.4.0\platform.txt というテキストファイルにあるのですが、アップロード時に実行されるコマンドの設定を

tools.nrfutil.upload.pattern="{cmd}" {upload.verbose} dfu serial -pkg "{build.path}/{build.project_name}.zip" -p {serial.port} -b 115200 --singlebank -t 1200

と、-t 1200を追加することで、アップロード時に一度ボーレートを1200に変更してから改めてボーレート115200で接続することができます。
ただし、BG770AですとDFUモードに入るとCOMポートが変わるので、これで行う場合はuploadコマンドが一度失敗するので、再度COM4ポートで接続し直す必要があります。

% arduino-cli -p com3 upload --fqbn SeeedJP:nrf52:wio_bg770a sample
# ↑DFUモードに変更した上で再接続とアップロードは失敗する
% arduino-cli -p com4 upload --fqbn SeeedJP:nrf52:wio_bg770a sample
# ↑COM4には正常に繋がってアップロードに成功する

どの方法が適切かは、環境や作業内容に応じて使い分けてください。なお、Arduino IDEだと自動的にこの動作を行ってくれますので、「スケッチのアップロード」ボタンを押すだけでOKでした。

GitHub Actionsで使う

さて、cliがあって、しかもボードに手を触れなくてもアップロードやモニターができるということは、CI/CDが組めそうですね。しかし、GitHub Actionsの環境でarduino-cliを動かしてコンパイルできるかのチェックをCIで行うことはできますが、残念ながらマイコンをGitHub hosted runnerのマシンに接続することができないので、アップロードと実行(テスト)が行えません。エミュレータを使うといった方法はありますが、やはりマイコンの開発では実機でテストを行いたいところです。

こんな時はself hosted runnerを使いましょう。self hosted runnerは、自身で用意した環境、それこそ自宅のPCなどの上でGitHub Actionsのジョブを動かすための機能です。Windows/Mac/Linuxに対応したエージェントをインストールし、このエージェントがGitHubとHTTPSで接続できるようになっていればOKです。つまり、self hosted runnerを動かす環境は、NATなどの後ろにいるマシンでも大丈夫です。

公式ドキュメントに従い、Arduinoの開発環境が整ってマイコンが接続されている手元のPCに、エージェントのインストールとセットアップを行います。

ワークフローを書く

登録したself hosted runnerを使うように、ワークフローを書きます。今回は最終的にはシリアルモニタへの出力で***BME6800***というデバッグメッセージが出ていればOKと判断するようにしました。

name: CI

on:
  push:
  workflow_dispatch:

env:
  BOARD_FQBN: SeeedJP:nrf52:wio_bg770a
  WAIT_SECONDS: 20
  OK_MESSAGE: "***BME6800***"

jobs:
  build:
    runs-on: self-hosted

    steps:
      - uses: actions/checkout@v4
      - name: build
        run: arduino-cli compile --fqbn $env:FQBN ./sample
        env:
          FQBN: ${{ env.BOARD_FQBN }}
      - name: upload
        run: |
          arduino-cli -p com3 upload --fqbn $env:FQBN ./sample
          arduino-cli -p com4 upload --fqbn $env:FQBN ./sample
        shell: pwsh
        env:
          FQBN: ${{ env.BOARD_FQBN }}
      - name: monitor
        run: |
          $process = Start-Process cmd.exe -ArgumentList "/c arduino-cli monitor -p com3 --fqbn $env:FQBN --raw > output.log" -PassThru
          Start-Sleep -Seconds $env:WAIT_SECONDS
          if (!$process.HasExited) {
            Stop-Process -Id $process.Id
          }
        shell: pwsh
        env:
          FQBN: ${{ env.BOARD_FQBN }}
          WAIT_SECONDS: ${{ env.WAIT_SECONDS }}
      - name: check monitor result
        run: |
          $content = Get-Content output.log
          if ($content -match [regex]::Escape($env:OK_MESSAGE)) {
            Write-Host "Success"
          } else {
            Write-Host "Failed"
            exit 1
          }
        shell: pwsh
        env:
          OK_MESSAGE: ${{ env.OK_MESSAGE }}

環境変数はシークレットとシークレット変数に外出しするとパラメータを変更する度にワークフローファイルを変更しないで済みますが、今回は分かりやすさを優先してワークフローファイルに埋めています。

monitorコマンドはGitHub Actionsでそのまま動かすとシリアルに接続できずにエラーになったため、Start-Procesで別のウインドウを開いて実行し、指定秒数後にプロセスを終了させ、結果はファイルで取得するようにしています。
この辺りはLinuxやMacであればもう少しシンプルに書けたかもしれませんが、特殊なマイコンの開発環境はWindowsしかないようなケースもありますので、この悪戦苦闘の結果が少しでもお役に立てば幸いです。

実際のスケッチファイルとワークフローファイルをGitHubのリポジトリに置いていますので参考にしてみてください。

まとめ

今回は、ArduinoのCLIツールであるarduino-cliとGitHubのself hosted runnerを使って、マイコン開発でもCI/CDを実現する方法を紹介しました。
マイコンやハードウェアの開発のように特定の環境や機器に依存する開発でも、self hosted runnerを使ってCI/CDを実現することができます。開発に必要なツールにcliがあると楽ですが、GUIのプログラムでも起動と操作さえCLIからコントロールできるならば十分に自動化を検討できるはずです。
特定の開発環境が必要なために自動化を諦めていたような現場でも、是非お試しいただければと思います。

皆様のお役に立てば幸いです。


サービス一覧 www.alterbooth.com cloudpointer.tech www.alterbooth.com