こんにちは、ENGかぴです。
Arduinoとトワイライトを使って超音波距離センサーUS-015から取得した距離のデータを表示するシステムを作ることができます。ArduinoとUS-015で一定間隔で距離データを計算しトワイライトで無線通信を使用してモニターします。
今回はArduinoとUS-015とトワイライトを組み合わせた距離測定モジュールを製作してみました。下記リンクの応用編になります。US-015単体の動作については下記リンクを参考にしてください。
Arduino UNOを使って動作確認を行ったことを下記リンクにまとめています。
Arduinoで学べるマイコンのソフト開発と標準ライブラリの使い方
トライライト(TWELITE)で動作確認したことについてまとめています。
トワイライト(TWELITE)のソフト開発と無線通信でできること
Arduinoとトワイライトの組み合わせの全体構成

親機はMONOSTICK(USBスティックの親機)を使用してパソコンでモニタ(Tera Term)します。親機はタイムスタンプを表示しながら子機からの受信を待ちます。動作手順は以下の通りです。
- Arduinoで超音波距離センサ(US-015)から距離データを取得し計算する
- トワイライトがウェイクアップしたらArduinoに対して距離データを要求する
- トワイライトはArduinoから取得した距離データを親機に無線通信する
- トワイライトは無線通信後スリープする
ArduinoはUS-015に対して一定間隔でパルス出力を行い距離データを計算します。トワイライトから距離データの要求電文が受信できれば距離データを送信します。トワイライトは消費電流を抑えるためにスリープを使って一定間隔(今回は1秒)毎に距離データの要求を行います。
スリープすることによって数mAの消費が1uA程度に抑えられるため電池が少しでも長く使えるようになります。MONOSTICKは距離データをモニタ表示するためにデータを換算するようにします。
Arduinoとトワイライトによる子機の構成(距離測定モジュール)

Arduinoは5V電源で動作しトワイライトは3.3V電源で動作するためArduinoの送信側の電圧をそのまま印加することができません。そのためR1とR2によってArudinoからトワイライトに向かう信号を分圧しています。Arduinoはトワイライトの出力の3.3Vを受けてもHレベルと判定できるためArduinoのRXに直接信号を入力しています。
Arduinoへの配線はトワイライトをシリアル通信に超音波距離センサをDIDO接続しています。Arduinoは距離センサーから250ms(任意でよい)毎に距離データを取得して4回分のデータを平均化してばらつきを押さえます。(ソースコード全体のUs015Filter()部分)
//トワイライトからシリアル通信を受信
void loop(){
while( Serial.available()){
rxarduino.buf[rxarduino.wp] = Serial.read();
if( ++rxarduino.wp >= RING_SZ ){ //次にデータを入れる場所を更新
rxarduino.wp = 0;
}
}
RxDataChk(); //受信したデータを確認して距離データを返信
}
/* RX function add */
void RxDataChk(){
if( chkdat[0]== HEADER1 && chkdat[1]== HEADER2 && chkdat[2]== HEADER3 ){ //ヘッダーをチェック
if( rxsz >= allsz ){
/*電文サイズ長分を格納*/
rxdata.sum = CalcSum(&rxdata.buf[0],sz); //電文のSUMを計算
if( rxdata.sum == rxdata.buf[sz]){ //SUMのチェック
if( rxdata.buf[0] == 1 ){
SerialTxSet(); //距離データを返信する関数
}
}
}
}
}
トワイライトがスリープからウェイクアップしたときシリアル通信を使ってデータの要求を行います。Arduinoはトワイライトから送信された電文をSerial.read()で受信してRxDataChk()で電文のチェックを行います。
Arduinoが受信するシリアルデータ(トワイライトが送信)もトワイライトのバイナリデータの電文フォーマットに従ってHEADER1(0xA5)・HEADER2(0x5A)・HEADER3(0x80)として電文ヘッダが一致することを確認してから受信データを受け取りSUMが一致すると正常なデータとして受け取るようにします。
外部機器と接続する際はメインとなる機器に対して電文が共通になるように管理すると可読性が良くなります。
電文が問題なければSerialTxSet()でUS-015から取得した距離データを返信する処理を行います。
/* TX function add */
void SerialTxSet(){
uint8_t *adrs;
uint8_t allsz = 0;
txdata.header[0] = HEADER1; //0xA5
txdata.header[1] = HEADER2; //0x5A
txdata.header[2] = HEADER3; //0x80
txdata.sz = sizeof(us015.dat);
txdata.buf[0] = (us015.dat >> 24); //uint32のデータをuint8に変換するためシフトして代入
txdata.buf[1] = (us015.dat >> 16);
txdata.buf[2] = (us015.dat >> 8);
txdata.buf[3] = (us015.dat & 0xFF);
txdata.sum = CalcSum(&txdata.buf[0],txdata.sz); //SUM値を代入
allsz = sizeof(txdata.header)+ sizeof(txdata.sz)+ txdata.sz; //データ長
adrs =&txdata.header[0]; //ポインタアドレスで先頭アドレスを指定
for(uint8_t i = 0; i < allsz; i++ ){
Serial.write(*adrs); //ポインタが示すアドレスに格納されている値
adrs++; //ポインタ1バイト分進める
}
Serial.write(txdata.sum);
}
トワイライトにバイナリデータでシリアル通信を行うためにはヘッダを含めてルールに従う必要があります。詳細は下記のリンクで説明しています。
トワイライト(TWELITE)とArduino間でシリアル通信する
トワイライトのSerialParser()の電文フォーマットに従って送信電文を作成します。
距離データは4バイトデータですが、txdata.buf[]は1バイトデータとして定義しているため4バイトデータをそのまま格納することができないためシフトによる分割を行って格納しています。
距離データしか送らないためtxdata.buf[]を4バイトデータとして宣言し4バイトデータをセットする方法もあります。この方法においてもデータ送信する際に1バイトのポインタとしてアドレスを更新しながらセットすることで4バイトデータも1バイトの単位で送信できます。
トワイライトの親機
トワイライトの親機はMONOSTICK(USBタイプ)子機からデータを受信するとシリアル通信を使ってArduinoにデータを送信するようにします。
void receive() {
//子機から無線データを受けた場合先に文字ヘッダを格納し判定する
if (strncmp(APP_FOURCHAR, fourchars, 4)) {return; }
expand_bytes(np,rx.get_payload().end(),us015);
us015_1 = us015 / 100; //整数部分
us015_2 = us015 % 100; //小数点以下
Serial << "ts:" << int(ts) << ":"
<< " Present Length is: " << (int)us015_1 << "." << (int)us015_2
<< "mm" << mwx::crlf << mwx::flush;
}
親機と子機の間でアプリケーションの判定をするため文字ヘッダによるデータの判別を行っています。strncmp()で文字ヘッダを比較して同一であれば残りのデータを受け入れる処理を行います。
US-015の距離データは100倍値になっているので100で割った商が整数部となり余りが小数点以下の値になります。これらをトワイライトのSerialモニタで表示するようにしています。
動作確認

本棚を使って動作確認を行いました。本棚は床から870mmの高さのものであり本棚の上に今回製作した距離測定モジュールを設置しました。Tera Termのモニタで確認すると割と正確に取得できていることが分かります。
段ボールを使ってUS-015やArduinoを固定できるようにしましたが設置環境によって誤差が出ることもありました。130mmの対象物を測定すると128mm付近になったりと不安定な部分もありましたが、誤差は大きくても30mm以内に収まる傾向でした。
ソースコード全体
ソースコードは記事作成時点において動作確認できていますが、使用しているライブラリの更新により動作が保証できなくなる可能性があります。また、ソースコードを使用したことによって生じた不利益などの一切の責任を負いかねます。参考資料としてお使いください。
リンクからZIPファイル形式のファイルをダウンロードし、任意の場所に展開していただくとテキストファイルが生成されます。
TWELITEのソースコードはMWSTAGEの環境でアクトのソースファイルにコピーすると使用できます。
参考記事のArduinoと超音波距離センサーUS-015で距離を測定では超音波距離センサの円筒のトップを基準にするために5mm分補正していましたが、距離が長くなるほど誤差が気にならなくなったためコメントアウトしています。
関連リンク
Arduinoのライブラリを使って動作確認を行ったことを下記リンクにまとめています。
Arduinoで学べるマイコンのソフト開発と標準ライブラリの使い方
Seeeduino XIAOで学べるソフト開発と標準ライブラリの使い方
ESP32-WROOM-32Eで学べるソフト開発と標準ライブラリの使い方
また無線モジュールであるトワイライトを使ってソフト開発したことについてまとめています。
トワイライト(TWELITE)のソフト開発と無線通信でできること
最後まで、読んでいただきありがとうございました。
自作の段ボールによる固定の誤差も大きく出ている可能性や音波を当てている床を移動しただけでも結果が数十mm変わることがあったので測定環境の影響もありそうです。誤差はありますが、それなりに測定できており段ボールで固定したりと作るのが面白かったの満足しています。