FrontPage

2013/05/12からのアクセス回数 29066

通勤時間を利用してManningのArduino in Actionを読み終わったので、その紹介と日本では入手困難な 部品の代替方法を説明します。

Arduino in Action は分かりやすく書かれたArduinoの教材です。 *1

ここでは、3章と6章の紹介ですが、その他は、以下の記事で紹介しています。

3章 入力と出力

著者のJordan Hochenbaumさんが、Arduinoを使った新しい音楽楽器を作る研究をされているため、 所々に音を使った例が挿入されています。

アナログ入力

Arduinoとブレッドボードはとても相性がよく、ブレッドボード用の部品も多く販売されています。 最初の例題で使うアナログ入力では10KΩの半固定抵抗を使いますが、 スイッチサイエンスからブレッドボードにそのままささる、 つまみの大きい半固定抵抗 10KΩ が販売されているので、1個あると便利です。

10K.png

さっそく図3.3にある回路をブレッドボードに組んでみましょう。

Fig3_3.png

組み上がったブレッドボードは、以下の通りです。 Atmega32U4とArduinoのピン番号の対応は、Arduino/ATmega32UのArduino化を参考にしてください。

Bread3_3.png

スケッチを描いて、動かしてみよう

早速例題のスケッチを入力して、動かしてみます。

// 3.1 Time to get analog
int  sensorPin = A0;
int  sensorValue = 0;

void setup() {
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  } 
}

void loop() {
  if (Serial) {
    sensorValue = analogRead(sensorPin);
    Serial.print("Sensor = ");
    Serial.println(sensorValue, DEC);
    delay(1000);
  }
}

Arduino IDEのツールメニューからシリアルモニターを選択すると入力ピンの電圧が0から1023の間の 値として表示されます。

Out3_3.png

音の出す

音というとアナログ出力をイメージするかも知れませんが、Arduinoでの音の出力はデジタルのPWMを使ったもので、 スピーカをデジタルピンに接続して音を出力します。

3.3章にでてくるピエゾ圧電素子を5枚接続して音を鳴らす例題ですが、ピエゾ圧電素子が1枚250円と高価なので、 代わりに 3x4のマトリックス式ボタンパッド を使用しました。

keypad.png

このパッドは、Arduinoのライブラリー Keypad を使っています。

ダウンロードして展開したKeypadを、ユーザのホームディレクトリ以下のDocuments/Arduino/libraries/に入れます。

音の出力には、tone関数を使用するのですが、Arduino IDE 1.0.1では、Leonardでフリーズして、音がでません。 Leonardで使用する場合には、Arduino IDEを1.0.1よりも新しいものを使って下さい。

マトリックス式ボタンパッドの接続

マトリックス式ボタンパッドからは、7本の線が出ており、コネクターの右から1番から7番と番号付けされています。

これをArduinoのデジタルピンに以下の様に接続します。

  • 1:右端列 - D5
  • 2:中列 - D4
  • 3:左端列 - D3
  • 4:下端行 - D6
  • 5:中下行 - D7
  • 6:中上行 - D8
  • 7:上端行 - D9

スケッチと動作確認

スケッチは、以下の様になります。

#include <Keypad.h>

// Tone
int toneDuration = 40;
int speakerPin = 2;
int index = 0;

const byte rows = 4; //four rows
const byte cols = 3; //three columns
char keys[rows][cols] = {
  {'1','2','3'},
  {'4','5','6'},
  {'7','8','9'},
  {'*','0','#'}
};
byte rowPins[rows] = {6, 7, 8, 9}; //connect to the row pinouts of the keypad
byte colPins[cols] = {3, 4, 5}; //connect to the column pinouts of the keypad
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, rows, cols );
int tones[]={262,294,330,392,440};  // C, D, E, G, A

void setup() {
  Serial.begin(9600);
}
// サンプル曲
// 123 123 4321232 123 123 4321231 4434554 33221
// 咲いた 咲いた チューリップの花が 
// 並んだ 並んだ 赤白黄色 どの花みてもきれいだな
void loop() {
  char key = keypad.getKey();

  if (key != NO_KEY){
    Serial.println(key);
    if (key >= '1' && key <= '5') {
      index = key - '1';
      tone(speakerPin, tones[index], toneDuration);
    }
     
  }
} 

試しに、123 123 4321232と押してみて下さい。懐かしい曲が聞こえてきます。

6章 物体の検出

超音波センサー

6章で最初に紹介されている超音波距離センサーは、Devantech SRF05とParallax Pingです。 秋月でParallax Pingが2500円だったので、Amazonの「サインスマート」でHC-SR04が 279円と信じられない金額(送料は1個に付き300円)だったので、ダメ元で購入してみました。

HC-SR04.png

Arduino in Actionの回路は図6.5のようになっていますが、

Fig6_5.png

図ではSRF05を使っているので、HC-SR04との接続は以下の様にしました。

  • VCC: 5V
  • triger: D8
  • echo: D9
  • GBD: GND

スケッチ

Arduino in Actionとはデバイスが異なるため、 Arduino and HC-SR04 ultrasonic sensor のサイトの情報を使ってスケッチを動かしました。

使ったスケッチは以下の通りです。

/*
 HC-SR04 Ping distance sensor]
 VCC to arduino 5v GND to arduino GND
 Echo to Arduino pin 9 Trig to Arduino pin 8
 More info at: http://goo.gl/kJ8Gl
 */

#define trigPin 8
#define echoPin 9

void setup() {
  Serial.begin (9600);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
}

void loop() {
  int duration, distance;
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(1000);
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH);
  distance = (duration/2) / 29.1;
  if (distance >= 200 || distance <= 0){
    Serial.println("Out of range");
  }
  else {
    Serial.print(distance);
    Serial.println(" cm");
  }
  delay(500);
}

上記サイトの説明では、pingは超音波を発信してそのエコーを受信するまでの時間を計測して距離を計算しているそうです。

例えば、\( \Delta t = 500 \) μ秒だとすると、その半分の 250μ秒が物体まで超音波が届くまでの時間になります。

音の速度cは、以下の式で求まります。 $$ c = 343.5 + 0.6*温度 $$ 気温が20℃だとすると、 c = 331.5 + 0.6 * 20 = 343.5 m/s となります。 単位をcm/μ秒に変換すると、 $$ c = 343.5 * 100/1000000 = 0.0345 cm / \mu s $$ これを使うと\( \Delta t = 500 \)の距離は、D = 250 * 0.03435 = 8.6 cmとなります。

スケッチで使われている29.1という値は、音の伝搬を距離当たりで計算した値(μ秒/cm)です。 $$ 音の伝搬の割合 = 1 / 0.03435 = 29.1 \mu s $$ パルスが戻ってくるまでの時間\(\Delta t \)が変数durationにセットされていますので、距離Dは以下の計算できます。 $$ D = (\Delta t /2 ) / 29.1 $$

動作確認

実際に動作させると40cmくらいの距離でout of rangeとなりました。

Bread6_5.png

赤外線センサー

地方に住んでいるとセンサーや部品を一つ一つ確認しながら購入するのが、大変なので「Arduino拡張キット」を購入しました。この中に含まれているSHARPの2Y0A21 F 29を検索したら、GP2D120とコンパチだということだったので、 赤外線センサーの例を試しみてみました。

データシートでは、電圧と距離の関係が以下のようになっていると出ています。

Sharp-GP2Y0A02.png

回路とブレッドボード

図6.8では、スピーカーを付けていますが、以下のスケッチではアナログ0番のみを使用しています。

ブレッドボードの配線もすごく簡単です。

Bread6_8.png

動作確認

以下のスケッチで、センサーの動作を確認しました。

int IRpin = 0;                                    // analog pin for reading the IR sensor
float ratio = 5.0/1024;

void setup() {
  Serial.begin(9600);                             // start the serial port
}

void loop() {
 
  float volts = analogRead(IRpin);               
  float distance = 65*pow(volts*ratio, -1.10);    // worked out from graph 65 = theretical distance / (1/Volts)S - luckylarry.co.uk
  Serial.println(distance);                       // print the distance
  delay(100);                                     // arbitary wait time.
}

どうも、このセンサーArduino DuemilanoveとATmega32U4では、戻り値が異なり精度にも問題があることが分かりました。

物体進入センサー

6章の最後に登場するのが、物体進入センサー Parallax PIRです。

今回は秋月で扱っている Parallax PIRセンサー RevA を使用しました。*2

残念ながら、Arduino in Actionの例題では上手く動作しなかったので、 ArduinoのPIRsense code のサイトを参考に動作確認しました。

接続は、PIRセンサー:Arduinoで

  • 赤:VCC(5V)
  • 黒:GND
  • 青:D3

PIR.png

テストに使用したスケッチは、以下のとおりです

/*
 * //////////////////////////////////////////////////
 * //making sense of the Parallax PIR sensor's output
 * //////////////////////////////////////////////////
 *
 * Switches a LED according to the state of the sensors output pin.
 * Determines the beginning and end of continuous motion sequences.
 *
 * @author: Kristian Gohlke / krigoo (_) gmail (_) com / http://krx.at
 * @date:   3. September 2006
 *
 * kr1 (cleft) 2006
 * released under a creative commons "Attribution-NonCommercial-ShareAlike 2.0" license
 * http://creativecommons.org/licenses/by-nc-sa/2.0/de/
 *
 *
 * The Parallax PIR Sensor is an easy to use digital infrared motion sensor module.
 * (http://www.parallax.com/detail.asp?product_id=555-28027)
 *
 * The sensor's output pin goes to HIGH if motion is present.
 * However, even if motion is present it goes to LOW from time to time,
 * which might give the impression no motion is present.
 * This program deals with this issue by ignoring LOW-phases shorter than a given time,
 * assuming continuous motion is present during these phases.
 * 
 */

/////////////////////////////
//VARS
//the time we give the sensor to calibrate (10-60 secs according to the datasheet)
int calibrationTime = 30;       

//the time when the sensor outputs a low impulse
long unsigned int lowIn;        

//the amount of milliseconds the sensor has to be low
//before we assume all motion has stopped
long unsigned int pause = 5000; 

boolean lockLow = true;
boolean takeLowTime; 

int pirPin = 3;    //the digital pin connected to the PIR sensor's output
int ledPin = 13;


/////////////////////////////
//SETUP
void setup(){
  Serial.begin(9600);
  pinMode(pirPin, INPUT);
  pinMode(ledPin, OUTPUT);
  digitalWrite(pirPin, LOW);

  //give the sensor some time to calibrate
  Serial.print("calibrating sensor ");
    for(int i = 0; i < calibrationTime; i++){
      Serial.print(".");
      delay(1000);
      }
    Serial.println(" done");
    Serial.println("SENSOR ACTIVE");
    delay(50);
  }

////////////////////////////
//LOOP
void loop(){

     if(digitalRead(pirPin) == HIGH){
       digitalWrite(ledPin, HIGH);   //the led visualizes the sensors output pin state
       if(lockLow){ 
         //makes sure we wait for a transition to LOW before any further output is made:
         lockLow = false;           
         Serial.println("---");
         Serial.print("motion detected at ");
         Serial.print(millis()/1000);
         Serial.println(" sec");
         delay(50);
         }        
         takeLowTime = true;
       }

     if(digitalRead(pirPin) == LOW){      
       digitalWrite(ledPin, LOW);  //the led visualizes the sensors output pin state

       if(takeLowTime){
        lowIn = millis();          //save the time of the transition from high to LOW
        takeLowTime = false;       //make sure this is only done at the start of a LOW phase
        }
       //if the sensor is low for more than the given pause,
       //we assume that no more motion is going to happen
       if(!lockLow && millis() - lowIn > pause){ 
           //makes sure this block of code is only executed again after
           //a new motion sequence has been detected
           lockLow = true;                       
           Serial.print("motion ended at ");      //output
           Serial.print((millis() - pause)/1000);
           Serial.println(" sec");
           delay(50);
           }
       }
  }

動かしてみると、以下の様に人を検出します。

このセンサーは人の動きを検出するため、人がいても動かないとLOWになってしまうため LOWの時間がpause時間(msec)続いたら検出を終了するようになっています。 この辺は、先述のセンサーと異なるところです。

....................... done
SENSOR ACTIVE
---
motion detected at 30 sec
motion ended at 73 sec
---
motion detected at 78 sec
motion ended at 95 sec
---
motion detected at 107 sec

コメント

選択肢 投票
おもしろかった 67  
そうでもない 0  
わかりずらい 20  

皆様のご意見、ご希望をお待ちしております。


(Input image string)


*1 まだMEAPというプレ・リリース版ですが、もうすぐ正式版がでると思います。月に1回程度の半額セールで購入するとお得です
*2 800円と手頃な値段も嬉しいです

添付ファイル: filePIR.png 2120件 [詳細] fileBread6_8.png 2176件 [詳細] fileFig6_8.png 1017件 [詳細] fileSharp-GP2Y0A02.png 2156件 [詳細] fileHC-SR04.png 2176件 [詳細] fileFig6_5.png 2664件 [詳細] fileBread6_5.png 2116件 [詳細] filekeypad.png 2063件 [詳細] fileOut3_3.png 2135件 [詳細] fileBread3_3.png 2037件 [詳細] fileFig3_3.png 1995件 [詳細] file10K.png 2124件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2020-05-06 (水) 12:22:45 (1611d)
SmartDoc