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では次の項目を確認します。
メニューから「ツール」→「ボード」を選択して表示が「Arduino Uno」であることと、「ボード情報を取得」の部分にArduinoボードが接続されているCOMポート番号が表示されていることを確認します。
次にメニューから「スケッチ」→「書き込み」を選択します。
現在表示されているスケッチの検証とコンパイルが行われ、Arduinoボードへプログラムの書き込みが実施されます。
Arduino IDEを利用したプログラムの書き込み方法の説明は以上です。
2.2 NEQTO Machine Driverを利用したプログラムの書き込み方法
続いて、NEQTO Machine Driverを利用してプログラムを書き込む方法について説明します。先に説明したArduino IDEの場合と同様にシリアルインターフェースを利用してデータの送受信を行います。その際、接続は図4のように行います。
具体的なプログラムの書き込み手順は「5. Machine Driver実施手順」で記載します。
3. プログラムの書き込みシーケンス
Optibootを利用したプログラムの書き込みは下図5のようなシーケンスで実施されます。詳しい説明は割愛しますが、シーケンスのトリガーとしてはArduinoマイコンに対するハードウェアリセットであり、Optibootはリセットが入力されてから一定時間の間にUARTによるアクセスの有無をチェックします。UARTによるアクセスがある場合はプログラムのダウンロードモードへ移行し、アクセスがない場合には既に書き込まれているプログラムを実行します。
Optibootの動作に関してはこちら をご確認ください。
引用元:GitHub
なお、UARTによるデータ制御はAtmel(現在はMicrochip Technology)が提供するアプリケーションノートAVR061 で定義される「STK500 通信プロトコル」を用いて行われます。
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
(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
(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
例)Command:0x50 0x20
Value Note 0x50 プログラミングモードへ移行します 0x20 CRC_EOP
例)Command:0x75 0x20
Value Note 0x75 ArduinoマイコンからデバイスIDを取得します 0x20 CRC_EOP
(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
(8) STK_PROG_PAGEコマンドを実行します。
例)Command:0x64 0x00 0x80 0x46 [128byteのデータ] 0x20
以降、STK_LOAD_ADDRESS コマンドとSTK_PROG_PAGEコマンドを必要なプログラムサイズ分繰り返し実行します。
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
(9) STK_LEAVE_PROGMODEコマンドを実行します。
例)Command:0x51 0x20
Value Note 0x51 Leave programming mode. 0x20 CRC_EOP
4. ハードウェア構成
それではNEQTO Machine Driverで書き込みを行うためのハードウェアを構成します。
前項「3. プログラムの書き込みシーケンス」で確認したように必要な機能は次の通りです。
機能 | 用途 |
---|---|
UART(TX, RX) | NEQTO とArduinoマイコン間のデータ通信を行います |
GPIO | NEQTOからArduinoマイコンのリセット信号を制御します |
上記の必要な機能を踏まえたハードウェア構成は以下の通りです。
今回は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をそれぞれ接続します。
信号線の接続は下表のように行います。
機能 | 色 | 用途 | 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 |
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