Arduinoで距離を測る(1)【超音波測距センサ with XBee(動作確認)】 [Arduino]
前回で2byteのシリアル通信ができたので、本番です。
測定した距離をバイナリデータとしてXBee間でシリアル通信して、PCのシリアルモニタに表示をさせます。
一度実測した値をもとに、誤差を修正するための補正値を組み入れました。
補正値を入れる前後の実績値を示します。
超音波測距センサの「SEN136B5B」の測定レンジは3cm~4m(400cm)ですので、測定レンジを外れたら"Out of Range"と表示します。
【スケッチ】
<送信側>
<受信側>
これで遠隔から距離データを取得することができました。
同じプログラムを使い回せば、他にも温度センサからのデータだったりとか、いろいろと応用できそうです。
測定した距離をバイナリデータとしてXBee間でシリアル通信して、PCのシリアルモニタに表示をさせます。
一度実測した値をもとに、誤差を修正するための補正値を組み入れました。
補正値を入れる前後の実績値を示します。
超音波測距センサの「SEN136B5B」の測定レンジは3cm~4m(400cm)ですので、測定レンジを外れたら"Out of Range"と表示します。
【スケッチ】
<送信側>
/******************************************************************************* 超音波測距センサ(SEN136B5B)用XBeeトランスミッタ ++++++ note ++++++ 超音波測距センサ(SEN136B5B)用にArduinoUNO-XBee送信機 *******************************************************************************/ // this constant won't change. It's the pin number of the sensor's output: const int pingPin = 7; // 初期化(電源投入/リセット時1回のみ実行): void setup() { Serial.begin(9600); //9600bpsでシリアルポートを開く } // main loop: void loop() { long duration; //変数を定義 int cm; //変数を定義 // The PING))) is triggered by a HIGH pulse of 2 or more microseconds. // モジュールに超音波発信のためのトリガーを与える // Give a short LOW pulse beforehand to ensure a clean HIGH pulse: pinMode(pingPin, OUTPUT); //pingPinを出力ピンに定義 digitalWrite(pingPin, LOW); //LOW出力 delayMicroseconds(2); //2us停止 digitalWrite(pingPin, HIGH); //HIGH出力 delayMicroseconds(5); //5us停止 digitalWrite(pingPin, LOW); //LOW出力 /* ①トリガー信号により40kHzの超音波パルスをモジュールは発信する。 ②超音波パルス発信中に、pingPinを出力→入力ピンに変更する。 ②超音波パルスを発信し終えたら、pinPinはHIGHに遷移する(超音波パルスをモジュールが受信する 間HIGHを継続(受信したらLOWに遷移))。 ④pinPinのHIGH継続時間を測定することで、距離に変換することができる。 */ // The same pin is used to read the signal from the PING))): a HIGH pulse // whose duration is the time (in microseconds) from the sending of the ping // to the reception of its echo off of an object. pinMode(pingPin, INPUT); //pingPinを入力ピンに定義 duration = pulseIn(pingPin, HIGH); //pingPinがHIGHになっている時間(パルスの長さ)を計測する // convert the time into a distance cm = microsecondsToCentimeters(duration); //パルスの長さ(時間)を距離(センチ)に変換 sendIntData(cm); delay(100); //シリアルポートを溢れさせないように ※delay():単位ms } //パルスの長さ(時間)を距離(センチ)に変換する関数 long microsecondsToCentimeters(long microseconds) { // The speed of sound is 340 m/s or 29 microseconds per centimeter. // The ping travels out and back, so to find the distance of the object we // take half of the distance travelled. return microseconds / 29 / 2; } // int型のデータを送信する関数 void sendIntData(int value) { Serial.write('H'); // ヘッダの送信 Serial.write(lowByte(value)); // 下位バイトの送信 Serial.write(highByte(value)); // 上位バイトの送信 }
<受信側>
/******************************************************************************* 超音波測距センサ(SEN136B5B)用XBeeレシーバ ++++++ note ++++++ 超音波測距センサ(SEN136B5B)用にArduinoUNO-XBee受信機 ・実測データより受信データが195以上(約2m)には+5cmの補正を加える ・距離データが3(約3cm)未満又は400(約4m)を超えたら、Out of Rangeと表示する *******************************************************************************/ #define VERSION "1.00a0" #define hosei 5; //補正値(実測データより求めた) int recv_data; //受信データ int range_data; //距離データ // 初期化(電源投入/リセット時1回のみ実行): void setup() { Serial.begin(9600); //9600bpsでシリアルポートを開く } // main loop: void loop(){ // 受信バッファに3バイト(ヘッダ+int)以上のデータが着ているか確認 if ( Serial.available() >= sizeof('H') + sizeof(int) ) { // ヘッダの確認 if ( Serial.read() == 'H' ){ int low = Serial.read(); //下位バイトの読み取り int high = Serial.read(); //上位バイトの読み取り recv_data = makeWord(high,low); //上位バイトと下位バイトを合体させてint型データを復元 // 受信データから表示させる距離データを作成 if(recv_data >= 195){ //195以上ならば補正値を加算する range_data = recv_data + hosei; } else{ range_data = recv_data; } // 距離データの表示 range_dataの値をハード・シリアルへ出力する(Arduino→PCモニタ) if((range_data >= 3) && (range_data <= 400)){ //range_dataが3以上400以下ならば、距離を表示する Serial.print("Range= "); Serial.print(range_data); Serial.println("[cm]"); } else{ //range_dataがそれ以外ならば、Out of Rangeと表示する Serial.println("Out of Range"); } } } }
これで遠隔から距離データを取得することができました。
同じプログラムを使い回せば、他にも温度センサからのデータだったりとか、いろいろと応用できそうです。
Arduinoで距離を測る(1)【2バイトのシリアル通信】 [Arduino]
超音波測距センサの「SEN136B5B」の測定レンジは3cm~4m(400cm)です。
測定した距離をバイナリデータとしてXBee間でシリアル通信して、PCのシリアルモニタに表示をさせたいのですが、ここで問題があります。
Serial.write(val)では送信する値(val)は1バイトなのです。
これでは測定レンジの最大値4m(400cm)は送ることができません。。。実際、テストスケッチで試してみても255はシリアルモニタに表示されましたが、256は0となってしまいました。
"それでは1バイトを超えたバイナリデータを送信するためには?"とネットを探し回ってみたところ、
kougaku (id:kougaku-navi)さんの『Imaginary Code』というタイトルのブログから「Arduinoのシリアル通信でint型のデータをやりとりする」のページが分かりやすかったので、参考にしたいと思います。
"https://kougaku-navi.hatenablog.com/entry/20140501/p1"
このページでは「12345」と「-12345」の2バイトのバイナリデータを交互に送信します。
【配線図】
最初はXBeeを使わずに、シリアルポートのTX/RXを有線でつなげて試してみます。
【スケッチ】
送信側から「12345」と「-12345」の2種類のデータを交互に送り、受信側でどちらのデータがきたかチェックして13番ピンに繋がっているLEDをON/OFFします。500ms間隔でLEDが点滅すればOKです。
また、受信側に接続したシリアルモニタで数値を表示します。←追加
<送信側>
・int型のデータを上位バイトと下位バイトに分けて送信する
・データを正しい順序で受信するためにヘッダをつけて送信する
<受信側>
・3バイト(ヘッダ+int)以上のデータが着ているか確認
・データが着てたらまずヘッダがあるか確認
・ヘッダがあったら、下位バイトと上位バイトを読み取り、その値を合体してint型のデータを復元
測定した距離をバイナリデータとしてXBee間でシリアル通信して、PCのシリアルモニタに表示をさせたいのですが、ここで問題があります。
Serial.write(val)では送信する値(val)は1バイトなのです。
これでは測定レンジの最大値4m(400cm)は送ることができません。。。実際、テストスケッチで試してみても255はシリアルモニタに表示されましたが、256は0となってしまいました。
"それでは1バイトを超えたバイナリデータを送信するためには?"とネットを探し回ってみたところ、
kougaku (id:kougaku-navi)さんの『Imaginary Code』というタイトルのブログから「Arduinoのシリアル通信でint型のデータをやりとりする」のページが分かりやすかったので、参考にしたいと思います。
"https://kougaku-navi.hatenablog.com/entry/20140501/p1"
このページでは「12345」と「-12345」の2バイトのバイナリデータを交互に送信します。
【配線図】
最初はXBeeを使わずに、シリアルポートのTX/RXを有線でつなげて試してみます。
【スケッチ】
送信側から「12345」と「-12345」の2種類のデータを交互に送り、受信側でどちらのデータがきたかチェックして13番ピンに繋がっているLEDをON/OFFします。500ms間隔でLEDが点滅すればOKです。
また、受信側に接続したシリアルモニタで数値を表示します。←追加
<送信側>
・int型のデータを上位バイトと下位バイトに分けて送信する
・データを正しい順序で受信するためにヘッダをつけて送信する
/******************************************************************************* テスト用シリアル通信プログラム2byte(送信側) ++++++ note ++++++ ・テスト用シリアル通信プログラム(2byte送信) TX→RX→PCモニタの一連の流れを確認する。 ・下記URLのサイトからサンプルプログラムをコピー https://kougaku-navi.hatenablog.com/entry/20140501/p1 *******************************************************************************/ void setup() { Serial.begin(9600); } void loop() { sendIntData(12345); // int型データの送信 delay(500); sendIntData(-12345); // int型データの送信 delay(500); } // int型のデータを送信する関数 void sendIntData(int value) { Serial.write('H'); // ヘッダの送信 Serial.write(lowByte(value)); // 下位バイトの送信 Serial.write(highByte(value)); // 上位バイトの送信 }
<受信側>
・3バイト(ヘッダ+int)以上のデータが着ているか確認
・データが着てたらまずヘッダがあるか確認
・ヘッダがあったら、下位バイトと上位バイトを読み取り、その値を合体してint型のデータを復元
/******************************************************************************* テスト用シリアル通信プログラム2byte(受信側) ++++++ note ++++++ ・テスト用シリアル通信プログラム(2byte送信) TX→RX→PCモニタの一連の流れを確認する。 ・下記URLのサイトからサンプルプログラムをコピー https://kougaku-navi.hatenablog.com/entry/20140501/p1 ・recv_dataの値をハード・シリアルへ出力する(Arduino→PCモニタ) *******************************************************************************/ int recv_data; // 受信データ void setup() { Serial.begin(9600); pinMode(13, OUTPUT); } void loop() { // 受信バッファに3バイト(ヘッダ+int)以上のデータが着ているか確認 if ( Serial.available() >= sizeof('H') + sizeof(int) ) { // ヘッダの確認 if ( Serial.read() == 'H' ) { int low = Serial.read(); // 下位バイトの読み取り int high = Serial.read(); // 上位バイトの読み取り recv_data = makeWord(high,low); // 上位バイトと下位バイトを合体させてint型データを復元 Serial.println(recv_data); //recv_dataの値をハード・シリアルへ出力する(Arduino→PCモニタ)←追加 } } // 受信したデータに基づいてLEDをON/OFF if ( recv_data == 12345 ) { digitalWrite(13, HIGH); } if ( recv_data == -12345 ) { digitalWrite(13, LOW); } }
Arduinoで距離を測る(1)【超音波測距センサ with XBee】 [Arduino]
一旦、それなりにRC戦車のベーシック部分ができたので、これからの応用編に向けて、基礎知識(ネタ?)も集めます。
Arduinoで距離を測ります!
このネタって、まぁネットで検索すれば、ここより100倍は良いサイトがあちこちにあるので、別にここで取り上げる必要も無いんだけど、自分の備忘録なんで。。。
最初は、超音波測距センサを取り上げます。よくロボットとかの目のように見える部分ですね。
それで使うのは、超音波測距センサの「SEN136B5B」です。
これも買ってから一度も使う間もなくディスコン?になってしまったようで、ネットで探しても在庫が見当たりません。。。物持ちがいいのも考えものです。
これです↓
超音波距離センサモジュール 3cm-4m
"https://www.switch-science.com/catalog/795/"
ただ、単純にArduinoに繋げてスケッチで動かして※、というのも少し面白みがないので、今後への応用のために取得したデータをXBeeで無線伝送しPCのシリアルモニタで表示できるようにしたいと思います。
※"https://www.arduino.cc/en/tutorial/ping"
【配線図】
今回、受信側はArduino UNO(以下UNO)とXBeeを使います。UNOとXBeeとの接続には、配線図ではうまく表現できなかったのですが、XBeeシールドを使いたいと思います。
KKHMF XBeeシールド V03 モジュール 拡張ボード Bluetooth対応 Arduino用
"https://www.amazon.co.jp/gp/product/B07SN3YHZF/ref=ppx_yo_dt_b_asin_title_o02_s00?ie=UTF8&psc=1"
中華製ですね。値段が安いのが決め手でした。
XBeeの確認をします。このときUNOはただPCとXBeeをつなぐ基板として使います。
最初、UNOに何も載せないでPCに接続します。
Arduino IDEを立ち上げて、
メニュー> スケッチ例>01.Basics>BareMinimum
でUNOに書き込みます。
書き込みが終わったら、UNOをPCから取り外します。
シールドにはスイッチがついています。XBeeがやり取りする相手に合わせて切り替えます。
USB:PC(USB接続)⇔XBee
XBEE:UNO⇔XBee
しっかし、表示に統一感がないので分かりにくいですねー。XBeeから見ての接続先を表示するなら、下段はXBEEでなくてUNOだと思うんですけどね。未だにどっちがどっちだか分からなく時があります。。。
今回は、PCとXBeeで直接やり取りするので、シールドのスイッチを「USB」側にします。
シールドをUNOに載せ、PCに接続します。
XCTUを立ち上げて、XBeeモジュールを認識できればOKです。
改めてスケッチを書き込む場合には、いったんUNOをPCから取り外し、シールドも外します。
再度UNOをPCに接続しArduino IDEを起動してから、受信側のスケッチを書き込みます。
Arduinoで距離を測ります!
このネタって、まぁネットで検索すれば、ここより100倍は良いサイトがあちこちにあるので、別にここで取り上げる必要も無いんだけど、自分の備忘録なんで。。。
最初は、超音波測距センサを取り上げます。よくロボットとかの目のように見える部分ですね。
それで使うのは、超音波測距センサの「SEN136B5B」です。
これも買ってから一度も使う間もなくディスコン?になってしまったようで、ネットで探しても在庫が見当たりません。。。物持ちがいいのも考えものです。
これです↓
超音波距離センサモジュール 3cm-4m
"https://www.switch-science.com/catalog/795/"
ただ、単純にArduinoに繋げてスケッチで動かして※、というのも少し面白みがないので、今後への応用のために取得したデータをXBeeで無線伝送しPCのシリアルモニタで表示できるようにしたいと思います。
※"https://www.arduino.cc/en/tutorial/ping"
【配線図】
今回、受信側はArduino UNO(以下UNO)とXBeeを使います。UNOとXBeeとの接続には、配線図ではうまく表現できなかったのですが、XBeeシールドを使いたいと思います。
KKHMF XBeeシールド V03 モジュール 拡張ボード Bluetooth対応 Arduino用
"https://www.amazon.co.jp/gp/product/B07SN3YHZF/ref=ppx_yo_dt_b_asin_title_o02_s00?ie=UTF8&psc=1"
中華製ですね。値段が安いのが決め手でした。
XBeeの確認をします。このときUNOはただPCとXBeeをつなぐ基板として使います。
最初、UNOに何も載せないでPCに接続します。
Arduino IDEを立ち上げて、
メニュー> スケッチ例>01.Basics>BareMinimum
でUNOに書き込みます。
書き込みが終わったら、UNOをPCから取り外します。
シールドにはスイッチがついています。XBeeがやり取りする相手に合わせて切り替えます。
USB:PC(USB接続)⇔XBee
XBEE:UNO⇔XBee
しっかし、表示に統一感がないので分かりにくいですねー。XBeeから見ての接続先を表示するなら、下段はXBEEでなくてUNOだと思うんですけどね。未だにどっちがどっちだか分からなく時があります。。。
今回は、PCとXBeeで直接やり取りするので、シールドのスイッチを「USB」側にします。
シールドをUNOに載せ、PCに接続します。
XCTUを立ち上げて、XBeeモジュールを認識できればOKです。
改めてスケッチを書き込む場合には、いったんUNOをPCから取り外し、シールドも外します。
再度UNOをPCに接続しArduino IDEを起動してから、受信側のスケッチを書き込みます。