2013/05/12からのアクセス回数 29066 通勤時間を利用してManningのArduino in Actionを読み終わったので、その紹介と日本では入手困難な 部品の代替方法を説明します。 Arduino in Action は分かりやすく書かれたArduinoの教材です。 *1 ここでは、3章と6章の紹介ですが、その他は、以下の記事で紹介しています。
3章 入力と出力 †著者のJordan Hochenbaumさんが、Arduinoを使った新しい音楽楽器を作る研究をされているため、 所々に音を使った例が挿入されています。 アナログ入力 †Arduinoとブレッドボードはとても相性がよく、ブレッドボード用の部品も多く販売されています。 最初の例題で使うアナログ入力では10KΩの半固定抵抗を使いますが、 スイッチサイエンスからブレッドボードにそのままささる、 つまみの大きい半固定抵抗 10KΩ が販売されているので、1個あると便利です。 さっそく図3.3にある回路をブレッドボードに組んでみましょう。 組み上がったブレッドボードは、以下の通りです。 Atmega32U4とArduinoのピン番号の対応は、Arduino/ATmega32UのArduino化を参考にしてください。 スケッチを描いて、動かしてみよう †早速例題のスケッチを入力して、動かしてみます。 // 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の間の 値として表示されます。 音の出す †音というとアナログ出力をイメージするかも知れませんが、Arduinoでの音の出力はデジタルのPWMを使ったもので、 スピーカをデジタルピンに接続して音を出力します。 3.3章にでてくるピエゾ圧電素子を5枚接続して音を鳴らす例題ですが、ピエゾ圧電素子が1枚250円と高価なので、 代わりに 3x4のマトリックス式ボタンパッド を使用しました。 このパッドは、Arduinoのライブラリー Keypad を使っています。 ダウンロードして展開したKeypadを、ユーザのホームディレクトリ以下のDocuments/Arduino/libraries/に入れます。 音の出力には、tone関数を使用するのですが、Arduino IDE 1.0.1では、Leonardでフリーズして、音がでません。 Leonardで使用する場合には、Arduino IDEを1.0.1よりも新しいものを使って下さい。 マトリックス式ボタンパッドの接続 †マトリックス式ボタンパッドからは、7本の線が出ており、コネクターの右から1番から7番と番号付けされています。 これをArduinoのデジタルピンに以下の様に接続します。
スケッチと動作確認 †スケッチは、以下の様になります。 #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円)だったので、ダメ元で購入してみました。 Arduino in Actionの回路は図6.5のようになっていますが、 図ではSRF05を使っているので、HC-SR04との接続は以下の様にしました。
スケッチ †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となりました。 赤外線センサー †地方に住んでいるとセンサーや部品を一つ一つ確認しながら購入するのが、大変なので「Arduino拡張キット」を購入しました。この中に含まれているSHARPの2Y0A21 F 29を検索したら、GP2D120とコンパチだということだったので、 赤外線センサーの例を試しみてみました。 データシートでは、電圧と距離の関係が以下のようになっていると出ています。 回路とブレッドボード †図6.8では、スピーカーを付けていますが、以下のスケッチではアナログ0番のみを使用しています。 ブレッドボードの配線もすごく簡単です。 動作確認 †以下のスケッチで、センサーの動作を確認しました。 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で
テストに使用したスケッチは、以下のとおりです /* * ////////////////////////////////////////////////// * //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 コメント †皆様のご意見、ご希望をお待ちしております。 Tweet |