納品済の Arduino 試作品ソフトを遠隔からアップデートする

Remotely update Arduino software already deployed in the field.

企業の皆様、こんな御経験はございませんでしょうか。

「Arduino で設計した試作品のソフトウェアを、遠隔から更新したい!」

…こんなことを言うと、

「何を言ってるんですか!  雨が降ろうと台風が来ようと、お客様の事業所に御挨拶に伺って、その場でソフトウェアを更新させて頂くのが、誠意というものではありませんか!?」

と叱られてしまうかもしれませんが、正直、お客様にとっても、忙しい日に、あるいは台風の日に、わざわざ来客に対応するというのはコスト要因ではないか、とも考えられます。

閑話休題。Arduino の試作品に限定しなくても良いのですが、遠方に納品した組込機器のソフトウェアを遠隔からアップデートしたい、というのは、特に現場の技術者レベルでは強いニーズがあるはずです。

もっともスマートなのは、納品した試作品に WCDMA あるいは LTE 等に対応した無線機能があり、インターネットに直接繋がっているケースですが、これは稀な例と言って良いでしょう。

そうでない場合に現実的なのは、

  • お客様サイトのイントラネットに、試作品を Ethernet あるいは Wi-Fi で繋がせてもらう
  • Wi-Fi 通信機器とモバイルルーターを、一緒に納品する

といったところでしょうか。セキュリティの観点から前者は厳しい場合があるかも知れませんが、後者なら実現性は高そうです。

今回はこのように、お客様のサイトで何らかのインターネット接続が可能であるという前提で、Arduino 環境のソフトウェアを遠隔から更新することを考えてみましょう。ただし、一口に Arduino といってもベースとなるハードウェア(マイコンデバイス)は多岐にわたります。

Arduino マイコン自身に Wi-Fi 機能がある場合

この条件において、もっとも利用ケースに挙がりそうなのが、最近流行りの Espressif ESP32 マイコンと Arduino 環境を使って試作品を納入した場合です。ESP32 のソフトウェア開発プラットフォームである ESP-IDF には、初めから OTA(over-the-air)アップデート機能が盛り込まれており、比較的簡単に、ソフトウェアの遠隔アップデート(フィールドアップデート)を実現できるようになっています。

ESP-IDF の OTA では、フラッシュ ROM のパーティションを複数に分割して、異なるバージョンのソフトウェアを展開したり、アップデート版のソフトウェアがセルフテストに失敗して、アップデートを中断しなくてはならなくなった場合にロールバックをしたりという機能も盛り込まれており、試作品レベルを超えて、量産システムでも十分に適用可能なものと言えそうです。

なお、この OTA 機能は Arduino プログラミング環境からでも十分に利用可能です。私としては ESP-IDF の OTA 機能も紹介してみたいところですが、ESP32 専門の話題となってしまうので、次の機会とさせて頂くことにします。

ESP-IDF の OTA に御興味のある方は、こちらを御参考ください。

一緒に Raspberry Pi を置かせて貰える場合

次に、一般的な Arduino Uno など、それ自身で Wi-Fi 機能を使ってソフトウェアをアップデートするのが困難な場合です。こちらのほうが、より一般的な利用ケースとなるかも知れません。

以下では、Arduino Uno や Arduino Mega 等の AVR マイコンを利用していることを前提としますが、他のマイコンでも、avrdude のようなソフトウェアを Raspberry Pi 上で動作させられるなら、似たような方法が利用できます。

このようなケースでは、もし、試作品と一緒に Raspberry Pi(ラズパイ)などの Linux コンピュータを一緒に納品(設置)させて貰えるのであれば、簡単な解決法があります。いや、お客様に利点をお話しして、是非一緒に納品させて頂きましょう!  最近は Raspberry Pi の入手が困難なのが問題ですが、何も最新の Raspberry Pi である必要はないので、御社の工具箱に転がっている Raspberry Pi を一つ探してください。Wi-Fi 機能が欲しいので Raspberry Pi Zero W あたりが安価で、良い選択肢かと思います。(Wi-Fi が搭載されていない場合は USB ドングル型の Wi-Fi アダプタが必要になります。)

なお、モバイルルーターに Ethernet ポートがあったり、お客様のイントラネットに Ethernet で接続させて貰える場合は、Wi-Fi 機能はなくても大丈夫です。(その代わり、今度は Raspberry Pi に Ethernet ポートが必要です。)

基本的なアイデアは次の通りです。

  • お客様への納品時に、Raspberry Pi の USB ホストポートと、Arduino の USB デバイスポートを、USB ケーブルで接続しておきます。
  • ソフトウェアのアップデートが必要になったら、(お客様にお願いして)お客様のサイトにあるモバイルルーターと Raspberry Pi の電源を入れて頂きます。
  • 更新済みの Arduino ソフトウェアを用意します。(後で説明します。)
  • 何らかの方法(後で説明します)で、御社の PC からお客様サイトに置かれている Raspberry Pi にリモートログインします。
  • Raspberry Pi に Arduino ソフトウェアを転送します。
  • Raspberry Pi 上で avrdude というソフトウェアを実行して、Arduino のソフトウェアを更新します。

さて。個々の要素をもう少し細かく説明していきましょう。

Arduino ソフトウェアのリリースファイルの用意

皆様が通常 Arduino を利用されるときは、Arduino IDE を Arduino に USB 接続して、IDE のメニューから「スケッチ → マイコンボードに書き込む」をなさると思います。今回のように、コンパイル済みのソフトウェアファイルを用意するには、少し工夫が必要です。ネットで検索すると詳しい情報が見つかると思いますので、ここでは簡単に説明します。(今回は、Arduino 1.8.19 で説明します。)

まず、Arduino IDE を起動したら、Preferences…(環境設定) メニューを開き、「より詳細な情報を表示する」を、「コンパイル」「書き込み」共にチェックしておきます。

続いて、Arduino IDE で更新済みのソフトウェアソースコードをロードしたら、まずは手元の Arduino(納品済みのものと同じタイプ)を USB ケーブルで PC に接続し、「スケッチ → マイコンボードに書き込む」を実行します。すると、IDE 下部のウィンドウにずらずらとメッセージが表示されますが、それをテキストエディタ等にコピーして、次のような行を探し出します。(以下は macOS の場合ですが、Windows でも同様です。)

(略)/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude -C/Users/(略)/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf -v -patmega328p -carduino -P/dev/cu.usbserial-DA0147I3 -b115200 -D -Uflash:w:/(略)/yourapp.ino.hex:i

これが見つかったら、-Uflash:w:なんとかかんとか/yourapp.ino.hex:i の部分の、なんとかかんとかというディレクトリ(フォルダ)を PC 上で探して開きます。(Explorer で OK です。)

そして、その中にある hex ファイル(ここでは yourapp.ino.hex)を、どこかにコピーしておきます。これが、遠隔アップデートで必要になるファイルです。

Raspberry Pi に avrdude をインストール

さて。上でコピーした行を覗くと分かりますが、コンパイルしたプログラムを Arduino に書き込むには、avrdude というソフトウェアを利用していることが分かります。つまり、この avrdude が Raspberry Pi 上で動作するならば、Arduino ソフトウェアの書き込みは、PC でなく Raspberry Pi でも可能だ、ということになります。(おそらく、USB ホストコネクタが付いていて、Debian/GNU Linux が動作する Linux ボードならば、同じことができると思います。)

最新の Raspberry Pi OS(Raspbian Bullseye)では、apt コマンドを使って、簡単に avrdude をインストールすることができます。やってみましょう。

bash$ sudo apt install --yes avrdude
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following additional packages will be installed:
  libftdi1 libhidapi-libusb0 libusb-0.1-4
Suggested packages:
  dfu-programmer avrdude-doc
The following NEW packages will be installed:
  avrdude libftdi1 libhidapi-libusb0 libusb-0.1-4
0 upgraded, 4 newly installed, 0 to remove and 0 not upgraded.
Need to get 334 kB of archives.
After this operation, 1,186 kB of additional disk space will be used.
(略)

無事にインストールできましたでしょうか。

なお書き忘れましたが、この作業は、お客様サイトに Raspberry Pi を持ち込む前にやっておいたほうが良いのは、言うまでもありません。(遠隔でもインストールできますが。)

お客様サイトにある Raspberry Pi にログイン

さて。おそらく次に問題になるのは、お客様サイトにある Raspberry Pi に、どうやってリモートログインするか、ということになるかと思います。なお、こちらの作業は、avrdude のインストールとは違い、納品前に準備しておかなくてはいけません。

遠隔の Raspberry Pi にログインする場合、一般的に使われる方法としては、Dynamic DNS と SSH を利用するやり方だと思います。しかし、これには以下のような問題があります。

  • SSH サーバーのセキュリティ維持が難しい。(IP ネットワークやファイアウォール等のセキュリティに関する、ある程度の知識が必要)
  • お客様サイトのイントラネットに繋がせてもらう場合、お客様サイトの外部から SSH でログインすることは、通常不可能。(ファイアウォールで閉じられている場合がほとんど。もし閉じられていなかったら、それはそれで不安。)

ここで私がお勧めする方法は、以下の ngrok という商用サービスを利用する方法です。

月額 US$ 10 からと安価ですし、使わなくなったらやめてしまえば OK です。ngrok の導入については、ネット上に豊富な情報がありますので、参考になさってください。(お問い合わせ頂ければ、導入をお手伝いさせて頂きます。)

ngrok は、ネットワークの内側から ngrok 社のサーバーに通信コネクションを張ることで、逆に、ネットワークの外部から内部に対する通信コネクションを実現することのできるソフトウェアです。(トンネリング技術と呼ばれるものの一種です。)

ngrok を使う場合、モバイルルーター上のファイアウォールで SSH ポートの開放をする必要がないので、SSH サーバーが外部からアタックされるリスクを最小限に抑えることができます。

なお、ngrok を利用するためには、Raspberry Pi 上で ngrok クライアントソフトを実行する必要があります。一番安心で、かつお客様の同意を得やすいのは、お客様に、お客様手元の Raspberry Pi にローカルでログイン頂いて、ngrok クライアントソフトを実行頂くという方法かと思います。

他に、Linux の設定にお詳しければ、起動時に自動的に ngrok クライアントを起動する、という方法もあるかも知れません。

ngrok で通信コネクションが張れたら、外部の PC(つまり、あなたの PC)から、お客様サイトの Raspberry Pi に SSH ログインするだけです。なお SSH の設定としては、パスワード認証を無効にして、公開鍵認証をお使いになるのが安全です。公開鍵認証を強くお勧めいたします。

実際に avrdude してみよう

さて、ここまでうまく行きましたでしょうか。一番の難関は、上記の ngrok かと思いますが、無事に Raspberry Pi にリモートログインできたとしましょう。(実際には、慣れれば ngrok の導入は簡単な作業です。)

最初に必要なのは、更新したい Arduino ソフトウェアファイル(hex ファイル)の用意と、Raspberry Pi への転送です。ファイルは、上記で yourapp.ino.hex として用意できていると思いますので、これを SSH(sftp)を使って Raspberry Pi 上にコピーしましょう。それができたら、後は簡単です。Raspberry Pi に Arduino が繋がっていることを確認し、Raspberry Pi 上で次のコマンドを実行します。コマンドの引数は、Arduino IDE のログ画面で見つけたものを参考にして頂きたいですが、私が試した例を下に示します。

bash$ avrdude -v \
    -p atmega328p \
    -c arduino \
    -P /dev/ttyUSB0 \
    -b 115200 \
    -D \
    -U flash:w:yourapp.ino.hex:i

注意点は、-p で指定するマイコンの種別、-P で指定する通信ポートの指定かと思います。yourapp.ino.hex は、上記で sftp にてコピーしたファイルです。ファイル名が違う場合は、皆様がアップロードしたファイル名に合わせてください。

うまく動作すると、次のような(おなじみの?)メッセージが出て、フラッシュ ROM の書き込みが終了します。

avrdude: Version 6.3-20171130
         Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
         Copyright (c) 2007-2014 Joerg Wunsch
(略)
Reading | ################################################## | 100% 0.01s
(略)
Writing | ################################################## | 100% 0.30s
(略)
avrdude: verifying ...
avrdude: 932 bytes of flash verified
(略)
avrdude done.  Thank you.

以下は余談ですが、このやり方で嬉しいのは、お客様から「ソフトを更新したら、逆に動作がおかしくなった!」等の御報告があった際に、すぐに以前のソフトウェアバージョンに戻せるということですね。(もちろん、以前のソフトウェアバージョンをコンパイルした hex ファイルを用意しておく必要があります。) 一方で OTA の場合は、上述の ESP-IDF OTA のようなロールバック機能がないと不安ですが、今回のように手動で更新する場合は、少し心に余裕ができますね。

さて、今回の記事が少しでも皆様のお役に立てましたら光栄です。今日はここまで。

お問い合わせはお気軽に!

お問い合わせを頂いた後、継続して営業活動をしたり、ニュースレター等をお送りしたりすることはございません。
御返答は 24時間以内(営業時間中)とさせて頂いております。必ず返信致しますが、時々アドレス誤りと思われる返信エラーがございます。返答が届かない場合、大変お手数ではございますが別のメールアドレスで督促頂けますと幸いです。