マイクロマウスの割り込み動作時間短縮

Analog discovery マイクロマウス

マイクロマウスでは壁検出のセンサ情報を姿勢制御のパラメータとして組み込んでいるため、マイコンの割り込み動作でセンサ値を定期的に取得しています。

私のロボットではセンサ値取得時、割り込み動作内で安定したセンサ値が取得できるまで時間を待ち、センサ値取得後、続きの動作を実行していました。つまり、待ち時間の間は何もせずただただボーっと待っている状態です。

機体には4つの赤外線センサを搭載しており、それぞれを250us毎に取得しているため、そのたびにこの待ち時間が発生していました。効率的ではありませんね。

ただ、最近のマイコンは高性能なので、そんなことは気にせずにソフトを作っても何とか動いてしまうのかもしれません。実際、私のマウスも地区大会の迷路サイズ16×16探索、最短共に何事もなく動作できています。

しかし、全国大会の32×32迷路サイズでの動作になってくると、迷路の経路情報が複雑になっていくにしたがって明らかな遅延が見られます。

これはメイン関数内で実行している迷路解析プログラムなどが新たな情報を得たことでだんだんと重くなっていき、処理が追い付かなくなったことが原因です。これでは安定してロボットの走行ができません。

解決策としては、メイン関数のプログラムを軽くすることも必要ですが、前述したよう効率的でないことがわかっている割り込み処理を軽くすることをここでは考えていきます。

プログラムはメイン関数と割り込みを繰り返して処理しています。割り込みされている間は、メイン関数の処理を実行することができません。

つまり、割り込みをする時間を減らせれば、メイン関数の処理を余裕をもって終わらせられるようになります。

今回の記事では、割り込み時間を減らすよう割り込み内でセンサ値取得待ちをしない方法と、その改良の結果をまとめます。

スポンサーリンク

システム概要

システムでは下記になります。

ARROWHEADシステム概要
ARROWHEAD システム構成概要

   

RX631:システム96MHz、AD変換48MHz
SPI通信:0.6MHz
GYRO,ENC:内部オシレータ

これらのセンサ値は0.25ms毎にCMT割り込みをして、1ms周期で全てを取得しています。

割り込み時間の改善方法

 改善方法は単純です。

  • CMT割り込み内で安定した赤外線センサ値が取得できるまで待つことをやめる。
  • CMT割り込み内でSPI通信で値の取得が完了するまで待つことをやめる。

初めのCMT割り込みでは取得の指示だけをします。待ち時間が経過したら改めて割り込み動作が発生するようにすることで、待っている時間に他の演算をすることができるようにします。

赤外線センサは、CMT1割り込み内でfor文でループを回すことで、待ち時間消費するようにしていましたが、新たにCMT2を導入することで、一定時間後に割り込み動作が働くようにしています。

ちなみに私は以前SHマイコンを使っていたことがあります。SHマイコンはCMTが2つ搭載されています。その場合、動作割り込み用(DUTY等計算)、センサ取得割り込み用で使い切ってしまうため、新たに追加することはできません。

今回の機体はRX631マイコンを使っているため、CMTを最大4つまで動作させることができます。3つ目のCMTを追加し、タイミングを計って割り込みをすることで、ぼーっと待っているのではなく、メインで流れている関数を処理できるようになりました。

次にSPI通信については、全データが取得完了するまで割り込み内でwhile文を回し取得待ちをしていました。それをやめることで、メインで流れている関数の処理時間を増やしました。

通信割り込みタイミングイメージ
割り込みイメージ

 ここで注意が必要なのは、

  • 多重割り込みの許可(setpsw_i(), clrpsw_i() )
  • 割り込み優先度の設定 ( IPR)

になります。

上記図の割り込み以外にも、動作を制御する割り込みなどが動いています。

RX631では、割り込み途中で別の割り込みがが入ると、通常は実行中の割り込みが終了したら、次の割り込みを実行することになります。赤外線センサは、いつでも一定の待ち時間で値を取得したいのに、割り込みが重なってしまうと待ち時間が変化し、値も変化してしまいます。

そこで多重割り込みを許可します。割り込み内(intprgなど)でsetpsw_i(), clrpsw_i()を実行することで、新たに発生した割り込みの優先度IPRが高ければ、実行中の割り込みを停止し、新たな割り込みに移行することができます。

これで赤外線センサ値を一定の待ち時間で取得することができるようになります。

SPI通信についても同様で、センサ値取得時に送信TXI・受信RXI割り込みが発生するため、優先度を適切に設定し処理できるようにします。

割り込み時間の測定方法

 次に実際の割り込み時間を実験で確かめます。方法は下記です。

  • 確かめる割り込みのソース先頭・末尾に汎用I/OポートをHI/LOにする文章を追加
  • その端子の出力をオシロスコープなどで読み取り、割り込み時間を測定

teraterm等での表示を行うために使っているSCI通信用のポートを汎用ポートに置き換え、その信号をAnalog discoveryで測定しました。

Analog discoveryはとても使うのが簡単で、webからwaveformというソフトウェアをダウンロードし、Analog discoveryの装置をPCにUSB接続し、目的の端子(汎用I/Oとチャンネル)をつなげるだけでした。オシロを買いたいなーという物欲が出てきていましたが、この便利さで収まってしまいました。

Analog discovery
Analog Discovery

割り込み時間の測定結果まとめ

 測定結果になります。

※SPI通信は3bytes分取得していますが、最終RXIのみを計算。
※赤外線センサの待ち時間はforループ700回分(約80us)

変更CMT0
占有時間
(動作制御割込)
1ms毎 [us]
CMT1
占有時間
(センサ値取得割込)
0.25ms毎[us]
CMT2
占有時間
(赤外線センサ取得値を処理)[us]
SPI 最終RXI
占有時間
(GYRO, ENC取得値を処理)[us] 
1ms内の割込占有時間合計[us]1ms内の割込占有率[%]
8.66118.7483.548.3
8.668.255.29582.88.3

1ms内で48.3%の時間を割り込みが占有していましたが、今回の変更を行うことで8.3%まで減らすことができています。

赤外線センサ値の待ち時間とSPI通信の待ち時間をそれぞれ個別で測定してみると、変更前のCMT1割り込み118.7us中、ほとんどをセンサ値の取得待ちで消費していたことがわかります。

単独測定待ち時間[us]
赤外線センサ値取得待ち
(forループ700)
70.7
gyro & enc spi取得待ち
(3byte)
43.4
SPI通信割り込み時間測定結果
割り込み時間測定結果

おわりに

 以上の変更で483us占有してた割り込み時間を、83usまで減らすことができました。減った分の400usはメインの処理を行うことができるようになり、実際のマイクロマウスの動作も少し滑らかになったように感じます。

それにしてもマイコンの処理速度には驚かされました。floatで物理値を結構たくさん演算させていた気でいたけど、まだまだ重い処理ができそうです。今後は個別の関数の処理を軽くしようとか考えないで、気にせずババっと実装だ!でいいかもしれません。

しかし、いつもですが今回も改善するのになかなか時間がかかってしまいました。ロボットの走行前は問題なくSPIセンサ値を取得できるのだが、実際動作が始まると暴走。

原因はCMT0の処理量が増えるとSPI通信でセンサ値が取得できなくなるという多重割り込みの設定ミスです。想定していなかったところでの割り込みとの干渉でした。

デバッグは直したと思ったら、次のバグが出てくるみたいなのが続いて大変です。実機にソフトを書きなおして実験を繰り返したりもするためでもっと楽にやれないか考えものです。

さて、皆さんはどのような割り込み動作をしていますでしょうか。

特に気にせず、割り込み中で待ち動作をしている人も多いのだろうか?

割り込みでいろいろ待ってるよって方は上記のように実験してみるといいと思います。うわさではマイクロマウス上位層(宇宙人)には、AD変換待ちですら節約している人もいるらしいです。

効率的な処理をすれば、やりたい機能をどんどん入れても動作させることができます。賢いロボットを作っていきましょう。

タイトルとURLをコピーしました