スピードコントローラとステアリングサーボの制御

スピードコントローラやステアリングサーボはON/OFFの信号の比率によってによって制御される。
Arduinoで簡単に制御するためには、Servoというライブラリを用いる。
使用することに対する定義例は下記となる。

#include <Servo.h> // Built-in Servo library
Servo servo[2]; // create servo object for speed controller and steering servo

その後Setup()内でピンの指定を行う。
servo[0].attach(9); // Pin 9 is for Stering Servo
servo[1].attach(10); // Pin 10 is for Speed Controller

Arduino UNOではPWMで使用できるピンが決まっているので、そのピンの番号を記載する必要がある。
この例ではスピードコントローラには10ピン、ステアリングサーボには9ピンを割り付けた。

ピンに出力を出すのは
servo[1].write(Motor_Val)
という記載を行う。 ここではMotor_Valという変数にスピードに相当する値を入れる。

実際に入れる数値は、スピードコントローラによって微妙に差がある。
なので実機に合わせてテストするとよい。

この場合、シリアルモニタで数値を上下しながらテストできるように、前出のデバック手法を用いる。 (スケッチの公開は順次。。。)

デバッグ方法について

Arduinoを使って何かを制御するときには、制御対象を見ながらプログラムを調整する必要が出てくる。 そこで使うのはシリアルモニタである。シリアルモニタにプログラムの変数を表示しながら調整するのだが、プログラムの変数の値も変更する必要が出てくる。

ここでは、シリアルモニタを利用して変数値を変更する手段の一例を示す。
最低限GPSロボットカーを動かすためには、スピードコントローラへの指示値やステアリングサーボへの指示値の実験に使う想定している。

void setup() {
   // set serial port speed (bps)
   Serial.begin(115200);

   // put your setup code here, to run once:
   pinMode(LED_BUILTIN, OUTPUT); // LED_BUILTINはArduinoにおける定数

}

void loop() {
   static int DelayTime= 500; // Default delay time (ms)
   int InValue; // シリアル通信で読み込んだ1文字のアスキーコードが入る。
   InValue = Serial.read(); // シリアル通信から読み込み

   if(InValue == 49 && DelayTime <= 900 ){ 
      DelayTime += 100;
   }
   if(InValue == 50 && DelayTime >= 100 ){
      DelayTime -= 100;
   }
   /*
   数字の1を入力するとアスキーコードの49が入る。
   数字の2を入力するとアスキーコードの50が入る。
   (900と100はdelay timeの上下限チェックである。)
   */

   Serial.print("InValue="); // Display data
   Serial.print(InValue);
   Serial.print(" DelayTime=");
   Serial.println(DelayTime);

   digitalWrite(LED_BUILTIN, HIGH); // LED control
   delay(DelayTime);
   digitalWrite(LED_BUILTIN, LOW);
   delay(DelayTime);
}

 

スピードコントローラの役割

スピードコントローラ(ESC: Electronic Speed Control)の主な役割は受信機から来た信号に合わせてバッテリの電気をモータに送ることである。

モーターの回転数を調整するためには電圧の上下をするわけではなく、パルスのONとOFFの比率を使って速度を制御している。ONの時間が長ければ速度は速くなり、OFFの時間が長ければ速度は遅くなる。このONとOFFの比率は受信機からくる信号にあわせて制御される。(この信号も同様にパルスである。)

スピードコントローラを見てみると、太い線が4本、赤黒がついになったケーブルが2セットと黒赤白のセットになったケーブルが1本出ている。それぞれの接続先は以下の通りである。
・太い赤栗:バッテリ
・太い黄青:モータ
・赤白:電源スイッチ
・赤白:受信機(受信機を動作させるための電源線)
・黒赤白:受信機からの制御線

このスピードコントローラは注意が必要である。大体以下を気にしていればよいかと思われるが、データシート(取扱説明書)は購入前に読めるようになっているケースが多いので確認しておくことが大事である。
・受信機との組み合わせ
コネクタが刺さる形状であってもピンの内容が違うこともある。
・スピードコントローラとモータの組み合わせ
これを間違えてしまうとモータやスピードコントローラを焼損してしまう可能性がある。 (そもそも動作しない時もある)
・スピードコントローラの設定
購入後の話だが、スピードコントローラ自体には設定が必要である。(結構マニアックな設定方法だが、、)

電気関係部品の構成

ラジコンカーに用いる電気部品はそんなに多くはない。

これは、ラジコンカーをキットで買ったときに標準的についていた部品をつけた状態である。 これはモータがついているキットだったために、付属していないサーボ、スピードコントローラ、受信機などは別途準備する必要がある。
モータとスピードコントローラ、受信機と送信機は組み合わせがあるので注意して選定する必要がある。

ロボットカーを作成する上では、受信機の代わりを何かしらの制御システムが担うことになる。ラジコンとして用いないのであれば、送受信機を準備する必要はない。 もちろん、フライトコントローラでラジコンでも制御したいときには必要である。

 

車体の話

GPS・QZSSロボットカーを作るうえで、車体の選択がある。
大きく分けると自作か市販品の流用に分かれるが、経験がないのであれば、市販品を流用するケースが多い。
ここでは、ラジオコントロール カーを用いた事例を紹介する。

ここで紹介するのは2010年位に購入したマシンである。
実際に大会に出賞させたマシンではないのだが、ここでは写真モデルに活躍してもらう。

大会は芝生の上で開催されるので、多少の走破性が求められる。
2WD:後輪駆動、4WD:全輪駆動があるが、これまで出場させてもらった限りでは、2WD/4WDどちらでも大きな問題ななさそうである。もちろん4WDのほうが走破性は高いのだが、その分価格も高く、構造が少し複雑になる。

半完成品も売っているが、構造や仕組みを覚えるためにもキットを薦めたい。

押しボタンスイッチ(2)

デジタル入力には大きく分けて二種類ある。
一つはON/OFFの状態を見るためのステータス入力。
もう一つは状態のONになった瞬間やOFFになった瞬間を見るためのエッジ入力である。
(入力の名称はここで勝手につけている。)

スタートスイッチなどは、操作者の手で押す可能性があり、
確実にスイッチを押すために、長めに押す場合がある。
通常の入力でロジックを作成してしまうと、
ロジックが2回スタートを検知してしまう場合がある。
もちろん、連続して2回検知しても問題のないロジックであれば問題ない。
問題のあるケースの一例として、スタートボタンが押されたときに、
自動的に過去情報を修正してキャリブレーションしているようなケースだと、
2回スタートボタンが押されると過去情報がなくなってしまったりする。
(ちょっと‏事例を作るために強引な説明だが (-_-;))

今回のスイッチは、OFFの状態で1となり、ONになったときに0となる。
ロジック上は1→0になったときに1周期だけONにするファンクションが望ましい。

ロジックはそんなに難しくなく、前回が1で今回が0となる関数 F_TRIGを
作成すればよい。(falling-edge trigger)

F_TRIGの中で変数にstaticで宣言しているが、
これは呼ばれる毎に変数がクリアされないようにしている。
ただ、このロジックには欠点があり、複数個所から呼ばれると正しく動作しない。
この辺りは、いくつか解決策があるので、工夫してみてほしい。

—-スケッチの例

const int START_SW_PIN_NO = 4;

void setup() {

   //***** set serial port speed (bps)
   Serial.begin(115200);

   //***** set pin mode
   pinMode(START_SW_PIN_NO, INPUT_PULLUP); // Enable pullup for input mode.
}

void loop() {
   int start_sw, trig;
   start_sw=digitalRead(START_SW_PIN_NO);
   trig=F_TRIG(start_sw);
   Serial.print("Start Switch =");
   Serial.print(start_sw);
   Serial.print(" Trigger=");
   Serial.println(trig);
   delay(200);
}

int F_TRIG(int X){
   int Q;
   static int lastX;
   if(X==0 && lastX==1){
      Q=1;
   }else{
      Q=0;
   }
   lastX=X;
   return Q;
}

 

押しボタンスイッチ(1)

ロボットカーで必須となる素材の一つは押しボタンである。
Arduinoではピンのモードを指定して用いるが、
多くの資料ではデジタル入力としてINPUTというモードを使用している。
しかし、目的がスイッチの入力を見るだけのケースが多いので、
その場合は、INPUT_PULLUPのモードで省配線できる場合がある。

 

この事例の場合は、以下の挙動となる。
スイッチ オフの場合:start_sw=1
スイッチ オンの場合:start_sw=0
—-スケッチの例

const int START_SW_PIN_NO = 4;

void setup() {
   //***** set serial port speed (bps)
   Serial.begin(115200);

   //***** set pin mode
   pinMode(START_SW_PIN_NO, INPUT_PULLUP); // Enable pullup for input mode.
}

void loop() {
   int start_sw;
   start_sw=digitalRead(START_SW_PIN_NO);
   Serial.print("Start Switch =");
   Serial.println(start_sw);
}

 

開発環境とLED点滅

開発環境例
・Windows 10 Home
・Arduino UNO
・Arduino IDE 1.8.1

Arduinoの基本的な使い方はたくさん紹介があるので、ここでは省略。

以下は、ボード上のLEDをチカチカさせる例

/// スケッチの例 LED
 void setup() {
   // put your setup code here, to run once:
   pinMode(LED_BUILTIN, OUTPUT);
   // LED_BUILTINはArduinoにおける定数
 }

void loop() {
   // put your main code here, to run repeatedly:
   digitalWrite(LED_BUILTIN, HIGH);
   delay(1000); // delay 1000 ms
   digitalWrite(LED_BUILTIN, LOW);
   delay(1000);
 }