超音波センサを使ったプログラミングに挑戦

1 超音波センサとは
2 超音波センサの取り付け
3 超音波センサで距離を測る
4 正面の超音波センサで障害物をよける
5 3つの超音波センサで障害物を回避
6 70CM幅のクランク走行
7 ロボットタイヤと床面の関係

ロボット講座の10回目です。前回は、ホールセンサをRaspberryPiのGPIOに接続し、車輪に取り付けた磁石の磁気を感知するところからスタートし、車輪の回転数を計測、その回転数とその時のデューティ比を記録、記録された結果に基づいて動作を再現するという、一連のセンサによる計測結果に基づいたティーチングを行いました。

今回は超音波センサをRaspberryPiのGPIOに接続し、壁などの障害物の有無、障害物からの距離を検知し、壁を避けて走行するロボットカーの制御に挑戦しました。

1 超音波センサとは

超音波センサとは、目には見えない「音の波」を使って、物の距離を測る装置です。超音波を出すトランスミッターという素子と跳ね返ってきた超音波を受けるレシーバという素子で構成されています。発信した超音波が跳ね返ってくるまでの時間を測り、音速が約340メートル毎秒 (m/s)であることから計算で物体までの距離を出します。

自動ドアや車の近接センサ、ロボットなどにも使われています。今回使用している超音波センサモジュールはHC-SR04で、VCCが5V、Triggerピンに10µsのパルスを入力するとTransmitter(送信機)から40kHz、8サイクルのパルスが出力され、ピンがHighになります。反射して きたパルスをReceiver(受信機)が受信するとEchoピンがLowになります。

この一連の動作を利用して、ほぼリアルタイムに障害物を検知、また障害物への距離を測ることができます。

2 超音波センサの取り付け

超音波センサをロボットカーのフロントと左右に取り付け、RaspberryPiのGPIOに下図のように配線しました。

超音波センサの電源は5Vで、センサの出力(Echo)も5Vとなります。それをそのままラズパイの入力端子に接続するとラズパイが壊れてしまので、2.7kΩと4.7kΩの抵抗で分圧して3.3V以下にしてBCM19ピンに入力しました。Trigger端子は3.3ⅤでそのままBCM20ピンからの信号を受けます。

3 超音波センサで距離を測る

今回使用しているHC-SR04という超音波センサは約2cmから約4mまで測定が可能です。早速、超音波センサで使ってみます。
超音波センサを利用するには、DistanceSensorという便利なクラスがあるので、これを使用しました。

DistanceSensorはecho端子とtrigger端子を指定したオブジェクト(このプログラムではfront_sensor)を生成し、そのオブジェクトに.distanceというメソッドを与えれば超音波を発信してから受信するまでの時間を測定して距離をメートルで出してくれます。3つの超音波センサが働いているかどうか、Pythonのプログラムを使用してチェックします。

4 正面の超音波センサで障害物をよける

超音波センサの取り付けとチェックが完了したら、フロントに取り付けたセンサだけを使って障害物を回避するコントロールに挑戦しました。

周囲をべニア板の壁に囲まれたフィールド内でロボットカーを走行させ、壁に近づいたら方向を変え、衝突を回避しながら走行し続ける制御に挑戦です。フロントの超音波センサだけなので、ロボットカーが壁と平行になってしまうと、壁に衝突する恐れがあります。ロボットカーの動作に工夫が必要です。

試行錯誤を重ねながら左右のモータのデューティ比を変え、動作時間を設定し、みんな壁を回避してロボットカーを走行させることができるようになりました。

5 3つの超音波センサで障害物を回避

いよいよフロント、右側面、左側面、3つの超音波センサを使って壁に囲まれたクランクを自動走行させます。3つのセンサがどのような検知を行うか場合分けと、その時の処理をプログラムに書き込んでいきます。このHC-SR04という超音波センサモジュールは正面から±7.5°程度の範囲では反射波を正確に受信できますが、少しずれると測定不可能になってしまうという特性があります。このため壁に対して斜めに侵入する場合は、壁に当たるくらい近づかないとわからないということになります。そこで左右のセンサは少し斜め(約15度)に取り付け、真横だけでなく「前斜め方向」までカバーでき、角のある通路や曲がり角に早く気づき、死角が減るようにしました。特に壁に対して斜めに侵入すると、進行方向と同じ向きに取り付けた場合、制御不能に陥りやすくなります。

このように、多くの条件で判断しなくてはならない場合に便利なのが『all関数』と『any関数』です。

6・7 70CM幅のクランク走行・ロボットタイヤと床面の関係

70cm幅の壁が迷路のように続いています。壁に当たらずにゴールしましょう。L1とL2の差が大きい時と小さい時では幅寄せの量を変える必要があります。

L1とL2の差が大きい時と小さい時では幅寄せの量を変える必要があります。差が小さければ、少しだけカーブし、差が大きい時は大きなカーブが必要になります。このときは絶対値を使うと便利です。abs(L1-L2)・・・・この絶対値が小さければまっすぐ走れと指示すればいいですね。

壁にセンサが近づいたら単純に反対方向へ曲がるだけでよいでしょうか?

①の場合、左右の超音波センサから得られる距離の差を求め、進行方向を調整します。しかし、②のように、左右の距離がほぼ同じになるとどうでしょう?左右の壁までの距離が等しいと判断して真直ぐ進み、今度は右側のセンサと壁との距離が小さくなるため、左に曲がろうとします。惰性があるため、左折の指示が間に合わなくなり、壁に衝突します。

ロボットカーが壁に向かって斜めに侵入すると壁に近づき、ロボットカーを右折させると思います。先ほどの例では、元の位置に戻り切れずに反対側の壁に衝突するので、スピードの調整が必要でしたが、ジグザグ走行になりがちです。反対側に曲がり始めると、右センサが中央ラインに近づくころに右センサは壁までの距離を読み取ります。

しかし、左センサはトリガーからパルスを発信させても、壁が斜めになってしまい、距離測定不可能の状態(最大値2mを表示)になります。ロボットカーは常に真ん中のラインをまっすぐ進むようにしたいですね。どうすればよいでしょうか。左右車輪のデューティ比を調整することにによってプログラムによらずに、まっすぐ走ります。これは、デューティ比を調整すれば、制御しなくても(プログラムに関係なく)まっすぐ走らせたり、円軌道を走行させることができます。ロボットカーの特性を理解した上で制御プログラムを作ると、より速く、より美しい走行を実現できます。

また、今回使用しているギヤボックスは模型用のものなので、車輪は方向転換の信号やstop信号を送っても惰性で走ってしまいます。この惰性を利用して制御するか、あるいはブレーキをいったんかけてから次の命令を出すか考える必要があります。しかし、while文の中でブレーキをかけると、何度もブレーキがかかるので、動作がぎこちなくなります。

ここまでの経験から、床面の摩擦によってロボットカーがうまく動いたり動かなかったりします。特にスピードを押さえて曲がろうとする場合に顕著です。6Vのモータですが、デューティ比が小さくなれば電圧が小さくなるので、ロボットを動かすのに大きな力を必要とする曲がる動作の場合には注意が必要です。自分のロボットカーの特性を理解し、その特性を利用してコントロールすると迷路も早く正確に抜けられます。挑戦してみましょう。

家でうまく走れたのに講座の中ではうまく走らないということがあります。その理由の多くは床面とタイヤの材質の影響です。特に今回のロボットで使用しているタイヤはとても柔らかいので、床面の起毛上で大きく変形することで力の損失が大きくなり、スピードが出ない場合があります。家で車輪のデューティ比を研究しても、講座では思うように走れず、再度、床面に応じたデューティ比に作り直さなくてはならない場合があります。その理由は次のとおりです。
(1)摩擦力には、駆動に必要な摩擦(静止摩擦)と走行を妨げる摩擦(転がり抵抗・変形損失)があります。
(2)柔らかいタイヤは変形が大きいということ。その変形によってエネルギーが奪われます(ヒステリシスロス)。
(3)摩擦の伝わり方が異なるということ。柔らかいゴムは摩擦が高いので、静止摩擦(滑らない力)はしっかり働き、 絨毯でもフロアでも空転しにくくなりますが、駆動に必要以上の摩擦があると、逆に転がり抵抗が増えてしまいます。
(4)柔らかいタイヤほど床の性質に左右されやすいとうこと。
(5)硬いタイヤだと、絨毯での変形が減り抵抗は少し減るが、表面が滑りやすいと空転しやすく、フロアではさらに転がり抵抗が小さくなり、もっと速く走る可能性がある。
対策としては、タイヤの変更やタイヤの改良などがありますが、ここでは現状のタイヤのみで競技を進め、プラスティック・ダンボール(プラダン)に床面の材質を統一します。