DIY ESP32 Camera Motor Shield - Wifi Camera Robot Car: Step 1: Design PCB Use Autodesk Eagle Software
DIY ESP32 Camera Motor Shield - Wifi Camera Robot Car: Step 1: Design PCB Use Autodesk Eagle Software
by bluino_electronics
This article is proudly sponsored by PCBWAY. PCBWAY. The Motor Shield for ESP32-Cam that I
developed in this project uses PCBWAY PCB services. In
PCBWAY make high quality prototyping PCBs for people this instructable, I will show you how to build Camera
all over the world. Try it for your self and get 10 PCBs for WiFi Robot Car use ESP32-Cam. Let's get started!
just $5 at PCBWAY with very great quality, Thanks
https://youtu.be/BUiqaGuOhfA
To design a PCB use Autodesk Eagle software, which is a You can download Eagle from Autodesk's website, and
CAD program speci cally designed for making circuit you will also need to sign up for a free Autodesk
boards. This software is free for 2-sided boards up to account.
80cm². This should be more than enough area for any
hobby project.You can download Eagle from Autodesk's To learn how to design a custom printed circuit board
website, and you will also need to sign up for a free for your prototype project. You can follow Circuit Board
Autodesk account. Design Class.
DIY ESP32 Camera Motor Shield - Wifi Camera Robot Car: Page 1
Step 2: Order PCB on PCBWAY
To make this project you need to order a prototype PCB 2. Open this PCB project link ESP32 Camera Motor Shield
on PCBWAY. How to order is very easy and you will get
10 Pcs PCB for $5 with very great PCB quality. 3. Click Add to cart.
Step to Order: 4. Wait moment for PCB review, then Click Check Out.
1. SignUp/Log in on pcbway.com
Here are the components that you will need to make ESP32 Cam Motor Shield:
This project has one SMD component, it is not too di cult to solder because the size of the SMD component is quite
large, so don't worry.
You will need tweezers as a tool to hold the components when soldered.
DIY ESP32 Camera Motor Shield - Wifi Camera Robot Car: Page 3
Step 5: Place the Components
After nish solder SMD component, next attach other trough hole components on the PCB following the pictures and
symbols on the PCB, for details you can follow step by step in the video.
DIY ESP32 Camera Motor Shield - Wifi Camera Robot Car: Page 4
Step 6: Soldering
Solder all the component legs on the back of the PCB, for details you can follow step by step in the video.
After nish solder, cut all the long legs of the component wire
Bend the short leg of the female header into an elbow 90 degrees, then attach it on the PCB pin hole as shown. then
solder it
DIY ESP32 Camera Motor Shield - Wifi Camera Robot Car: Page 5
Step 8: Attach Long Leg of the Female Header
Bend the long leg of the female header into an elbow 90 degrees. Attach it to other straight long leg of the female
header as shown.
Then by using the ESP32-Cam as a mold to hold the pin header, you can solder to the PCB.
DIY ESP32 Camera Motor Shield - Wifi Camera Robot Car: Page 6
Step 9: Attach IC, ESP32-Cam & USB to TTL Module
Install IC L293D (dual motor driver) on the IC socket, see its position do not reverse.
Attach the USB to TTL CP2102 module which already has a male pin header into the female header socket that leads
outward.
DIY ESP32 Camera Motor Shield - Wifi Camera Robot Car: Page 7
Step 10: PCB Mainboard Is Ready
DIY ESP32 Camera Motor Shield - Wifi Camera Robot Car: Page 8
Step 11: Attach Mainboard Into Chassis
You can use a custom chassis that you have or you made left and right, if you make four wheels, it is only installed
yourself. The mainboard PCB is the same shape and size in parallel. Connect the left motor and the right motor to
as the Arduino Uno, so you can easily nd a chassis that the screw terminals on the PCB mainboard motor driver
ts this one. output. Connect 2 x 18650 3.7V batteries to the power
source terminal screw on the PCB mainboard.
For wheeled motors, it doesn't matter if you use four or
two, actually the output of the motor driver is only two,
DIY ESP32 Camera Motor Shield - Wifi Camera Robot Car: Page 9
Step 12: Upload Firmware to ESP32-Cam Board
To make WiFi Camera Robot Car can controlled by smartphone Android, you have to program ESP32-Cam rst. The easy
way to program ESP32-Cam that you can use this Android App follow this step:
Otherwise, you can program ESP32-Cam board through a computer using the Arduino IDE software use this sketch:
Note: First, your Arduino IDE must be setup to be able use to programming ESP8266 board
#include "esp_camera.h"
#include <WiFi.h>
#include <ArduinoOTA.h>
/* Wifi Crdentials */
//String sta_ssid = "$your_ssid_maximum_32_characters"; // set Wifi network you want to connect to
//String sta_password = "$your_pswd_maximum_32_characters"; // set password for Wifi network
/* define CAMERA_MODEL_AI_THINKER */
#define PWDN_GPIO_NUM 32
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 0
#define SIOD_GPIO_NUM 26
#define SIOC_GPIO_NUM 27
#define Y9_GPIO_NUM 35
#define Y8_GPIO_NUM 34
#define Y7_GPIO_NUM 39
#define Y6_GPIO_NUM 36
#define Y5_GPIO_NUM 21
#define Y4_GPIO_NUM 19
#define Y3_GPIO_NUM 18
#define Y2_GPIO_NUM 5
#define VSYNC_GPIO_NUM 25
#define HREF_GPIO_NUM 23
#define PCLK_GPIO_NUM 22
extern int ledPin = 4; // set digital pin GPIO4 as LED pin (use biult-in LED)
extern int buzzerPin = 2; // set digital pin GPIO2 as LED pin (use Active Buzzer)
extern int servoPin = 2; // set digital pin GPIO2 as servo pin (use SG90)
void startCameraServer();
void initServo() {
ledcSetup(8, 50, 16); /*50 hz PWM, 16-bit resolution and range from 3250 to 6500 */
ledcAttachPin(servoPin, 8);
}
void initLed() {
ledcSetup(7, 5000, 8); /* 5000 hz PWM, 8-bit resolution and range from 0 to 255 */
ledcAttachPin(ledPin, 7);
}
void setup() {
Serial.begin(115200); // set up seriamonitor at 115200 bps
Serial.setDebugOutput(true);
Serial.println();
Serial.println("*ESP32 Camera Remote Control - L293D Bluino Shield*");
Serial.println("--------------------------------------------------------");
DIY ESP32 Camera Motor Shield - Wifi Camera Robot Car: Page 11
initLed();
camera_config_t config;
config.ledc_channel = LEDC_CHANNEL_0;
config.ledc_timer = LEDC_TIMER_0;
config.pin_d0 = Y2_GPIO_NUM;
config.pin_d1 = Y3_GPIO_NUM;
config.pin_d2 = Y4_GPIO_NUM;
config.pin_d3 = Y5_GPIO_NUM;
config.pin_d4 = Y6_GPIO_NUM;
config.pin_d5 = Y7_GPIO_NUM;
config.pin_d6 = Y8_GPIO_NUM;
config.pin_d7 = Y9_GPIO_NUM;
config.pin_xclk = XCLK_GPIO_NUM;
config.pin_pclk = PCLK_GPIO_NUM;
config.pin_vsync = VSYNC_GPIO_NUM;
config.pin_href = HREF_GPIO_NUM;
config.pin_sscb_sda = SIOD_GPIO_NUM;
config.pin_sscb_scl = SIOC_GPIO_NUM;
config.pin_pwdn = PWDN_GPIO_NUM;
config.pin_reset = RESET_GPIO_NUM;
config.xclk_freq_hz = 20000000;
config.pixel_format = PIXFORMAT_JPEG;
//init with high specs to pre-allocate larger buffers
if(psramFound()){
config.frame_size = FRAMESIZE_UXGA;
config.jpeg_quality = 10;
config.fb_count = 2;
} else {
config.frame_size = FRAMESIZE_SVGA;
config.jpeg_quality = 12;
config.fb_count = 1;
}
// camera init
esp_err_t err = esp_camera_init(&config);
if (err != ESP_OK) {
Serial.printf("Camera init failed with error 0x%x", err);
return;
}
Serial.println();
Serial.println("Hostname: "+hostname);
void loop() {
// put your main code here, to run repeatedly:
ArduinoOTA.handle();
}
#include "esp_http_server.h"
#include "esp_timer.h"
#include "esp_camera.h"
#include "img_converters.h"
#include "Arduino.h"
/* Initializing pins */
extern int DRV_A;
extern int DRV_B;
extern int DIR_A;
extern int DIR_B;
extern int ledPin;
extern int buzzerPin;
extern int servoPin;
extern int ledVal;
typedef struct {
httpd_req_t *req;
size_t len;
} jpg_chunking_t;
static size_t jpg_encode_stream(void * arg, size_t index, const void* data, size_t len){
jpg_chunking_t *j = (jpg_chunking_t *)arg;
if(!index){
j->len = 0;
}
if(httpd_resp_send_chunk(j->req, (const char *)data, len) != ESP_OK){
return 0;
}
j->len += len;
return len;
DIY ESP32 Camera Motor Shield - Wifi Camera Robot Car: Page 13
}
fb = esp_camera_fb_get();
if (!fb) {
Serial.printf("Camera capture failed");
httpd_resp_send_500(req);
return ESP_FAIL;
}
httpd_resp_set_type(req, "image/jpeg");
httpd_resp_set_hdr(req, "Content-Disposition", "inline; filename=capture.jpg");
size_t fb_len = 0;
if(fb->format == PIXFORMAT_JPEG){
fb_len = fb->len;
res = httpd_resp_send(req, (const char *)fb->buf, fb->len);
} else {
jpg_chunking_t jchunk = {req, 0};
res = frame2jpg_cb(fb, 80, jpg_encode_stream, &jchunk)?ESP_OK:ESP_FAIL;
httpd_resp_send_chunk(req, NULL, 0);
fb_len = jchunk.len;
}
esp_camera_fb_return(fb);
int64_t fr_end = esp_timer_get_time();
Serial.printf("JPG: %uB %ums", (uint32_t)(fb_len), (uint32_t)((fr_end - fr_start)/1000));
return res;
}
while(true){
fb = esp_camera_fb_get();
if (!fb) {
Serial.printf("Camera capture failed");
res = ESP_FAIL;
} else {
if(fb->format != PIXFORMAT_JPEG){
bool jpeg_converted = frame2jpg(fb, 80, &_jpg_buf, &_jpg_buf_len);
esp_camera_fb_return(fb);
fb = NULL;
if(!jpeg_converted){
Serial.printf("JPEG compression failed");
res = ESP_FAIL;
}
} else {
_jpg_buf_len = fb->len;
_jpg_buf = fb->buf;
}
}
if(res == ESP_OK){
size_t hlen = snprintf((char *)part_buf, 64, _STREAM_PART, _jpg_buf_len);
res = httpd_resp_send_chunk(req, (const char *)part_buf, hlen);
}
if(res == ESP_OK){
res = httpd_resp_send_chunk(req, (const char *)_jpg_buf, _jpg_buf_len);
}
DIY ESP32 Camera Motor Shield - Wifi Camera Robot Car: Page 14
}
if(res == ESP_OK){
res = httpd_resp_send_chunk(req, _STREAM_BOUNDARY, strlen(_STREAM_BOUNDARY));
}
if(fb){
esp_camera_fb_return(fb);
fb = NULL;
_jpg_buf = NULL;
} else if(_jpg_buf){
free(_jpg_buf);
_jpg_buf = NULL;
}
if(res != ESP_OK){
break;
}
int64_t fr_end = esp_timer_get_time();
last_frame = 0;
return res;
}
buf_len = httpd_req_get_url_query_len(req) + 1;
if (buf_len > 1) {
buf = (char*)malloc(buf_len);
Serial.println(buf);
if(!buf){
httpd_resp_send_500(req);
return ESP_FAIL;
}
if (httpd_req_get_url_query_str(req, buf, buf_len) == ESP_OK) {
if (httpd_query_key_value(buf, "var", variable, sizeof(variable)) == ESP_OK &&
httpd_query_key_value(buf, "val", value, sizeof(value)) == ESP_OK) {
} else {
free(buf);
Serial.println(buf);
httpd_resp_send_404(req);
return ESP_FAIL;
}
} else {
free(buf);
Serial.println(buf);
httpd_resp_send_404(req);
return ESP_FAIL;
}
Serial.println(buf);
free(buf);
} else {
httpd_resp_send_404(req);
Serial.println(ESP_FAIL);
return ESP_FAIL;
}
if(!strcmp(variable, "framesize")) {
if(s->pixformat == PIXFORMAT_JPEG) res = s->set_framesize(s, (framesize_t)val);
}
else if(!strcmp(variable, "quality")) res = s->set_quality(s, val);
else if(!strcmp(variable, "contrast")) res = s->set_contrast(s, val);
else if(!strcmp(variable, "brightness")) res = s->set_brightness(s, val);
else if(!strcmp(variable, "saturation")) res = s->set_saturation(s, val);
else if(!strcmp(variable, "gainceiling")) res = s->set_gainceiling(s, (gainceiling_t)val);
DIY ESP32 Camera Motor Shield - Wifi Camera Robot Car: Page 15
else if(!strcmp(variable, "gainceiling")) res = s->set_gainceiling(s, (gainceiling_t)val);
else if(!strcmp(variable, "colorbar")) res = s->set_colorbar(s, val);
else if(!strcmp(variable, "awb")) res = s->set_whitebal(s, val);
else if(!strcmp(variable, "agc")) res = s->set_gain_ctrl(s, val);
else if(!strcmp(variable, "aec")) res = s->set_exposure_ctrl(s, val);
else if(!strcmp(variable, "hmirror")) res = s->set_hmirror(s, val);
else if(!strcmp(variable, "vflip")) res = s->set_vflip(s, val);
else if(!strcmp(variable, "awb_gain")) res = s->set_awb_gain(s, val);
else if(!strcmp(variable, "agc_gain")) res = s->set_agc_gain(s, val);
else if(!strcmp(variable, "aec_value")) res = s->set_aec_value(s, val);
else if(!strcmp(variable, "aec2")) res = s->set_aec2(s, val);
else if(!strcmp(variable, "dcw")) res = s->set_dcw(s, val);
else if(!strcmp(variable, "bpc")) res = s->set_bpc(s, val);
else if(!strcmp(variable, "wpc")) res = s->set_wpc(s, val);
else if(!strcmp(variable, "raw_gma")) res = s->set_raw_gma(s, val);
else if(!strcmp(variable, "lenc")) res = s->set_lenc(s, val);
else if(!strcmp(variable, "special_effect")) res = s->set_special_effect(s, val);
else if(!strcmp(variable, "wb_mode")) res = s->set_wb_mode(s, val);
else if(!strcmp(variable, "ae_level")) res = s->set_ae_level(s, val);
else {
res = -1;
}
if(res){
return httpd_resp_send_500(req);
}
sensor_t * s = esp_camera_sensor_get();
char * p = json_response;
*p++ = '{';
buf_len = httpd_req_get_url_query_len(req) + 1;
if (buf_len > 1) {
DIY ESP32 Camera Motor Shield - Wifi Camera Robot Car: Page 16
buf = (char*)malloc(buf_len);
Serial.println(buf);
if(!buf){
httpd_resp_send_500(req);
return ESP_FAIL;
}
} else {
free(buf);
Serial.print("*");
Serial.println(ESP_FAIL);
httpd_resp_send_404(req);
return ESP_FAIL;
}
} else {
free(buf);
Serial.print("**");
Serial.println(ESP_FAIL);
httpd_resp_send_404(req);
return ESP_FAIL;
}
free(buf);
} else {
Serial.print("***");
Serial.println(ESP_FAIL);
httpd_resp_send_404(req);
return ESP_FAIL;
}
int res = 0;
if(!strcmp(cmd, "F")) {
Serial.println("Forward");
digitalWrite(DRV_A, HIGH);
digitalWrite(DRV_B, HIGH);
digitalWrite(DIR_A, HIGH);
digitalWrite(DIR_B, HIGH);
httpd_resp_set_type(req, "text/html");
return httpd_resp_send(req, "OK", 2);
}
DIY ESP32 Camera Motor Shield - Wifi Camera Robot Car: Page 17
else if(!strcmp(cmd, "G")) {
Serial.println("Forward Left");
digitalWrite(DRV_A, HIGH);
digitalWrite(DRV_B, LOW);
digitalWrite(DIR_A, HIGH);
digitalWrite(DIR_B, HIGH);
httpd_resp_set_type(req, "text/html");
return httpd_resp_send(req, "OK", 2);
}
else {
res = -1;
}
if(res){
return httpd_resp_send_500(req);
}
void startCameraServer(){
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
httpd_uri_t status_uri = {
.uri = "/status",
.method = HTTP_GET,
.handler = status_handler,
.user_ctx = NULL
};
httpd_uri_t cmd_uri = {
.uri = "/control",
.method = HTTP_GET,
.handler = cmd_handler,
.user_ctx = NULL
};
httpd_uri_t capture_uri = {
.uri = "/capture",
.method = HTTP_GET,
.handler = capture_handler,
.user_ctx = NULL
};
httpd_uri_t stream_uri = {
.uri = "/stream",
.method = HTTP_GET,
.handler = stream_handler,
.user_ctx = NULL
};
httpd_uri_t state_uri = {
.uri = "/state",
.method = HTTP_GET,
.handler = state_handler,
.user_ctx = NULL
DIY ESP32 Camera Motor Shield - Wifi Camera Robot Car: Page 20
.user_ctx = NULL
};
config.server_port += 1;
config.ctrl_port += 1;
Serial.printf("Starting stream server on port: '%d'", config.server_port);
if (httpd_start(&stream_httpd, &config) == ESP_OK) {
httpd_register_uri_handler(stream_httpd, &stream_uri);
}
}
DIY ESP32 Camera Motor Shield - Wifi Camera Robot Car: Page 21
The WiFi robot can be controlled via the Android app in two ways, controlled directly from android to ESP32-Cam (AP
mode), connect android to SSID of ESP32-Cam then set ip address on app 192.168.4.1.
Other way is ESP32-Cam (STA mode), android is connected to the same router network then set the IP address on app
according to the IP address that is owned by ESP32-Cam(i.e. 192.168.0.2).
Hi,
I tried this wonderful application. I recommend it to everyone.
I studied a lot of documentation and I haven't found a joystick application so far.
It's hard to drive with buttons.
I would have put the camera image on the left side of the screen and the joystick on the right
side.
Below him a "bar" for acceleration. But I'm not a programming specialist and I can't do that.
I will follow your articles in the future. Thanks again for your effort!
Doru Sandu
[email protected]
Specialist technician in automation
Europe, Romania
Very, very good project.
Congratulations!
Really well done! Great photos :D
DIY ESP32 Camera Motor Shield - Wifi Camera Robot Car: Page 22