IoTサービス「Blynk」を携帯電話にインストールし、これをロボットカーのコントローラにして、小型Wi-Fiモジュール「ESP-8266」で動作するロボットカーを作成します。ロボットカーのシャーシは、タミヤの「ダブルギヤボックス」を使用します。関連するリンクを次に示します。

ロボットカーの構成

作成したロボットカーの画像を次に示します。車体は、タミヤのユニバーサルプレートにダブルギヤボックスを取り付けます。ユニバーサルプレートには電池ホルダーと基板を取り付けます。基板に取り付けた赤基板はモータードライバ「TB6612FNG」で、青基板は小型Wi-Fiモジュール「ESP-8266」です。電池ホルダーは車体の後ろに2段に積み重ね、2種類使用しています。ESP-8266用には単三6本(9V)を降圧して3.3Vにし、モータ用には単三4本(6V)を、PWMにより3Vで使用しています。コネクタは、左右の車輪用のモータへの電源、電池からESP-8266用とモータ用で4個のコネクタを基板に取り付けます。オレンジ色のLEDは、コントローラと接続しているかを確かめるために使用します。基板の後ろ端には、スライドスイッチを設けて電源をON/OFFし、基板の中央にあるRSETスイッチによりロボットカーをリセットします。

ESP-8266でロボットカー

ESP-8266でロボットカー

車体に使用したタミヤの部品については、「ESP8266とモータードライバ「TB6612FNG」とタミヤの「ダブルギヤボックス」を使ったモータ制御」を参照してください。

ESP8266とモータードライバ「TB6612FNG」のモーターを制御する信号ピン6本は、次にように接続します。

ESP8266とTB6612FNGのモーター制御信号ピン
ESP8266 TB6612FNG
3.3V VCC
GND GND(2か所)
IO2 PWMA
IO13 AIN1
IO15 AIN2
IO5 PWMB
IO4 BIN2
IO14 BIN1
IO12 STBY



1. STBYへの信号は、ESP-8266をリセットするとアクティブになりロボットカーが暴走するので、トランジスタ(2SA1015)を使って極性を反対にします。詳細については「ESP8266のリセット時の各ピンの信号レベルとPWMの設定方法」を参照してください。
2. VCCへは、単三電池9VをDC/DCコンバータ(AMS1117-3.3モジュール)で3.3Vに降圧して供給します。電池の容量が少ないと、モーターを動かすときにESP-8266がリセットが頻発します(4本ではダメ)。

次に左右のモーターからのケーブルとモータードライバー「TB6612FNG」の出力ピンは、次のように接続します。

モーターからTB6612FNGの出力ピン
モーター TB6612FNG
5V          VM
左モーター黒ケーブル AOUT1
左モーター赤ケーブル AOUT2
右モーター赤ケーブル BOUT1
右モーター黒ケーブル BOUT2

その他にLEDをIO16に接続し、リセットボタンをResetに接続します。

Blynkによるコントローラの作成

AQUOS PAD「SH-08E」でBlynkを起動し、LEDとジョイスティックのWidgetを次のように配置します。なお、Blynkのインストールおよび設定については、「Raspberry Pi 3にBlynkサーバの構築」に示します。

Blynkによるロボットカーのコントローラ

ジョイスティックは次のように設定し、ジョイスティックの動きにより、エンコードされたx/yデータが-100から100の値をとるように設定します。

Blynkによるロボットカーのコントローラ

ESP-8266のプログラム

ESP8266とモータードライバ「TB6612FNG」とタミヤの「ダブルギヤボックス」を使ったモータ制御」で作成したESP-8266のプログラムに、Blynkから渡されるジョイスティックデータに従いモータを制御する機能を追加します。Blynkのジョイスティックを前方に動かすと前進し、後方に動かすと後進し、右に動かすと右折し、左に動かすと左折、ジョイスティックを動かさないと停止します。曲がり方は、右上にすると前進右折となり、右下にすると後進右折等となります。ジョイスティックの動きが中心から小さいと無効のデータとして捨てられます。

carrobot.ino

// TB6612FNG
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>

#define INVALID 30  // 無効エリア
#define SPEED 60  


// Set Blynk Auth Token and WiFi credentials.
const char *auth = "xxxx";
const char *ssid = "xxxx";
const char *pass = "xxxx";

// DRV8835
// GPIO
#define AIN1 13  // Right Motor Blue
#define AIN2 15  // Right Motor Yellow
#define PWMA 2
#define BIN1 14  // Left  Motor Yellow
#define BIN2 5   // Left  Motor Blue
#define PWMB 4
#define STBY 12

// PWN
#define PWN_FREQ 1000 // PWM frequency: 1000Hz(1kHz)
#define PWN_RANGE 100 // PWN range: 100

// Joystick x axis, y axis
BLYNK_WRITE(V1) {
  int x = param[0].asInt(); // Joystick x axis
  int y = param[1].asInt(); // Joystick y axis

//  Serial.print("x:");
//  Serial.println(x);
//  Serial.print("y:");
//  Serial.println(y);

  if ((x == 0) && (y == 0)) {
    // 停止
    digitalWrite(AIN1, HIGH);
    digitalWrite(AIN2, LOW);
    analogWrite(PWMA, 0);
    digitalWrite(BIN1, HIGH);
    digitalWrite(BIN2, LOW);
    analogWrite(PWMB, 0);
//    Serial.println("Stop");
  }
  else if ((abs(x) < INVALID) && (abs(y) < INVALID)) {
    // 無効エリア
//    Serial.println("Invalid Area");
  }
  else if ((y > 0) && (x > INVALID)) {
    // 前進右回り
    digitalWrite(AIN1, LOW);
    digitalWrite(AIN2, HIGH);
    analogWrite(PWMA, SPEED);
    digitalWrite(BIN1, LOW);
    digitalWrite(BIN2, HIGH);
    analogWrite(PWMB, SPEED/2);
//    Serial.println("Forward Right");
  }
  else if ((y > 0) && (x < -INVALID)) {
    // 前進左回り
    digitalWrite(AIN1, LOW);
    digitalWrite(AIN2, HIGH);
    analogWrite(PWMA, SPEED/2);
    digitalWrite(BIN1, LOW);
    digitalWrite(BIN2, HIGH);
    analogWrite(PWMB, SPEED);
//    Serial.println("Forward Left");
  }
  else if ((y < 0) && (x > INVALID)) {
    // 後進右回り
    digitalWrite(AIN1, HIGH);
    digitalWrite(AIN2, LOW);
    analogWrite(PWMA, SPEED);
    digitalWrite(BIN1, HIGH);
    digitalWrite(BIN2, LOW);
    analogWrite(PWMB, SPEED/2);
//    Serial.println("Back Right");
  }
  else if ((y < 0) && (x < -INVALID)) {
    // 後進左回り
    digitalWrite(AIN1, HIGH);
    digitalWrite(AIN2, LOW);
    analogWrite(PWMA, SPEED/2);
    digitalWrite(BIN1, HIGH);
    digitalWrite(BIN2, LOW);
    analogWrite(PWMB, SPEED);
//    Serial.println("Back Left");
  }
  else if (y > 0) {
    // 前進
    digitalWrite(AIN1, LOW);
    digitalWrite(AIN2, HIGH);
    analogWrite(PWMA, SPEED);
    digitalWrite(BIN1, LOW);
    digitalWrite(BIN2, HIGH);
    analogWrite(PWMB, SPEED);
//    Serial.println("Forward");
  }
  else if (y < 0) {
    // 後進
    digitalWrite(AIN1, HIGH);
    digitalWrite(AIN2, LOW);
    analogWrite(PWMA, SPEED);
    digitalWrite(BIN1, HIGH);
    digitalWrite(BIN2, LOW);
    analogWrite(PWMB, SPEED);
//    Serial.println("Back");
  }
  digitalWrite(STBY, LOW);
}

void setup() {
  delay(10);
//  Serial.begin(9600);
//  Serial.println("start!");

  // Initialize GPIO mode
  pinMode(AIN1, OUTPUT);
  pinMode(AIN2, OUTPUT);
  pinMode(BIN1, OUTPUT);
  pinMode(BIN2, OUTPUT);
  pinMode(STBY, OUTPUT);

  // Initialize PWN
  analogWriteFreq(PWN_FREQ);
  analogWriteRange(PWN_RANGE);

  digitalWrite(STBY, HIGH);
  digitalWrite(AIN1, LOW);
  digitalWrite(AIN2, LOW);
  analogWrite(PWMA, 0);
  digitalWrite(BIN1, LOW);
  digitalWrite(BIN2, LOW);
  analogWrite(PWMB, 0);

  // Connect WiFi and Blynk cloud server
  Blynk.begin(auth, ssid, pass);
}

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

ロボットカーの走行

基板のスライドスイッチをオンにすると、DC/DCコンバータのLEDが点灯し、DC/DCコンバータが電池から入力した9Vを3.3Vに変換し、ESP-8266の電源に供給します。同時に、モーターの電源として電池から4.5VがTB6612FNGに供給されます。Blynkを起動し、LEDのボタンを押すと、基板上のLEDが点滅します。Blynkのジョイスティックを回すと、ジョイスティックの動きに応じてロボットカーが走行します。