本記事について
ATOM Mate for toio には距離検出センサがついている。
その値を取得して以下のような機能の作り方を紹介する。
壁からの距離を画面に表示
環境
MacBook Air M2
macOS 13.3
PlatformIO
AtomS3
AtomLite (ATOMS3 Liteではない)
前提
M5AtomS3, LiteでHelloWorldできていること
ATOM Mate for toio とは
- 下部に toio コアキューブとくっつけられる (物理的にくっつくだけなため、なくても動作変わらない)
- 上部にAtomLite / AtomMatrix を取り付けられることが想定されている。(AtomS3も同様に取り付けられた)
- 距離検出センサ(VL53L0X)とバッテリ
- 2022-11-15発売 (ATOM S3は同年12月のためそれより前)
- スイッチサイエンスのページに UiFlow のサンプルはあったが、Arduino のサンプルはなかった(2023/7時点)
距離検出センサ VL53L0X について
デバイス制御およびデータ転送用のI2Cインタフェース
I2C通信というものに対応している。
VL53L0X を使うためのライブラリには以下がある。
Arduino library for Adafruit VL53L0X
Pololu Arduino library for VL53L0X
本記事の実装では2023/07時点でダウンロード数の多い Adafruit のライブラリを使用することにした。
I2C通信を使う方法
ESP32 の I2C(アイ スクエアド シー)のドキュメントは以下にあった。
Wire のソースは以下にあった。
ATOM Lite での実装
#include "Adafruit_VL53L0X.h"
#include <M5Unified.h>
#include <FastLED.h>
#define NUM_LEDS 1
#define LED_DATA_PIN 27
#define SDA_PIN 25
#define SCL_PIN 21
Adafruit_VL53L0X lox = Adafruit_VL53L0X();
CRGB leds[NUM_LEDS];
void setup()
{
auto cfg = M5.config();
M5.begin(cfg);
FastLED.addLeds<WS2811, LED_DATA_PIN, GRB>(leds, NUM_LEDS);
FastLED.setBrightness(20);
Wire.setPins(SDA_PIN, SCL_PIN);
if (!lox.begin())
{
Serial.println(F("Failed to boot VL53L0X"));
while (1)
;
}
Serial.println(F("Start App\n\n"));
lox.startRangeContinuous();
}
void loop()
{
if (lox.isRangeComplete())
{
Serial.print("Distance in mm: ");
Serial.println(lox.readRange());
leds[0] = CRGB::Red;
FastLED.show();
}
else
{
leds[0] = CRGB::Blue;
FastLED.show();
}
delay(500);
}
測定した距離は単位「mm」で Serial に出力。
正常に測定できている場合には LED を赤くしている
ポイント
PINの指定
lox.begin
内でWire.begin
が実行される。
このとき、ピンは定義済みのSDA, SCLが使われる。
以下ドキュメントより、使いたいピンは 25, 21。
Board を M5ATOM にしていた場合 SDA, SDLは定義ジャンプすると以下のように定義されている
static const uint8_t SDA = 26;
static const uint8_t SCL = 32;
これらが使いたいピンと異なっているため自分で定義してWire.setPins
でピンを指定している
Adafruit_VL53L0X ライブラリの使い方
ATOM S3 での実装
#include <M5Unified.h>
#include "Adafruit_VL53L0X.h"
Adafruit_VL53L0X lox = Adafruit_VL53L0X();
void setup()
{
auto cfg = M5.config();
M5.begin(cfg);
USBSerial.begin(115200);
M5.Display.setTextSize(2);
Wire.setPins(SDA, SCL);
if (!lox.begin())
{
USBSerial.println("Failed to boot VL53L0X");
while (1)
;
}
USBSerial.println("Start App\n\n");
lox.startRangeContinuous();
}
void loop()
{
M5.Display.startWrite();
auto distance = lox.readRange();
M5.Display.clear(BLACK);
M5.Display.setCursor(0, 20);
M5.Display.printf("Distance\nmm: %d\n", distance);
M5.Display.endWrite();
USBSerial.println("Distance in mm: " + String(distance));
delay(200);
}
ポイントは Atom Lite と特に変わらない。
AtomS3 では理由はわからないが isRangeComplete が false を返し続けたので消した(消しても特に問題がなかった)。
追記 2023/12/2)
上記コードだとloopごとに読みに行くのはまずいだろうということで再度 lox.isRangeComplete() いれてみたら true 返すようになっていました。原因わからないのですが。。