目次
前
次
tutebot実現
tutebot(チュートボット)は、MITのロボット工学を
専攻する学生が実習で作成する自走式ロボット。
tutebotは、壁づたいに移動して部屋のドアから
外にでることを、試行錯誤しながら実現します。
tutebotは、ブレッドボードに実装した回路で動作。
その回路は、以下。
半田付けした基板は、次の写真で示すようになっています。
左の2ピンをマイクロスイッチに、右の2ピンをモータに接続。
用意したメカで、マイクロスイッチを接続すると、以下。
(プラ板にマイクロスイッチをつけてます)
プラスチックケースに基板を入れ、メカの上に取り付け。
(このプラスチックケースは、電子回路専用)
剥き出しの基板では、衝突時に破損することもあります。
電子部品の破損、配線ワイヤー切断等が考えられます。
移動中に、アクシデントが発生しても、ボックス内に
回路があれば、様々な不具合発生を回避できると判断
しています。
マイクロスイッチを使い、障害物に衝突すると後退。
このとき、左右のモータの回転時間に差があるので
前進を再開したときには、衝突の前とは少し異なる
角度で移動。
前進→衝突→後退を何度か繰り返すと、衝突しない
経路を見つけ出します。これが、知的動作に見える
ので、知能を考えるキッカケを与えられます。
tutebotは、アナログ回路でモータの回転を制御すると
ともに、知的動作をRC積分回路で実現。
tutebotを、ライントレーサのメカを使い
エミュレートしてみます。
tutebotでは、モータの回転数を細かく制御できないので
カクカクした動きになります。タイムチャートでみると
以下。
後退は、キャパシタに蓄えた電荷を放電するまで続きます。
放電時間は、左右で異なるので、右あるいは左に曲げながら
後退します。
カクカクした動きは、ラインを探しているように見えるので
考えているようには、思えますが、時間を無駄にしていると
も言えるので、滑らかに動けるようにします。
センサーは6個利用して、床面の状況を表現する
情報量を増やしておきます。
使うセンサーは、以下。
本来は、黒白を判定しますが、物体が近づいていると
白黒は、無関係に何かあるという信号を出力。
このセンサーを、床面ではなく、壁に向かうように
シャーシの前面に配置して対応。
10ピンケーブルに、次のように信号が配置されています。
1 Vcc
2 sensor_7(MSB)
3 sensor_6
4 sensor_5
5 sensor_4
6 sensor_3
7 sensor_2
8 sensor_1
9 sensor_0(LSB)
10 GND
MSBとLSBを、ポートCに接続。
1 Vcc : Vcc
2
3
4
5
6
7
8 sensor_7(MSB) : PORTC.B1
9 sensor_0(LSB) : PORTC.B0
10 GND : GND
モータには、PWM波形を送ればよいので
ポートBにドライバ基板を接続。
ピンアサインは、以下。
1 Vcc : Vcc
2 LED(red) : PORTB.B4
3 LED(green) : PORTB.B3
4 mode_switch
5 start switch : PORTB.B0
6
7 motor_driver : PORTB.B2
8
9 motor_driver : PORTB.B1
10 GND : GND
ドライバ基板は、以下を利用。
ドライバ回路では、PWMの波形を1回路につき1出力と
なっているので、リレーのNC、NOの接続を次のように
変えます。また、後退制御をマイコンで扱えるように
しておきます。
追加したデバイスを半田付けすると、以下。
センサーからの信号で、壁がありと判定したなら
次のシーケンスを動かせばよいでしょう。
- PWM波形出力停止
- reverse controlに論理値の'1'を与える
- PWM波形出力再開
- 時間待ち
- PWM波形出力停止
- reverse controlに論理値の'0'を与える
- PWM波形出力再開
reverse controlには、利用していないポートCの
いずれかのピンに接続すればよいでしょう。
ピンアサインは、以下。
1 Vcc : Vcc
2
3
4
5
6
7 reverse control : PORTC.B2
8 sensor_7(MSB) : PORTC.B1
9 sensor_0(LSB) : PORTC.B0
10 GND : GND
接続ピンを決めたならば、Forthで使うワードを
定義していきます。
ポート初期化
ポートBは、LSBだけ入力で他は出力。
ポートCは、LSBとその上のビットが入力で他は出力。
この設定をひとつのワードで指定。
: init.tutebot ( -- )
$00 PORTB c! $fe DDRB c!
$00 PORTC c! $fc DDRC c!
;
センサー入力
ポートCのLSBとその上のビットが入力になっているので
どちらかに論理値の'1'があれば、フラグに'1'を設定と
しておきます。
: cur.sensor ( -- x)
PINC c@ 3 and 0 = if 0 else 1 then
;
結果を示す論理値は、スタックに入れておきましょう。
前進と後退の指定
ポートCの2ビットが、前進と後退の制御トランジスタに
接続されているので論理値を出力することで対応。
: set.fwd ( -- )
PORTC c@ $04 or PORTC c!
;
: set.rev ( -- )
PORTC c@ $fb and PORTC c!
;
PWM波形生成
ポートBの2、1ビットが、タイマー1のアウトプット
コンペアマッチ出力なので、その使い方を指定。
: init.timer1 ( -- )
$06 DDRB c@ or DDRB c!
19999 ICR1 !
%10100010 TCCR1A c! \ both pin impress low on compare matched
%10 3 lshift %11 or TCCR1B c! \ /64 = 250kHz
;
次にPWM波形のDUTY比を設定するワードを定義。
: set.duty ( x -- )
dup 400 * swap 400 *
OCR1A ! OCR1B !
;
動作シーケンス
後退動作をひとつのシーケンスとして定義。
: do.rev
0 set.duty \ stop
set.rev \ set reverse direction
50 set.duty \ resume
3000 MS \ delay
0 set.duty \ stop
set.fwd \ set forward direction
50 set.duty \ resume
;
動作をポートの入出力、DUTY比設定を含めて
もう一度考えてみます。
- ポート初期化
- DUTY比設定
- PWM波形出力開始
- 前進設定
- センサー値を入力し、判定フラグが1なら後退処理、0なら前進処理
- ステート5に戻る
tutebotの動作としてまとめます。
: run_tutebot
init.tutebot
50 set.duty init.timer1
set.fwd
begin 1 while
cur.sensor 0 = if set.fwd else set.rev then
repeat
;
PWMを利用してのスピード制御が必要ないなら
移動は、次のワードで充分。
: move.rev
set.rev \ set reverse direction
3000 MS \ delay
;
: move.tutebot
init.tutebot
set.fwd
begin 1 while
cur.sensor 0 = if set.fwd else move.rev then
repeat
;
値の入れ替え処理は、配列を使うと扱いやすくなります。
2進数でセンサー入力とモータ制御出力の
相関関係をリストすると、以下。
00(input) : 11(output)
01(input) : 10(output)
10(input) : 01(output)
11(input) : 00(output)
入力を10進数で書き直してみると
次のようになります。
0(input) : 11(output)
1(input) : 10(output)
2(input) : 01(output)
3(input) : 00(output)
モータ制御のピンアサインは、以下。
1 Vcc : Vcc
2 LED(red) : PORTB.B4
3 LED(green) : PORTB.B3
4 mode_switch
5 start switch : PORTB.B0
6
7 motor_driver : PORTB.B2
8
9 motor_driver : PORTB.B1
10 GND : GND
ポートBの2、1ビットに値を出力すれば
モータは回るので、配列には10進数で値を
格納しておいて、それを出力するとよいと
考えます。
配列のインデックスと格納値の10進数
で対応は、以下。
0(index) : 3
1(index) : 2
2(index) : 1
3(index) : 0
配列の値格納は、次のようにすれば充分。
create MOTV 4 allot
3 MOTV 0 + c!
2 MOTV 1 + c!
1 MOTV 2 + c!
0 MOTV 3 + c!
センサーから0から3の値を入力できたとき
モータを動かすワードを定義すればよいはず。
: SND.MOT MOTV + c@ 1 lshift PORTB c@ $06 and or PORTB c! ;
このワードを使って、センサーから
路面情報を取得し、移動を制御する
には、次のようにタイプ。
PINC c@ $03 and SND.MOT
動かすには、ループを構成します。
: MOVE.TUTEBOT
begin
PINB c@ 1 and
while
PINC c@ $03 and SND.MOT
1000 MS
repeat
;
目次
前
次