LoginSignup
10
7

More than 3 years have passed since last update.

M5Stackでスマホから操作できるラジコンを作ってみた

Posted at

概要

マイコンを使ってなにか作りたいな〜と思い、ラジコンを作ってみます。
電子工作の入門の1つとしていい題材になるのではないかと思います。

IMB_bXGkmj.GIF

目標

スマホから操作できるラジコンを作ること。

開発環境

  • OS: macOS Mojave
  • IDE: Visual Studio Code + PlatformIO(拡張機能)
  • その他: スマホからの操作にはBlynkを使用

部品の購入

今回使用したもの

合計で1万円くらいになりますね...安くはないけど高くもないです。。
まぁM5Stackは色んな所に使えるので実質0円ですね!

モバイルバッテリー

5Vが出力されればなんでもいいと思いますが、今回使用したのは自動パワーOFFモードがないもの。
最近のモバイルバッテリーは電流を一定以上引いていないときは自動的にパワーOFFしてくれる機能がついているものが多いですが、マイコン系にいたっては消費電流が少なく意図せずOFFしてしまう事があるため注意です。

ロボットカーキット

ハードを作るのは色々と大変なので、キットを選択しました。モーター、タイヤ、シャシー、コントローラがついており、モーターは連続回転サーボなので制御も簡単なのではないかと思います。
自作する場合はそれぞれの部品を個別に購入する必要があり、シャシーに至っては3Dプリンタで出力するなりホームセンターで部材を買って加工する必要があるので最初はキットを選んでおくと楽です。

M5Stack GRAY

マイコンは今流行のM5Stackを選択。少し値はしますがIMUやLCD等が搭載されているため別途購入が不要ですぐ使えるのでいろんなところに転用できます。決して無駄な出費ではない!はず

組み立て

説明書を見ながらキットを組み立て、モバイルバッテリーとM5Stackをいい感じに固定します。
いいものが周りになかったのでジャンパーワイヤーで固定しています(笑)

信号線は右側を2ピン、左側を5ピンに接続しました。電源線は5VとGNDに接続しています。

IMG_7227.jpg

動かしてみる

パラメータ計算

ロボットカーキットのデータシートに2つの大事なことが書かれていました。
1. Highレベルのパルス幅の時間が1000~1480μsならCCW回転1480~1520μsならCW回転1520~2000μsならCW回転
2. パルス周期は20msは確保すること

これにより、パルス周期が20msとなるためにPWM周波数を50Hzに設定。それぞれの回転方向のデューティー比を算出し、コードを作成しました。

IMG_3731.jpg

プログラミング

モーターの回転方向が違う場合は配線を反転させるかソースコードのcw, ccwを逆にしてあげてください
M5Stackのボタンを押すことでサーボが回転すれば成功です!

main.cpp
#include <Arduino.h>
#include <M5Stack.h>

//PIN設定
const int PIN_MOTOR_RH = 2;
const int PIN_MOTOR_LH = 5;

const int PIN_BUTTON_A = 39;
const int PIN_BUTTON_B = 38;
const int PIN_BUTTON_C = 37;

//PWMの設定
const double PWM_FREQ = 50;  // PWMの周波数
const uint8_t PWM_BITS = 16; // PWMの分解能

// プロトタイプ宣言
void goStraight();
void turnRight();
void turnLeft();
void stop();

// パラメータ
int param_cw = 5243;   // 正回転 (パルス幅1600usecねらい)
int param_ccw = 4587;  // 逆回転 (パルス幅1400usecねらい)
int param_stop = 4915; // 停止 (パルス幅1500usecねらい)

// variables
String myStatus = "";

void setup()
{

  // LCD設定
  M5.begin();
  M5.Lcd.setBrightness(100);
  M5.Lcd.setTextSize(2);
  M5.Lcd.setTextColor(WHITE, BLACK);

  // ピン設定
  pinMode(PIN_MOTOR_RH, OUTPUT);
  pinMode(PIN_MOTOR_LH, OUTPUT);

  pinMode(PIN_BUTTON_A, INPUT);
  pinMode(PIN_BUTTON_B, INPUT);
  pinMode(PIN_BUTTON_C, INPUT);

  //PWMチャンネル設定
  ledcSetup((uint8_t)1, PWM_FREQ, PWM_BITS);
  ledcSetup((uint8_t)2, PWM_FREQ, PWM_BITS);

  //モータのピンとチャンネルの設定
  ledcAttachPin(PIN_MOTOR_RH, 1);
  ledcAttachPin(PIN_MOTOR_LH, 2);
}

void loop()
{
  // ボタンの入力を取得
  bool buttonA = !digitalRead(PIN_BUTTON_A);
  bool buttonB = !digitalRead(PIN_BUTTON_B);
  bool buttonC = !digitalRead(PIN_BUTTON_C);

  if (buttonA)
  {
    if (myStatus != "right")
    {
      turnRight();
      myStatus = "right";
    }
  }
  else if (buttonB)
  {
    if (myStatus != "straight")
    {
      goStraight();
      myStatus = "straight";
    }
  }
  else if (buttonC)
  {
    if (myStatus != "left")
    {
      turnLeft();
      myStatus = "left";
    }
  }
  else
  {
    if (myStatus != "stop")
    {
      stop();
      myStatus = "stop";
    }
  }
}

void goStraight()
{
  M5.Lcd.clear();
  M5.Lcd.setCursor(0, 20);
  M5.Lcd.printf("Go straight\n");
  ledcWrite(1, param_cw);
  ledcWrite(2, param_ccw);
}

void turnRight()
{
  M5.Lcd.clear();
  M5.Lcd.setCursor(0, 20);
  M5.Lcd.printf("Turn right\n");
  ledcWrite(1, param_stop);
  ledcWrite(2, param_ccw);
}

void turnLeft()
{
  M5.Lcd.clear();
  M5.Lcd.setCursor(0, 20);
  M5.Lcd.printf("Turn left\n");
  ledcWrite(1, param_cw);
  ledcWrite(2, param_stop);
}

void stop()
{
  M5.Lcd.clear();
  M5.Lcd.setCursor(0, 20);
  M5.Lcd.printf("Stop\n");
  ledcWrite(1, param_stop);
  ledcWrite(2, param_stop);
}

スマホから操作できるようにする

どうやってスマホから操作するか

スマホとM5StackをBLE接続してデータを送信し、操作できるようにしたいですが、UIやBLE通信を実装するのは知識がないと難しそうなので簡単にできる方法の1つであるBlynkを使おうと思います。

UIの作成

BlynkでUIを作成していきます、こちらの手順は「BlynkとM5Stackをつなぐ」を参考にします。

IMG_7231.PNG

マイコン側のプログラミング

Blynkのライブラリを導入し、ボタンの情報を受取って動作するようなプログラムに変更していきます

main.cpp
#include <Arduino.h>
#include <M5Stack.h>
#include <BlynkSimpleEsp32_BLE.h>

char blynkAuth[] = "auth keyを入力";

//PIN設定
const int PIN_MOTOR_RH = 2;
const int PIN_MOTOR_LH = 5;

const int PIN_BUTTON_A = 39;
const int PIN_BUTTON_B = 38;
const int PIN_BUTTON_C = 37;

//PWMの設定
const double PWM_FREQ = 50;  // PWMの周波数
const uint8_t PWM_BITS = 16; // PWMの分解能

// プロトタイプ宣言
void goStraight();
void turnRight();
void turnLeft();
void stop();

// パラメータ
int param_cw = 5250;   // 正回転 (パルス幅1600usecねらい)
int param_ccw = 4580;  // 逆回転 (パルス幅1400usecねらい)
int param_stop = 4915; // 停止 (パルス幅1500usecねらい)

// variables
String myStatus = "";

// Blynkから受信するデータの変数
int v1 = 0;
int v2 = 0;
int v3 = 0;

// blynk functions
BLYNK_WRITE(V1)
{
  v1 = param.asInt();
}

BLYNK_WRITE(V2)
{
  v2 = param.asInt();
}

BLYNK_WRITE(V3)
{
  v3 = param.asInt();
}

void setup()
{

  // LCD設定
  M5.begin();
  M5.Lcd.setBrightness(100);
  M5.Lcd.setTextSize(2);
  M5.Lcd.setTextColor(WHITE, BLACK);

  // ピン設定
  pinMode(PIN_MOTOR_RH, OUTPUT);
  pinMode(PIN_MOTOR_LH, OUTPUT);

  pinMode(PIN_BUTTON_A, INPUT);
  pinMode(PIN_BUTTON_B, INPUT);
  pinMode(PIN_BUTTON_C, INPUT);

  //PWMチャンネル設定
  ledcSetup((uint8_t)1, PWM_FREQ, PWM_BITS);
  ledcSetup((uint8_t)2, PWM_FREQ, PWM_BITS);

  //モータのピンとチャンネルの設定
  ledcAttachPin(PIN_MOTOR_RH, 1);
  ledcAttachPin(PIN_MOTOR_LH, 2);

  // Blynk設定
  Blynk.setDeviceName("M5Stack_radicon");
  Blynk.begin(blynkAuth);
}

void loop()
{
  // run Blynk proccess
  Blynk.run();

  if (v2)
  {
    if (myStatus != "right")
    {
      turnRight();
      myStatus = "right";
    }
  }
  else if (v1)
  {
    if (myStatus != "straight")
    {
      goStraight();
      myStatus = "straight";
    }
  }
  else if (v3)
  {
    if (myStatus != "left")
    {
      turnLeft();
      myStatus = "left";
    }
  }
  else
  {
    if (myStatus != "stop")
    {
      stop();
      myStatus = "stop";
    }
  }
}

void goStraight()
{
  M5.Lcd.clear();
  M5.Lcd.setCursor(0, 20);
  M5.Lcd.printf("Go straight\n");
  ledcWrite(1, param_cw);
  ledcWrite(2, param_ccw);
}

void turnRight()
{
  M5.Lcd.clear();
  M5.Lcd.setCursor(0, 20);
  M5.Lcd.printf("Turn right\n");
  ledcWrite(1, param_stop);
  ledcWrite(2, param_ccw);
}

void turnLeft()
{
  M5.Lcd.clear();
  M5.Lcd.setCursor(0, 20);
  M5.Lcd.printf("Turn left\n");
  ledcWrite(1, param_cw);
  ledcWrite(2, param_stop);
}

void stop()
{
  M5.Lcd.clear();
  M5.Lcd.setCursor(0, 20);
  M5.Lcd.printf("Stop\n");
  ledcWrite(1, param_stop);
  ledcWrite(2, param_stop);
}

動作確認

M5Stackへソースコードを書き込みます。
Blynkアプリから作成したUIを開き、BLEウィジェットをタップしてM5Stakとコネクトします。
RUNボタンでBlynkを動かし、ボタンを押したりすることでラジコンが動けば成功です!
遠隔コントロール部分がこんなに簡単に実現できるのは本当にありがたいですね!

IMB_bXGkmj.GIF

10
7
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
7