2012年12月9日日曜日

赤外線リモコンカーを作ってみる



ハード的には、ここでつくったライントレーサーに赤外線受信モジュールを接続しただけ。
ヒートシンクの上部、隙間に挟んでいるのがそれ。
取り外すのが面倒だったので、ライントレース用のセンサーはつけっぱなしです。
モーター用電源は1.5Vx4。
arduino用電源は1.2Vx2 →100均DCDCコンバータで5V。
タミヤ ツインモーターギヤーボックス(ギア比203:1)
モーター、ギアボックス付属FA-130x2。



受信した赤外線コードにしたがって、モータードライバに指示を出します。
モーター制御に関するスケッチはほぼそのまま。

使うのは東芝BAZOOKA用リモコン(NECフォーマット)

赤外線リモコンに関する投稿はこちら
Arduinoで赤外線リモコンを受信、解析してみる
Arduinoで赤外線リモコンを受信、解析してみる(2)

リーダー部を受信したら、pulseInでLED OFFの時間を測り、32ビットを受信します。
LSBファーストで送られてきますが、信号を区別できればいいだけなので、ir_dataの上位から埋めていってます。
後は、送られたコードで条件分岐し、モータードライバに指示。


使用するボタンは
1  2  3
5  6  7
9  10 11 : 進行方向指示
(5,7は戦車で言う超信地旋回、左右のタイヤを逆方向に回し旋回)
ボリュームUP、DOWN : スピード変更


注意:当投稿、下記スケッチのままでは、モーター用に7.5V以上の電源をつないでも、モーターに掛かる電圧は5Vが上限になります。詳しくはこちらの投稿で。


スケッチ:
// 赤外線リモコンカー by cranberry
// http://cranberrytree.blogspot.jp/
//                           2012/12/09

boolean cwccw = true;
byte pin_pwm[2] = {10, 5}; //PWM_output motor0:pin10 motor1:pin5
byte pin_sig[2][2] = {     //CW/CCW signal IN1,IN2
{9,8},                     //motor0:pin9,8
{6,7},                     //motor1:pin6,7
};
byte pin_ir = 2;
unsigned long st, dur;
byte time[33];
unsigned long ir_data;
int timeout = 5000;
unsigned long last_code = 0;
byte pw = 50;
boolean flag_pw = 0;

void setup(){
  Serial.begin(9600);
  for(byte pin = 5; pin < 11; pin++){
    pinMode(pin, OUTPUT);
  }
}

void loop(){
  int i = 0;
  if(digitalRead(pin_ir) == HIGH){
    st = micros();
    while(digitalRead(pin_ir) == HIGH){
      if(micros() - st >= timeout){
        break;
      }
    }
    dur = micros() - st;
    if(dur>=4000 && dur<5000){
      while(dur != 0){
        if(dur < 1000){
          time[i] = 0;
        }
        if(dur >= 1000){
          time[i] = 1;
          bitSet(ir_data, 32-i);
        }
        dur = pulseIn(pin_ir, HIGH, 2000);
        i += 1;
      }
    }
    if(dur>=2000 && dur<2500){     //リピートコードは無視
//      ir_data = last_code;
    }
  }
  if(ir_data != 0){
    switch(ir_data){
      case 0x2FD48B7: //POWER
        last_code = ir_data;
        motor_stop(0,0);
        motor_stop(1,0);
        Serial.println(ir_data,HEX);
        break;
      case 0x2FD807F: //ボタン1
        last_code = ir_data;
        motor_cw(0,1);
        motor(0,pw);
        motor_cw(1,1);
        motor(1,pw / 1.5);
        Serial.println(ir_data,HEX);
        break;
      case 0x2FD40BF: //ボタン2
        last_code = ir_data;
        motor_cw(0,1);
        motor(0,pw);
        motor_cw(1,1);
        motor(1,pw);
        Serial.println(ir_data,HEX);
        break;
      case 0x2FDC03F: //ボタン3
        last_code = ir_data;
        motor_cw(0,1);
        motor(0,pw / 1.5);
        motor_cw(1,1);
        motor(1,pw);
        Serial.println(ir_data,HEX);
        break;
      case 0x2FDA05F: //ボタン5
        last_code = ir_data;
        motor_cw(0,1);
        motor(0,pw);
        motor_cw(1,0);
        motor(0,pw);
        Serial.println(ir_data,HEX);
        break;
      case 0x2FD609F: //ボタン6
        last_code = ir_data;
        motor_stop(0,0);
        motor_stop(1,0);
        Serial.println(ir_data,HEX);
        break;
      case 0x2FDE01F: //ボタン7
        last_code = ir_data;
        motor_cw(0,0);
        motor(0,pw);
        motor_cw(1,1);
        motor(1,pw);
        Serial.println(ir_data,HEX);
        break;
      case 0x2FD906F: //ボタン9
        last_code = ir_data;
        motor_cw(0,0);
        motor(0,pw);
        motor_cw(1,0);
        motor(1,pw / 1.5);
        Serial.println(ir_data,HEX);
        break;
      case 0x2FD50AF: //ボタン10
        last_code = ir_data;
        motor_cw(0,0);
        motor(0,pw);
        motor_cw(1,0);
        motor(1,pw);
        Serial.println(ir_data,HEX);
        break;
      case 0x2FDD02F: //ボタン11
        last_code = ir_data;
        motor_cw(0,0);
        motor(0,pw / 1.5);
        motor_cw(1,0);
        motor(1,pw);
        Serial.println(ir_data,HEX);
        break;
      case 0x2FD58A7: //ボタンVOLUME UP
        flag_pw = 1;
        pw += 10;
        if(pw > 100){
          pw = 100;
        }
        Serial.println(ir_data,HEX);
        delay(100);
        break;
      case 0x2FD7887: //ボタンVOLUME DOWN
        flag_pw = 1;
        pw -= 10;
        if(pw < 10){
          pw = 10;
        }
        Serial.println(ir_data,HEX);
        delay(100);
        break;
      default:
        Serial.print("No case.. ");
        Serial.println(ir_data,HEX);
    }
  }
  if(flag_pw == 0){
    ir_data = 0;
  }
  else{
    ir_data = last_code;
    flag_pw = 0;
  }
}

void motor(byte num, byte pw){
  pw = map(pw, 0, 100, 0, 255);
  analogWrite(pin_pwm[num], pw);
}

void motor_cw(byte num, boolean cw){
  digitalWrite(pin_sig[num][0],LOW);
  digitalWrite(pin_sig[num][1],LOW);
  delay(1);
  if(cw == true){
    digitalWrite(pin_sig[num][0],HIGH);
    digitalWrite(pin_sig[num][1],LOW);
  }
  else{
    digitalWrite(pin_sig[num][0],LOW);
    digitalWrite(pin_sig[num][1],HIGH);
  }
}

void motor_stop(byte num,int dur){
  digitalWrite(pin_sig[num][0],LOW);
  digitalWrite(pin_sig[num][1],LOW);
  if(dur >0){
    delay(dur);
  }
}

void motor_brake(byte num,int dur){
  digitalWrite(pin_sig[num][0],LOW);
  digitalWrite(pin_sig[num][1],LOW);
  delay(1);
  digitalWrite(pin_sig[num][0],HIGH);
  digitalWrite(pin_sig[num][1],HIGH);
  if(dur >0){
    delay(dur);
  }
}


環境:arduinoUNO R3、arduino1.0.2、win7





0 件のコメント:

コメントを投稿