A simple WiFi controlled robot prototype for a club at my university. Uses the ESP32 dev board, a L293 dual H-Bridge, and is mostly 3D printed.
A small proof-of-concept ESP32 Bot
To make the experience fit your profile, pick a username and tell us what interests you.
We found and based on your interests.
A simple WiFi controlled robot prototype for a club at my university. Uses the ESP32 dev board, a L293 dual H-Bridge, and is mostly 3D printed.
esp32 mini-bot joystick control.zipHTML Web-page served by the botZip Archive - 897.00 bytes - 02/22/2019 at 20:24 |
|
|
ESP32 Mini-Bot Schematic.pdfAdobe Portable Document Format - 31.22 kB - 02/21/2019 at 21:30 |
|
|
All STL Files.zipSTL Files of ESP32 Mini-BotZip Archive - 111.08 kB - 02/21/2019 at 21:29 |
|
|
esp32_tank.zipArduino Sketch FilesZip Archive - 2.74 kB - 02/21/2019 at 21:27 |
|
|
Tank Mech Build.FCStdMaster FreeCAD Modelfcstd - 2.48 MB - 02/21/2019 at 21:26 |
|
Finally we're here at the end; time to talk about how this thing actually moves. The original bots that my club utilized were remote control tanks, ideally this bot would move and turn just like a tank. I can't manage to find two matching rubber bands to string across the wheels but that was the intention. In order to make this bot move properly the program must be capable of varying the amount of power to each motor, interpreting the relative power to each motor based on input, and be continuous and predictable (it shouldn't immediately turn left if the user is 1 degree off forward).
Varying the speed is simple, since this project uses a L293 all that the program needs to do is send a PWM signal to the EN pins on the channel controlling each motor. In Arduino this is easy, for the ESP32 its more involved but still way less than pure AVR C. using the ledc library we can assign two PWM channels to two separate pins and assign outputs:
pinMode(O4A, OUTPUT);
pinMode(O3A, OUTPUT);
pinMode(O2A, OUTPUT);
pinMode(O1A, OUTPUT);
//PWM Setup
ledcSetup(pwmRightChannel, pwmFreq, pwmRes);
ledcSetup(pwmLeftChannel, pwmFreq, pwmRes);
ledcAttachPin(EN34, pwmLeftChannel);
ledcAttachPin(EN12, pwmRightChannel);
Each pin is labeled in accordance with what it's connected to on the L293. The PWM channel can be written to utilizing the function:
ledcWrite(pwmChannel, val);
Its also worth noting that the resolution is definable with the ESP32, in the case of this sketch its set to a resolution of 8-bits so 0-255.
Now there's fine control of each of the motors, what about direction? That's where the setMotors() function comes in:
void setMotors(int _right, int _left) {
int rightVal = abs(_right) ;
int leftVal = abs(_left);
//
Serial.print("Right ");
Serial.print(_right);
Serial.print(" Left ");
Serial.println(_left);
if (_right > 0) {
ledcWrite(pwmRightChannel, map(rightVal, 0, 100, 0, 245));
digitalWrite(O2A, HIGH);
digitalWrite(O1A, LOW);
} else if (_right < 0) {
ledcWrite(pwmRightChannel, map(rightVal, 0, 100, 0, 245));
digitalWrite(O2A, LOW);
digitalWrite(O1A, HIGH);
} else {
ledcWrite(pwmRightChannel, map(rightVal, 0, 100, 0, 245)); //it'll only get here if its zero anyway
digitalWrite(O2A, LOW);
digitalWrite(O1A, LOW);
}
if (_left > 0) {
ledcWrite(pwmLeftChannel, map(leftVal, 0, 100, 0, 245));
digitalWrite(O4A, LOW);
digitalWrite(O3A, HIGH);
} else if (_left < 0) {
ledcWrite(pwmLeftChannel, map(leftVal, 0, 100, 0, 245));
digitalWrite(O4A, HIGH);
digitalWrite(O3A, LOW);
}
else {
ledcWrite(pwmLeftChannel, map(leftVal, 0, 100, 0, 245));
digitalWrite(O3A, LOW);
digitalWrite(O4A, LOW);
}
}
for the right motor, we can set the direction of the motor by changing the values on the 2A and 1A pins of the L293, 2A high and 1A low makes the right motor move forward. Changing the pin values to 2A low and 1A high will make the right motor go in reverse. Toggling the EN pin high will enable the right motor and toggling it low will disable the right motor. The PWM signal is fed into the EN pin, since using this method only one pin has to be modified rather than modifying both the inputs on the L293.
Now the bot has XY coordinates coming in and a way to vary the speed and direction of each motor, the program still needs to be able to interpret these values. There's a lot of ways to manage this here's the method I used:
void setMotorsXY(int x, int y) {
//lets move things to polar, it will make the motor setting much easier since we really only have to look at theta
double theta = PI / 2; //default to forward
double rightSpeed = 0;
double leftSpeed = 0;
if (x != 0) { //just some exception handling here
if (y > 0) {
theta = PI - atan2(y, x * (-1));
} else if (y < 0) {
theta = 2 * PI + atan2(y, x);
}
} else {
if (y > 0) {
theta = PI / 2;
} else {
theta = 3 * PI / 2;
}
}
double r = sqrt(x * x + y * y) / 100; //we want this value to be...
Read more »
Before this project I had limited experience with the ESP32 and for the most part I followed this tutorial to get the project up and running in the beginning and modified from it. That tutorial got me started, however, since the software for this project is probably the most likely reused part of it, there were not a lot of compromises and I had a few goals:
So lets start with the web page the ESP32 serves every time a user connects:
<html><head><meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<script src = "https://cdn.jsdelivr.net/gh/jeromeetienne/virtualjoystick.js/virtualjoystick.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<style>
body {overflow : hidden;background-color: #BBB;}
#container {width: 100%;height: 100%;overflow: hidden;padding:0;margin:0;-webkit-user-select:none;-moz-user-select:none;}
</style><title> ESP32 Bot Control Site </title></head><body>
<div id="container"><h1>ESP32 Bot Control</h1></div><div id="info"><span id="result"></span></div> <script>
console.log("touchscreen is", VirtualJoystick.touchScreenAvailable() ? "available" : "not available");
var joystick = new VirtualJoystick({
container : document.getElementById('container'),
mouseSupport : true,
limitStickTravel : true,
stickRadius : 100
});
joystick.addEventListener('touchStart', function(){
console.log('down')
})
joystick.addEventListener('touchEnd', function(){
console.log('up')
})
$.ajaxSetup({timeout:50});
setInterval(function(){
var message = "/?M/?X"+Math.round(joystick.deltaX())+"/X/?Y"+Math.round(joystick.deltaY())+"/Y/M";$.get(message);var outputEl = document.getElementById('result');}, 50);
</script></body></html>
which looks like:
I can't embed the web-page directly into this log, but the full HTML file is posted on the main page of this project.
The blue circles you see in the image above are actually a joystick. I didn't create this joystick, the credit for that goes to jeromeetienne on github. The virtualjoystick.js github page can be found here.
Now, as I said in the first log this project write up is for someone who wants to do something similar to this project. The web interface specifically took the majority of the time I spent on this project and I really want someone else who does this to have an easier time. there are two very important parts in this website that make the whole thing work as intended, first loading the javascript externally:
<script src = "https://cdn.jsdelivr.net/gh/jeromeetienne/virtualjoystick.js/virtualjoystick.js"></script>
Notice the script tag is pulling the .js file from somewhere that's not the ESP32, github will not let you load a file directly with one of their raw URL's, additionally the javascript file is too big to be sent by the ESP32 (it can do it but you're adding 40ms to the transmission time). The solution to this is to use jsdelivr.com to offer up the JavaScript file to any computer that loads the web-page. This offloads the burden from the ESP32 to the device connected to it.
second sending the information to the ESP32:
$.ajaxSetup({timeout:50});
setInterval(
function(){
var message = "/?M/?X"+Math.round(joystick.deltaX())+"/X/?Y"+Math.round(joystick.deltaY())+"/Y/M";
$.get(message);}
, 50);
(which is all on the same line in the code posted above)
The bottom part of the code simply composes a string with the x and y coordinates of the joystick, formats it, then requests it as a URL from the ESP32 every 50ms. The ESP32 receives this then processes it, for the longest time this code would not work because the ESP32 would become backlogged with requests. The longer it spent running, the more behind it was with the requests. Eventually the bot was impossible to control,...
Read more »Let me just say, FreeCAD is a great tool. Coming from google sketchup for my personal projects this has been a breath of fresh air and just simplified the entire process. If you're looking for a good open-source (and more importantly free) CAD program then give FreeCAD a shot.
The body design for this project was fairly simple. the design had to fit the populated perf-board, hold a lithium ion battery, and support the wheel and motors. Here's what I came up with:
without the cover:
Note: I never modeled the lithium ion battery into the design, it fits in the area below the board stand in.
The model for this project went through a few redesigns. Originally, before the motors even arrived, the drive wheels were placed directly onto the motors. As a result that design never went anywhere quick and would frequently be a general pain to play with. Using the FreeCad plugin FCGears the rear wheels and motor mount were redesigned to have some reduction. This improved the performance of the bot considerably but not as much as intended.
adding the geared wheels also required the wheels themselves to be moved down and back slightly. This resulted in the ridges seen on the bottom of the model. These ridges are far from ideal for a 3D printer and required the entire model to be printed with support material, adding another hour to the print time.
The wheels came out well, each wheel had as much material removed as possible in CAD to save on print time. On each of the wheels there is a groove intended for a rubber band to improve traction on the plastic surface which works well.
Overall this design is alright, in hindsight i should have spent some time looking for better motors for all the trouble these ones have caused me.
The STL files and FreeCAD project file are available for download on the main page of this project!
The goal here is to build a proof of concept, so I went a little cheap on the motors and found whatever came in at the lowest price on amazon. That doesn't affect the hardware too much, since the intention is still to make a cheap-proof of concept that can use more powerful motors. However, it does come into play in the design of the body and this is the best place to mention it. The hardware is simple and to the point:
The upper-left corner contains all the power circuitry, power comes in from the battery through the lithium ion battery module then gets fed into a boost converter. The output of the boost converter, is then fed into both a LM7805 and the L239 motor driver. While it would be possible to connect the ESP32 Board directly to the 12V output through the EXT_5V pin, it's not ideal. Pins 12, 14, 25, 26, 27, and 33 on the ESP32 are connected directly to the L293. The outputs of the L293 then connect to the motors with proper diode protection as shown in the IC's datasheet.
This circuit was assembled on perf-board and works properly. Utilizing the boost converter and lithium ion battery modules saved a great deal of time soldering.
I've already completed this project, however, since a lot of work has gone into each part of this project i'm going to split up the logs for better readability. I hope that someone looking to create a similar project finds this project and can use it as a jumping off point, there were no shortage of hurdles to overcome over the course of this project for me. With that said, what were the goals for creating this project:
With that said lets get into it starting with the hardware!
Create an account to leave a comment. Already have an account? Log In.
Become a member to follow this project and never miss any updates