知的好奇心 for IoT

IoT関連の知的好奇心を探求するブログです

<日本で入手できる部品で>ESP8266とモータードライバを使ってBlynkで操作するキャタピラ車を作ってみた

前回の記事では、WeMos D1 miniとMotor Shieldを使ってキャタピラ車のモーターを制御してみました。Motor ShieldはI2Cインターフェース対応で制御用にピンを2つしか消費しないエコな作りになっている上に、用意されているライブラリを使って非常に簡単にモーターを制御することができます。

しかーし、いかんせん、日本で売ってなくて入手の敷居が高いという問題がありました。

そこで、日本で入手可能な部品で作るとどうなるか試してみることにしました。

 

ブレッドボード版キャタピラ車

f:id:IntellectualCuriosity:20171024000443j:plain

 

代わりに使ったもの

WeMos D1 miniとMotor Shieldの代わりに、ブレッドボードで作った回路に使用した部品のリストです。

今回メインの「TB6612使用 Dual DCモータードライブキット」はMotor Shieldと同じTB6612を使用していて、ブレッドボードで使えるように基板に半田付けされています。

また、今回は電源を1つに統合しました。モーター用に単三電池2本、WeMos D1 mini用にモバイルバッテリーを使用してたのを、レギュレーターを使ってモーターとESP8266の両方に電源を供給することで、モバイルバッテリーだけで動作するようにしました。

※2017/12/28追記

ダイソーで300円で買えるモバイルバッテリーは過電流保護回路が付いているらしく、1電源で使用していると電流供給がストップすることが多々あります。このモバイルバッテリーの仕様は1Aとなっているので、2A程度の電流供給能力のあるモバイルバッテリーであれば1電源で使えると思います。

また、秋月電子ESP-WROOM-02開発ボードは、ハズレを引くと外部電源での動作が安定しなくなります。FAQ参照。FAQにはTXDをプルアップするとありますが、この対処を行ってもスケッチが動作しないことが多々ありました。

 

実写回路

f:id:IntellectualCuriosity:20171024161151j:plain

ブレッドボード配線図

f:id:IntellectualCuriosity:20171024161346p:plain

配線表

TB6612 ESP8266 MOTOR
PWMA GPIO14  
AIN2 GPIO13  
AIN1 GPIO12  
VCC 3V3  
STBY GPIO2  
GND GND  
BIN1 GPIO15  
BIN2 GPIO4  
PWMB GPIO5  
A01   Motor Right +
A02   Motor Right -
B02   Motor Left -
B01   Motor Left +
GND GND  
VM 3V3  

 

テストコース試走映像

スマホのBlynk Joystick操作はクラウドサーバー経由でESP8266に届きますが、動作は非常にスムーズです。Motor Shieldの時は反応が悪かったので原因を探ってみたら、Motor Shieldのライブラリに記述されていたdelay(100);が原因でした。

 

スケッチ

TB6612の真理値表

IN1 IN2 PWM STBY MODE
H H H/L H SHORT BREAK
L H H H CCW
L H L H SHORT BREAK
H L H H CW
H L L H SHORT BREAK
L L H H STOP
H/L H/L H/L L STANDBY

TB6612の真理値表に従って、TB6612の入力端子に繋がっているESP8266のGPIOを制御すればモーターを動かすことができますが、前回WeMos Motor Shield用のスケッチ作りましたので、それを活かせるようにMotor Shieldライブラリのクラスと同じ仕様のクラスにTB6612のGPIO制御を書いてみました。

BlynkTankスケッチの#include <WEMOS_Motor.h>#include "TB6612_Motor.h"に変更して、次の2つのファイルをBlynkTankスケッチフォルダに保存すれば動作します。

TB6612_Motor.h

/*
 * TB6612_Motor.h
 * October 24, 2017
 * By Hiroyuki ITO
 * http://intellectualcuriosity.hatenablog.com/
 * MIT Licensed.
 *
 * This file was created with reference to "WEMOS_Motor.h".
 * Thanks to WEMOS Electronics for publishing a great library.
 *
*/
#define _MOTOR_A     0
#define _MOTOR_B     1

#define _SHORT_BRAKE 0
#define _CCW         1
#define _CW          2
#define _STOP        3
#define _STANDBY     4

class Motor {
public:
  Motor(uint8_t address, uint8_t motor, uint32_t freq);
  void setmotor(uint8_t dir, uint8_t pwm_val);
  void setmotor(uint8_t dir);
private:
  uint8_t _motor;
};

TB6612_Motor.ino

/*
 * TB6612_Motor.ino
 * October 24, 2017
 * By Hiroyuki ITO
 * http://intellectualcuriosity.hatenablog.com/
 * MIT Licensed.
 *
 * This file was created with reference to "WEMOS_Motor.cpp".
 * Thanks to WEMOS Electronics for publishing a great library.
 *
*/
// GPIO Define
#define PIN_AIN1 12
#define PIN_AIN2 13
#define PIN_PWMA 14
#define PIN_BIN1 15
#define PIN_BIN2  4
#define PIN_PWMB  5
#define PIN_STBY  2

/*
 * Motor()
 * address:
 *   DUMMY
 * freq:
 *   PWM's frequency
*/
Motor::Motor(uint8_t address, uint8_t motor, uint32_t freq) {
  _motor = motor;
  pinMode(PIN_STBY, OUTPUT);
  digitalWrite(PIN_STBY, LOW);
  pinMode(PIN_AIN1, OUTPUT);
  pinMode(PIN_AIN2, OUTPUT);
  pinMode(PIN_PWMA, OUTPUT);
  pinMode(PIN_BIN1, OUTPUT);
  pinMode(PIN_BIN2, OUTPUT);
  pinMode(PIN_PWMB, OUTPUT);
  analogWriteFreq(freq);
  analogWriteRange(100);
}

/*
 * setmotor() -- set motor
 * dir:
 *   _SHORT_BRAKE 0
 *   _CCW         1
 *   _CW          2
 *   _STOP        3
 *   _STANDBY     4
 * pwm_val:
 *   0 - 100 (%)
*/
void Motor::setmotor(uint8_t dir, uint8_t pwm_val) {
  if (_motor == _MOTOR_A) {
    switch (dir) {
      case _SHORT_BRAKE :
        digitalWrite(PIN_AIN1, HIGH);
        digitalWrite(PIN_AIN2, HIGH);
        break;
      case _CCW :
        digitalWrite(PIN_AIN1, LOW);
        digitalWrite(PIN_AIN2, HIGH);
        digitalWrite(PIN_STBY, HIGH);
        break;
      case _CW :
        digitalWrite(PIN_AIN1, HIGH);
        digitalWrite(PIN_AIN2, LOW);
        digitalWrite(PIN_STBY, HIGH);
        break;
      case _STOP :
        digitalWrite(PIN_AIN1, LOW);
        digitalWrite(PIN_AIN2, LOW);
        break;
      case _STANDBY :
        digitalWrite(PIN_STBY, LOW);
        break;
    }
    analogWrite(PIN_PWMA, pwm_val);
  } else {
    switch (dir) {
      case _SHORT_BRAKE :
        digitalWrite(PIN_BIN1, HIGH);
        digitalWrite(PIN_BIN2, HIGH);
        break;
      case _CCW :
        digitalWrite(PIN_BIN1, LOW);
        digitalWrite(PIN_BIN2, HIGH);
        digitalWrite(PIN_STBY, HIGH);
        break;
      case _CW :
        digitalWrite(PIN_BIN1, HIGH);
        digitalWrite(PIN_BIN2, LOW);
        digitalWrite(PIN_STBY, HIGH);
        break;
      case _STOP :
        digitalWrite(PIN_BIN1, LOW);
        digitalWrite(PIN_BIN2, LOW);
        break;
      case _STANDBY :
        digitalWrite(PIN_STBY, LOW);
        break;
    }
    analogWrite(PIN_PWMB, pwm_val);
  }
}

void Motor::setmotor(uint8_t dir) {
  setmotor(dir, 100);
}

 

おわり