スマホの加速度センサーつかってラジコン制御

# はじめに
以前、M5StickCとLEGOとBlynkを使ってラジコンを作った（[M5StickC Plus (ESP32)と3DプリンタとBlynkとLEGOでラジコン作った。 - Qiita](https://qiita.com/optimisuke/items/4996ab9b06633822647f)
）。
操作性に難あり＋せっかく画面あるのに活用できてなかったので、少し改善した。
改善点は下記2点。

1. スマホの加速度センサーで動かせるようにした
2. 画面に目をうすことにした

![IMG_20210424_155513.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184221/94a553ee-3aeb-6cf7-206d-0061d420f31c.jpeg)

# コード

## M5StickC側
こんな感じ。`my token`を変えたら動くはず。
加速度センサーの向きと動く向きと目の向きをあわせるのに苦労した。
注意したのは、モータが左右逆向きについてるから両方プラスだとタイヤが片方は前方向、片方は後ろ方向に回転して、本体はその場で回転するところ。ややこい。

目の形は、`fillRect()`で四角を書いた。`constrain()`で画面の枠からはみ出ないようにした。
あれ、`constrain()`の返り値は、intっぽい。勝手にキャストしてくれてんのかな？まぁ動いてるしいいか。
[constrain() - Arduino Reference](https://www.arduino.cc/reference/en/language/functions/math/constrain/)


LCD周りはここらを参考にした。
[M5StickCのDisplay周り解析 | Lang-ship](https://lang-ship.com/blog/work/m5stickc-display/)
[m5-docs/lcd.md at master · m5stack/m5-docs](https://github.com/m5stack/m5-docs/blob/master/docs/ja/api/lcd.md)
[m5-docs/lcd.md at master · m5stack/m5-docs](https://github.com/m5stack/m5-docs/blob/master/docs/en/api/lcd.md)

BLE切断時のコールバックとかも作れそうやけど、なんか安定してなさそうやったので、改善希望。

```cpp
#define BLYNK_PRINT Serial
#define BLYNK_USE_DIRECT_CONNECT

#include <BlynkSimpleEsp32_BLE.h>
#include <BLEDevice.h>
#include <BLEServer.h>
#include "esp32-hal-ledc.h"
#include <M5StickCPlus.h>

char auth[] = "my token";

const int WIDTH_BIT = 10;
const int FREQ = 50;
const int LEFT_PIN = 26;
const int LEFT_CH = 2;
const int RIGHT_PIN = 25;
const int RIGHT_CH = 3;
const int OFFSET = 75;
const int GAIN = 5;

void setup()
{
  Serial.begin(115200);
  Serial.println("Waiting for connections...");
  Blynk.setDeviceName("Blynk");
  Blynk.begin(auth);

  ledcSetup(LEFT_CH, FREQ, WIDTH_BIT);
  ledcAttachPin(LEFT_PIN, LEFT_CH);
  ledcSetup(RIGHT_CH, FREQ, WIDTH_BIT);
  ledcAttachPin(RIGHT_PIN, RIGHT_CH);

  M5.begin();
  M5.Lcd.fillScreen(TFT_BLACK);
  M5.Lcd.setRotation(1);
  M5.Lcd.fillRect(30, 70, 40, 10, TFT_WHITE);
  M5.Lcd.fillRect(170, 70, 40, 10, TFT_WHITE);
}

void loop()
{
  Blynk.run();
}

BLYNK_WRITE(V1) {
  int16_t x_axis = (int16_t) param[0].asInt();
  int16_t y_axis = (int16_t) param[1].asInt();
  int16_t right = - GAIN * (+ x_axis + y_axis) + OFFSET;
  int16_t left = + GAIN * (+ x_axis - y_axis) + OFFSET;

  ledcWrite(LEFT_CH, left);
  ledcWrite(RIGHT_CH, right);
  
  M5.Lcd.fillScreen(TFT_BLACK);
  M5.Lcd.setRotation(1);

  // Resolution: 135*240
  const int16_t low_xlim = 0;
  const int16_t upp_xlim = 239;
  const int16_t low_ylim = 0;
  const int16_t upp_ylim = 134;
  
  int16_t x_position_left = constrain(35-2*y_axis, low_xlim, upp_xlim);
  int16_t x_position_right = constrain(185-2*y_axis, low_xlim, upp_xlim);
  int16_t y_position = constrain(60-2*x_axis, low_ylim, upp_ylim);
  M5.Lcd.fillRect(x_position_left, y_position, 20, 20, TFT_WHITE);
  M5.Lcd.fillRect(x_position_right, y_position, 20, 20, TFT_WHITE);

  Serial.println(left);
  Serial.println(right);
}
```

## スマホ（Blynk）側
すごくシンプル。
BLEとGRAVITYだけ。
パラメータもOUTPUTをV1にしただけ。Z-axisもあるけど、つかってない。
スマホを水平にすると、X-axisとY-axisが0になる。
送られてきたデータを見ると-10〜+10の間で変化してそう。

![Screenshot_20210424_232910_cc.blynk.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184221/147c312c-5739-1762-cd55-80255870bee0.jpeg)

![Screenshot_20210424_232917_cc.blynk.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184221/30d267f5-7bcf-29af-643e-0cae889259e5.jpeg)

# 動き
こんな感じ。

https://twitter.com/optimisuke/status/1385594482356199429?s=20

https://twitter.com/optimisuke/status/1385961613283401728?s=20

# おわりに
細かい見た目とか曲がる方向とか変更しようと思うと、微調整＋デバッグに時間がかかる。
それなりに、大変やったけど、満足できた。

次は、センサーつけるか、タイヤを卒業するか。どーしよっかなぁ。