ある日、秋月電子さんの通販サイトを見ていたら、面白そうなデザインのTAMIYAの工作セットが幾つか登録されいるのを見つけました。
レスキュークローラーとブルドーザーは結構前から発売されていて、操作用の有線リモコンがセットになっています。
カムプログラムロボットは最近発売されたもので、オルゴールっぽい仕組みでギアの付いた棒に突起を付けてプログラムするようになっています。
デザイン的にはレスキュークローラーにかなり魅力を感じたのですが、IoT化するとリモコンが無駄になってしまうため、初めからマイコンボードでのコントロールも想定した作りになっているカムプログラムロボットをIoT化してみることにしました。
IoT化したカムプログラムロボット
使ったもの
カムプログラムロボットのIoT化で追加したものの一覧です。
- ESP-WROOM-02開発ボード 秋月電子
※製品のFAQに書いている対処を行っても外部電源ではスケッチが動かないことがあります。 - 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モードの真理値表はこのようになっています。
でも、カムプログラムロボットに付属しているモーター(たぶんFA-130RA)も含め、日本のモーターはCCW(反時計回り)のため、CW(正転)とCCW(逆転)が逆になります。
データシートの裏面に書かれているサンプルプログラムは、日本仕様のモーター用になっているらしく、真理値表と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によるアナログ値が入力できるようになっています。
回路図
バッテリー
バッテリーに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つ配置しました。
プロジェクトレイアウト
Joystick Widget
Button Widget左目用
Button Widget右目用
スケッチ
スケッチはいたってシンプルです。
工夫しているところは、JoystickのX軸とY軸の値をシンプルなロジックで左右のモーター の前後の動きに対応させていることぐらいです。
PWM制御の初期化として周波数を設定する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
// PWM
#define PWM_FREQ 1000 // PWM frequency: 1000Hz(1kHz)
#define PWM_RANGE 100 // PWM range: 100
// LED GPIO
#define PIN_EYER 4 // Right LED
#define PIN_EYEL 5 // Left LED
// ABS Function
int setABS(int pwm_value) {
pwm_value = abs(pwm_value);
if (pwm_value > 100) {
pwm_value = 100;
}
return pwm_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_pwm; // Right motor speed
int ml_pwm; // Left motor speed
// Forward or Reverse ?
if (y > -1 ) {
mr_pwm = y - x;
ml_pwm = y + x;
} else {
mr_pwm = y + x;
ml_pwm = y - x;
}
// Right Motor
if (mr_pwm > -1) {
// CW Forward
analogWrite(PIN_AIN1, 0);
analogWrite(PIN_AIN2, setABS(mr_pwm));
} else {
// CCW Reverse
analogWrite(PIN_AIN1, setABS(mr_pwm));
analogWrite(PIN_AIN2, 0);
}
// Left Motor
if (ml_pwm > -1) {
// CW Forward
analogWrite(PIN_BIN1, 0);
analogWrite(PIN_BIN2, setABS(ml_pwm));
} else {
// CCW Reverse
analogWrite(PIN_BIN1, setABS(ml_pwm));
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 PWM
analogWriteFreq(PWM_FREQ);
analogWriteRange(PWM_RANGE);
// Connect WiFi and Blynk cloud server
Blynk.begin(auth, ssid, pass);
}
void loop() {
Blynk.run();
}
おわり