テクノロジー遊び

Arduinoでセンシングしてモーターを動かす

ちょっと作ってみたい。

メインの材料は、

  • Arduino+モータードライブIC
  • モーター
  • 人感センサー
  • cds()

モータードライブ付きArduino

秋月電子でDFRobotのロボット用Arduino(Romeo: An Arduino Robot Control Board)が販売されているのに、使ってみた事例が見当たらないような気がします。
Arduino Uno R3は腐るほど持っているのですが、便利そうなので購入してしまいました。

センサー付きのゴミ箱を作ろうか、と。

なので資料の調査結果を記録しておきたいと思います。

基本的な資料はこちら

バラバラ大事なこと

  • DCジャックには14Vまで
  • 秋月電子で販売されているものは、V1.1でUno相当です。
  • ロボット用なのでBluetoothか、DFRobotの通信モジュールapc220で拡張できるらしいです。ArduinoにTCP/IPを送受するプログラムを乗せるのは重すぎるので興味ありません
  • DCモーター独自のパワーサプライが可能。12Vまで。2つのポートがあり各々2Aまで。
  • サーボ(PWM制御)もモーターとは別にサポートされている。7Vまで。

モーター制御ピン ジャンパー

モーター制御ピン ジャンパーを付加すると、ピン 5、6、7、8 がモーター制御に割り当てられます。
ジャンパーを取り外すと、上記のピンが解放され、モーター コントローラーは無効になります。

サーボ電源制御ピン ジャンパー

ほとんどのサーボは、USB電源が供給できる(0.5A)以上の電流を消費します。サーボに別途、電力を供給するためにサーボ電源端子が用意されています。
このオプションは、サーボ電源選択ジャンパーで有効/無効にできます。
サーボ電源選択ジャンパーが付加されている場合、サーボは内部 5Vから電力供給されます。
サーボ電源選択ジャンパーが適用されていない場合、サーボは外部電源から電力供給されます。

Romeo V1.0 は、電源選択に自動スイッチャーを使用します。外部電源が適用されている場合、サーボは USB 電源ではなく外部電源で自動的に電力供給されます。

制御ボタン

Romeoには5個のボタンがついていて、analogポート7に接続されています。
次のスケッチで動作確認できるらしいですが、今回、私は使ってないのよ。

char msgs[5][15] = {
  "Right Key OK ",
  "Up Key OK    ",
  "Down Key OK  ",
  "Left Key OK  ",
  "Select Key OK" };
char start_msg[15] = {
  "Start loop "};
int  adc_key_val[5] ={
  30, 150, 360, 535, 760 };
int NUM_KEYS = 5;
int adc_key_in;
int key=-1;
int oldkey=-1;
void setup() {
  pinMode(13, OUTPUT);  //we'll use the debug LED to output a heartbeat
  Serial.begin(9600);

  /* Print that we made it here */
  Serial.println(start_msg);
}

void loop()
{
  adc_key_in = analogRead(7);    // read the value from the sensor
  digitalWrite(13, HIGH);
  /* get the key */
  key = get_key(adc_key_in);    // convert into key press
  if (key != oldkey) {   // if keypress is detected
    delay(50);      // wait for debounce time
    adc_key_in = analogRead(7);    // read the value from the sensor
    key = get_key(adc_key_in);    // convert into key press
    if (key != oldkey) {
      oldkey = key;
      if (key >=0){
        Serial.println(adc_key_in, DEC);
        Serial.println(msgs[key]);
      }
    }
  }
  digitalWrite(13, LOW);
}
// Convert ADC value to key number
int get_key(unsigned int input)
{
  int k;
  for (k = 0; k < NUM_KEYS; k++  )
  {
    if (input < adc_key_val[k]) { return k; } } if (k >= NUM_KEYS)
    k = -1;     // No valid key pressed
  return k;
}

モーターコントロール

モーターの接続は普通のブラシモーター(マブチモーターとか)を想定します。
PWM制御は直流電圧をパルス化してスピードコントロール可能です。ですからブラシモーターでもPWMモードを選ぶことが普通ではないかと思います。
PWMモードの場合のピン設定は次のようになるらしいですー。逆にいえば、ピン4,5,6,7は他の用途に使えません。

デジタルピン モーター番号 役割
4 1 回転方向設定
5 1 PWMコントロール
6 2 PWMコントロール
7 2 回転方向設定

サンプルとしてMotor1のみを全力で動かしてみます。

//Standard PWM DC control
int E1 = 5;     //M1 Speed Control
int E2 = 6;     //M2 Speed Control
int M1 = 4;    //M1 Direction Control
int M2 = 7;    //M1 Direction Control

void stop(void) {                   // PWMをLOWにすると停止
   digitalWrite(E1,LOW);
}
void advance(char a){          //Move forward
   analogWrite (E1,a);      //PWM Speed Control
   digitalWrite(M1,HIGH);
}
void back_off (char a){          //Move backword
   analogWrite (E1,a);
   digitalWrite(M1,LOW);
}

void setup(void){
    pinMode(4, OUTPUT);
    pinMode(5, OUTPUT);
    pinMode(6, OUTPUT);
    pinMode(7,OUTPUT);
    Serial.begin(9600);      //Set Baud Rate
    Serial.println("Run keyboard control");
}
void loop(void){
   if(Serial.available()){
    char val = Serial.read();
    if(val != -1){
      switch(val){
        case 'w'://Move Forward
          advance (255);   //move forward in max speed same as  digitalWrite(HIGH)
          break;
       case 's'://Move Backward
          back_off (255);   //move back in max speed same as  digitalWrite(HIGH)
          break;
       case 'x':
          stop();
          break;
      }
    }
   else stop();
  }

簡単です。

回路図

人感センサー

もちろん秋月電子で買えるSB412Aを使います。
電源は3V-12VなのでArduino直結で動きますね。
このセンサーは基板上に51kΩから300kΩまで変えられるボリュームがついております。約10秒~60分のON時間を設定する事ができるということです。
この時間をどう考えるかというと、おそらく動作中に次の検知をしてしまうとめんどくさいので、検知してからやる一連のアクションが終了する、十分な時間を取ればいいでしょう。
人を検知すると出力が3Vに上がるようです。ArduinoのDigital Inputはまさに3V以上をHighと捉えるので、直結でよさそうです。

ループで待つか、割り込みを使うか

ピンの変化のイベントをループの中でチェックしてからやりたいことをやるか、ピンの変化で割り込みを起こして、割り込みがあったことを記すフラグをたてておいて、ループの中でチェックしてからやりたいことをやるか、このふたつで悩んだことはありませんか?

見方を変えるとイベントが起きたら、すぐに記録しておいて、処理は後からやるのか、イベントを自分の都合のいい時に見つけて、処理をやるのか、の違いです。

経験からは明らかに割り込みでフラグを立ててから処理をしたほうがいいです。
なにより、応答性がよくなります。

Arduinoの標準ライブラリーのPCINTが使えるピンは2か3ですが、PinChangeInterruptライブラリーを使うとどのピンでも割り込みを起こすことができます。

というわけで、人感センサーで人を見つけたらモーターを動かすプログラムは以下のとおりとなりました。
人感センサーがピンをアップしている間に処理を終わるべきです。でないと、割り込みがおきたことをキューする必要が出てきてしまいます。

#include <PinChangeInterrupt.h>

#define SensePin 11 // Sensor Pin
#define LEDPin 13 // onboad for check.

//Standard PWM DC control
int E1 = 5; //M1 Speed Control
int E2 = 6; //M2 Speed Control
int M1 = 4; //M1 Direction Control
int M2 = 7; //M1 Direction Control
unsigned long time; // for measurement

void stop(void) { // PWMをLOWにすると停止
  digitalWrite(E1,LOW);
}

void liftUp(void){ //Move forward
  digitalWrite(M1,LOW);
  digitalWrite(E1,HIGH); //PWM Speed Control digitalWrite(M1,HIGH);
}

void moveDown(void){ //Move backword
  digitalWrite(M1,HIGH);
  digitalWrite(E1,HIGH);
}
void sense_TEST(){
  if (digitalRead(SensePin) == HIGH){
    Serial.println("Sensor detect."); time = (millis()-time)/1000;
    time = millis();
    digitalWrite(LEDPin, HIGH);
  } else { // LOW
    time = (millis()-time) / 1000;
    Serial.print(time);
    Serial.println("sec passed");
    digitalWrite(LEDPin, LOW);
  }
}

void setup(void){
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7,OUTPUT);
  pinMode(LEDPin, OUTPUT);

  digitalWrite(LEDPin,LOW);

  attachPCINT(digitalPinToPCINT(SensePin), sense_TEST, CHANGE);

  Serial.begin(9600); //Set Baud Rate
  Serial.println("Start Sensor Robo.");
}

void loop(void){
  if (digitalRead(LEDPin) == HIGH){
    liftUp();
    delay(4000); //300mSec=3Sec
    Serial.println("UP end.");

    stop();
    delay(3000); //Keep open
    Serial.println("Keep end.");

    moveDown();
    delay(4000);
    Serial.println("Dwon end.");
    Serial.println("Sensor work ended.");
  }
  // still hi, consume loop
  while (digitalRead(LEDPin) == HIGH){
    delay(100);
  }
  delay(1000); // wait 1 sec.
}

関連記事

  1. M1 Mac(Monterey)にm5stackのための開発環境を

  2. Arduinoで脈拍を測る

  3. ESP-WROOM-02の勉強(1)

  4. M5StickCなどをさらに研究

  5. Mac OSXでのFTDIの問題

  6. プロトタイプとプロダクションの間にある深ーい谷

  7. Raspberry piで温度、湿度、気圧を測定してGoogle sp…

  8. Arduinoに複数のシリアル通信をさせる