Retro-fitting a toy radio control car with an ESP32-CAM to enable Wi-Fi control and video streaming on a mobile phone
This tutorial is fairly advanced and more of an experiment than a finished project. Hopefully there are some ideas and code to learn from that might help with a similar projects.
I bought a cheap radio control car from a local toy shop with the intention of converting the normal radio control elements to a system using an ESP32 micro-controller communicating over WiFi. The ESP32-CAM used in this tutorial features WiFi and a camera so a video stream can be sent from the car.
Unfortunately the ESP32-CAM suffers from a lack of usable pins. I have only found two pins that can be used as outputs so some workarounds and compromises have been made in the design. One pin is used for steering and the other for forward speed control.
Conventionally to control an RC car you need to be able to set four different things, steer left, steer right, go forward, go reverse. The RC car I used doesn’t have analogue steering, it’s just left or right so I used servo motor to push limit switches to turn current on and off to the steering motor.
A motor controller needs two free pins so a reverse signal can be sent in addition to a PWM signal to control speed. However after using one pin for steering there is just one pin left on the ESP32-CAM so while the forward speed can be controlled there’s no way to tell the motor to go the opposite direction.
A possible solution that I haven’t investigated is to add another micro-controller to the system. This could receive data from the ESP32-CAM via the two available pins and parse this data in another Sketch that outputs over multiple pins . For example the ESP32-CAM could output data on a pin in the range 0 to 100, a Sketch on the second microcontroller would interpret the data in the range 0 to 50 to be reverse speeds and 51 – 100 to be forward speeds and activate output pins appropriately.
RC Car Hardware Components
These are the components installed in the RC car. I used 3.3v volts to power the ESP32 with a step down module to make the voltage from the 4 AA cells more stable . The steering is controlled by the two limit switches which make one or other side of the motor live when activated. The limit switches are pushed closed by a servo motor. The motor controller receives a PWM signal from the ESP32 and controls the motor speed.
A closer view of the steering system with the servo and limit switches. When the switches are in the position below, both sides of the steering motor are connected to negative side of the battery. When the servo pushes a limit switch closed, that side of the steering motor is connected to the positive side of the battery.
I used a fish-eye lens with a longer cable for the camera. There are various replacement cameras available from here: https://es.aliexpress.com/item/32981773363.html
This is how it looks assembled. The red and black wires top left are normally connected to the power connector block next to the steering motor.
This is how I wired it all together:
The car’s speed and steering are controlled using a touch interface on a mobile phone or tablet. Below the the touch interface is a live view from the camera.
RC Car Sketch
If you’ve not used the ESP32-CAM before you will need to read through this tutorial first – https://robotzero.one/esp32-cam-arduino-ide/ to get familiar with it.
The ArduinoWebsockets and ESPAsyncWebServer libraries need to be installed for this Sketch…
ESPAsyncWebServer: I’m not sure whether this library has to be used but during the process of developing this project I appeared to have problems with other web server libraries so I ended up with this one. You have to install it manually by copying it to the Arduino libraries folder. https://github.com/me-no-dev/ESPAsyncWebServer
Download the code from Github: https://github.com/robotzero1/esp32cam-rc-car/blob/main/esp32cam-rc-car.ino
The index_html_gz variable in the code is for the controller interface. If you want to edit this code see this tutorial: https://robotzero.one/esp32-cam-custom-html/
The code uses Web Sockets to stream the camera data to the browser:
client.sendBinary((const char *)fb->buf, fb->len)
and also receive control data from the touch interface on the mobile or tablet:
void handle_message(WebsocketsMessage msg) { // do stuff}
Project Demonstration Video
In there’s a lot of interest in this project (coffees!) I’ll work on a simpler version with a 3D printed chassis with servo control for steering and foreward/reverse and space for the ESP32-CAM to be located without bending pins etc.
You can also find this project on YouTube here: https://youtu.be/BwsH1kLxDmQ
Buy Me A Coffee
If you found something useful above please say thanks by buying me a coffee here...
References
Touch Interface: https://www.kirupa.com/html5/drag.htm
Nice project. Have you ever tried the DRV8871 DC motor drivers? They are MOSFET based and have a lower voltage drop and better performance , price wise very similar.
Maybe for another project but it looks like the DRV8871 needs a minimum of 6.5v. The ones I used are a quarter of the price and work from 2v – https://aliexpress.com/item/32920407851.html
Ahh. Yes, you are right about that, there is also a low voltage dual channel version , DRV8833.
Thanks for the great write up.
Very nice project. I just would like to see the code responsible to send commands when we move the button. Could you tell where I can found it ?
Or you just uploaded the https://github.com/me-no-dev/ESPAsyncWebServer and verything started to works ?
Thanks.
The HTML etc for the interface? It’s in this variable index_html_gz in the code. There’s a little explanation in the tutorial. You can also view source in the browser to view it.
I want to congratulate you on your work, you can share the html, since I would like to modify something in the code, I am thinking of implementing it in an ESP32 wrover without a camera, sorry for the translation, my English is not very good
Hi, HTML here: https://pastebin.com/iMyxJBEM
https://robotzero.one/esp32-cam-custom-html/
This website you gave shows how to edit the html for your own file but you didnt give us the code you used which has the joystick.
Can you upload that too?
Very nice tutorial btw.
Hi, Here’s the HTML: https://pastebin.com/iMyxJBEM
Nice work send you some coffe 🙂
Modfied html and triyng to understand the code!
Q: What is the number 8191
Thanks for the coffee! That part of the code comes from here: https://github.com/espressif/arduino-esp32/blob/master/libraries/ESP32/examples/AnalogOut/LEDCSoftwareFade/LEDCSoftwareFade.ino you can see where the number comes from. I don’t 100% understand it all through.
Nice project.
I have tested on ipdad, iphone and 2 android tablets.
in the iPAD it’s very fast
on my iPhone 6S I can’t see the video… I’m not sure why ? What do you think it could be?
on the Android Tablet, there is a Lag (not from the video) but from the commands. it looks like every 4-5 seconds there is a delay.
What do you think could be?
Thanks! excellent work!
The lag might be Wi-Fi related. I sometimes had a problem with the video framerate or the video dropping on this project. On others the control was sometimes laggy. If there’s a delay every x number of seconds it could also be the websocket data is being sent too fast and the buffer fills up.
The video not showing on the 6s.. maybe this is a CSS layout problem and the video panel is hidden somewhere.
Great work !
In order to overcome the pins limitation I used an arduino nano and talked to it over serial then you can use all the nano ports do add FPV camera and many more.
Thanks! I have another project planned where I intend to do something like that.
Thanks for the project. It works fine. My only problem is that every time I power up the ESP32 cam module I have to manually press the onboard reset switch to start video streaming. Is there a workaround? Thanks for all the hard work and Merry Christmas.
That’s a bit odd. Connecting the power and pressing the reset should do the same thing – start the sketch up. Maybe it’s a power thing somewhere on the board.
Great project.. trying to put together a micro crawler with it but having trouble trying to figure out how to rotate that video feed and center the motor as my fwd/rev is around 140 on the controller and not at 0. Any suggestions? Thanks
I don’t think the feed can rotated 90 degrees on the camera but possibly in CSS in the HTML. Can you do some maths in the code? Or change the map values? – forwardValue = map(forwardValue, 0, -90, 500, 2000);
I modified your html code to meet my needs.
But I don’t know how to convert HTML code to Hex.
Could you please tell me how to convert HTML to Hex.
I have a tutorial for that here: https://robotzero.one/esp32-cam-custom-html/
You might consider a continuous rotation server for the drive system.
You would get forward/reverse and speed control.
Real problem in physical interface though…
Apparently other pins are usable but I’ve not tried yet. If the SD card is put into 1-line mode supposedly 4 and 13 also become available. I need to test.
Any way to stream to a Windows 10 PC?
You can stream to any browser on any OS.
Is it possible to integrate with AutoConnect or WiFimanager so the WiFi credentials need not have to be hard-coded?
Should be possible. Or checkout the this tutorial to use Bluetooth to set the Wi-Fi credentials – https://robotzero.one/esp32-wi-fi-connection-bluetooth/
Thats cool.. thanks..
How do I integrate it with by sketch?
Ah.. you have to work it out yourself! Shouldn’t be too hard to cut and paste something together.
ESPAsyncWebServer.h:210:5: error: ‘AsyncClient’ does not name a type
And it’s the same for all the examples in the library ESPAsyncWebServer
How to get out of it?
How did you install the ESPA library?
Thanks, it’s a good project.
I am modifying the html code to add a button to turn on/off LED but I am still struggling.
Could you help please.
Do you need help with the HTML part? Should just be a case of copying the code for one of the existing buttons to make a new one. In the JavaScript part as well.
Some Hardware-hints:
To drive up to 16 servos /ESC/ LEDs / solenoids (mixed) with only 2 ESP32 port-pins, you can use https://learn.adafruit.com/16-channel-pwm-servo-driver?view=all . It’s cheap, easy to get from nearly all well-known suppliers, and more precise.
If you decide to use a brushed DC-Motor (including LEGO Technic) search for “20A brushed mini esc car”, easy to get from nearly all well-known suppliers. Both directions and a switch selectable brake. Advantage: More speed variations by gear-ratio and more reliable than a pimped servo (bad experience with the rubbish MG946 clones which burned after minutes) . You can it also connect to the PCA9685. With 2 of them, you can control tanks. Think: If you decide to use stronger ESC or brushless Motors with ESC, only CAR-type provides both directions. Planes fly only foreward and neither have reverse direction nor brake.
Ah cool! I was vaguely aware of the servo drivers but hadn’t researched them. I’ve got more motor projects in the pipeline so I’ll take a look.
You can also control up to 8 Servos / ESC with only one Portpin (output) by using a PPM (Standard output of all older RC-Systems) to PWM decoder. You need only 4 easy available and cheep devices: A Resistor, a Diode, a capacitor and a decade-Counter 4017.
http://myrobotlab.org/content/all-info-we-need-get-good-ppmi2c-servo-control-and-using-less-cables
(R1 220Ohms on the schematic goes to VCC Pin 16 and is not needed (EMC-Reasons for the 27MHz receiver).
Advantage: You can use every standard RC-Device as servo, ESC, Switches… and a loss of PPM leads to a standstill of the ESC. Some kind of “fail-safe” 🙂
I use this simple device very often because you can encode, transmit and decode the serial PPM very simple (AM, FM, SSB, CW..) and then feed the Reciver-signal to the decade counter.
Hint: If the Output has problems to discharge the 22nF Capacitor, use 470k/10nF instead for Reset.
http://www.mftech.de/ppm_en.htm
https://hackaday.io/project/2465-manucon-a-glove-based-controller/log/8254-ppm-output
https://www.arduinolibraries.info/libraries/pulse-position
Addition: Some ESC provide a 5V BEC (Battery eliminating circuit) , so you can feed the ESP32 directly with 5V from the ESC.
Example: https://de.aliexpress.com/item/4000544091026.html?spm=a2g0o.productlist.0.0.676d13fd4r8Rax&algo_pvid=b8baaeb0-5380-4542-95b5-63ddca8c9d0c&algo_expid=b8baaeb0-5380-4542-95b5-63ddca8c9d0c-8&btsid=0ab50f4915906771867116854e5a86&ws_ab_test=searchweb0_0,searchweb201602_,searchweb201603_
Don’t belive the 320A 🙂 1/10 is more than enough for the ESC but should be enough for a normal project.
i have a question is there a way to make it standalone like controlling it directly from my phone without in need of wifi outer connection and as i know esp32 cam has Bluetooth so maybe a Bluetooth vitiation
Easiest way would be to change the Wi-Fi code on the ESP32 to be an access point (AP) so you connect straight to the ESP32 without using a router.
Suggestion for tutorial: An “on screen display” or “heads up display” for the ESP-32 camera dev. board.
Could display GPS info, voltages, and other data overlaid on the Web app.
Has anyone seen anything like this?
It’s possible to add text overlays to the stream – the CameraWebServer example does this. If you want graphical data you would have to overlay the JPEG data somehow before it’s sent. Maybe I’ll do a tutorial for this. (Make sure you subscribe to the newsletter to get an email for new projects.)
Hello,
I have a problem with compilation of project to esp32 dev module. Do you know solution of this problem, because I have tried several settings but it didn’t work. Can you help me please?
Hi, What error do you see when it fails to compile?
Hello Dear, where is the source code?
Can not see a link for the souce code. Can you plaese the source code
Hi code was in the article but I’ve moved it to Github for better formatting: https://github.com/robotzero1/esp32cam-rc-car