知的好奇心 for IoT

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

ESP8266とDRV8835とBlynkを使ってTAMIYAのカムプログラムロボットをIoT化した

ある日、秋月電子さんの通販サイトを見ていたら、面白そうなデザインのTAMIYAの工作セットが幾つか登録されいるのを見つけました。

レスキュークローラーとブルドーザーは結構前から発売されていて、操作用の有線リモコンがセットになっています。

カムプログラムロボットは最近発売されたもので、オルゴールっぽい仕組みでギアの付いた棒に突起を付けてプログラムするようになっています。

デザイン的にはレスキュークローラーにかなり魅力を感じたのですが、IoT化するとリモコンが無駄になってしまうため、初めからマイコンボードでのコントロールも想定した作りになっているカムプログラムロボットをIoT化してみることにしました。

f:id:IntellectualCuriosity:20180410172302j:plain

IoT化したカムプログラムロボット

 

使ったもの

カムプログラムロボットのIoT化で追加したものの一覧です。

  • ESP-WROOM-02開発ボード 秋月電子
  • DRV8835使用ステッピング&DCモータドライバモジュール 秋月電子
  • 抵抗内蔵5mm黄緑色LED(5V用) OSG8NU5B64A-5V(10個入) 秋月電子
  • ブレッドボード BB-801 秋月電子
  • ブレッドボード・ジャンパーワイヤ(オス-オス)10cmセット 秋月電子
  • 電池ボックス 単3×3本 リード線・フタ・スイッチ付 秋月電子
  • ニッケル水素充電池 単3×3本 100均ショップ
  • 線材 少々
  • 熱収縮チューブ 少々

いつもながら、ほぼ秋月電子さんで調達しています。

今回の一番のポイントは、モータードライバを今まで使っていたTB6612からDRV8835に変えたことです。

どちらも1チップで2個のモーターを制御できる優秀なICですが、TB6612が2個のモーターの制御に最低6つのGPIOを使うのに対して、DRV8835は4つのGPIOで済むんです。

ESP8266にはGPIOが9つしかないので、使用するGPIOの数が6つか4つかには大きな違いがあるのです!

でも、DRV8835のデータシートはちょっと不親切なので、最初は少し戸惑ってしまいました。

DRV8835

DRV8835のデータシートに書いてあるIN/INモードの真理値表はこのようになっています。

xIN1 xIN2 xOUT1 xOUT2 FUNCTION
0 1 L H CCW 逆転
1 0 H L CW 正転
1 1 L L BREAK ブレーキ

でも、カムプログラムロボットに付属しているモーター(たぶんFA-130RA)も含め、日本のモーターはCCW(反時計回り)のため、CW(正転)とCCW(逆転)が逆になります。

xIN1 xIN2 xOUT1 xOUT2 FUNCTION
0 1 L H CCW 逆転 CW 正転
1 0 H L CW 正転 CCW 逆転
1 1 L L BREAK ブレーキ

データシートの裏面に書かれているサンプルプログラムは、日本仕様のモーター用になっているらしく、真理値表とCW(正転)とCCW(逆転)が逆になっています。

if (STATUS == 1) { // CCW 逆転
  analogWrite(IN1, PWM_VALUE);
  analogWrite(IN2, 0);
}
if (STATUS == 2) { // CW 正転
  analogWrite(IN1, 0);
  analogWrite(IN2, PWM_VALUE);
}
if (STATUS == 0) { // BREAK ブレーキ
  analogWrite(IN1, 255);
  analogWrite(IN2, 255);
} 

サンプルプログラムでは当然のようにサラッとanalogWriteを使っていますが、xIN1とxIN2はPWMによるアナログ値が入力できるようになっています。

 

回路図

f:id:IntellectualCuriosity:20180412031404p:plain

バッテリー

バッテリーにDURACELLのアルカリ乾電池の絵を使っていますが、実際はニッケル水素充電池です。普通の電池は1.5Vですがニッケル水素充電池は1.2Vなので、必ずニッケル水素充電池を使ってください。

モーター

モーターの配線の色が実際と違います。黄色は同じですが緑ではなく青です。

10kΩ抵抗

ESP-WROOM-02開発ボードのFAQに書いてあるように、Micro USB以外の電源を使うとスケッチが動作しない場合があるって、えー、それ、大問題でしょ!で、その対策としてTxDをプルアップするのに10kΩの抵抗を付けています。

LED

抵抗入りのLEDがあるなんて知らなかったんですが、これを使うと抵抗を使わずに直接GPIOに繋ぐことができます。5V用と書いてありましたが、3.6Vでも明るさの違いはわかりませんでした。

 

Blynkの設定

今回もIoTプラットフォームサービスにBlynkを使っています。

Joystick Widgetの他に両目のLEDを制御するButton Widgetを2つ配置しました。

プロジェクトレイアウト

f:id:IntellectualCuriosity:20180412043118p:plain

Joystick Widget

f:id:IntellectualCuriosity:20180412043422p:plain

Button Widget左目用

f:id:IntellectualCuriosity:20180412043700p:plain

Button Widget右目用

f:id:IntellectualCuriosity:20180412043710p:plain

 

スケッチ

スケッチはいたってシンプルです。

工夫しているところは、JoystickのX軸とY軸の値をシンプルなロジックで左右のモーター の前後の動きに対応させていることぐらいです。

PWN制御の初期化として周波数を設定するanalogWriteFreq()とデューティ比の範囲を設定するanalogWriteRange()を使っています。

/*
 * Robot.ino
 * April 12, 2018
 * By Hiroyuki ITO
 * http://intellectualcuriosity.hatenablog.com/  
 * MIT Licensed.
*/
#define BLYNK_PRINT Serial

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

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

// DRV8835
// GPIO
#define PIN_AIN1 14  // Right Motor Blue
#define PIN_AIN2 12  // Right Motor Yellow
#define PIN_BIN1 13  // Left  Motor Yellow
#define PIN_BIN2 15  // Left  Motor Blue
// PWN
#define PWN_FREQ 1000 // PWM frequency: 1000Hz(1kHz)
#define PWN_RANGE 100 // PWN range: 100

// LED GPIO
#define PIN_EYER 4  // Right LED
#define PIN_EYEL 5  // Left  LED

// ABS Function
int setABS(int pwn_value) {
  pwn_value = abs(pwn_value);
  if (pwn_value > 100) {
    pwn_value = 100;
  }
  return pwn_value;
}

// Joystick x axis, y axis
BLYNK_WRITE(V1) {
  int x = param[0].asInt(); // Joystick x axis
  int y = param[1].asInt(); // Joystick y axis
  int mr_pwn;               // Right motor speed
  int ml_pwn;               // Left  motor speed

  // Forward or Reverse ?
  if (y > -1 ) {
    mr_pwn = y - x; 
    ml_pwn = y + x;
  } else {
    mr_pwn = y + x; 
    ml_pwn = y - x;
  }

  // Right Motor
  if (mr_pwn > -1) {
    // CW Forward
    analogWrite(PIN_AIN1, 0);
    analogWrite(PIN_AIN2, setABS(mr_pwn));
  } else {
    // CCW Reverse
    analogWrite(PIN_AIN1, setABS(mr_pwn));
    analogWrite(PIN_AIN2, 0);
  }

  // Left Motor
  if (ml_pwn > -1) {
    // CW Forward
    analogWrite(PIN_BIN1, 0);
    analogWrite(PIN_BIN2, setABS(ml_pwn));
  } else {
    // CCW Reverse
    analogWrite(PIN_BIN1, setABS(ml_pwn));
    analogWrite(PIN_BIN2, 0);
  }
}

// Left LED Button
BLYNK_WRITE(V2) {
  digitalWrite(PIN_EYEL, param.asInt());
}

// Right LED Button
BLYNK_WRITE(V3) {
  digitalWrite(PIN_EYER, param.asInt());
}

void setup() {
  delay(10);
  Serial.begin(74880);

  // Initialize GPIO mode
  pinMode(PIN_AIN1, OUTPUT);
  pinMode(PIN_AIN2, OUTPUT);
  pinMode(PIN_BIN1, OUTPUT);
  pinMode(PIN_BIN2, OUTPUT);
  pinMode(PIN_EYER, OUTPUT);
  pinMode(PIN_EYEL, OUTPUT);

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

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

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

おわり