PlatformIO で ATOM Mate for toio™ の距離検出センサの値の取得

## 本記事について

ATOM Mate for toio には距離検出センサがついている。
その値を取得して以下のような機能の作り方を紹介する。

![output.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113504/d573039e-05f5-bd7c-be4c-317b429763ca.gif)

壁からの距離を画面に表示

## 環境

MacBook Air M2
macOS 13.3
PlatformIO
AtomS3
AtomLite (ATOMS3 Liteではない)

## 前提

M5AtomS3, LiteでHelloWorldできていること

https://qiita.com/Teach/items/9d0f21736808f44e2abc

## ATOM Mate for toio とは

https://www.switch-science.com/products/8500

- 下部に toio コアキューブとくっつけられる (物理的にくっつくだけなため、なくても動作変わらない)
- 上部にAtomLite / AtomMatrix を取り付けられることが想定されている。(AtomS3も同様に取り付けられた)
- 距離検出センサ(VL53L0X)とバッテリ
- 2022-11-15発売 (ATOM S3は同年12月のためそれより前)
- スイッチサイエンスのページに UiFlow のサンプルはあったが、Arduino のサンプルはなかった(2023/7時点)

## 距離検出センサ VL53L0X について

https://www.st.com/ja/imaging-and-photonics-solutions/vl53l0x.html

> デバイス制御およびデータ転送用のI2Cインタフェース

I2C通信というものに対応している。

VL53L0X　を使うためのライブラリには以下がある。

[Arduino library for Adafruit VL53L0X](https://github.com/adafruit/Adafruit_VL53L0X)

[Pololu Arduino library for VL53L0X
](https://github.com/pololu/vl53l0x-arduino)

![スクリーンショット_2023-07-01_17_32_45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113504/c977a417-7dc2-ba00-4ed7-3d20debd415a.png)

本記事の実装では2023/07時点でダウンロード数の多い Adafruit のライブラリを使用することにした。

## I2C通信を使う方法

ESP32 の I2C(アイ スクエアド シー)のドキュメントは以下にあった。

https://docs.espressif.com/projects/arduino-esp32/en/latest/api/i2c.html?highlight=Wire

Wire のソースは以下にあった。

https://github.com/espressif/arduino-esp32/tree/master



## ATOM Lite での実装

https://github.com/teach310/AtomLiteSample/tree/tof

```main.cpp
#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。

https://docs.m5stack.com/en/core/atom_lite

Board を M5ATOM にしていた場合 SDA, SDLは定義ジャンプすると以下のように定義されている

```
static const uint8_t SDA = 26;
static const uint8_t SCL = 32;
```

これらが使いたいピンと異なっているため自分で定義して`Wire.setPins`でピンを指定している

#### Adafruit_VL53L0X ライブラリの使い方

https://github.com/adafruit/Adafruit_VL53L0X/blob/master/examples/vl53l0x_continuous/vl53l0x_continuous.ino


## ATOM S3 での実装

https://github.com/teach310/AtomS3Sample/tree/atom_mate_for_toio

```main.cpp
#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　返すようになっていました。原因わからないのですが。。