以前、次のような記事を書いたのですが、このロボット、対象年齢が10歳以上っと書いてある割には作るのが大変で時間がかかるんです。特にギアボックスがっ!
それで、もっと簡単で安く動くものを作ることができないかなぁと思っていたんです。
そうしたら、たまたま秋月電子で良さげなものを見つけました。
早速作って見た結果がこれです!
既に秋月電子の製品ぺージを見ている人は”あれっ?”という印象を持ったと思いますが、下の写真のようにマニュアルではタイヤの方が後ろになっています。
しかし、よく考えてください。小さい球の付いたベアリングホイールが前だと、ちょっとした障害物にも引っかかってしまいますよね?移動は前に進むことが圧倒的に多いので、前進しやすい状態にするためにぼくは前後を逆にしたんです。
動作ビデオ
回路
タミヤのロボットの時と使っている部品は同じで、両目のLEDを外しただけなので、回路は殆ど変わっていません。
ただ、筐体が小さくなったのに合わせて、小さいブレッドボードと単4電池3本用の電池ボックスに変更しています。(電池はニッケル水素1.2Vでないとダメですよ。1.5Vの電池だと3本で4.5Vになってしまうので、WeMos D1 miniやモーターの動作電圧を上回ってしまいます。)
使用部品リスト
- VL53L0X使用 レーザー測距センサモジュール(ToF) 1,080円(税込)
- DRV8835使用ステッピング&DCモータドライバモジュール 300円(税込)
- ブレッドボード BB-601 130円(税込)
- 電池ボックス 単4×3本 リード線・フタ・スイッチ付 120円(税込)
- WeMos D1 mini (ESP8266) 950円(税別)
Blynkアプリ
今回は追っかけ機能はやめて、レーザー距離センサは衝突防止・後ずさり用に使っているので、Blynkのウィジェットは操作用のジョイスティックと距離表示だけにしています。
JoystickとGaugeの配置
JoystickとGaugeの設定
スケッチ
スケッチはタミヤのロボットのものをベースに、クルクル回りやすくなっているので左右の動作を緩慢にしたり 、衝突防止・後ずさり動作とジョイスティック操作を両立するように工夫しています。
/* * Robot2.ino * June 15, 2019 * By Hiroyuki ITO * http://intellectualcuriosity.hatenablog.com/ * MIT Licensed. */ #define BLYNK_PRINT Serial #include <ESP8266WiFi.h> #include <BlynkSimpleEsp8266.h> #include <Wire.h> #include <Adafruit_VL53L0X.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 // D5 Right Motor Blue #define PIN_AIN2 12 // D6 Right Motor Yellow #define PIN_BIN1 13 // D7 Left Motor Yellow #define PIN_BIN2 15 // D8 Left Motor Blue // PWM #define PWM_FREQ 1000 // PWM frequency: 1000Hz(1kHz) #define PWM_RANGE 100 // PWM range: 100 // Distance #define RANGE_REVERSE 100 // 100 mm #define RANGE_STOP 200 // 200 mm // VL53L0X Adafruit_VL53L0X lox = Adafruit_VL53L0X(); // Global int mr_pwm = 0; // Right motor speed int ml_pwm = 0; // Left motor speed int distance = 0; // Ranging distance int x = 0; // Joystick x axis int y = 0; // Joystick y axis boolean Reverse_flag = false; BlynkTimer timer; VL53L0X_RangingMeasurementData_t measure; /* * ABS Function */ int setABS(int pwm_value) { pwm_value = abs(pwm_value); if (pwm_value != 0) { pwm_value = pwm_value; if (pwm_value > 100) { pwm_value = 100; } } return pwm_value; } /* * Set Motor */ void setMotor() { // 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); } } /* * Keep Distance */ void keepDistance() { if (Reverse_flag) { mr_pwm = 0; ml_pwm = 0; Reverse_flag = false; } lox.rangingTest(&measure, false); // pass in 'true' to get debug data printout! if (measure.RangeStatus != 4) { // phase failures have incorrect data distance = measure.RangeMilliMeter; if (distance < RANGE_REVERSE) { // Less than 100 mm mr_pwm = -100; ml_pwm = -100; Reverse_flag = true; } } else { distance = 9999; // dummy value } if (distance > RANGE_STOP || y < 0) { // Greater than 200 mm or Reverse if (y > -1 ) { // Forward mr_pwm = y; ml_pwm = y + x; } else { // Reverse mr_pwm = y + x; ml_pwm = y; } } setMotor(); } /* * Send Distance */ void sendDistance() { Blynk.virtualWrite(V2, distance); BLYNK_LOG2("sendDistance: ", distance); } /* * Joystick x axis, y axis */ BLYNK_WRITE(V1) { x = param[0].asInt(); // Joystick x axis y = param[1].asInt(); // Joystick y axis BLYNK_LOG2("Joystick x:", x); BLYNK_LOG2("Joystick y:", y); } void setup() { delay(10); Serial.begin(74880); // Initialize GPIO pinMode(PIN_AIN1, OUTPUT); pinMode(PIN_AIN2, OUTPUT); pinMode(PIN_BIN1, OUTPUT); pinMode(PIN_BIN2, OUTPUT); // Initialize PWM analogWriteFreq(PWM_FREQ); analogWriteRange(PWM_RANGE); // Initialize VL53LOX lox.begin(); // Connect WiFi and Blynk cloud server Blynk.begin(auth, ssid, pass); timer.setInterval(100L, keepDistance); // 100 msec timer.setInterval(1000L, sendDistance); // 1000 msec } void loop() { Blynk.run(); timer.run(); }
おわり