目次
前
次
ライントレーサスケッチ
ライントレーサは、床面に引いたラインに追従して
移動するロボットです。
写真は、無限軌道を利用したライントレーサです。
能開大のG棟の教室にあるコースは、以下。
Arduinoを利用して、次のメカをライントレーサに
仕立てます。
メカにはハイスピードギアが接続されていますが
ドライブ回路とセンサーを載せなければ、ロボット
になりません。
ドライブ回路は、次のものを利用します。
回路は、モータを回転させるためのPWM波形を
入力し絶縁して伝達するフォトカプラとMOSFET
で構成します。また、ラインセンサーのモニタ
用LEDをつけてあります。
回路図は、以下。
センサーは、密着タイプを利用します。
回路図は、以下。
ライントレーサを動かす前に、次のテストをして
回路が正しく動くことを確認しておきます。
- モータドライバにPWM波形を与えて、モータが回転
- スタートトリガースイッチの状態表示
- 方向指定スイッチの状態表示
- 密着タイプセンサーの出力値確認
各項目ごとにスケッチを作成して
テストしていきます。
ただし、テスト数は少ない方がよいので
スタートトリガースイッチとモータドライバの
テストは、合体させます。
また、方向設定スイッチとセンサーの出力値の
確認も合体させます。
モータ回転テストスケッチ
モータを回転させるには、PWM波形をMOSFETに
与えればよいので、analogWriteを使います。
モータ回転テストの仕様を決めます。
スイッチを押している間、モータを回転させる。
モータの回転は、DUTY比を50%とする。
プッシュスイッチになっているのは、回路図から
スタートトリガーです。また、負論理であること
に注意します。
ピンアサインを決めます。
- プッシュスイッチ入力 ENABLE 9
- 右モータパルス出力 MOTOR_R 10
- 左モータパルス出力 MOTOR_L 11
50%のDUTY比は、analogWriteが0〜255の値を
とるので、128とします。
スイッチには、チャタリングがあるので
1秒ごとに状態を入力し、PWM波を出力
するか否かを指定します。
テストなので、単純に仕様を決め、スケッチは
次のように定義しました。
#define INTERV 1000
#define PWMV 128
// define data types
typedef unsigned char UBYTE ;
typedef unsigned short UWORD ;
// pin assign
#define ENABLE 9
#define MOTOR_R 10
#define MOTOR_L 11
// variables
UBYTE flag ;
UWORD xinterval ;
void setup() {
// enable pin
pinMode(ENABLE,INPUT);
// PWM pin
pinMode(MOTOR_R,OUTPUT);
pinMode(MOTOR_L,OUTPUT);
// set interval
xinterval = INTERV ;
}
// the loop() method runs over and over again,
// as long as the Arduino has power
void loop()
{
// get switch state
flag = digitalRead(ENABLE);
// judge
if ( flag == LOW ) {
analogWrite(MOTOR_R,PWMV);
analogWrite(MOTOR_L,PWMV);
} else {
analogWrite(MOTOR_R,0);
analogWrite(MOTOR_L,0);
}
// delay
delay(xinterval);
}
密着タイプセンサーテストスケッチ
密着タイプセンサーの出力は、8ビットありますが
ArduinoのポートB、C、Dのピンは6ビットだけです。
両端のセンサー出力とは接続しないことにします。
センサー出力は、時々刻々変化するとして
1秒周期で読み取ることにします。
センサー出力値は、ArduinoIDEに端末エミュレータが
あるので、シリアルでPersonalComputerに転送します。
方向設定スイッチの状態も知りたいので、こちらも
シリアルで転送します。
シリアルでPersonalComputerに、ASCIIコードを転送
するときは、Serial.printかSerial.printlnを利用
します。
センサー出力値は6ビットなので、1ビットごとに
数値から数字に変換して対応します。
次のように1ビットごとに取出し、変換します。
*(msg+0) = '0' ;
if ( sensor & 0x20 ) { *(msg+0) = '1' ; }
デフォルト値を入力しておき、その値と異なる
場合だけ、変更します。
センサー値とスイッチの状態には、スペースを
入れて見やすくしておきます。
おおよその仕様が確定したので、スケッチを作成します。
#define INTERV 1000
// define data types
typedef unsigned char UBYTE ;
typedef unsigned int UWORD ;
// pin assign
#define DIRSW 2
// variables
UBYTE flag ;
UBYTE sensor ;
UWORD xinterval ;
UBYTE msg[7] ;
void setup() {
// enable pin
pinMode(DIRSW,INPUT);
// PORT_C inputs
DDRC = 0x00 ;
//
Serial.begin(9600);
// set interval
xinterval = INTERV ;
// set initial values
*(msg+0) = '0' ; *(msg+1) = '0' ;
*(msg+2) = '0' ; *(msg+3) = '0' ;
*(msg+4) = '0' ; *(msg+5) = '0' ;
*(msg+6) = '\0' ;
}
// the loop() method runs over and over again,
// as long as the Arduino has power
void loop()
{
UBYTE i ;
// default
for ( i = 0 ; i < 6 ; i++ ) {
*(msg+i) = '0' ;
}
// get sensor state
sensor = PINC ;
// separate
if ( sensor & 0x20 ) { *(msg+0) = '1' ; }
if ( sensor & 0x10 ) { *(msg+1) = '1' ; }
if ( sensor & 0x08 ) { *(msg+2) = '1' ; }
if ( sensor & 0x04 ) { *(msg+3) = '1' ; }
if ( sensor & 0x02 ) { *(msg+4) = '1' ; }
if ( sensor & 0x01 ) { *(msg+5) = '1' ; }
// get switch state
flag = digitalRead(DIRSW);
flag += '0' ;
// show
for ( i = 0 ; i < 6 ; i++ ) {
Serial.print(*(msg+i));
}
Serial.print(" ");
Serial.println(flag);
// delay
delay(xinterval);
}
動作シーケンス処理
各ブロックのテストが終わったなら、動作
シーケンスを考えます。
一般に、次のようなシーケンスを利用します。
- スタートトリガー待ち
- センサーから情報入力
- センサー情報からモータ回転数計算
- モータ回転数設定
- ディレイ
- スタートトリガーをチェックし、2にもどるか7に進む
- モータ回転数をゼロに設定
- モータ回転数設定
- 1に戻る
loop関数の中に、シーケンスを記述します。
状態変数stateを用意して、ステートマシンを
構成します。
#define OFF 0
#define ON OFF+1
#define RIGHT 0
#define LEFT RIGHT+1
UBYTE state ;
UBYTE sensor ;
UBYTE rmotor ;
UBYTE lmotor ;
switch (state) {
// wait start trigger
case 0 : state = 0 ;
if ( strg == ON ) {
strg = OFF ;
state = 1 ;
}
break ;
// get sensor state
case 1 : sensor = PINC ;
state = 2 ;
break ;
// calcualte both motor PWM
case 2 : rmotor = calculate(RIGHT,sensor) ;
lmotor = calculate(LEFT ,sensor) ;
state = 3 ;
break ;
// set motor PWM duty
case 3 : analogWrite(MOTOR_R,rmotor);
analogWrite(MOTOR_L,lmotor);
state = 4 ;
break ;
// delay
case 4 : delay(xinterval);
state = 5 ;
break ;
// judge
case 5 : state = 1 ;
if ( strg == ON ) {
strg = OFF ;
state = 6 ;
}
break ;
// clear motor PWM
case 6 : rmotor = 0 ;
lmotor = 0 ;
state = 7 ;
break ;
// stop both motor
case 7 : analogWrite(MOTOR_R,rmotor);
analogWrite(MOTOR_L,lmotor);
state = 0 ;
break ;
// others
default : state = 0 ;
break ;
}
ステートマシンが出来ればセンサー値で
モータの回転数に、いくらにするのかを
計算する関数calculateを定義します。
センサー値から、モータの回転数を求めるには
テーブルルックアップで対応します。
センサー値は6ビットで入力されるので
左右それぞれに対応する値は、最大64に
なります。
64サイズの8ビット配列を2つ用意するか
センサー値から、右モータの回転数だけを
64サイズの8ビット配列に入れて、左モータ
の回転数は、右モータの回転数を若干補正
した値にします。
(under construction)
目次
前
次