Beauto ステップアップ講座3 ON-OFF制御器

注意

VS-WRC003に搭載されているモータードライバICは、使用条件によっては発熱、更には壊れる場合があります。異常動作や過度の発熱が見られた場合はロボットの電源を切ってください。本項目のサンプルプログラムはモーターの正逆転を頻繁に切り替えるため、注意が必要です。下のImpress Robot Watchのページも参考にしてください。

Robot Watch-コラム-ヴイストン「Beauto Chaser」で学ぶプログラミング入門講座 -ヴイストン「Beauto Chaser」で学ぶプログラミング入門講座

本講座(当ブログにて「Beauto講座」カテゴリーに分類されている記事)の文章およびサンプルプログラムを使用した結果のロボットの破損等について筆者は責任を負いませんのであらかじめご了承ください。

私の推測では、初期のBeauto Chaserに採用されていたモーターは通常のFA-130で1.5V用のため、4.8Vや6.0Vの電源で使用するとモータードライバの許容できる電流を超えて発熱や破壊を招くのではないかと思います。私の持っているBeauto Chaserではモーターの巻線抵抗が通常のFA-130より大きく、より高い電圧用のモーターに変更された模様です。4.8V電源で使用してきましたがドライバの発熱はほとんどありません。※このあたりのDCモーターの特性についてもまた改めて説明したく思っています。

Beauto Builderでのライントレースとの違い

本講座のプログラムの考え方は,Beauto Builder等を使ってフローチャートの形で動作手順を記述するものとは全く異なります.

  1. 動作時間の指定はしない
  2. 条件判断ではなく実数の計算による

2については次回以降説明します。まずは1について。

Beauto Builderではモーターへの指令はたとえば「直進を0.5秒」というように,動作の種類+時間を指定するようになっています.この例の場合0.5秒の間はセンサーが変化を検知しても関係なくモーターを回し続けます.

本講座で紹介する方法ではセンサーの情報とモーターの出力を常に連動させます。そのために十分短い時間ごとにセンサーを読み取る→計算する→モーター出力を変化させるという処理を繰り返します。次のような構造のプログラムで実現できます。

while(1) {
   センサーを読む
   センサーの値をもとに次のモーターへの指令を計算する
   モーターに指令する
   余った時間待機する
}

最後の「余った時間待機」はVS-WRCのサンプルプログラムで提供されているSync()関数で実現できます。Sync関数は先にInit関数(同サンプルプログラムで提供)で指定した制御周期の時間が経過するまで実行を止めます。繰り返しの周期を一定にするために必要です。周期を一定にすると便利な理由は次々回以降説明する予定です。

センサーを読む部分は前回説明しました。あとはセンサーの値からどのようにモーターへの指令を計算するかだけ決めれば完成します。一番簡単な方法として、右にずれていたら左に、左にずれていたら右に車体を回転させるようにしてみましょう。

使い方

ビルド方法は前回、前々回を参考にしてください。

センサー2個用となっています。4個使用する場合は前回のプログラムを元に、下の「解説」にあるソースリストを適切な箇所に書き足す等で対応してください。※センサーの値を直接使わず、前回示したline_posを使うため今回追加部分はこのままで対応可能です。

まず前回同様、センサー調整を行います。センサー全部を黒い線の上に載せてスペースキーを押し、続いてセンサー全部を白い床の上に移動させてスペースキーを押します。

ラインが進行方向になるようにロボットをライン上に置き、更にもう1回スペースキーを押すとライン追従動作を始めます。今回のプログラムはいわば「前進速度が0のライントレース」であるため放っておいても動きませんが、ロボットのセンサーを左右にずらすと中央に復帰するように回転しようとします。

動作中更に何かキーを押すと正規化センサー値とライン位置が表示されます(前回を参照)。

なお、センサーの取り付け方、モーターの配線方法によってはライン追従ではなくてラインから逃げるようになってしまいます。プログラムのMtr_Runの引数を逆にする等で対処してください。なお参考までに、サンプルプログラムは次の組み方をしたBeauto Chaserに合わせて作りました。

解説

前回のプログラムのwhileループ内、ライン位置を計算する部分の直後にモータードライバへの指令を追加しています。

        line_pos = (sval[0] * (-1) + sval[1] * 1) / sum;

        if(line_pos < -0.2) {          // (1)ラインが左側にあるとき
            Mtr_Run(50, 50, 0, 0);     // (2)車体を左回転させる
        } else if(0.2 < line_pos) {    // (3)ラインが右側にあるとき
            Mtr_Run(-50, -50, 0, 0);   // (4)車体を右回転させる
        } else {                       // ラインが大体真ん中にあるとき
            Mtr_Run(0x80, 0x80, 0, 0); // (5)ブレーキをかける
        }
        // 中略
        Sync();
    }

3通りの場合分けです。せっかく実数でライン位置を計算したのにもったいないのですが、その点は次回以降順次改善していきます。

ラインが大体真ん中にあるときはブレーキを掛けます。ここの0x80を0に変更すると、ブレーキではなくてフリー状態になり、若干動作が変わります。興味のある方は試してみてください。効果が分かりにくい時はロボットを浮かせて車輪を空転させるとはっきりわかります。

(1)と(3)にある-0.2と0.2で、ラインが「大体真ん中」とは中央からどれだけずれた状態までを言うのかを決めています。これを-0.1と0.1等にするとより厳密に真ん中にあわせようとします。また(2)と(4)の50、-50はモーターをどれだけの速さで回そうとするかを決めます。絶対値を大きく(最大127)するとより力強く動きます。但しあまり大きくすると行き過ぎて左右にがたがた震えるようになる場合があります。(1)(3)の数値を小さくした場合も同様です。

このように数値を少し変えてみて動作を見る度にプログラムを書き込むのは大変です。次回はこのような試行錯誤をもう少し簡単に出来るようにします。

余談: DCモーターのPWM制御について簡単に補足

モーターのPWM制御はよく「スイッチのONとOFFを高速で繰り返す」と説明されますが、これは半分間違っています。確かにこの通りにする場合もありますが、Beauto Chaserのような自動制御ロボットのモーター制御では「モーターを電池に繋げるのと、モーターの端子同士をショートさせて電磁ブレーキを掛けるのを交互に高速で繰り返す」という方式をとる場面が多いのです。理由の一つは加速と減速を対称に行うためです。本当にスイッチをOFFしてモーターの端子に何も繋がない状態にしてしまうと、モーター自身は回転を止める力を出さないのです。機械的な摩擦のために徐々に減速はしますが、それでも電源ONで加速したときと比べてずっと長い時間が掛かります。

VS-WRC003のサンプルプログラムにあるMtr_Run関数で64(最大値である127の半分)を指定すると、半分の時間正転で、残り半分の時間ブレーキを掛けるという動作になります(実際は少しの時間フリーになりますが)。他の数値でもOFFの時間はブレーキを掛けています。そのため-1と1の間は0ではなく、ブレーキ動作として定義されている0x80の方が自然につながるのです。

なお、VS-WRC003LVではモータードライバ回路の設計上、フリーの動作ができません。Mtr_RunやMtr_Run_lv関数で0を指定するとブレーキがかかります。

山口辰久

Valid HTML 4.01! Valid CSS!