M5Stack

Arduino互換機(M5Stack)とセンサで作るミニリモコンカー!【最終回】

M5Stackをスマホと連動させてコントロールする

 

第1回:小型Arduino互換機(M5Stack)で電子工作を楽しむ
第2回:M5Stackでモータドライバを使う
第3回:M5Stackでセンサを使って自動運転と自動回避機能を搭載

 

こんにちは、ヨシケンです!

小型Arduino互換機のM5Stackを使ってリモコンカーを作る本連載。モータードライバを使って前後左右に動くようにしたり、センサで自動運転するようになりましたが、最終回の今回は外部からリモートコントロールできるようにしてみたいと思います。今回は、BlynkというスマホからM5Stackを操作できる仕組みを導入していきます。

arduino-m5stack-remote-control-car-04-01

M5Stackとスマホを連携させたリモコンカー

 

今回の記事の流れ

  1. スマホアプリBlynkの導入
  2. Wi-Fi経由でスマホからM5Stackを操作
  3. モータ操作のジョイスティックを追加
  4. まとめ

 

今回の記事で必要な物一覧

M5Stack Core

ESP32を搭載したArduino互換機

arduino-m5stack-remote-control-car-02

 

Grove I2C モータドライバ

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

arduino-m5stack-remote-control-car-07_01

 

ローム照度・近接センサ (RPR-0521RS)

赤外線を発し光の強度や近接度を計測

arduino-m5stack-remote-control-car-04-02

 

超音波距離センサ (HC-SR04)

超音波を発し距離を測定するモジュール

arduino-m5stack-remote-control-car-03-04

 

小型モーター、車輪など

arduino-m5stack-remote-control-car-08

 

9V電池電池ボックス

arduino-m5stack-remote-control-car-02-02

 

1. スマホアプリのBlynkの導入

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

arduino-m5stack-remote-control-car-04-03

 

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

arduino-m5stack-remote-control-car-04-04

 

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

arduino-m5stack-remote-control-car-04-05

 

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

arduino-m5stack-remote-control-car-04-06

 

これでスマホ、Arduino IDEの両方で、Blynkを使う準備ができました。

 

2. Wi-Fi経由でスマホからM5Stackを操作

M5Stackとスマホをつなげる設定ができたので、それを操作するための機能を画面に追加します。
Blynkアプリの画面を押すと、右側から追加できるWidget(機能)が出てくるので、まずButtonを追加してみます。

arduino-m5stack-remote-control-car-04-07

 

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

arduino-m5stack-remote-control-car-04-08

arduino-m5stack-remote-control-car-04-09

左:ボタンを押していない状態 右:ボタンを押した状態

 

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

arduino-m5stack-remote-control-car-04-10

 

それではArduino IDEでプログラミングをおこないます。まずM5StackのサンプルとしてSpeakerというスケッチ例があるので、それをコピーします。

そこに以下3〜9、13〜22、28〜29、36行目の部分の追記をします。スケッチ中のxxxxの部分に先ほどコピーしたAUTH TOKENを入れます。yyyyとzzzzは自分のWifi環境のユーザ/パスワードになります。またV1のボタンを押したらビープ音が鳴るようにします。

[M5Stack_Speaker_Blynk.ino]

Code-Example
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#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に接続します。画面上でボタンを押すと、ビープ音がすると思います。

arduino-m5stack-remote-control-car-04-11

 

3. モータ操作のジョイスティックを追加

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

arduino-m5stack-remote-control-car-04-12

 

最後に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]

Code-Example
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
#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の方も動いたでしょうか?壁に近づいたり、机から落ちそうになるとそれを避けようとするのは、前回と同様です。

arduino-m5stack-remote-control-car-04-13

 

動いている動画はこちらです。モータの接続方法に合わせて、回転の向きや回転数、速度などを調整してみてください。

 

4. まとめ

今回の連載では、M5Stackを使ってリモコンカーを自動運転させるための工作を紹介してきました。

スマホからM5Stackに接続できるアプリBlynkを使うと、簡単にスマホ上から操作できる機能を追加できます。ボタンとM5Stackのスピーカを連動させたり、ジョイスティックで前後左右移動できるようになりました。

BlynkのWidgetはいろいろなものがあるので、M5Stackのセンサなどに合わせて、もっと多様な機能を付けてみるのも面白いかもしれません。物との近接度や温湿度センサで測定した値などを表示する方法も考えられますね。

ぜひ、やりたいことに合わせていろいろ工夫してみてください!最後までお読み頂きありがとうございました!

 

 

今回の連載の流れ

第1回:小型Arduino互換機(M5Stack)で電子工作を楽しむ
第2回:M5Stackでモータドライバを使う
第3回:M5Stackでセンサを使って自動運転と自動回避機能を搭載
第4回:M5Stackをスマホと連動させてコントロールする(今回)

アバター画像

普通の会社に勤めるサラリーマンですが、モノ作りが好きな週末メイカーで、電子書籍MESHBOOKを出したり、ブログを書いたりしています!

http://blog.ktrips.net

高専ロボコン2015 出場ロボット解剖計画