My seven year old grandson wanted to build a battlebot. He had seen them at a local robotics show. The SMARS looked like a good way for us to learn some basics and provide him with a low budget project that he could assemble himself.
This project uses the basic SMARS wheels, chassis, tank treads, and motors as suggested on Thingiverse. Where it is different is the microcontroller, motor driver, and mounting plate for the electronics and battery.
Instead of using an Arduino and bluetooth as the SMARS design calls for I decided to go a different direction. This looked like the perfect project to use a WEMOS D1 Mini, an L9110S H-bridge Dual DC stepper Motor driver controller. The WEMOS enables WiFi communication with the bot interfacing the BLYNK app on my iPhone.
This project does not teach you how to set up BLYNK on your iPhone. There are plenty of online resources available to show you how to do it including the BLYNK website. It also does not cover assembling the SMARS. An assembly manual can be found on the Thingiverse website.
In evaluating the means of steering the bot using BLYNK there were three possibilities. The first one I tried was to use the BLYNK joystick widget. The joystick didn't give sufficient resolution to give a good steering experience. The second steering option I tried was to use two BLYNK long slider switches, one for the left track and one for the right.
You will notice that the slider ranges from -1023 to +1023. This sets the pulse width modulation (PWM) range in the sketch. ESP8266 based devices use 10 bit resolution on PWM or a range of 1023 versus 256 for Arduino. The control scheme here was to be able to independently adjust the sliders to change the speed and direction of each track. This scheme works better than the joystick but it is a little challenging to find the zero points on the sliders and it is hard to hold the phone and adjust the sliders at the same time.
The third steering scheme I tried was to use the accelerometers in the phone via the BLYNK app to steer the bot. iPhone's have three axis accelerometers that can be accessed by the BLYNK app. The idea here is to use the y-axis accelerometer to steer left - right and the z-axis accelerometer to adjust the speed by the amount of tilt and direction by tilting the phone away or toward the user.
This scheme also permits the magnitude of the y-axis rotation to be translated into track speed; the greater the magnitude of y-axis rotation the slower the track speed of the track in the direction of the steer. In other words, for a left turn the more the phone is rotated counterclockwise the slower the left track speed.
The BLYNK interface is arranged as in the photo above. When the yellow RUN/STOP switch is in the STOP mode the WEMOS will set the slider switches to zero. When the yellow RUN/STOP is in the RUN mode the slider switches are activated and the bot can be operated with the sliders. The sketch logic is set up to only allow bot activity if one switch is on and the other off. The switches and sliders are set up as in the photos below. When the red RUN/STOP switch is in the run mode the bot is operated via the accelerometers in the iPhone.
The sketch: (ESP-8266 components need to be added to your Arduino IDE to use this sketch - see - https://github.com/esp8266/Arduino for installation details)
/*
SMARS Tracked Vehicle Controller via BLYNK and Wemos D1 mini WiFi
On your phone in the Blynk app you need the following 4 widgets:
-SliderL on Virtual Pin: V0, Labelled Left -1023 to +1023
-SliderL on Virtual Pin V1, Labelled Right -1023 to +1023
-Switch on Virtual Pin V2, Labelled Run/Stop
-Accelerometer on Virtual Pin V3
-Switch on Virtual Pin V4 Labelled Run/Stop
The SMARS will operate in two modes with this setup
-Slider switches to increase or decrease and reverse track speed independent of each other to skid steer
and,
-Making use of the iPhone y and z axis accelerometers such that changing the orientation of the iphone
z-axis will increase or decrease and reverse track speed and y-axis will turn the bot left or right by
reducing the track speed relative to the amount of y-axis change.
Uses L9110 2-CHANNEL MOTOR DRIVER. Spec sheet-https://tinyurl.com/y88pgaka
MIT License
Copyright (c) 2020 jlmyra
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
// **********Use this code at your own risk!**********
*/
//**********Libraries**********
//#define BLYNK_USE_DIRECT_CONNECT
#define BLYNK_PRINT Serial
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
//**********Blynk***********
// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "XXXXXXXXXXXXXXXXXXXXXXXXXXX"; // Blynk Authentication Token
// Your WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "XXXXXXXXXXXX";// iphone wifi hotspot ssid
char pass[] = "XXXXXXXXXXXX";// iphone wifi hotspot password
//**********Blynk***********
//********************MOTORS***************************
#define motorA1A D1 //A1A Front Motor +
#define motorA1B D2 //AIB Front Motor -
#define motorB1A D5 //B1A Rear Motor +
#define motorB1B D6 //B1B Rear Motor -
//********************MOTORS***************************
//*************Slider Control Mode Variables****************
int leftMotorSpeed; //PWM value for motor speed
int rightMotorSpeed; //PWM value for motor speed
int stopGo = 0; //Blynk Switch for slider controls
//*************Slider Control Mode Variables****************
//*************Accelerometer Control Mode Variables*********
float y_Steer; //Y-Axis accelerometer value
float z_Speed; //Z-Axis accelerometer value
float motorSpeed; // PWM value from z_Speed for drive track
float motorSpeedADJ; //y-Steer adjusted PWM for skid turn track
int accel_Ready = 0; // Blynk V4 Switch On-Off Accelerometer Mode
//*************Accelerometer Control Mode Variables*********
//*****************************************************************************
//********************************VOID SETUP***********************************
//*****************************************************************************
void setup() {
Serial.begin(115200);
pinMode(motorA1A,OUTPUT); //Set Wemos D1 PIN to OUTPUT
pinMode(motorA1B,OUTPUT); //Set Wemos D2 PIN to OUTPUT
pinMode(motorB1A,OUTPUT); //Set Wemos D5 PIN to OUTPUT
pinMode(motorB1B,OUTPUT); //Set Wemos D6 PIN to OUTPUT
Blynk.begin(auth, ssid, pass); //START BLYNK
}
//**********************************************************************
//*************************END VOID SETUP*******************************
//**********************************************************************
//**********************************************************************
//***************************VOID LOOP**********************************
//**********************************************************************
void loop(){
Blynk.run();
}
//**************************************************************************
//*************************END VOID LOOP************************************
//**************************************************************************
//**********Read BLYNK LEFT Motor Slider - Slider Control Mode **********
BLYNK_WRITE(V0) {
leftMotorSpeed = param.asInt();
if (stopGo != 0 && accel_Ready != 1) {
if (leftMotorSpeed > 0) {
analogWrite(motorA1A, 0); //V0 is positive move left track forward
analogWrite (motorA1B, leftMotorSpeed);
} else {
leftMotorSpeed = -leftMotorSpeed;
analogWrite (motorA1A, leftMotorSpeed); //V0 is negative move left track backward
analogWrite (motorA1B, 0); //Turning Side slower than opposing side
}
}
}
//**********Read BLYNK LEFT Motor Slider - Slider Control Mode **********
//**********Read BLYNK RIGHT Motor Slider - Slider Control Mode **********
BLYNK_WRITE(V1) {
rightMotorSpeed = param.asInt();
if (stopGo != 0 && accel_Ready != 1) {
if (rightMotorSpeed > 0) {
analogWrite (motorB1A, 0); //V1 is positive move right track forward
analogWrite (motorB1B, rightMotorSpeed);
} else {
rightMotorSpeed = -rightMotorSpeed;
analogWrite (motorB1A, rightMotorSpeed); //V1 is negative move right track backward
analogWrite (motorB1B, 0);
}
}
}
//**********Read BLYNK RIGHT Motor Slider - Slider Control Mode **********
//**********Read STOP / RUN Switch - Slider Control Mode **********
BLYNK_WRITE(V2) {
stopGo = param.asInt();
if (stopGo == 0)
Blynk.virtualWrite (V0, 0); //Set the Blynk slide switches to zero
Blynk.virtualWrite (V1, 0); //Set the Blynk slide switches to zero
analogWrite (motorA1A, 0);
analogWrite (motorA1B, 0);
analogWrite (motorB1A, 0);
analogWrite (motorB1B, 0);
}
//**********Read STOP / RUN Switch - Slider Control Mode **********
//**************** Accelerometer - Accelerometer Control Mode****************
BLYNK_WRITE(V3) {
y_Steer = param [1].asFloat(); //Accelerometer y-axis for left(-)/right(+) turns
z_Speed = param [2].asFloat(); //Accelerometer z-axis for forward(-)/reverse(+)
if (accel_Ready == 0 && stopGo == 0) { //if switch is off turn off motors
analogWrite(motorA1A, 0);
analogWrite(motorA1B, 0);
analogWrite(motorB1A, 0);
analogWrite(motorB1B, 0);
}
if (stopGo != 1 && accel_Ready != 0 ) { //Skip this if stopGo button is ON.
Serial.print (" y_Steer: ");
Serial.print (y_Steer);
Serial.print (" z_Speed: ");
Serial.println (z_Speed);
//if (accel_Ready ==1){ //ENGAGE Accelerometer Function
//STOP
if ((z_Speed >= -0.3) && (z_Speed <= 0.3)) {
analogWrite (motorA1A, 0);
analogWrite (motorA1B, 0);
analogWrite (motorB1A, 0);
analogWrite (motorB1B, 0);
Serial.println (" stop ");
} else
//FORWARD
if ((z_Speed < -0.3) && (y_Steer < 0.3 && y_Steer > -0.3)) {
motorSpeed = (z_Speed * -1023);
Serial.print (" Forward "); Serial.print (" motorSpeed= "); Serial.println (motorSpeed);
analogWrite (motorA1A, 0);
analogWrite (motorA1B, motorSpeed);
analogWrite (motorB1A, 0);
analogWrite (motorB1B, motorSpeed);
} else
//BACKWARD
if ((z_Speed) > 0.3 && (y_Steer < 0.3 && y_Steer > -0.3)) {
motorSpeed = ((z_Speed) * 1023);
Serial.println (" BACKWARD "); Serial.print (" motorSpeed= "); Serial.println (motorSpeed);
analogWrite (motorA1A, motorSpeed); //Turning Side slower than opposing side
analogWrite (motorA1B, 0); //Turning Side s0er than opposing side
analogWrite (motorB1A, motorSpeed);
analogWrite (motorB1B, 0);
} else
//FORWARD DIAGONAL RIGHT
if ((z_Speed) < -0.3 && (y_Steer) < -0.3) {
motorSpeed = (z_Speed * -1023);
motorSpeedADJ = (motorSpeed * (1 + y_Steer));
Serial.println (" Forward diagonal right ");Serial.print (" motorSpeed= "); Serial.print (motorSpeed);
Serial.print (" motorSpeedADJ= "); Serial.println (motorSpeedADJ);
analogWrite (motorA1A, 0);
analogWrite(motorA1B, motorSpeed);
analogWrite (motorB1A, 0);
analogWrite(motorB1B, motorSpeedADJ);
} else
//BACKWARD DIAGONAL RIGHT
if ((z_Speed) > 0.3 && (y_Steer < 0.3)) {
motorSpeed = ((z_Speed) * 1023);
motorSpeedADJ = (motorSpeed * (1 + y_Steer));
Serial.println (" BACKWARD DIAGONAL RIGHT ");Serial.print (" motorSpeed= "); Serial.print (motorSpeed);
Serial.print (" motorSpeedADJ= "); Serial.println (motorSpeedADJ);
analogWrite (motorA1A, motorSpeedADJ); //Turning Side slower than opposing side
analogWrite(motorA1B, 0); //Turning Side slower than opposing side
analogWrite (motorB1A, motorSpeed);
analogWrite(motorB1B, 0);
} else
//BACKWARD DIAGONAL LEFT
if ((z_Speed) > 0.3 && (y_Steer) > 0.3) {
motorSpeed = ((z_Speed) * 1023);
motorSpeedADJ = (motorSpeed * (1 - y_Steer));
Serial.println (" BACKWARD DIAGONAL LEFT ");Serial.print (" motorSpeed= "); Serial.print (motorSpeed);
Serial.print (" motorSpeedADJ= "); Serial.println (motorSpeedADJ);
analogWrite (motorA1A, motorSpeed); //Turning Side slower than opposing side
analogWrite(motorA1B, 0); //Turning Side slower than opposing side
analogWrite (motorB1A, motorSpeedADJ);
analogWrite(motorB1B, 0);
} else
//FORWARD DIAGONAL LEFT
if ((z_Speed) < -0.3 && (y_Steer) > 0.3) {
motorSpeed = (z_Speed * -1023);//z_Speed is negative here - needs to be +
motorSpeedADJ = (motorSpeed * (1 - y_Steer)); //z_Speed is negative here, subtracting from 1
Serial.println (" FORWARD DIAGONAL LEFT ");Serial.print (" motorSpeed= "); Serial.print (motorSpeed);
Serial.print (" motorSpeedADJ= "); Serial.println (motorSpeedADJ);
analogWrite(motorA1A, 0);
analogWrite (motorA1B, motorSpeedADJ);
analogWrite(motorB1A, 0);
analogWrite (motorB1B, motorSpeed);
}
// }
}
}
//**************** Accelerometer - Accelerometer Control Mode****************
//*************Read RUN/STOP Switch - Accelerometer Control Mode***************
BLYNK_WRITE (V4) {
accel_Ready = param.asInt();
/*
if (accel_Ready == 0) {
analogWrite(motorA1A, 0);
analogWrite(motorA1B, 0);
analogWrite(motorB1A, 0);
analogWrite(motorB1B, 0);
}
*/
}
//*************Read RUN/STOP Switch - Accelerometer Control Mode***************
- Mounting the Parts: I designed a mounting plate for the WEMOS and Motor Controller that fits into the chassis using the groove intended for an Arduino. This plate holds a 2-cell 18650 battery holder. The plate could be improved on but it is functional in it's existing state, I used 2.54mm two-pole screw terminal block connectors on the WEMOS and motor controller to insure good connections. I also used a 5 volt UBEC to supply the WEMOS board and gave the motor controller the full output of 2-18650 batteries. The UBEC is in the belly of the chassis under the mounting plate.
Comments
Please log in or sign up to comment.