Arduinoで光に反応するロボットを作成

電子工作を始めて数ヶ月になりますが、これまではセンサを用いた実務的なものばかりを作ってきました。
この手のものばかりを作っていてもつまらないので、たまにはおもちゃを作ってみようと思い立ちました。

何かに反応して動くようなものを作りたいと思い、素材を探していると、これが見つかりました。
子供が数年前に買って、組み立て途中で放ったらかしになっていた「タミヤ 楽しい工作シリーズ組み立てキット リモコンロボット(クローラータイプ)」です。
これにArduinoを搭載し、スケッチに従って動く「ロボット」を作りたいと思います。


前後左右に動くだけで良いので、上のアーム部分とリモコンボックスは撤去し、各部のネジを締め直しました。
モーター2個で、前後左右の動きをコントロールできる状態になりました。

次に、Arduinoと、モータドライバIC(TA7291P) 2個を追加しました。ロボットが前後に動くだけのスケッチを作成し、正常に動くことを確認しました。
その後、四角を描くように動いたり、丸を描くように動いたりするようにスケッチを改良し、いずれも正常動作しました。見ていた子供は大喜びでした(やっぱり動くものは、子供の食いつきが違います)。

ロボットがArduinoで制御できるようになったので、次に、ロボットの全面左右に光センサを取り付けました。ロボットが左右の明るさの差を認識して、懐中電灯のある方向を向くようにしました。思ったより簡単に正常動作させることができました。
さらに、子供の提案を活かして、ロボットの後面にも光センサを追加しました。後ろから光をあてた時に、ロボットが反転するようにします。
あわせて、モータードライバICのVREF端子に、Arduino出力信号を繋ぐように変更しました。左右の明るさの差が大きい時には速く、差が小さい時にはゆっくり動くようにスケッチを改良しました。

できあがりです。

最終的な回路図は以下のとおりです。

また、スケッチは以下のとおりです。

int L1 = 5;
int L2 = 6;
int R1 = 3;
int R2 = 4;
int VREF = 9;
int MaxSpeed = 200;
int MinSpwwd = 120;

void setup() {
  Serial.begin(9600);
  pinMode( A0, INPUT );
  pinMode( A1, INPUT );
  pinMode( A2, INPUT );
  pinMode( L1, OUTPUT );
  pinMode( L2, OUTPUT );
  pinMode( R1, OUTPUT );
  pinMode( R2, OUTPUT );
  pinMode( VREF, OUTPUT );
}

void loop() {
  int Beye = analogRead(A0);
  int Leye = analogRead(A1);
  int Reye = analogRead(A2);
  Serial.print(" L:");
  Serial.print(Leye);
  Serial.print(" R:");
  Serial.print(Reye);
  Serial.print(" B:");
  Serial.print(Beye);
  Serial.println();

  if(Beye-Leye>50 && Beye-Reye>50){
    if(Leye>Reye){
      analogWrite( VREF, MaxSpeed );
      digitalWrite( L1, LOW );
      digitalWrite( L2, HIGH );
      digitalWrite( R1, HIGH );
      digitalWrite( R2, LOW );
      delay( 3000 );
    }
    else{
      analogWrite( VREF, MaxSpeed );
      digitalWrite( L1, HIGH );
      digitalWrite( L2, LOW );
      digitalWrite( R1, LOW );
      digitalWrite( R2, HIGH );
      delay( 3000 );
    }
  }
  else if(Leye-Reye>50){
    int Speed = Leye-Reye+100;
    if(Speed>MaxSpeed){
      Speed=MaxSpeed;
    }
    analogWrite( VREF, Speed );
    digitalWrite( L1, LOW );
    digitalWrite( L2, HIGH );
    digitalWrite( R1, HIGH );
    digitalWrite( R2, LOW );
    delay( 50 );
  }
  else if(Reye-Leye>50){
    int Speed = Reye-Leye+100;
    if(Speed>MaxSpeed){
      Speed=MaxSpeed;
    }
    analogWrite( VREF, Speed );
    digitalWrite( L1, HIGH );
    digitalWrite( L2, LOW );
    digitalWrite( R1, LOW );
    digitalWrite( R2, HIGH );
    delay( 50 );
  }
  else{
    digitalWrite( L1, HIGH );
    digitalWrite( L2, HIGH );
    digitalWrite( R1, HIGH );
    digitalWrite( R2, HIGH );
    delay( 50 );
  }
}

動きはガタガタしていて、スケッチの各数値をチューニングする必要はありますが、とりあえず当初考えていた動作は実現できました。