Arduinoを使ったリアルタイム制御,とくに母艦PCとのシリアルデータ通信をしながら制御するときの注意点についてまとめておきます.
ここで試しているArduinoはArduino Fioです.ハード概要は以下の通り.
- CPU ATmega328P, 8MHz
- 動作電圧 3.3V
- 無線通信(マイコン側) XBee シリーズ1 チップアンテナ型
- 無線通信(PC側) XBeeエクスプローラUSBドングル
- シリアル通信速度 57600bps
Arduinoでどのくらいの制御周期が出せるか
loop() 関数の中に適当なリアルタイムコードを書いてウェイトなしで全力疾走してみます.以下はよくある制御則(AD入力→1次のフィルタ+線形状態フィードバック→DA出力)を実装した場合です.1ループごとにON/OFFを反転するテスト信号を出してオシロで確認してみます.上図のカーソル間隔は720us程度.当然ばらつきはありますが,だいたい800us (1.25kHz) くらいの制御周期は出せると考えてよいでしょう.少々の演算なら長めに見積もっても1〜2ms以内で終わるようです.
疑似タイマ割り込み
Arduinoにはタイマ割り込みがありません.したがって,一定周期でループをまわしたい場合は,delay()関数を使ってウェイトの自動調整をする必要があります.たとえばlong int s_time, e_time;
const int dT = 1000; /* sampling period in [usec])
...
ループの始めで:
s_time = micros();
ループの終わりで:
e_time = micros();delayMicroseconds(max(0, s_time+dT-e_time));
のようにすると約 1ms で回せます.このときの結果が以下の通り.
多少ばらつきはありますが,おおむね指定周期をキープできています.
さて,マイコンとPCの間でリアルタイムでデータ通信(特に無線通信)ができると非常に便利ですが,迂闊に使うととんでもなく時間を食います.これについては次の記事で.
追記:リアルタイムの限界性能
テスト信号のON/OFF以外に何も処理をせず,全開で回したときのループ周期は 460μsec ほどでした.これが限界の性能です.Arduinoには初心者にとって非常に親切なファームウェアが入っている分,オーバーヘッドもそれなりにあるようですね.