[[FrontPage]]

#contents

2013/05/12からのアクセス回数 &counter;

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

[[Arduino in Action>http://www.manning.com/mevans/]]
は分かりやすく書かれたArduinoの教材です。
((まだMEAPというプレ・リリース版ですが、もうすぐ正式版がでると思います。月に1回程度の半額セールで購入するとお得です))

ここでは、3章と6章の紹介ですが、その他は、以下の記事で紹介しています。
-- &new(Arduino/ArduinoInAction.Chap5); モータ制御
-- &new(Arduino/ArduinoInAction.Chap7); LCDを使う
-- &new(Arduino/ArduinoInAction.Chap8); イーサネット接続


** 3章 入力と出力 [#rd5433f6]
著者のJordan Hochenbaumさんが、Arduinoを使った新しい音楽楽器を作る研究をされているため、
所々に音を使った例が挿入されています。

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

&ref(10K.png);

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

&ref(Fig3_3.png);

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

&ref(Bread3_3.png);


*** スケッチを描いて、動かしてみよう [#e4fdbaec]
早速例題のスケッチを入力して、動かしてみます。

#pre{{
// 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の間の
値として表示されます。

&ref(Out3_3.png);

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

3.3章にでてくるピエゾ圧電素子を5枚接続して音を鳴らす例題ですが、ピエゾ圧電素子が1枚250円と高価なので、
代わりに
[[3x4のマトリックス式ボタンパッド>http://www.switch-science.com/products/detail.php?product_id=1298]]
を使用しました。

&ref(keypad.png);

このパッドは、Arduinoのライブラリー
[[Keypad>http://playground.arduino.cc/Code/Keypad]]
を使っています。

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

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

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

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

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

*** スケッチと動作確認 [#cde8b0b2]
スケッチは、以下の様になります。

#pre{{
#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章 物体の検出 [#jb37484f]
** 超音波センサー [#r7884511]

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

&ref(HC-SR04.png);

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

&ref(Fig6_5.png);

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

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

*** スケッチ [#w93cc85c]
Arduino in Actionとはデバイスが異なるため、
[[Arduino and HC-SR04 ultrasonic sensor>http://trollmaker.com/article3/arduino-and-hc-sr04-ultrasonic-sensor]] 
のサイトの情報を使ってスケッチを動かしました。

使ったスケッチは以下の通りです。
#pre{{
/*
 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
$$

*** 動作確認 [#f8be4bcb]
実際に動作させると40cmくらいの距離でout of rangeとなりました。

&ref(Bread6_5.png);

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

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

&ref(Sharp-GP2Y0A02.png);

*** 回路とブレッドボード [#v85ea4da]
図6.8では、スピーカーを付けていますが、以下のスケッチではアナログ0番のみを使用しています。

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

&ref(Bread6_8.png);

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

#pre{{
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では、戻り値が異なり精度にも問題があることが分かりました。

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

今回は秋月で扱っている
[[Parallax PIRセンサー RevA>http://akizukidenshi.com/catalog/g/gM-05426/]]
を使用しました。((800円と手頃な値段も嬉しいです))

残念ながら、Arduino in Actionの例題では上手く動作しなかったので、
[[ArduinoのPIRsense code>http://playground.arduino.cc/Code/PIRsense ]]
のサイトを参考に動作確認しました。

接続は、PIRセンサー:Arduinoで
- 赤:VCC(5V)
- 黒:GND
- 青:D3

&ref(PIR.png);

テストに使用したスケッチは、以下のとおりです
#pre{{
/*
 * //////////////////////////////////////////////////
 * //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)続いたら検出を終了するようになっています。
この辺は、先述のセンサーと異なるところです。

#pre{{
....................... 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
}}


** コメント [#jbdb3dbf]
#vote(おもしろかった[40],そうでもない[0],わかりずらい[11])
#vote(おもしろかった[67],そうでもない[0],わかりずらい[20])

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


トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
SmartDoc