2014年5月28日水曜日

arduinoで超音波センサーを使ってみる



超音波センサーを使ってみました。
超音波を発射、壁などに反射し戻ってきた超音波を受信。
かかった時間を計測して、距離を算出しました。
後部のバンパーについてる車もありますね。
自動ドアにもあるのでしょうか?電波の方が一般的かな?

下記センサーの中心周波数は40KHzで超音波を発射、受信します。
人間の可聴範囲は12Hz~23KHz。
超音波を利用して飛行、餌を取るコウモリの可聴範囲は1,200Hz~400KHz。
犬の可聴範囲は15Hz~60KHzらしいです。
参考: 動物の可聴域




購入パーツは秋月電子、超音波センサ(送受信セット)300円(2014/5/27現在)
完成品もありますが2,500円。アマゾンには中国製?格安の完成品もあります。
 参考サイト
Arduinoの動かせ方入門 超音波センサーで物体の距離を測ってみます
の配線図2

回路はこのままです。
ただ手持ちのオペアンプ4588DDを使い、増幅率も変更しました。
<マイコンへ>直前のC4 2200pFが手持ちがなかったので接続しませんでした。

ブレッドボードで組んでの実験動画
arduino簡易オシロで波形も表示しています。



センサー間(センサー中心から中心)32mm

発射した超音波を直接受信してしまうので、スケッチでは発射から一定時間の受信は無視しています。
そのために測定可能距離は約20cm~約3mになっています。
完成品はセンサーの距離はセンサー間は近いのに、測定距離は数cmからになっています。
どうなっているんでしょうか。

距離を開けると発射した超音波が直接受信されるのを防ぎ、測定可能距離は縮まりますが、発射、反射、受信の経路が長くなり、反射物までの近距が近いほど誤差が大きくなります。
センサー間を広めて、近距離の誤差を小さくしようとすると、三角関数を使い反射物までの距離を算出しないといけません。
下記スケッチでは単純に発射から受信までの往復の時間を測り2で割っています。

秋月C型基板に乗せ、距離に合わせて圧電ブザーを鳴らしました。

PCにつなげばシリアルモニタで距離を出力します。
音速は一般に340m/sと言われますが、1気圧、気温15℃の時です。
wikipediaに温度と音速の関係が載っていましたので、厳密な計算式と近似値の計算式でも音速を出し、距離を算出しています。
気圧による変化もあるようですが、あまり変わらないようなので考慮していません。

気温25℃での音速と2mを進む時間と厳密な計算との誤差
340m/sで計算     -36.5mm
近似値の計算346.5m/s +1.0mm
厳密な計算346.29m/s (5,775μs)

温度センサーをつけて計測すれいいのですが、スケッチでは25℃として計算しています。
40KHzはtone関数で作っています。便利ですね。

気温補正をしてもスケッチの処理にかかる時間からか、数cmの誤差が出ました。
実測との誤差を補正する式を組み込めばかなり正確に測れるのではないでしょうか。


long dur;                            //超音波を送信開始から受信までの時間
long sum_dur;                        //受信までの時間合計
byte cnt;                            //計測回数のカウント
byte cnt_end = 5;                    //何回平均するか
float distance;                      //計算された距離

byte pin_sensor_in = A4;             //センサー入力 ※アナログ入力
byte pin_ultrasonic_out = 2;         //40KHz送信ピン番号 tone()は3,11番ピンのPWM出力を妨げる
byte pin_buzz = 4;                   //圧電ブザー接続する

void setup(){
  Serial.begin(9600);
  pinMode(pin_sensor_in, INPUT);
  pinMode(pin_ultrasonic_out, OUTPUT);
}

void loop(){
  ultrasonic();
  delay(10);
}

void ultrasonic(){
  noTone(pin_buzz);                           //ブザー停止
  long st = micros();                         //送信開始時間
  tone(pin_ultrasonic_out, 40000);            //40KHzの生成
  delayMicroseconds(50);                      //送信時間μs 40KHzは1サイクル25μs
  noTone(pin_ultrasonic_out);                 //tone停止
  delayMicroseconds(800);                     //送信部からの直接波を無視
  while(analogRead(pin_sensor_in) < 400){     //しきい値 5V / 1024 * 400 ≒ 1.95V
    if(micros()-st > 30000){                  //反射がなかったタイムアウトμs 30,000μs≒10.2(5.1)m
      Serial.println("out of range");
      break;
    }
  }
  dur = micros() - st;                        //送信開始から受信までの時間μs
  calc_distance();
}

void calc_distance(){
  sum_dur += dur;                                                          //受信までの時間合計
  cnt += 1;                                                                //加算回数のカウント
  if(cnt == cnt_end){
    float avg_dur = sum_dur / float(cnt);                                  //平均時間
    float temperature = 25;                                                //気温
// 340(m/s) / 1000(ms) / 1000(μs) * avg_dur(μs) * 100(cm) / 2(一往復)
    float distance_340 = 340 * avg_dur / 20000.0;                          //340m/s(15℃)で計算した距離
//wikipediaより 20.055 * ( 気温 + 273.15 ) ^ 0.5
    float speed_of_sound = 20.055 * sqrt( temperature + 273.15 );          //厳密に音速を算出
    distance = speed_of_sound * avg_dur / 20000.0;
//wikipediaより 近似値オイラー級数 331.5 + 0.6 * 気温
    float speed_of_sound_approx = 331.5 + 0.6 * temperature;               //近似値の音速
    float distance_approx = speed_of_sound_approx * avg_dur / 20000.0;

    Serial.print(temperature);
    Serial.print("\t");
    Serial.print(speed_of_sound);
    Serial.print("\t");
    Serial.print(avg_dur);
    Serial.print("\t");
    Serial.print(distance_340, 1);              //340m/s(15℃)で計算した距離
    Serial.print("\t");
    Serial.print(distance_approx, 1);           //気温補正した距離 近似値
    Serial.print("\t");
    Serial.println(distance, 1);                //厳密に気温補正した距離
    sum_dur = 0;
    cnt = 0;
    buzzer();
  }
}

void buzzer(){
  int buzz_freq = map(distance, 20, 300, 4000, 100);   //近ければ高い、遠ければ低い音
  tone(pin_buzz, buzz_freq);
}



環境:arduinoUNO、arduinoIDE1.0.5、win7(64)



0 件のコメント:

コメントを投稿