Arduinoで超音波センサを使って障害物までの距離をとってみる

皆さんこんにちわ
中部のhurusuです。

前回はArduinoを使ったi2c通信について、お勉強の記事を書きました。
今回は超音波センサと圧電ブザーを使った電子工作のお勉強をしてみようと思います。
超音波センサで障害物までの距離を測定し、障害物が近づいたり離れたりしたときにブザーをならします。
そして、センサから離れたら音階があがっていき、近づいたら音階を下げていくようなものを作ります。

今回のレシピ
-
・Arduino nano  2880円
・USBケーブル A-Mini(B) 249円
・ブレッドボード用DCジャック DIP化キット 150円
・ブレッドボード 1081円
・超音波センサ HC-SR04     https://www.switch-science.com/catalog/1606/  不具合があるので現在販売停止らしい？
・圧電ブザー 部屋でホコリ被ってたので詳細は不明
・16×2 LCDディスプレイ(i2c対応)　部屋でホコリ被ってたもの
・ACアダプター 9V 1.3A  (前回と同じもの)

ほとんど大須の第2アメ横ビルの「タケイムセン」で部品揃えました。いつもお世話になってます。
![IMG_2617.JPG](https://qiita-image-store.s3.amazonaws.com/0/149669/d8213224-2952-666d-cec9-5a9180f23bcd.jpeg)

※画像のLCDディスプレイは大須で買ったものですが、i2c通信できず、配線がじゃまになる(10ピンくらい使う)ので、結局使わず、自宅でホコリを被ってたi2c対応の別のものを使いました。

Arduino Nanoに関して
-
前回の記事で使用したArduino UNOよりかなり小さいです。
ちなみにArduino UNOと違ってDCジャックがありません。
そのため、お手製でDCジャックを回路に設置してACアダプターから電源供給する必要があります。
Arduino NanoのVINへの電圧供給は7v～12Vの範囲なので、今回使う9VのACアダプターで問題ありません。
![IMG_2618.JPG](https://qiita-image-store.s3.amazonaws.com/0/149669/1fbc5b4b-46a5-a615-c59a-05172de0d7fc.jpeg)

NanoとUNOを比べた図です。

まずはDCジャックを作る
-
ピンソケットと、DCジャック変換基板、DCジャックとDCジャック変換基板の結合部分をはんだづけします。ぼやけて分かりづらいけどご容赦を...
![IMG_2626.JPG](https://qiita-image-store.s3.amazonaws.com/0/149669/d24d4ae5-3ceb-67c8-5de8-34a2a2d5eb9f.jpeg)
![IMG_2625.JPG](https://qiita-image-store.s3.amazonaws.com/0/149669/1e48df17-8048-ef2e-f1c9-a060d1ad2c37.jpeg)

終わったら、ACアダプタを挿して通電の確認をします。
これ、やっとかないと、Arduinoが起動しなかったときの調査が面倒くさくなります。
9VでてたのでOKです。
![IMG_2624.JPG](https://qiita-image-store.s3.amazonaws.com/0/149669/0207a8fb-9dc0-9ea9-9d03-8a2de83a71ad.jpeg)

配線図
-
今回の配線はこのように配線しました。
■電源
Arduuino:VIN ⇔ DCジャック変換基板+
Arduuino:GND ⇔ DCジャック変換基板-

■超音波
Arduuino:D12 ⇔ 超音波センサECHO
Arduuino:D11 ⇔ 超音波センサTRIG
Arduuino:5v  ⇔ 超音波センサVCC
Arduuino:GND ⇔ 超音波センサGND

■圧電ブザー
Arduuino:D10 ⇔ 圧電ブザー+
Arduuino:GND ⇔ 圧電ブザー-

■16×2 LCD(i2c)
Arduuino:A4 ⇔ LCD SDA
Arduuino:A5 ⇔ LCD SCL
Arduuino:5V ⇔ LCD VCC
Arduuino:GND ⇔ LCD GND

![adventcalender3_ブレッドボード.png](https://qiita-image-store.s3.amazonaws.com/0/149669/0021f951-792b-01c6-1603-4456b1db1508.png)


完成図
-
実際に配線した図は以下となります。
Arduio Nanoは小さいけど、ブレッドボードが大きいのであんまり意味なかったという
![IMG_2627.JPG](https://qiita-image-store.s3.amazonaws.com/0/149669/e684ee1a-c9fd-2425-196e-5f2c5345fdfd.jpeg)


ソース
-
```cpp:adventcalender2.ino
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

/********************************
 * ピン定義
 * D11 ブザー (out)
 * D12 HC-SR04トリガー (in)
 * D13 HC-SR04エコー   (out)
 ********************************/
#define PIN_BUZZER 10
#define PIN_ECHO   12
#define PIN_TRIG   11


/************************
 * 音階周波数定義
 ************************/
#define NOTE_C4  262 //ド
#define NOTE_D4  294 //レ
#define NOTE_E4  330 //ミ
#define NOTE_F4  349 //ファ
#define NOTE_G4  392 //ソ
#define NOTE_A4  440 //ラ
#define NOTE_B4  494 //シ
#define NOTE_C5  523 //ド

#define TONE_ARRAYSIZE sizeof(tone_array)/sizeof(short)
short tone_array[]= {NOTE_C4,
                     NOTE_D4,
                     NOTE_E4,
                     NOTE_F4,
                     NOTE_G4,
                     NOTE_A4,
                     NOTE_B4,
                     NOTE_C5
                     };
/********************************
 * 圧電スピーカ用定義
 ********************************/
#define MELO_TIME 100       // ブザーを鳴らす時間(msec)
#define MELO_DISTANCE 2.0   // 障害物の距離がどれくらい変化したらブザーを鳴らすか(cm)


/********************************
 * 超音波センサ HC-SR04用変数
 ********************************/
struct ST_HC_SR04 {
  int duration;
  float distance;
  float distance_bk;
};
ST_HC_SR04 hc_sr04;


/********************************
 * LCD用 クラス
 ********************************/
//LiquidCrystal lcd(9, 8, 7, 6, 5, 4, 3);
LiquidCrystal_I2C lcd(0x27,2,1,0,4,5,6,7,3, POSITIVE);

/********************************
 * 障害物までの距離を計測する
 ********************************/
void measure_distance(void)
{
  /**************************************************************************
    トリガ端子を10us以上Highにしてください。
    このセンサモジュールが40kHzのパルスを8回送信して受信します。
    受信すると、出力端子がHighになります。
    出力端子がHighになっている時間がパルスを送信してから受信するまでの時間です。
    出力端子がHighになっている時間の半分を音速で割った数値が距離です。
  ***************************************************************************/
  // トリガをLowにする
  digitalWrite(PIN_TRIG,LOW);
  delayMicroseconds(1);

  // トリガを11μ秒Highにする (センサが40kHzのパルスを8回送信)
  digitalWrite(PIN_TRIG,HIGH);
  delayMicroseconds(11);

  // トリガをLowに落とす
  digitalWrite(PIN_TRIG,LOW);

  // エコーがhighになるまでの時間を計測する(戻り値はパルスの長さ(μ秒))
  hc_sr04.duration = pulseIn(PIN_ECHO,HIGH);

  if (hc_sr04.duration>0) {
    // 時間の半分を音速で割る
    hc_sr04.distance_bk = hc_sr04.distance;
    hc_sr04.distance = hc_sr04.duration/2;    
    hc_sr04.distance = hc_sr04.distance*340*100/1000000; // ultrasonic speed is 340m/s = 34000cm/s = 0.034cm/us
  }
}

/*******************
 * Buzzerを鳴らす
 * 障害物までの距離が遠のいたら音階を上げてく
 * 障害物までの距離が近づいた音階を下げてく
 ******************/
void buzzer(void) {
    static short tone_index = 0;
    float diff = hc_sr04.distance_bk - hc_sr04.distance;

  
    if(abs(diff) > MELO_DISTANCE)
    {
      if (diff < 0.0 )
      {
        if(tone_index < 0 || tone_index > TONE_ARRAYSIZE -1)
          tone_index = 0; 
        tone(PIN_BUZZER,tone_array[tone_index],MELO_TIME) ;
        delay(MELO_TIME);
        tone_index++;
      } else {
        if(tone_index < 0 || tone_index > TONE_ARRAYSIZE -1)
            tone_index = TONE_ARRAYSIZE -1;
        tone(PIN_BUZZER,tone_array[tone_index],MELO_TIME);
        delay(MELO_TIME);
        tone_index--;
      }
    }
}
/*******************
 * LCDに表示する
 ******************/
void display_Distance(void) {
    // 1行目 エコーがhighになるまでの時間(μs)
    //  2行目 距離(cm)
    lcd.clear();
    lcd.setCursor(3, 0);
    lcd.print(String(hc_sr04.duration) + " us ");
    lcd.setCursor(3, 1);
    lcd.print(String(hc_sr04.distance) + " cm ");
}


void setup() {
  Serial.begin(9600);

  /********************************
   * Pinの設定: トリガ端子に出力
   * Pinの設定: エコー端子から入力
   *******************************/
  pinMode(PIN_TRIG,OUTPUT);
  pinMode(PIN_ECHO,INPUT);

  /*****************************
   * LCD初期化
   ****************************/  
  lcd.begin(16, 2);
  lcd.backlight();

  /*****************************
   * 障害物への距離計測
   ****************************/  
  measure_distance();
}


void loop() {

  // 障害物までの距離を計測
  measure_distance();

  // LCDディスプレイに障害物までの距離を表示
  display_Distance();

  // Buzzerを鳴らす
  buzzer();

  delay(500);
}
```

動作
-
![IMG_2630.JPG](https://qiita-image-store.s3.amazonaws.com/0/149669/d0305418-169e-9631-146c-0e792ee8875c.jpeg)

LCDには、超音波の反射がセンサに入ってくるまでの時間(μs)と、障害物までの距離(cm)が表示されます。
超音波センサから離れると圧電ブザーが鳴りドレミファソラシドで音階があがっていきます。
超音波センサに近づいていくと圧電ブザーが鳴りドシラソファミレドで音階が下がっていきます。

最後に
-
今回は超音波センサを使った電子工作に挑戦しました。
突貫工事で1日で作りましたけど、作業時間の1/4はDCジャックのはんだづけに失敗してて通電してないことに気づくのが遅れて「起動しない！」ってハマってました。通電の確認は怠らないようにしようといういい教訓になりました。



参考資料
-
作るにあたって、動作のロジック等は以下の記事を参考にさせて頂きました。ありがとうございます。
・圧電ブザーを鳴らせてみよう　https://fabkura.gitbooks.io/arduino-docs/content/chapter7.html
・スイッチサイエンス 超音波距離センサモジュールHC-SR04  https://www.switch-science.com/catalog/1606/
・「回路用電源」の確保　http://blogs.yahoo.co.jp/aquagcb/39766275.html

今回の記事と関係ないけど今のちょっとした楽しみ
-
実は、業務の一環で、Genuino 101を入手しました。
Genuino 101はArduino(LLC)とIntelの共同設計のArduinoです。
今年(2016年3月)に発売されたばかりの先端をいってるマイコンです。パッケージと実物はこちら。

![IMG_2631.JPG](https://qiita-image-store.s3.amazonaws.com/0/149669/3916bde7-a5fd-2187-21dc-c0a849e5613e.jpeg)

パッケージにもマイコンにもきっちりIntelはいってるwww
ちなみにUNOもNANOもATmega328Pっていうプロセッサーでして、101はIntel® Curie
というプロセッサーとなります。

101の特徴としては、加速度センサ、ジャイロセンサ、BLE、RTCがオンボードなところです。
BLEは特に技適云々で国内で使えるものが制限されるのですが、
Genuino 101はちゃーんと技適マークも入ってますので安心して国内で使えますね。
![IMG_2632.JPG](https://qiita-image-store.s3.amazonaws.com/0/149669/fa40da28-4f53-9dc3-0714-585cec519168.jpeg)
※技適マークが付いていない無線機器を使用すると、電波法違反になるらしいですよ

あとクロックスピードがAruduino UNOとNanoの2倍です。
フラッシュメモリとSRAMのメモリのサイズも数倍以上違う。
ただし、EEPROMはないのかな？
あと、とっても気になるのが、スイッチサイエンスのプロダクトページだとGenuino101の1ピンあたりの最大出力電流が4mAって書かれているんですが、UNO(20mA)、NANO(40mA)より全然小さい！？
https://www.switch-science.com/catalog/2670/

うーん、本家のArduino.ccの説明みると 20mAって書かれてるようだけど誤記かしら？
PWMのピン数と間違えてるようにしかみえないのですが...
https://www.arduino.cc/en/Main/ArduinoBoard101

何にしてもお試しで触ってみるのが楽しみですだ。