ESP32 RC Car Over Wifi using MicroPython
Learning by doing. ESP32 based WiFi Controlled Car.
Reproducing the Project
- Gather the required parts as mentioned below
- Follow the Fritzing diagram for the wiring(exact GPIO can be infered from Main.py code)
- Make your Boot.py to suit your Wifi SSID or AP modes
- Connect to your WiFi in case of AP client mode Boot.py OR Connect to your ESP32 based AP, if Boot.py contains AP mode
- Open browser and point to the ESP32 IP, to get remote control as webpage
- Drive away!
Parts list
- ESP32 board
- L298N Motor Driver
- 2 x 18650 + Battery holder
- 4 x 3V-12V DC BO motor
- Chassis for mounting everything
- Mini project bread board
- Soldering iron
Fritzing Diagram
Wiring
Remove the Jumper from ENA1+ENA2 and ENB1+ENB2
LEFT SIDE MOTORS
- ENA1 –> GPIO 4
- IN1 –> GPIO 2
- IN2 –> GPIO 15
RIGHT SIDE MOTORS
- ENA1 –> GPIO 13
- IN3 –> GPIO 14
- IN4 –> GPIO 12
MicroPython Code
Borrowed from many places
Main.py
import machine
import time
class engines:
def __init__(self, machine):
self.machine = machine
# Left side DC Motor Control
self.ena1_gpio = 4
self.in1_gpio = 2
self.in2_gpio = 15
# Right side DC Motor Control
self.enb1_gpio = 13
self.in3_gpio = 14
self.in4_gpio = 12
# Set the duty for PWM
#self.full_pwm_duty = 500
#self.half_pwm_duty = 200
# Control INx pins for forward or backward
#self.in1 = machine.Pin(self.in1_gpio, machine.Pin.OUT, value=0)
#self.in2 = machine.Pin(self.in2_gpio, machine.Pin.OUT, value=1)
#self.in3 = machine.Pin(self.in3_gpio, machine.Pin.OUT, value=0)
#self.in4 = machine.Pin(self.in4_gpio, machine.Pin.OUT, value=1)
print("init")
def forward(self, duty=600):
self.stop()
# Right side DC Motor Speed Control and direction
ena1=machine.PWM(self.machine.Pin(self.ena1_gpio),freq=100,duty=duty)
enb1=machine.PWM(self.machine.Pin(self.enb1_gpio),freq=100,duty=duty)
# Control INx pins for forward
self.in1 = machine.Pin(self.in1_gpio, machine.Pin.OUT, value=0)
self.in2 = machine.Pin(self.in2_gpio, machine.Pin.OUT, value=1)
self.in3 = machine.Pin(self.in3_gpio, machine.Pin.OUT, value=0)
self.in4 = machine.Pin(self.in4_gpio, machine.Pin.OUT, value=1)
print("forward")
def forward_left(self):
self.stop()
# Right side DC Motor Speed Control and direction
ena1=machine.PWM(self.machine.Pin(self.ena1_gpio), freq=100, duty=300)
enb1=machine.PWM(machine.Pin(self.enb1_gpio), freq=100, duty=600)
# Control INx pins for forward
self.in1 = machine.Pin(self.in1_gpio, machine.Pin.OUT, value=0)
self.in2 = machine.Pin(self.in2_gpio, machine.Pin.OUT, value=1)
self.in3 = machine.Pin(self.in3_gpio, machine.Pin.OUT, value=0)
self.in4 = machine.Pin(self.in4_gpio, machine.Pin.OUT, value=1)
print("forward_left")
def forward_right(self):
self.stop()
# Right side DC Motor Speed Control and direction
ena1=machine.PWM(self.machine.Pin(self.ena1_gpio),freq=100,duty=600)
enb1=machine.PWM(self.machine.Pin(self.enb1_gpio),freq=100,duty=300)
# Control INx pins for forward
self.in1 = machine.Pin(self.in1_gpio, machine.Pin.OUT, value=0)
self.in2 = machine.Pin(self.in2_gpio, machine.Pin.OUT, value=1)
self.in3 = machine.Pin(self.in3_gpio, machine.Pin.OUT, value=0)
self.in4 = machine.Pin(self.in4_gpio, machine.Pin.OUT, value=1)
print("forward_right")
def reverse(self, duty=600):
self.stop()
# Right side DC Motor Speed Control and direction
ena1=machine.PWM(self.machine.Pin(self.ena1_gpio),freq=100,duty=duty)
enb1=machine.PWM(self.machine.Pin(self.enb1_gpio),freq=100,duty=duty)
# Control INx pins for backward
self.in1 = machine.Pin(self.in1_gpio, machine.Pin.OUT, value=1)
self.in2 = machine.Pin(self.in2_gpio, machine.Pin.OUT, value=0)
self.in3 = machine.Pin(self.in3_gpio, machine.Pin.OUT, value=1)
self.in4 = machine.Pin(self.in4_gpio, machine.Pin.OUT, value=0)
print("reverse")
def reverse_left(self):
self.stop()
# Right side DC Motor Speed Control and direction
ena1=machine.PWM(self.machine.Pin(self.ena1_gpio), freq=100, duty=600)
enb1=machine.PWM(self.machine.Pin(self.enb1_gpio), freq=100, duty=300)
# Control INx pins for backward
self.in1 = machine.Pin(self.in1_gpio, machine.Pin.OUT, value=1)
self.in2 = machine.Pin(self.in2_gpio, machine.Pin.OUT, value=0)
self.in3 = machine.Pin(self.in3_gpio, machine.Pin.OUT, value=1)
self.in4 = machine.Pin(self.in4_gpio, machine.Pin.OUT, value=0)
print("reverse_left")
def reverse_right(self):
self.stop()
# Right side DC Motor Speed Control and direction
ena1=machine.PWM(self.machine.Pin(self.ena1_gpio),freq=100,duty=600)
enb1=machine.PWM(self.machine.Pin(self.enb1_gpio),freq=100,duty=300)
# Control INx pins for backward
self.in1 = machine.Pin(self.in1_gpio, machine.Pin.OUT, value=1)
self.in2 = machine.Pin(self.in2_gpio, machine.Pin.OUT, value=0)
self.in3 = machine.Pin(self.in3_gpio, machine.Pin.OUT, value=1)
self.in4 = machine.Pin(self.in4_gpio, machine.Pin.OUT, value=0)
print("reverse_right")
def stop(self):
machine.PWM(self.machine.Pin(self.ena1_gpio),freq=0,duty=0)
machine.PWM(self.machine.Pin(self.enb1_gpio),freq=0,duty=0)
self.in1 = machine.Pin(self.in1_gpio, machine.Pin.OUT, value=0)
self.in2 = machine.Pin(self.in2_gpio, machine.Pin.OUT, value=0)
self.in3 = machine.Pin(self.in3_gpio, machine.Pin.OUT, value=0)
self.in4 = machine.Pin(self.in4_gpio, machine.Pin.OUT, value=0)
print("stop")
E=engines(machine)
try:
import usocket as socket
except:
import socket
CONTENT = b"""\
HTTP/1.0 200 OK
Hello #%d
"""
CONTENT = b"""\
<!DOCTYPE html>
<html lang="en">
<meta charset="UTF-8">
<title>:: SERVO WEB CONTROL ::</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<style type="text/css" media="screen">
.rcdiv {
border: 3px outset red;
background-color: lightblue;
text-align: center;
}
.container {
margin: 10px auto;
max-width: 600px;
text-align: center;
}
.rctable {
margin-left: auto;
margin-right: auto;
border: 1;
}
.rcbtn {
border: 2px solid black;
background-color: white;
color: black;
padding: 14px 28px;
font-size: 16px;
cursor: pointer;
border-color: #2196F3;
color: dodgerblue
background: #2196F3;
color: white;
}
h1 {
margin: 30px 0;
font-size: 4em;
line-height: 1;
letter-spacing: -1px;
}
</style>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
var DEVICE_URL = 'http://%s'
function iotAction(action){
var requestURL = DEVICE_URL + "/?action="+action
$.get (requestURL)
}
</script>
<body>
<div class="container">
<h2>CAR WIFI REMOTE</h2>
<table class="rctable">
<tbody>
<tr><!-- First row -->
<td><button class="rcbtn" name='btnForwardLeft' style="width:100px;height:160px" ontouchstart="iotAction('forward_left')" ontouchend="iotAction('stop')"/></td>
<td><button class="rcbtn" name='btnForward' style="width:100px;height:160px" ontouchstart="iotAction('forward')" ontouchend="iotAction('stop')"/></td>
<td><button class="rcbtn" name='btnForwardRight' style="width:100px;height:160px" ontouchstart="iotAction('forward_right')" ontouchend="iotAction('stop')"/></td>
</tr>
<tr><!-- Second row -->
<td><button class="rcbtn" name='btnReverseLeft' style="width:100px;height:160px" ontouchstart="iotAction('reverse_left')" ontouchend="iotAction('stop')"/></td>
<td><button class="rcbtn" name='btnReverse' style="width:100px;height:160px" ontouchstart="iotAction('reverse')" ontouchend="iotAction('stop')"/></td>
<td><button class="rcbtn" name='btnReverseRight' style="width:100px;height:160px" ontouchstart="iotAction('reverse_right')" ontouchend="iotAction('stop')"/></td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
"""
def main(E,micropython_optimize=False):
s = socket.socket()
# ai = socket.getaddrinfo("192.168.0.159", 80)
ai = socket.getaddrinfo("192.168.0.219", 80)
addr = ai[0][-1]
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(addr)
s.listen(5)
while True:
res = s.accept()
client_sock=res[0]
if not micropython_optimize:
client_stream = client_sock.makefile("rwb")
else:
client_stream = client_sock
req = client_stream.readline()
get = req.split()[1].decode('utf-8')
if get == '/?action=forward_left':
E.forward_left()
elif get == '/?action=forward':
E.forward()
elif get == '/?action=forward_right':
E.forward_right()
elif get == '/?action=reverse_left':
E.reverse_left()
elif get == '/?action=reverse':
E.reverse()
elif get == '/?action=reverse_right':
E.reverse_right()
elif get == '/?action=stop':
E.stop()
else:
pass
while True:
h = client_stream.readline()
if h == b"" or h == b"\r\n":
break
client_stream.write(CONTENT % station.ifconfig()[0])
client_stream.close()
if not micropython_optimize:
client_sock.close()
main(E)