C-Styleで割り込み(その3)

次のような無条件ループでプログラムする場合、ループ内で時間のかかる処理があると、センサ値を読むタイミングによっては、センサ値の変化に気づかない場合がある。
f:id:ohguma:20190224095347p:plain

内部で50ミリ秒の時間がかかる処理があるとセンサ値を読むタイミングは50ミリ秒ごとになる。
センサ値を読んだ後の10~30ミリ秒でセンサ値が変化終了すると、次のセンサ値を見たときには変化が読み取れない。
f:id:ohguma:20190224101851p:plain


そこで、時間のかかる処理とは別に、割り込み内でセンサ値の変化をチェックすることで読み飛ばしを防ぐ。
f:id:ohguma:20190224095413p:plain

センサ値が大きくなる変化を読み取る場合は、次のような感じでセンサ値の最大値(グラフでは点線)を保存しておけば読み飛ばしを防げる。

  • メインプログラム側でセンサ保存値をリセット
  • 割り込み内でセンサ値をチェックし、センサ保存値より値が大きければ、センサ保存値を更新
  • メインプログラム側でセンサ保存値を使って処理
  • (以下繰り返し)

f:id:ohguma:20190224101903p:plain



自走するロボットが秒速1mで進む場合、50ミリ秒で5cm進む。

  • 秒速1mとは
    • 1秒で1m (1000ミリ秒で1000mm)
    • 0.1秒で10cm (100ミリ秒で100mm)
    • 0.01秒で1cm (10ミリ秒で10mm)

処理に時間のかかる超音波センサなどを使う場合、その処理中にセンサ値の変化が終わり、変化を読み飛ばすことは十分考えられる。

C-Styleで割り込み(その2)

割り込みをもう少しテストしてみる。

超音波センサ(PING)は超音波を使い距離を測る。
超音波も音なので、音速を超えた処理はできず、一般的に超音波センサは遅い。
ja.wikipedia.org

センサから出た超音波が1m先の何かに反射して戻ってくる場合、往復で2m。
音速を340m/sとしたとき、2mの往復にかかる時間は約0.0059秒=5.9ミリ秒。
ja.wikipedia.org


C-StylePINGを使う場合にかかる時間と割り込み処理について、次のプログラムで確認する。
f:id:ohguma:20190223141336p:plain

メインプログラムでは以下を行う。

  • 変数A、Bの初期化
  • タイマー1を使い、1秒間のループ
  • ループ内で
    • PING計測し変数Cに代入、
    • 計測回数を変数Bでカウント
  • 1秒のループ後に、変数A、B、Cを表示
    • 変数Cは1秒間のループ中の最後に計測したPINGの値となる

割り込みで処理されるサププログラムでは

  • サブプログラム実行回数を変数Aでカウント


結果は次の通り。今回PINGは未接続だったため、変数Cは0となった。
f:id:ohguma:20190223141357p:plain

PING処理は割り込みに比べると相当遅い事がわかる。

C-Styleで割り込み

C-Styleで割り込みができるようになった。
ja.wikipedia.org

使い方は新しいマニュアル「C-Style 操作編」に追記されている。
割り込み処理中に実行できないこととして「モータ、PINGサーボモータ、I2C 等の制御」が挙げられているが、割り込みタイミング等の記載はないので調べてみる。


サンプルプログラムは次の通り。
f:id:ohguma:20190223091909p:plain

メインプログラムでは以下を行う。

  • 変数Aの初期化
  • 無条件ループ内での赤1LEDの点滅
  • タイマー1を使った1秒の待機
  • 変数Aの表示(C-Codeブロックで「printf("%ld\r\n", gV[VAR_A]);」)

割り込みで処理されるサププログラムでは

  • 赤3LEDの点灯
  • 変数Aの加算。サブプログラム実行ごとに1づつ増える。
  • タイマー1を使い、0.5秒ごとに赤2LEDの点滅

このプログラムで以下が確認できる。

  • 赤LED3がONになるタイミングが、割り込み処理の初回実行タイミング
  • 割り込み処理とメインプログラムで変数、タイマーがが共有できるか
  • 変数Aを表示することで、1秒間に実行される割り込み処理の回数


変数Aを確認するにはセンサーモニタを使う。
手順は次の通り。

センサモニターのタイトル付近「センサモニタ & 出力チェック」をダブルクリック。
f:id:ohguma:20190223091926p:plain

センサモニターのウィンドウが拡大したら、モニタ開始。
f:id:ohguma:20190223091943p:plain

モニタ開始すると、各CNの値が表示されるので、TJ3BをSTARTさせる。
f:id:ohguma:20190223091959p:plain

変数Aが表示され始める。
f:id:ohguma:20190223092014p:plain


ロボット作りには欠かせない機能だと思う。

TJ3B C-Style Ver.190216

ダイセンのダウンロードサイトに新しい C-Style が公開された。

www.daisendenshi.com

  • TJ3B C-Style 操作編
  • プログラミングソフト C-Style Ver.19021

インストール先「C:\Daisen\C-Style for TJ3B V190216」(デフォルトの場合)にある修正履歴には、「①サブプログラムをTimer割込み内で動作する機能を追加」と記述があり、マニュアルの「C-Style 操作編」にもその機能の使い方が追加されている。

アナログジャイロセンサーについて(その7)

モニタ表示があれば、センサーの値を使ったプログラムのデバッグが容易になる。
I2C接続のモニタだと結線も容易にできる。
f:id:ohguma:20190112110313p:plain



アナログジャイロセンサ

動画で使っているOLEDはこちら。ドライバICがSSD1306のもので、AdafruitのArduino用SSD1306ライブラリを使うことで簡単に利用できる。


loop()内では、毎周ではなく、適当な周回(動画では50周ごと)で画面を更新し、三角関数を使い図形を作成している。

      int x1_, y1_, x2_, y2_, x3_, y3_;
      float x1, y1, x2, y2, x3, y3;
      float sn, cs;
      sn = sin(- 3.14 * mydeg / 180);
      cs = cos(- 3.14 * mydeg / 180);
      x1 = 0;
      y1 = 15;
      x2 = -4;
      y2 = -15;
      x3 = 4;
      y3 = -15;
      x1_ = (int)(x1 * cs - y1 * sn) + 16;
      y1_ = (int)(x1 * sn + y1 * cs) + 16;
      x2_ = (int)(x2 * cs - y2 * sn) + 16;
      y2_ = (int)(x2 * sn + y2 * cs) + 16;
      x3_ = (int)(x3 * cs - y3 * sn) + 16;
      y3_ = (int)(x3 * sn + y3 * cs) + 16;
      display.drawLine(x1_, y1_, x2_, y2_, WHITE);
      display.drawLine(x2_, y2_, x3_, y3_, WHITE);
      display.drawLine(x3_, y3_, x1_, y1_, WHITE);


三角関数が理解できれば、プログラムの幅も広がるので、良くわからない方には以下をオススメ。


一連のブレッドボードのイメージはFritzingで作成した。
Fritzingでは独自のパーツも作成できる。

(ProMicroのMicroUSBコネクタがもげたので、おわり)