Mounting an ESP32-CAM into a pan and tilt platform with a mobile phone touch interface to control and view the video stream.
This servo part of this project was much harder to make work than with other ESP32 modules. The ESP32-CAM has limited resources available and at every turn it presented a new problem!
With a standard ESP32, controlling servo motors is easy using the ESP32Servo library. For example this pan and tilt sketch controls the 3D printed pan and tilt platform below. You can even power the servos from the 5v pin of the micro-controller.
Attempting to use this library with the ESP32-CAM however led to instant hangs. From my experiments it appears there is a clash on the channels. I found some different code that allows the channels to be chosen and after a few tests I found I could use channels 2 and 4 with the ESP32-CAM.
Mounting the ESP32-CAM in a pan and tilt platform was also a bit tricky. In the end I 3D printed some parts and glued and bolted it together. It doesn’t look great and could do with being designed from the ground up but this is just a proof of concept for later projects so it doesn’t matter
I also tried various web server libraries and the ESPAsyncServer library seemed to work the best. I also moved to WebSockets for the data transfer because it seemed to be more efficient and not queue up requests from the mobile phone.
ESP32-CAM Pan Tilt Code
If you need help with the ArduinoWebSockets or ESPAsyncWebServer libraries please see this tutorial: https://robotzero.one/esp32-cam-rc-car/
Demonstration Video
I got variable results from the ESP32-CAM. Sometimes it was as fluid as the Lolin in the video below and other times it was quite jerky. I don’t know if this is an issue with (my) Wi-Fi or if the data transfer from the video overwhelms the web socket servo control data.
References
Lolin32 Pan and Tilt Platform: https://www.thingiverse.com/thing:708819
ESP32-CAM Pan Tilt with Servos: https://www.ebay.es/itm/201544779605
Touch Interface: https://www.kirupa.com/html5/drag.htm
Do you think it would be possible to overlay the pan tilt control on top of the camera image, a bit like this
https://youtu.be/NSowf_ctzAw?t=12
I looked at the Github quickly and it looks like he’s using HTML Canvas https://www.w3schools.com/html/html5_canvas.asp to draw the interface on top of the video. This could be one approach. It might also work using CSS Z-Index to layer the control with a transparent background on top of the video.
I made a little investigation abd foun out that this part on ESP32 Cam code is preventing Servo library to work:
—
// camera init
esp_err_t err = esp_camera_init(&config);
if (err != ESP_OK) {
Serial.printf(“Kaamera init viga 0x%x”, err);
return;
}
sensor_t * s = esp_camera_sensor_get();
s->set_framesize(s, FRAMESIZE_SVGA);
It should be OK. Which camera are you using?
Hello my friend!!!
I am quite a beginner and I would very much like to carry out your project. Can you send me screenshots of Arduino ID to learn out which sketch you use, which board, which file (.in) because this one is here (.cpp) and only I can’t add it.
I apologize for my bad English !!!
Thank you very much !!!
Hi, everything is in the tutorial. You can use any ESP32 board. The code in the tutorial is an .ino file so you just paste it into a new Sketch in the Arduino IDE.
It worked….. 🙂 Supeeeerrrrrr !!!
Thank you so much!!!
Hi, and thank you for this useful tutorial. It works fine to me.
In my case, I want to pan and tilt an ESP32-CAM as a surveillance camera through internet.
Using NO-IP services I can use Dynamic DNS (I did it in another application).
For security reasons, I want to change ports 80 and 82 you are using in your program, which I will port forward in my router. So far I haven’t had any success. It seems to work only with 80 and 82 ports. How can I do it?
Please help me. Thank you.
Hi, Did you you change the ports in the HTML? See this tutorial for help with this – https://robotzero.one/esp32-cam-custom-html/
Hello Fellow Maker,
Great tutorial, I am doing something very similar and wanted get your opinion/advice on the following.
Currently I have an application that is sending polar coordinates (magnitude, theta) and wanted to know what would you suggest to map the panValue & tiltValue so that it can handle the conversion.
I’m thinking that magnitude could be used as the “speed” or “power” of the servo and convert the theta into some useable mapping angle value.
Magnitude = 0 to 1
Theta = 0 to 359.99
I’m having a bit of trouble with the logic and trying to use your example as a base when handling the WebSockets on the ESP32 Cam
panValue = map(panValue, -90, 90, 0, 180); // 0-180
tiltValue = map(tiltValue, -90, 90, 180, 0); // 0-180 reversed
any advice is greatly appreciated 🙂
Hi, I’m not really sure but one thing to note is map is only for integers so you need to multiple the numbers to get whole numbers first. For example magnitude should be 0 to 100 to map it. With map you start with the values you get from your sensor or whatever and ‘map’ them to a range of values you need for the function (servo in this case). If you need help with more maths stuff this site is great: https://math.stackexchange.com/
Hi again, and thank you for your reply.
Studding your tutorial you mention above, and using CyberChef, I converted hex to html. The only point I can change port is in line const WS_URL = “ws://” + window.location.host + “:82”;
I changed 82 with 8084.
I converted html to hex again and correct the index_html_gz length to 1744 in camera code.
Also in camera code, I changed line 120, the WSserver.listen(82); to WSserver.listen(8084);
and the line 38, the AsyncWebServer webserver(80); to AsyncWebServer webserver(8082);
After uploading code, removing GND from IO0, pressing RESET button, in browser look for 192.168.x.x:8082.
The only I can see in browser, is the touch interface in the upper portion of screen, with the yellow spot in the middle, but I cannot move it to any direction. No image at all, no servo movement.
Probably I miss something. Have you any advice to give me?
Thank you.
Hi. Sounds like you are doing well following the tutorial. Can you press F12 in the browser can take a look in the Console tab at the moment. It sounds like the Javascript isn’t loading.
Hi again.
I followed your advice (Console tab using F12). A Syntax Error appeared:
“SyntaxError: An invalid or illegal string was specified 192.168.1.7:8082:71
http://192.168.1.7:8082/:71”
What is that :71 ? There is neither in code nor html.
Also I changed the 8082 and 8084 ports with 2 digit number (p.s. 90 and 92) but the same error appeared.
That error is not appearing when using 80 and 82 ports.
Have you any suggestion?
Thank again for your time.
Hi, Can you post the HTML and sketch into two pastes here: https://pastebin.com/ and I’ll take a look.
OK I made registration to Pastebin and I made two pastes.
I am not familiar with Pastebin.
Now how do you will see them?
Ah.. I need the link to the pastes. When you save them, just copy the URL into a comment here.
Wednesday 25th of March 2020 04:19:49 PM CDT (My registration)
Postes, a few minutes later…
Hi, When you copy and paste into Pastebin and save, you can just copy the URL of the page and paste it here.
https://pastebin.com/gy5hmXXL
https://pastebin.com/zhbuzmyy
Thanks
I think I’ve sussed it. Try:
const WS_URL = "ws://" + window.location.hostname + ":8084";
host includes the port number. I didn’t know this before.
IT IS WORKING !!!!!!
THANK YOU VERY MUCH…
I appreciate your help.
Thanks again !!!
Hi will be great if you can post the working program with the port set for 8084.
I am trying the same and not able to get it to work.
IF you check this comment (with the two examples) and my correction below it should work: https://robotzero.one/pan-and-tilt-control-for-an-esp32-cam/#comment-45254
hi . very nice project . it works very good.
Please help me for working this project on other port not “80” .
thanks alot for your project
Hi. You should be able to change the port here:
AsyncWebServer webserver(80);
and then just go to http://your.ip.address.here:81/
I havent connected up the servo’s, but it worked first time for me.
I have dissected the code and removed the servo control and html interface so I can use the cam websocket stream by itself.
I was using my esp32 with it cam with a tcp interface, websockets os much quicker.
The code does not work. You have two references to index_html_gz, but have never defined or included it anywhere.
As given, the code returns
exit status 1
‘index_html_gz’ was not declared in this scope
Is there a working version of the code that you could post? Perhaps this was an earlier version or something?
Something weird has happened with the paste on Pastebin. If you look at the bottom of the page https://pastebin.com/jzNmwEB9 the raw paste has the definition. I’ll move this to Github later.
Hi, awesome project. I have tried out the code from the raw paste, and have attached everything according to the schematic provided, the camera works fine but I am unable to make the servo work (have tested that servo is working with normal Arduino).
I have connected the servo to an external 5V power source, so the power issue should have been settled, may I ask which partition scheme did you choose for your ESP32 cam board, or if possible all the options that you picked.
Hi partition scheme shouldn’t affect this project. If you choose one too small it just won’t flash. Maybe try some Serial.print() commands before this code to make sure the panValue and tiltValue are correct.
ledcAnalogWrite(2, panValue); // channel, value
ledcAnalogWrite(4, tiltValue);
This pan/tilt/camera works beautifully. Indoors. When I take it outside in the bright sunlight the feed freezes and will only normalize again in the shade or indoors. Anyone else experience this? Using the same esp32 cam the Arduino example sketch has no issues.
Hi, Are you sure it’s not just losing connection to the Wi-Fi? The websocket connection seems to be more sensitive to connection problems than the normal http.
Thanks for the coffee BTW!
I am running it in AP mode, with the camera and tablet both in hand. The Wi-Fi connection appears to remain stable. I’ll do some more experimenting today. Thanks.
Which card are you using, I got an error Compilation error for the card AI Thinker ESP32-CAM.
Probably a problem with the code display from Pastebin. I should move this to Github. In the meantime the raw view should be OK: https://pastebin.com/raw/jzNmwEB9
Hi,
very good work!!!
please post the original content of intex.html ( not gz)
thanks
Hi, View Source in the browser and you will see all the HTML etc.
thanks a lot … I resolved with
https://gchq.github.io/CyberChef/
and I seen(decode) HTML code with that receipt:
From_Hex(‘Auto’)
Gunzip()
thei I modified the HTML
(I add code for rotation 90 degree:
document.getElementById(“stream”).style.transform = ‘rotate(‘ + deg + ‘deg)’;
Tutorial: https://diyprojects.io/5-tips-esp32-cam-fixed-ip-address-ap-mode-image-rotation-90-automatic-recovery-wifi-connection-html-code-storage/#rotationimage }
and finally I re-encode with this receipt:
Gzip(‘Dynamic Huffman Coding’,”,”,false)
To_Hex(‘0x with comma’,16)
In this moment all work in rule for me….
thanks
Hi! Thanks for the great tutorial!
I have implemented this model, and I need a couple of ajustments:
1 – I would like to set both servos to start at position 90 degrees (center). When I touch the controls the tilt servo goes immediately to the up position.
2 – I have placed the ESP32 in a horizontal position, so I need to rotate the image of the camera in 90 degrees.
How can I implement these changes in the code?
Just an update about item #2, I have followed the instructions from the comment above, so I’ve converted the hex code to HTML and included a row with the suggested syntax, then I’ve transformed into hex again and uploaded the code. Although it managed to create the web server correctly, the page shows nothing… after converting again, do I need to perform other changes in the code?
Hi, Can you see anything in the browser when you ‘view source’?