LEGOとM5StickCとBlynkでラジコン作った。

# はじめに
前回、M5StickC Plusで、サーボモータを制御してLEGOで作った車を動かした。
モータへの給電もM5StickCを使うことで、とってもすっきりしていい感じやった。
![https___qiita-image-store.s3.ap-northeast-1.amazonaws.com_0_184221_220cf892-6dd6-9789-fd76-6fc532f73150.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184221/d7c7b5c9-9cf1-0828-0ead-184467ec7170.jpeg)

[LEGOとM5StickCで動く車作った。 - Qiita](https://qiita.com/optimisuke/items/04d466e852a25444e1b0)

ただ、せっかくBluetoothとWi-Fi使えるM5Stick使ったので、ラジコン化することにした。
あと、せっかくディファレンシャルギア（まがるときに右左でいい感じに回転数変わる）使ったので、ステアリング用のサーボモータ追加して曲がれるようにした。

なにより、息子くんの尊敬を得るために、がんばることにした。

![IMG_20210313_201541.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184221/1bf0b743-edd4-bdad-e1ba-55acf69db753.jpeg)
完成したやつの写真。息子くんアレンジ。

# まがらせる
前後に動かすモータには360度まわるサーボモーターを使ってた。
今回、ステアリングのモータは270度角度を変えられるサーボモータを使った。
GeekServoの灰色のやつ。360度まわるサーボと同じようにPWMでかんたんに制御できる。いい感じ。

[GeekServo 9G Servo-Gray - SWITCH-SCIENCE](https://www.switch-science.com/catalog/6811/)

M5StickCにサーボを２つつけるのどうしよか考える必要があった。5VとGNDを共有しないといけないので。
方法いくつかありそうやけど、よくあるピンからケーブル分岐させることにした。はんだ付けちょいむずやった。ピンをブレッドボードにさした状態ではんだすればよかった。プラスチック部分がとけて金属部分が傾いて、なおすのに時間かかった。ミスった。すこし格闘したあと、写真にある感じで落ち着いた。5VとGNDの部分。

![IMG_20210214_133702.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184221/bd7e5179-da64-b0b8-0875-26c236806910.jpeg)

あんまり安定してないけど、こんな感じで接続。
![IMG_20210313_202929.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184221/5fc170d8-83b1-a1dc-8fce-ab144f5ddb31.jpeg)

LEGOはこんな感じで固定した。ちょうどよいのがないので、無駄に灰色のギアの部品を使った。
車体の前につけたほうがいい感じに曲がれる気がするけど、息子くんアレンジ的に後ろにつけることにした。
![IMG_20210313_201555.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184221/637d8ba4-426f-26f6-a5b9-3d86977c7b9c.jpeg)

これで、まがらせる準備できた。

# ラジコン化
## 技術選定
ラジコン化も、選択肢多いけど、気軽にやりたかったので、Blynkってアプリつかった。昔、触ったことあったのと友人が使ってるの見ていい感じやったので。

[Blynk IoT platform: for businesses and developers](https://blynk.io/)

ラズパイとかArduinoとかいろんなプラットフォームに対応してる、お気軽にマイコンとスマホをつなぐことができるサービス。制限ありで無料。
クラウドとアプリと各プラットフォームのライブラリで構成されてる。スマホ側でインターフェースをGUIで良い感じに設定して、マイコン側でライブラリ使っていい感じにデータを送ったり受けたりする。トークンを使ってスマホとマイコンを接続する。Wi-Fiも使えるけど、今回はBLEでつなぐことにした。

## スマホ側
こんな感じで、部品を並べる。今回は、JOYSTICKとBLEのパーツ。
![Screenshot_20210313_203801_cc.blynk.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184221/5e45e07a-317b-1712-6507-9057ddd16122.jpeg)

Joystickの設定はこんな感じ。outputは2つあって、M5Stick側の実装にあわせてる。
レンジを決めれるのがすごく便利。モーターの回転の向きもここであわせられるから、M5Stick側を気にしなくて良い。何回も書き込みしなくてすむのですごく楽。
![Screenshot_20210313_213329_cc.blynk.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184221/0d76e9b9-317e-7789-61a2-d10088dac121.jpeg)

AutoreturnはJoystickから手をはなしたときに真ん中に戻るやつで、Rotate on tiltはスマホの向きでx, yかわるやつ。
![Screenshot_20210313_203820_cc.blynk.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184221/dd097873-bead-28c2-c74b-9110d49230d4.jpeg)

BLEのセッティングは特に不要。おくだけ。つなぐとき、Connect BLE deviceする。
![Screenshot_20210313_203830_cc.blynk.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184221/5781d900-b6ce-522d-7c97-1d39e5525309.jpeg)

こんな画面になる。
![Screenshot_20210313_203844_cc.blynk.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184221/a5d42b1f-121c-90fa-6e47-162a349f72f0.jpeg)


## M5StickC側
M5StickCがわはこんな感じ。トークンをちゃんとしたやつに変えたら動く。
Exampleにある`ESP32_BLE.ino`を真似して書いた。

PWMは前回と同様、`ledcWrite`を使った。

`ledcAttachPin`のチャンネルはなぜか、2からしか動かない。0とか1だと動かない。`M5StickCPlus.h`を使うとそうなった。`M5StickC.h`だと0を指定しても動く。謎。中身読んだらわかるかもやけど、諦めた。イシューとしてあげといたほうがよいのか。気が向いたときにするか。

`V1`ってのが、アプリ側とそろえる必要のある変数。

```c++
#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[] = "YourAuthToken";

const int WIDTH_BIT = 10;
const int FREQ = 50;
const int SPEED_PIN = 26;
const int SPEED_CH = 2;
const int STEERING_PIN = 25;
const int STEERING_CH = 3;

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

  ledcSetup(SPEED_CH, FREQ, WIDTH_BIT);
  ledcAttachPin(SPEED_PIN, SPEED_CH);
  ledcSetup(STEERING_CH, FREQ, WIDTH_BIT);
  ledcAttachPin(STEERING_PIN, STEERING_CH);

  M5.begin();
  M5.Lcd.fillScreen(TFT_BLACK);
  M5.Lcd.setTextColor(TFT_WHITE);
  M5.Lcd.setCursor(20, 40, 2);
  M5.Lcd.print("SERVO");
}

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

BLYNK_WRITE(V1) {
  int16_t steering = param[0].asInt();
  int16_t speed = param[1].asInt();
  ledcWrite(SPEED_CH, speed);
  ledcWrite(STEERING_CH, steering);
  M5.Lcd.fillScreen(TFT_BLACK);
  M5.Lcd.setCursor(20, 80, 2);
  M5.Lcd.print(speed);
  M5.Lcd.setCursor(20, 120, 2);
  M5.Lcd.print(steering);
  Serial.println(speed);
  Serial.println(steering);
}
```

# 完成
いい感じに操作できるようになった。

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

# おわりに
Blynk使って、いい感じにスマホから操作できるようになった。いい感じ。
ただ、息子くん、あまり興味持たず。息子くんの尊敬得られず、失敗。
先日買ったLEGO BOOSTが完成度高すぎて、目が肥えてしまってる模様。ぐぬぬ。