M5Stackをスマホと連動させてコントロールする
第1回:小型Arduino互換機(M5Stack)で電子工作を楽しむ
第2回:M5Stackでモータドライバを使う
第3回:M5Stackでセンサを使って自動運転と自動回避機能を搭載
こんにちは、ヨシケンです!
小型Arduino互換機のM5Stackを使ってリモコンカーを作る本連載。モータードライバを使って前後左右に動くようにしたり、センサで自動運転するようになりましたが、最終回の今回は外部からリモートコントロールできるようにしてみたいと思います。今回は、BlynkというスマホからM5Stackを操作できる仕組みを導入していきます。

M5Stackとスマホを連携させたリモコンカー
今回の記事の流れ
今回の記事で必要な物一覧
M5Stack Core
ESP32を搭載したArduino互換機

Grove I2C モータドライバ
Grove端子で接続して使えるモータドライバ

ローム照度・近接センサ (RPR-0521RS)
赤外線を発し光の強度や近接度を計測

超音波距離センサ (HC-SR04)
超音波を発し距離を測定するモジュール

小型モーター、車輪など

9V電池と電池ボックス

1. スマホアプリのBlynkの導入
M5Stackで作った車を、スマホから操作するためにBlynkというアプリを導入します。
iOS又はAndroidで、Blynkアプリを検索しインストールします。

ダウンロードが済んだら、アプリを開くとアカウント作成が求められるので、メールアドレスなどで登録し、ログオンします。最初の画面に、”New Project”というのがあるので、名前を付けて新しいプロジェクトを作ります。

詳細設定で、Deviceは”ESP32 Dev Board”、Connectionは”WiFi”を選んで下さい。そうすると真っさらなプロジェクト画面が出るので、これでスマホの方の準備は完了です。

次にプログラミングするArduino IDEの方で、Arduino用のBlynkライブラリを入手します。以下のリンクからライブラリをダウンロードし、メニューのインクルードから、Zipファイルを追加します。
BlynkのGithubサイト

これでスマホ、Arduino IDEの両方で、Blynkを使う準備ができました。
2. Wi-Fi経由でスマホからM5Stackを操作
M5Stackとスマホをつなげる設定ができたので、それを操作するための機能を画面に追加します。
Blynkアプリの画面を押すと、右側から追加できるWidget(機能)が出てくるので、まずButtonを追加してみます。

ここでは、このボタンを押すとM5Stackのスピーカからビープ音を鳴らすようにしたいと思います。ボタンの詳細設定画面で、OutputとしてVirtualを選んでV1を指定します。これは後ほどM5Stack上でV1を指定することになるので覚えておいてください。他に押している間だけ信号が送られる”PUSH”を選んだり、ラベル名(Beep)などの設定をします。


左:ボタンを押していない状態 右:ボタンを押した状態
最後にM5Stackと接続する為のトークンを取得しておきます。プロジェクト作成時にメールで送られているか、”Project Settings”を開くと下の方に”AUTH TOKEN”があるので、それをコピーしておいて下さい。後ほどArduino IDEで指定します。

それではArduino IDEでプログラミングをおこないます。まずM5StackのサンプルとしてSpeakerというスケッチ例があるので、それをコピーします。
そこに以下3〜9、13〜22、28〜29、36行目の部分の追記をします。スケッチ中のxxxxの部分に先ほどコピーしたAUTH TOKENを入れます。yyyyとzzzzは自分のWifi環境のユーザ/パスワードになります。またV1のボタンを押したらビープ音が鳴るようにします。
[M5Stack_Speaker_Blynk.ino]
#include <M5Stack.h>
#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>
char auth[] = "xxxx”; //BlynkアプリのYourAuthTokenを入力
char ssid[] = "yyyy"; //WifiのI D、パスを入力
char pass[] = "zzzz";
#define NOTE_DH2 661
int BEEP_Flag = 0;
BLYNK_WRITE(V1)
{
BEEP_Flag = param.asInt();
if(BEEP_Flag == 1){
M5.Lcd.printf("Blynk wasPressed \r\n");
M5.Speaker.beep(); //beep
}
M5.update();
}
void setup() {
// Initialize the M5Stack object
M5.begin();
M5.Lcd.setTextSize(3);
Blynk.begin(auth, ssid, pass);
M5.Power.begin();
M5.Lcd.printf("M5Stack Speaker:\r\n");
}
void loop() {
Blynk.run();
if(M5.BtnA.wasPressed()) {
M5.Lcd.printf("A wasPressed \r\n");
M5.Speaker.beep(); //beep
}
if(M5.BtnB.wasPressed())
{
M5.Lcd.printf("B wasPressed \r\n");
M5.Speaker.tone(NOTE_DH2, 200); //frequency 3000, with a duration of 200ms
}
M5.update();
}
このプログラムを流したあと、Wi-Fi接続が完了すると、シリアルモニタにこのような表示がされます。スマホで同じWifi環境に入った状態で、BlynkからM5Stackに接続します。画面上でボタンを押すと、ビープ音がすると思います。

3. モータ操作のジョイスティックを追加
それではスマホからM5Stackのモータを動かす機能を追加します。進行方向や回転速度を操作するのにJoystickがあるので、それを画面上にセットします。Joystickの出力をV0として、その出力数値範囲を-50から50とセットします。

最後にBlynkからM5Stackを動かすプログラムを記述します。前回作ったセンサに反応するプログラムM5Stack_Near_Dist_Motor.inoにBlynkの記述を追加します。
以下15〜31、96、116行目が先ほどのスピーカで使った部分です。
それに33〜93、111〜112、123〜126、162〜163行目のJoystickに合わせてモータを動かす記述を追加しています。
[M5Stack_Near_Dist_Motor_Blynk.ino]
#include <M5Stack.h>
#include <Wire.h>
#include <RPR-0521RS.h>
RPR0521RS rpr0521rs;
#define TRIG 2
#define ECHO 5
int times;
int distance;
#include "Grove_I2C_Motor_Driver.h"
#define I2C_ADDRESS 0x0f
#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>
char auth[] = "xxxx”; //BlynkアプリのYourAuthTokenを入力
char ssid[] = "yyyy"; //WifiのI D、パスを入力
char pass[] = "zzzz";
int BEEP_Flag = 0;
BLYNK_WRITE(V1)
{
BEEP_Flag = param.asInt();
if(BEEP_Flag == 1){
M5.Lcd.printf("Blynk wasPressed \r\n");
M5.Speaker.beep(); //beep
}
M5.update();
}
long Speed;
long Speed1, Speed2;
long SpeedL, SpeedR;
//ジョイスティックのデータ受信
BLYNK_WRITE(V0) {
M5.Lcd.setCursor(10,180);
long x = param[0].asInt();
long y = param[1].asInt();
Speed = sqrt(x*x+y*y);
if(Speed > 50){
Speed = 50;
}
SpeedR = Speed - Speed1;
SpeedL = Speed - Speed2;
if(y >= 0){
if(x >= 0){
Speed1 = abs(x);
Speed2 = 0;
}else{
Speed1 = 0;
Speed2 = abs(x);
}
Serial.print(" R:");
Serial.print(SpeedR);
Serial.print(" L:");
Serial.println(SpeedL);
Motor.speed(MOTOR1, -SpeedR);
Motor.speed(MOTOR2, SpeedL);
M5.Lcd.print("Fwd!");
delay(500);
Motor.speed(MOTOR1, 0);
Motor.speed(MOTOR2, 0);
}else{
if(x >= 0){
Speed1 = abs(x);
Speed2 = 0;
}else{
Speed1 = 0;
Speed2 = abs(x);
}
Serial.print(" -R:");
Serial.print(SpeedR);
Serial.print(" -L:");
Serial.println(SpeedL);
Motor.speed(MOTOR1, SpeedR);
Motor.speed(MOTOR2, -SpeedL);
M5.Lcd.print("Back!");
delay(500);
Motor.speed(MOTOR1, 0);
Motor.speed(MOTOR2, 0);
}
}
void setup() {
Blynk.begin(auth, ssid, pass);
Serial.begin(115200);
while (!Serial);
byte rc;
rc = rpr0521rs.init();
pinMode(TRIG, OUTPUT);
pinMode(ECHO, INPUT);
Motor.begin(I2C_ADDRESS);
M5.begin();
M5.Lcd.setTextSize(4);
Wire.begin(21,22);
M5.Lcd.setCursor(10,0);
M5.Lcd.println(ssid);
}
void loop() {
Blynk.run();
byte rc;
unsigned short ps_val;
float als_val;
byte near_far;
M5.lcd.clear();
M5.Lcd.setCursor(10,0);
M5.lcd.print("M5 Blynk");
M5.Lcd.setCursor(10,50);
rc = rpr0521rs.get_psalsval(&ps_val, &als_val);
if (rc == 0) {
Serial.print(F("RPR-0521RS (Proximity) = "));
Serial.print(ps_val);
Serial.print(F(" [count]"));
near_far = rpr0521rs.check_near_far(ps_val);
if (near_far == RPR0521RS_NEAR_VAL) {
Serial.println(F(" Near"));
M5.lcd.print("Near!");
} else {
Serial.println(F(" Far"));
M5.lcd.print("Far!");
}
}
digitalWrite(TRIG, HIGH); // 超音波を発生させる
delayMicroseconds(10);
digitalWrite(TRIG, LOW);
times = pulseIn(ECHO, HIGH); // 超音波を受け取る
distance = (int)(times * 0.017);
Serial.println(distance); // ディスプレイに表示させる
M5.Lcd.setCursor(10, 100);
M5.Lcd.print(distance);
if ( ((distance > 0) and (distance < 6)) or (near_far != RPR0521RS_NEAR_VAL) ) {
Motor.speed(MOTOR1, 50);
Motor.speed(MOTOR2, -50);
delay(800);
Motor.speed(MOTOR1, 50);
Motor.speed(MOTOR2, 50);
M5.Lcd.setCursor(10,150);
M5.lcd.print("Danger!");
delay(800);
} else {
Motor.speed(MOTOR1, 0);
Motor.speed(MOTOR2, 0);
}
delay(300);
}
それでは動作させてみましょう。先ほどと同様に、同じWi-Fi環境に入って、M5Stackと接続します。ジョイスティックを前後左右に動かすと、それに応じてM5Stackの方も動いたでしょうか?壁に近づいたり、机から落ちそうになるとそれを避けようとするのは、前回と同様です。

動いている動画はこちらです。モータの接続方法に合わせて、回転の向きや回転数、速度などを調整してみてください。
4. まとめ
今回の連載では、M5Stackを使ってリモコンカーを自動運転させるための工作を紹介してきました。
スマホからM5Stackに接続できるアプリBlynkを使うと、簡単にスマホ上から操作できる機能を追加できます。ボタンとM5Stackのスピーカを連動させたり、ジョイスティックで前後左右移動できるようになりました。
BlynkのWidgetはいろいろなものがあるので、M5Stackのセンサなどに合わせて、もっと多様な機能を付けてみるのも面白いかもしれません。物との近接度や温湿度センサで測定した値などを表示する方法も考えられますね。
ぜひ、やりたいことに合わせていろいろ工夫してみてください!最後までお読み頂きありがとうございました!
今回の連載の流れ
第1回:小型Arduino互換機(M5Stack)で電子工作を楽しむ
第2回:M5Stackでモータドライバを使う
第3回:M5Stackでセンサを使って自動運転と自動回避機能を搭載
第4回:M5Stackをスマホと連動させてコントロールする(今回)
