• Arduinoを遠隔から書き換え!NEQTO Machine Driver

本記事のポイント

本記事は、IoT-CoreエンジンNEQTOの機能の1つであるMachine Driverの活用例として、ワンボードマイコンの1つであるArduino UNO R3のプログラムをArduino IDEを使わずに、無線通信により遠隔から書き換える方法を説明します。

なお、本記事は、「NEQTO Machine Driverとは?便利な機能をご紹介」の応用編にあたる内容のため、最初にこちらの記事からご確認いただくことをお勧めします。



1. はじめに

Arduinoボードに対してプログラム(Arduinoではスケッチと呼ぶ)の書き込みまたは更新を行うための手段としては、Arduino IDE(コーディング、コンパイル、デバッグなどのプログラミング機能や作成したプログラムをArduinoボードに書き込む機能を有した統合環境と呼ばれるソフトウェア)がインストールされたパソコンとArduinoボードをUSBケーブルで接続する方法が一般的です。

Arduinoボードを使用するためには、コーディング→コンパイル→書き込みという一連の作業がある事と、主にプロトタイプの動作検証目的に用いられるためパソコンと接続する機会が多くなりますが、普段パソコンを利用するワークスペースから離れた場所でArduinoボードを使用している場合、プログラムを更新するたびに、「パソコンをArduinoボードの設置場所まで持ち運ぶ」、または「Arduinoボードをワークスペースまで移動させる」などの移動を伴うことになり大変です。このような作業が遠隔から実施することができれば使い勝手の向上が見込まれます。

本記事では比較的入手しやすく無線機能を持たないArduinoボードの一つであるArduino UNO R3を一例として、NEQTO Machine Driver機能を用いてArduinoボードのプログラムを遠隔から更新する方法を説明していきます。 なお、本内容はArduinoボードの部分を皆さまがお使いのオフライン機器や装置に置き換えてご利用いただける可能性があります。ご不明な点はNEQTOのWebサイトでお問い合わせください。

2. プログラムの書き込み方法


2.1  Arduino IDEを利用したプログラムの書き込み方法


先ずは一般的なプログラムの書き込み手段であるArduino IDEを利用した方法について説明します。

通常は下図1のような構成でArduino IDEが起動されているパソコンとArduinoボードをUSBケーブルで接続し、シリアルインターフェースを用いてプログラムの書き込みを行います。USB信号はArduinoボードに搭載されたUSB to UART変換デバイスによりUART信号に変換されてデータの送受信が行われます。

なお、Arduino IDE を利用してシリアルインターフェースでプログラムの書き込みを行うためにはArduinoマイコンにブートローダーが書き込まれている必要があります。市販品のArduino UNO R3にはOptibootと呼ばれるブートローダーが書かれた状態で販売されていますがArduinoマイコンを単体で購入する際にはブートローダーが書かれていないものもあります。その際には別途ブートローダーを書き込む作業が必要となるので事前にご確認ください。

Arduino IDEを利用する構成

図1. Arduino IDEを利用する構成

Arduino IDEでは次の項目を確認します。
メニューから「ツール」→「ボード」を選択して表示が「Arduino Uno」であることと、「ボード情報を取得」の部分にArduinoボードが接続されているCOMポート番号が表示されていることを確認します。

ツールメニューの表示

図2. ツールメニューの表示

次にメニューから「スケッチ」→「書き込み」を選択します。
現在表示されているスケッチの検証とコンパイルが行われ、Arduinoボードへプログラムの書き込みが実施されます。

スケッチメニューの表示

図3. スケッチメニューの表示

Arduino IDEを利用したプログラムの書き込み方法の説明は以上です。


2.2  NEQTO Machine Driverを利用したプログラムの書き込み方法


続いて、NEQTO Machine Driverを利用してプログラムを書き込む方法について説明します。先に説明したArduino IDEの場合と同様にシリアルインターフェースを利用してデータの送受信を行います。その際、接続は図4のように行います。

NEQTO Machine Driverを利用する構成

図4. NEQTO Machine Driverを利用する構成

具体的なプログラムの書き込み手順は「5. Machine Driver実施手順」で記載します。

3. プログラムの書き込みシーケンス

Optibootを利用したプログラムの書き込みは下図5のようなシーケンスで実施されます。詳しい説明は割愛しますが、シーケンスのトリガーとしてはArduinoマイコンに対するハードウェアリセットであり、Optibootはリセットが入力されてから一定時間の間にUARTによるアクセスの有無をチェックします。UARTによるアクセスがある場合はプログラムのダウンロードモードへ移行し、アクセスがない場合には既に書き込まれているプログラムを実行します。

Optibootの動作に関してはこちら をご確認ください。
引用元:GitHub

なお、UARTによるデータ制御はAtmel(現在はMicrochip Technology)が提供するアプリケーションノートAVR061 で定義される「STK500 通信プロトコル」を用いて行われます。

Optiboot Basic Logic-1

図5. Optiboot Basic Logic-1
引用元:GitHub

NEQTO Machine Driverを利用したプログラム更新に対応するためにはシーケンスを考慮したfup.js(Machine Driver実行中の処理が記述されたJavaScript)を記述する必要があり、少なくとも図5からはGPIOポートによりハードウェアリセットを制御すること、UARTによるデータ通信が必要であることが分かります。

fup.jsで記述する主な内容は以下の通りです。
なお、以下は一例であり、実現する動作によって記述内容が異なる場合があります。

  • ① 更新用プログラムファイルを指定する
    NEQTO Consoleに登録したMachine Driverパッケージからダウンロードするファイルを指定します。

  • ② ハードウェアリセットを制御するIOポートを定義する
    「new GPIO(gpioNo,mode)」でGPIOインスタンスを生成します。
    gpioNoはGPIO番号を指定し、modeは5:OUT、PUSH-PULLを指定します。
    また、IOポートの出力値は「.setValue(value)」で設定します。

  • ③ データ制御に利用するUARTを定義する
    次に「new UART(nodeNo)」でUARTインスタンスを生成します。
    nodeNoはNEQTOで使用するUARTインターフェースのノード番号を指定します。
    次に通信を開始するために、「.open(baudrate,flow,parity[,dataBit[,stopBit]])」を設定します。今回はbaudrate:115200、flow:false、parity:0、dataBit:8、stopBit:1を設定します。

  • ④ Arduinoマイコンとのやり取りを定義する
    シーケンスに関しては図5のようになりますが、Arduinoマイコンとのやり取りにはSTK500 通信プロトコルで定義されているコマンドを使い次のように行います。
    コマンドの詳細については前述の「アプリケーションノートAVR061」をご確認ください。

    (1) Arduinoマイコンに対しハードウェアリセットを実行します。
    ハードウェアリセットを解除するとOptibootが起動します。

    (2) Optibootが起動したら1秒以内にSTK_GET_SYNCコマンドを実行します。
    例)Command:0x30 0x20

    Value Note
    0x30 同期がとれなくなったとき、再同期を試みるコマンドです。
    Resp_STK_INSYNCを受信するまでこのコマンドを送信する必要があります。
    0x20 CRC_EOP

    表1.パラメーター

    コマンドを実行するとOptibootが起動した状態を維持しますが、コマンドを実行せずに1秒経過すると通常プログラムが起動するので注意してください。

    (3) STK_SET_DEVICEコマンドを実行します。
    例)Command:0x42 0x86 0x00 0x00 0x01 0x01 0x01 0x01 0x03 0xFF 0xFF 0xFF 0xFF 0x00 0x80 0x04 0x00 0x00 0x00 0x80 0x00 0x20

    Value Note
    0x42 デバイスのプログラミング・パラメータを設定します
    0x86 Device code as defined in “devices.h”
    0x00 Device revision
    0x00 Defines which Program modes is supported
    0x01 Defines if the device has a full parallel interface or a pseudo parallel programming interface
    0x01 Defines if polling may be used during SPI access
    0x01 Defines if programming instructions are self timed
    0x01 Number of Lock bytes. Currently not used.
    0x03 Number of Fuse bytes. Currently not used.
    0xFF FLASH polling value1
    0xFF FLASH polling value2
    0xFF EEPROM polling value 1
    0xFF EEPROM polling value 2
    0x00 Page size in bytes for pagemode parts, High Byte of 16-bit value.
    0x80 Page size in bytes for pagemode parts, Low Byte of 16-bit value.
    0x04 EEPROM size in bytes, High Byte of 16-bit value.
    0x00 EEPROM size in bytes, Low Byte of 16-bit value.
    0x00 FLASH size in bytes, byte 4 (High Byte) of 32-bit value.
    0x00 FLASH size in bytes, byte 3 of 32-bit value.
    0x80 FLASH size in bytes, byte 2 of 32-bit value.
    0x00 FLASH size in bytes, byte 1 (Low Byte) of 32-bit value.
    0x20 CRC_EOP

    表2.パラメーター

    主な内容はFlashメモリに関する内容でメモリのサイズやページサイズ(プログラムはページ単位で行われます)を設定します。

    (4) STK_SET_DEVICE_EXT コマンドを実行します。
    例)Command:0x45 0x05 0x04 0xD7 0xC2 0x00 0x20

    Value Note
    0x45 デバイスの追加パラメータを設定します
    0x05 Defines how many bytes of additional parameters the command contains.
    0x04 EEPROM page size in bytes.
    0xD7 Defines to which port pin the PAGEL signal should be mapped.
    0xC2 Defines to which port pin the BS2 signal should be mapped.
    0x00 Defines whether a part has RSTDSBL Fuse (value = 1) or not (value = 0).
    0x20 CRC_EOP

    表3.パラメーター

    (5) STK_ENTER_PROGMODE コマンドを実行します。
    例)Command:0x50 0x20

    Value Note
    0x50 プログラミングモードへ移行します
    0x20 CRC_EOP

    表4.パラメーター

    (6) STK_READ_SIGNコマンドを実行します。
    例)Command:0x75 0x20

    Value Note
    0x75 ArduinoマイコンからデバイスIDを取得します
    0x20 CRC_EOP

    表5.パラメーター

    Arduino UNO R3の場合には ATmega328Pであることを示す「0x1E 0x95 0x0F 」を取得できます。

    (7) STK_LOAD_ADDRESSコマンドを実行します。
    例)Command:0x55 0x00 0x00 0x20

    Value Note
    0x55 メモリへの読み取りまたは書き込みアドレスを設定します
    0x00 0x00 値はLSB byte of address、MSB byte of addressの並びです
    0x20 CRC_EOP

    表6.パラメーター

    書き込みを開始する先頭アドレスをwordアドレス単位で設定します。Flashメモリには128byte単位で書き込むため2回目の書き込みアドレスは0x40 0x00を設定します。以降、同様に64word分を追加します。

    (8) STK_PROG_PAGEコマンドを実行します。
    例)Command:0x64 0x00 0x80 0x46 [128byteのデータ] 0x20


    Value Note
    0x64 指定したメモリへデータを書き込むコマンドです
    0x00 0x80 Byte of data block size:128byte
    0x46 Memory type: Flash
    0xXX – 0xXX Data to program into Flash:128byte分
    0x20 CRC_EOP

    表7.パラメーター

    以降、STK_LOAD_ADDRESS コマンドとSTK_PROG_PAGEコマンドを必要なプログラムサイズ分繰り返し実行します。

    (9) STK_LEAVE_PROGMODEコマンドを実行します。
    例)Command:0x51 0x20

    Value Note
    0x51 Leave programming mode.
    0x20 CRC_EOP

    表8.パラメーター

    コマンドを実行するとWDT(WatchdogTimer)が起動し、タイムアウト後は新たに書き込んだプログラムが動作します。

4. ハードウェア構成

それではNEQTO Machine Driverで書き込みを行うためのハードウェアを構成します。
前項「3. プログラムの書き込みシーケンス」で確認したように必要な機能は次の通りです。

機能 用途
UART(TX, RX) NEQTO とArduinoマイコン間のデータ通信を行います
GPIO NEQTOからArduinoマイコンのリセット信号を制御します

表9. プログラムの書き換えに必要な機能

上記の必要な機能を踏まえたハードウェア構成は以下の通りです。
今回はNEQTO対応ハードウェアとしてSTマイクロエレクトロニクス社のSTM32 Discovery kit(B-L4S5I-IOT01A 以降、STM32 Discovery kitとする)を使用します。
制御線はSTM32 Discovery kitのTXとArduinoボードのRX、STM32 Discovery kitのRXとArduinoボードのTX、STM32 Discovery kitのGPIOとArduinoボードのRESETをそれぞれ接続します。

ハードウェア構成図

図6. ハードウェア構成図

信号線の接続は下表のように行います。

機能 用途 NEQTO
STM32 Discovery kit
Arduino UNO R3
UART_TX 送信制御信号 CN3-2 DIGITAL 0
UART_RX 受信制御信号 CN3-1 DIGITAL 1
GPIO リセット制御信号 CN3-3 POWER_RESET
GND CN1-7 POWER_GND

表10. 信号線布線表

5. Machine Driver実施手順

実際にNEQTO Machine Driverを利用してプログラムを書き込む際の手順を記載します。
下記の(1)および(2)についてはMachine Driverパッケージを登録する際に必要となるファイルを作成する内容であり、Arduino IDEにおける標準的な操作であることからここでの説明は割愛します。

  • (1) Arduino IDEでプログラムを作成し、コンパイルを実施します。
  • (2) Arduino IDEのメニューバーから[スケッチ]→[コンパイル済みバイナリをエクスポート]を選択してバイナリファイルを出力します。
  • (3) NEQTO ConsoleにアクセスしてMachine Driverパッケージを登録します。パッケージの登録にはfup.jsとファイルが必要です。 fup.jsは「3. プログラムの書き込みシーケンス」で検討したものを使用し、ファイルは上記(2)で出力したバイナリファイルを使用します。
  • (4) 登録したMachine Driverパッケージをテンプレートにひもづけます。
  • (5) 最後にNEQTO ConsoleのメニューからMachine Driverを実行します。

なお、上記(3)から(5)の具体的な方法については、「NEQTO Machine Driverとは?便利な機能をご紹介」に記載されているのでご確認ください。

6. おわりに

無線通信機能を持たないArduinoボードのプログラムを遠隔から書き換える方法を説明しましたが、いかがでしたでしょうか。

今回は一例としてArduinoボードを使用しましたが、fup.jsに記述する処理内容を変更することで、Arduinoボード以外のデバイスが接続された場合でもMachine Driverを利用することができます。
また、本記事ではMachine Driverをプログラム更新のために利用しましたが、Machine Driverの基本的な機能は、NEQTO Consoleから「Machine Driverパッケージとして登録されているファイルをダウンロード」して「NEQTOに接続されているデバイスへファイルを送信する」ということです。

Machine Driverに興味をお持ちでしたら、最小の構成で実現できるSTM32 Discovery kitでNEQTOをお試しいただいてはいかがでしょうか。


リンク

STM32 Discovery Kit [B-L4S5I-IOT01A]:STマイクロエレクトロニクス
Arduino UNO R3:Arduino