以前、「M5Stackで距離を測る」という記事でいくつかの測距センサで距離を測りましたが、10mぐらいの距離が測れる安価なセンサが欲しかったので、TFMini-Sという赤外線測距センサを使ってみました。
TFMini-S – Micro LiDAR Module
TFMini-S – Micro LiDAR Moduleは赤外線を使い、対象物まで赤外線が往復する時間から距離を測るセンサです。測れる距離は対象物の反射率によって異なり、反射率90%の白い物体の場合10cmから12mまで、反射率10%の黒い物体の場合10cmから7mまで測れます。
マイコンとはシリアルかI2Cで通信し、初期状態ではシリアルで通信するように設定されています。
「M5Stackで距離を測る」で評価した測距センサとTFMini-Sのスペックを比較すると次のようになります。
接続
TFMini-Sは初期状態で、シリアルで通信するので、M5StickCともシリアルで通信することにします。TFMini-SとM5StickCとは次のように接続しました。
TFMini-S | M5StickC |
① 黒 GND | GND |
② 赤 5V | 5V |
③ 白 RXD/SDA | G0 |
④ 緑 TXD/SCL | G26 |
2020/12/20: ③白と④緑の接続を入れ替えて、③白-G0、④緑-G26にしました。
プログラム
TFMini-Sのマニュアルによると、シリアル通信は次のような仕様です。
ボーレート | 115200 |
データビット | 8 |
ストップビット | 1 |
パリティチェック | None |
M5StickCでG26をTXD、G0をRXDにして同じ条件で通信するには、次のように初期設定します。
Serial1.begin(115200, SERIAL_8N1, 0, 26);
シリアル通信のデータは次のような9バイトのフォーマットになっています。距離の単位はセンチ(cm)です。
バイト0 | 0x59 | フレームヘッダ |
バイト1 | 0x59 | フレームヘッダ |
バイト2 | Dist_L | 距離(下位バイト) |
バイト3 | Dist_H | 距離(上位バイト) |
バイト4 | Strength_L | 信号強度(下位バイト) |
バイト5 | Strength_H | 信号強度(上位バイト) |
バイト6 | Temp_L | 温度(下位バイト) |
バイト7 | Temp_H | 温度(上位バイト) |
バイト8 | Checksum | チェックサム |
フレームヘッダを見つけ、9バイトのフレームを受信し、チェックサムを計算するプログラムは次のようになります。
動作確認
プログラムを動かし、机から天井までの距離を測り、結果をシリアルプロッタに表示してみました。
値はほぼ134cmです。個体差かもしれませんが、LIDAR-Lite v3HPが測るたびに5〜6cmの幅で値がぶれたのに対して、TFMini-Sの出力値は非常に安定していて、複数回測って平均を取る必要もありません。
上記のプログラムはTFMini-Sで対象物までの距離を測り、距離と信号強度をM5StickCのLCDに表示します。134cm離れた白い壁までの距離を測ったときの信号強度は3880程度、5m離れた焦げ茶色のドアで300ぐらいでした。信号強度が100未満になると測定結果は信頼できなくなるとのことでした。
I2Cで通信する
1台のマイコンで複数台の測距センサを扱いたい場合があります。TFMini-Sは初期状態ではシリアルで通信するので、このままでは複数台つないで制御できません。そこで、TFMini-SをI2Cモードに切り替えて通信しました。
I2C通信モードに切り替える
TFMini-SをI2Cモードに切り替えるには、シリアル通信でコマンドを送ります。M5StickCにTFMini-Sを接続し、次のプログラムを動かすことで、I2Cモードに切り替えられます。
TFMini-Sのシリアル通信は通信速度115200bps、データ8ビット、ストップビット1ビット、パリティチェックなしなので、次のようにSerial1オブジェクトを初期設定して通信します。TFMini-SのRDX(白)線をM5StickCのG0、TXD(緑)線をG26につなぎます。
Serial1.begin(115200, SERIAL_8N1, 26, 0);
このプログラムを実行すると、M5StickCの液晶画面に「set I2C mode」「save settings」と表示され、TFMini-SはI2Cモードに切り替わります。それ以降はシリアルでは通信できなくなるので、注意が必要です。
シリアル通信モードに切り戻す
TFMini-Sをシリアル通信モードに戻すには、I2C通信でコマンドを送ります。TFMini-SをI2Cでアクセスするライブラリがあるので、Arduino IDEにインストールします。Arduino IDEの「ツール」メニューから「ライブラリを管理…」を選択してライブラリマネージャを立ち上げます。検索窓に「tfmpi2c」と入力し、TFMPI2Cというライブラリを探し、「インストール」をクリックします。
TFMini-Sをシリアルモードに切り替えるプログラムは次のようになります。
このプログラムを実行すると、M5StickCの液晶画面に「set Serial Mode..」「save settings..」と表示され、TFMini-Sはシリアルモードに切り替わります。それ以降はI2Cでは通信できなくなります。
I2C通信で距離を測る
TFMini-SをI2Cでアクセスするライブラリには getData という関数があり、この関数で距離と信号強度、センサ温度が取得できます。
bool getData( int16_t &dist, int16_t &flux, int16_t &temp);
getData 関数を使って距離を測り、M5StickCの液晶画面に表示するプログラムは次のようになります。
複数台のTFMini-Sを制御する
TFMini-SのデフォルトI2Cアドレスは0x10ですが、コマンドでI2Cアドレスを変更できます。複数台のTFMini-Sを制御するには、それぞれのI2Cアドレスを別の値に変えておいて、TFMini-Sをバス接続して制御することもできます。
別の方法として、I2Cハブを使う方法があります。M5Stackのユニットに「M5Stack用Port A(I2C)拡張ハブユニット」があり、これ使うと、同じI2Cアドレスのデバイスであっても複数制御できます。プログラムは次のようになります。この他に
* https://github.com/m5stack/M5Stack/tree/master/examples/Unit/PaHUB_TCA9548A
の下にある ClosedCube_TCA9548A.cpp と ClosedCube_TCA9548A.h というファイルをダウンロードして、同じフォルダに置きます。
プログラムはTFMini-Sを管理する TFMPI2C というオブジェクトを一つ定義し、1つのオブジェクトで複数台のTFMini-Sにアクセスしています。I2C通信でコマンドを送り、センサデータを取得するまでは通信対象のデバイスは切り替わらないので、1つのオブジェクトで複数台のデバイスと通信できます。