- 追加された行はこの色です。
- 削除された行はこの色です。
[[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(おもしろかった[63],そうでもない[0],わかりずらい[15])
#vote(おもしろかった[67],そうでもない[0],わかりずらい[20])
皆様のご意見、ご希望をお待ちしております。
#comment_kcaptcha