SSブログ

リモートコントロール(RC)戦車をつくる【スケッチ_モータ制御②】 [RC戦車]

前回の記事(リモートコントロール(RC)戦車をつくる【赤外線コントロール②】)で赤外線リモコンのコードが判ったのでスケッチを修正するのですが、もう一つ修正する箇所があります。

これまでは
 >#define SPEED 128 //モータへの電圧(スピード)は一定
として、どの方向に対してもスピードを一定にしていましたが、緩旋回では左右のキャタピラのスピードに差分をつけるため、左右のモータへかける電圧(Vref)を変える必要があります。
ジョイスティックであればアナログ的に電圧を変化させる(スピードを変化させる)ことができるのですが、今回はリモコンボタンのため2種類の電圧を組み合わせての変化とします。
他にも全般的にスケッチを見直して修正しています。

【スケッチ】
/*
  SparkFun Electronics 2013
  Playing with Infrared Remote Control
  
  IR Receiver Breakout (SEN-8554): Supply voltage of 2.5V to 5.5V
    Attach
    OUT: To pin 13 on Arduino
    GND: GND
    VCC: 5V
  
  This is based on Ken Shirriff's code found on GitHub:
  https://github.com/shirriff/Arduino-IRremote/

  This code works with cheap remotes. If you want to look at the individual timing
  of the bits, use this code:
  http://www.arduino.cc/playground/Code/InfraredReceivers
*/

#include <IRremote.h>          // 赤外線送受信用ヘッダファイル

int RECV_PIN = 11;              // 赤外線受信モジュール
IRrecv irrecv(RECV_PIN);        // 赤外線受信用オブジェクトの設定
decode_results results;         // 赤外線受信結果を格納する
#define POWER 0x8F71BE4 
#define A 0x8F71FE0
#define B 0x8F71EE1
#define C 0x8F71AE5
#define UP 0x8F705FA
#define DOWN 0x8F700FF
#define LEFT 0x8F708F7
#define RIGHT 0x8F701FE
#define SELECT 0x8F704FB
#define UP_LEFT 0x8F78D72
#define DOWN_LEFT 0x8F78877
#define UP_RIGHT 0x8F7847B
#define DOWN_RIGHT 0x8F7817E

#define SPEED_0 0               //モータへの電圧(スピード)を3種類用意
#define SPEED_1 77
#define SPEED_2 153             //0~255(MAX):Vref電圧を3Vまでに制限

// set pin numbers:
 // 右キャタピラ用ピン
const int R_Vref = 5;           //D5(PWM)
const int R_OUT1 = 3;           //D3
const int R_OUT2 = 4;           //D4
 // 左キャタピラ用ピン
const int L_Vref = 6;           //D6(PWM)
const int L_OUT1 = 7;           //D7
const int L_OUT2 = 8;           //D8

// 初期化(電源投入/リセット時1回のみ実行):
void setup()
{
  Serial.begin(9600);
  irrecv.enableIRIn(); // Start the receiver

// initialize the motor driver pin as an output(Arduinoにモータドライバへのピンが出力であることを伝える)
  pinMode(R_Vref, OUTPUT);
  pinMode(R_OUT1, OUTPUT);
  pinMode(R_OUT2, OUTPUT);
  pinMode(L_Vref, OUTPUT);
  pinMode(L_OUT1, OUTPUT);
  pinMode(L_OUT2, OUTPUT);
}

// main loop:
void loop() 
{
  if (irrecv.decode(&results))  //(★これが無いと動作しない)
  {
    switch(results.value)
    {
      case UP:                  //UPなら前進
        analogWrite(R_Vref, SPEED_2); // モータドライバのスピードを指定
        analogWrite(L_Vref, SPEED_2);

        digitalWrite(R_OUT1, LOW);    //貫通電流防止(ストップ)
        digitalWrite(R_OUT2, LOW);
        digitalWrite(L_OUT1, LOW);
        digitalWrite(L_OUT2, LOW);

        digitalWrite(R_OUT1, HIGH);
        digitalWrite(R_OUT2, LOW);
        digitalWrite(L_OUT1, HIGH);
        digitalWrite(L_OUT2, LOW);
        break;
      case RIGHT:               //RIGHTなら右超信地旋回
        analogWrite(R_Vref, SPEED_2); // モータドライバのスピードを指定
        analogWrite(L_Vref, SPEED_2);

        digitalWrite(R_OUT1, LOW);    //貫通電流防止(ストップ)
        digitalWrite(R_OUT2, LOW);
        digitalWrite(L_OUT1, LOW);
        digitalWrite(L_OUT2, LOW);

        digitalWrite(R_OUT1, LOW);
        digitalWrite(R_OUT2, HIGH);
        digitalWrite(L_OUT1, HIGH);
        digitalWrite(L_OUT2, LOW);
        break;
      case LEFT:                //LEFTなら左超信地旋回
        analogWrite(R_Vref, SPEED_2); // モータドライバのスピードを指定
        analogWrite(L_Vref, SPEED_2);

        digitalWrite(R_OUT1, LOW);    //貫通電流防止(ストップ)
        digitalWrite(R_OUT2, LOW);
        digitalWrite(L_OUT1, LOW);
        digitalWrite(L_OUT2, LOW);

        digitalWrite(R_OUT1, HIGH);
        digitalWrite(R_OUT2, LOW);
        digitalWrite(L_OUT1, LOW);
        digitalWrite(L_OUT2, HIGH);
        break;
      case DOWN:                //DOWNなら後進
        analogWrite(R_Vref, SPEED_2); // モータドライバのスピードを指定
        analogWrite(L_Vref, SPEED_2);

        digitalWrite(R_OUT1, LOW);    //貫通電流防止(ストップ)
        digitalWrite(R_OUT2, LOW);
        digitalWrite(L_OUT1, LOW);
        digitalWrite(L_OUT2, LOW);

        digitalWrite(R_OUT1, LOW);
        digitalWrite(R_OUT2, HIGH);
        digitalWrite(L_OUT1, LOW);
        digitalWrite(L_OUT2, HIGH);
        break;
      case SELECT:              //SELECTなら停止(ブレーキ→ストップ)
        analogWrite(R_Vref, SPEED_0); // モータドライバのスピードを指定
        analogWrite(L_Vref, SPEED_0);

        digitalWrite(R_OUT1, LOW);    //貫通電流防止(ストップ)
        digitalWrite(R_OUT2, LOW);
        digitalWrite(L_OUT1, LOW);
        digitalWrite(L_OUT2, LOW);

        digitalWrite(R_OUT1, HIGH);   //ブレーキ
        digitalWrite(R_OUT2, HIGH);
        digitalWrite(L_OUT1, HIGH);
        digitalWrite(L_OUT2, HIGH);

        digitalWrite(R_OUT1, LOW);    //ストップ
        digitalWrite(R_OUT2, LOW);
        digitalWrite(L_OUT1, LOW);
        digitalWrite(L_OUT2, LOW);
        break;
      case UP_RIGHT:                  //UP_RIGHTなら右前進緩旋回
        analogWrite(R_Vref, SPEED_1); // 右キャタピラの速度を遅く
        analogWrite(L_Vref, SPEED_2); // 左キャタピラの速度を速く

        digitalWrite(R_OUT1, LOW);    //貫通電流防止(ストップ)
        digitalWrite(R_OUT2, LOW);
        digitalWrite(L_OUT1, LOW);
        digitalWrite(L_OUT2, LOW);

        digitalWrite(R_OUT1, HIGH);
        digitalWrite(R_OUT2, LOW);
        digitalWrite(L_OUT1, HIGH);
        digitalWrite(L_OUT2, LOW);
        break;
      case DOWN_RIGHT:                //DOWN_RIGHTなら右後進緩旋回
        analogWrite(R_Vref, SPEED_1); // 右キャタピラの速度を遅く
        analogWrite(L_Vref, SPEED_2); // 左キャタピラの速度を速く

        digitalWrite(R_OUT1, LOW);    //貫通電流防止(ストップ)
        digitalWrite(R_OUT2, LOW);
        digitalWrite(L_OUT1, LOW);
        digitalWrite(L_OUT2, LOW);

        digitalWrite(R_OUT1, LOW);
        digitalWrite(R_OUT2, HIGH);
        digitalWrite(L_OUT1, LOW);
        digitalWrite(L_OUT2, HIGH);
        break;
      case UP_LEFT:                  //UP-LEFTなら左前進緩旋回
        analogWrite(R_Vref, SPEED_2); // 右キャタピラの速度を速く
        analogWrite(L_Vref, SPEED_1); // 左キャタピラの速度を遅く

        digitalWrite(R_OUT1, LOW);    //貫通電流防止(ストップ)
        digitalWrite(R_OUT2, LOW);
        digitalWrite(L_OUT1, LOW);
        digitalWrite(L_OUT2, LOW);

        digitalWrite(R_OUT1, HIGH);
        digitalWrite(R_OUT2, LOW);
        digitalWrite(L_OUT1, HIGH);
        digitalWrite(L_OUT2, LOW);
        break;
      case DOWN_LEFT:                //DOWN-LEFTなら左後進緩旋回
        analogWrite(R_Vref, SPEED_2); // 右キャタピラの速度を速く
        analogWrite(L_Vref, SPEED_1); // 左キャタピラの速度を遅く

        digitalWrite(R_OUT1, LOW);    //貫通電流防止(ストップ)
        digitalWrite(R_OUT2, LOW);
        digitalWrite(L_OUT1, LOW);
        digitalWrite(L_OUT2, LOW);
        
        digitalWrite(R_OUT1, LOW);
        digitalWrite(R_OUT2, HIGH);
        digitalWrite(L_OUT1, LOW);
        digitalWrite(L_OUT2, HIGH);
        break;
      default:
        break;
    }
      irrecv.resume();          // 受信機をリセットする(★これが無いと1回のみの制御となる)
  }
}

※#include <IRremote.h>は表示の不具合で全角<>で記載しています。本当は半角<>ですのでご注意ください。

【動作確認】
早速、動かしてみます。
右/左と緩旋回もできています。動作の変化時のwaitも外したので、前回よりスムーズに動作してラジコンらしい動きになりました。直進でやや左に寄ってしまうのはおそらく車軸がずれているか?、それともVref電圧に少々の電圧差があるのかもしれません。真っ直ぐ走らせるためにはこのズレを補正する形でVref電圧を調整すればよいのですが、今回はやりません。(動けばOK!だったので。。。)



profile_picture_40×40.JPG
(2020.06.14 スケッチ修正)
#define SPEED_2 153 //0~255(MAX):Vref電圧を3Vまでに制限
SPEED_2が196だとVrefにかかる電圧が3.8Vとなり、モータへの電圧が高過ぎるはずなので、Vrefにかかる電圧を3Vにするために、MAXを255*(3[V]/5[V]) = 153
に修正する。
nice!(0)  コメント(0) 

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。