ESP32-CAM Ai Thinker with servos and dc motors

hi i am using an ESP32-CAM with 4 DC motors and 3 Servo Motors and i made a python script to control them via GUI app or via ps4 Controller (by sending requests to the esp server) so i have everything's works separately when all goes together the cam stream lags and the requests take more time to excute (the ps4 sending reads to the laptop then the laptop sending requests to the esp) (i cant run the ps4 controlelr directly to the esp because it runs away from ram)

i am using the esp in AP (access point) mode
the esp code :

#include "esp_controller_functions.h"
#include <WiFi.h>
#include "esp_camera.h"
#include <ArduinoJson.h>
#include <WebServer.h>

#define CAMERA_MODEL_AI_THINKER  // Has PSRAM

#include "camera_pins.h"

const char* ssid = "EC";
const char* password = "Hunter1235";

IPAddress local_ip(192, 168, 1, 4);
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 255, 0);


void startCameraServer();
void setupLedFlash(int pin);

void setup() {
  
  ESP32PWM::allocateTimer(2);
  ESP32PWM::allocateTimer(3);
  
  Serial.begin(115200);
  Serial.setDebugOutput(true);
  Serial.println();


  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_sccb_sda = SIOD_GPIO_NUM;
  config.pin_sccb_scl = SIOC_GPIO_NUM;
  config.pin_pwdn = PWDN_GPIO_NUM;
  config.pin_reset = RESET_GPIO_NUM;
  config.xclk_freq_hz = 20000000;
  config.frame_size = FRAMESIZE_SVGA;//XGA 
  config.pixel_format = PIXFORMAT_JPEG;  // for streaming
  config.grab_mode = CAMERA_GRAB_WHEN_EMPTY;
  config.fb_location = CAMERA_FB_IN_PSRAM;
  config.jpeg_quality = 12;
  config.fb_count = 1;
  if (config.pixel_format == PIXFORMAT_JPEG) {
    if (psramFound()) {
      config.jpeg_quality = 10;
      config.fb_count = 2;
      config.grab_mode = CAMERA_GRAB_LATEST;
    } else {
      config.frame_size = FRAMESIZE_SVGA;
      config.fb_location = CAMERA_FB_IN_DRAM;
    }
  } else {
    config.frame_size = FRAMESIZE_240X240;
#if CONFIG_IDF_TARGET_ESP32S3
    config.fb_count = 2;
#endif
  }
#if defined(CAMERA_MODEL_ESP_EYE)
  pinMode(13, INPUT_PULLUP);
  pinMode(14, INPUT_PULLUP);
#endif
  esp_err_t err = esp_camera_init(&config);
  if (err != ESP_OK) {
    Serial.printf("Camera init failed with error 0x%Ox", err);
    return;
  }
  sensor_t* s = esp_camera_sensor_get();
  if (s->id.PID == OV3660_PID) {
    s->set_vflip(s, 1);        // flip it back
    s->set_brightness(s, 1);   // up the brightness just a bit
    s->set_saturation(s, -2);  // lower the saturation
  }
  if (config.pixel_format == PIXFORMAT_JPEG) {
    s->set_framesize(s, FRAMESIZE_QVGA);
  }

#if defined(CAMERA_MODEL_M5STACK_WIDE) || defined(CAMERA_MODEL_M5STACK_ESP32CAM)
  s->set_vflip(s, 1);
  s->set_hmirror(s, 1);
#endif

#if defined(CAMERA_MODEL_ESP32S3_EYE)
  s->set_vflip(s, 1);
#endif
#if defined(LED_GPIO_NUM)
  setupLedFlash(LED_GPIO_NUM);
#endif


  WiFi.softAP(ssid, password);
  WiFi.softAPConfig(local_ip, gateway, subnet);
  startCameraServer();
  Serial.print(F("Camera Ready! Use 'http://"));
  Serial.print(local_ip);
  Serial.println(F("' to connect"));
  
  server.on("/OnPressUpArrow", HTTP_GET, UpArrowButtonOnPressFunc);
  server.on("/OnPressRightArrow", HTTP_GET, RightArrowButtonOnPressFunc);
  server.on("/OnPressLeftArrow", HTTP_GET, LeftArrowButtonOnPressFunc);
  server.on("/OnPressDownArrow", HTTP_GET, DownArrowButtonOnPressFunc);
  server.on("/OnPressTr", HTTP_GET, TriangleOnPressFunc);
  server.on("/OnPressCircle", HTTP_GET, CircleOnPressFunc);
  server.on("/OnPressSquare", HTTP_GET, SquareOnPressFunc);
  server.on("/OnPressX", HTTP_GET, XOnPressFunc);
  server.on("/OnPressLt", HTTP_GET, LTOnPressFunc);
  server.on("/OnPressRt", HTTP_GET, RTOnPressFunc);
  server.on("/OnPressLb", HTTP_GET, LBOnPressFunc);
  server.on("/OnPressRb", HTTP_GET, RBOnPressFunc);


  server.on("/OnReleaseUpArrow", HTTP_GET, UpArrowButtonOnReleaseFunc);
  server.on("/OnReleaseRightArrow", HTTP_GET, RightArrowButtonOnReleaseFunc);
  server.on("/OnReleaseLeftArrow", HTTP_GET, LeftArrowButtonOnReleaseFunc);
  server.on("/OnReleaseDownArrow", HTTP_GET, DownArrowButtonOnReleaseFunc);
  server.on("/OnReleaseTr", HTTP_GET, TriangleOnReleaseFunc);
  server.on("/OnReleaseCircle", HTTP_GET, CircleOnReleaseFunc);
  server.on("/OnReleaseSquare", HTTP_GET, SquareOnReleaseFunc);
  server.on("/OnReleaseX", HTTP_GET, XOnReleaseFunc);
  server.on("/OnReleaseLt", HTTP_GET, LTOnReleaseFunc);
  server.on("/OnReleaseRt", HTTP_GET, RTOnReleaseFunc);
  server.on("/OnReleaseLb", HTTP_GET, LBOnReleaseFunc);
  server.on("/OnReleaseRb", HTTP_GET, RBOnReleaseFunc);


  server.on("/R1Up", HTTP_GET, R1UpFunc);
  server.on("/R1Down", HTTP_GET, R1DownFunc);
  server.on("/R1Right", HTTP_GET, R1RightFunc);
  server.on("/R1Left", HTTP_GET, R1LeftFunc);
  server.on("/R2Up", HTTP_GET, R2UpFunc);
  server.on("/R2Down", HTTP_GET, R2DownFunc);
  server.on("/R2Right", HTTP_GET, R2RightFunc);
  server.on("/R2Left", HTTP_GET, R2LeftFunc);
  server.on("/R1Stop", HTTP_GET, R1Stop);
  server.on("/R2Stop", HTTP_GET, R2Stop);
  // server.on("/distance", HTTP_GET, distance);

  server.begin();
  // pinMode(Led, OUTPUT);
  pinMode(Motor1F, OUTPUT);
  pinMode(Motor1B, OUTPUT);
  pinMode(Motor2F, OUTPUT);
  pinMode(Motor2B, OUTPUT);
  pinMode(buzzer, OUTPUT);

  servoShoot.attach(ShootPin);
  servoUD.attach(ServoUDPin);
  servoLR.attach(ServoLRPin);

  servoUD.write(0);
  servoLR.write(0);
  servoShoot.write(180);
  
  
}

void loop() {
  server.handleClient();
}

"esp_controller_functions.h "file code

 #ifndef ESP_CONTROLLER_FUNC_H_
#define ESP_CONTROLLER_FUNC_H_

#include <WebServer.h>
#include <ESP32Servo.h>

WebServer server(80);

#define Motor1F 4
#define Motor1B 2
#define Motor2F 3
#define Motor2B 1
#define ShootPin 15
#define ServoUDPin 13
#define ServoLRPin 12
// #define Led 4
#define buzzer 14

int ServoUDPos = 0;
int ServoLRPos = 0;

bool ServoUD_State = true ;

Servo servoShoot;
Servo servoUD;
Servo servoLR;


// void LedOnOff() {
//   digitalWrite(Led, !digitalRead(Led));
// }

void Buzzer()
{
  digitalWrite(buzzer,HIGH);
  delay(500);
  digitalWrite(buzzer,LOW);
  delay(500);
}

void Shoot_Func() {
  servoShoot.write(110);
  Serial.println("shoot");
  delay(1000);                       
  servoShoot.write(180);
  Serial.println("return");
  delay(100);                       
  
}

void ServoUD_Stop()
{
  ServoUD_State = false;
}

void ServoUD_U() {
    if (ServoUDPos <= 90 ) {
      ServoUDPos+=1;
      Serial.println(ServoUDPos);
      servoUD.write(ServoUDPos);
    }
}

void ServoUD_D() {
    if (ServoUDPos > 0 ) {
      ServoUDPos-=1;
      Serial.println(ServoUDPos);
      servoUD.write(ServoUDPos);
    }
}

void ServoLR_L() {
  if (ServoLRPos > 0 ) {
    ServoLRPos-=5;
    Serial.println(ServoLRPos);
    servoLR.write(ServoLRPos);
  }
}

void ServoLR_R() {
    if (ServoLRPos <= 160 ) {
    ServoLRPos+=5;
    Serial.println(ServoLRPos);
    servoLR.write(ServoLRPos);
  }
}

void DcMotorsForward(void) {
  digitalWrite(Motor1F, HIGH);
  digitalWrite(Motor2F, HIGH);
  digitalWrite(Motor1B, LOW);
  digitalWrite(Motor2B, LOW);
}
void DcMotorsBackward(void) {
  digitalWrite(Motor1F, LOW);
  digitalWrite(Motor2F, LOW);
  digitalWrite(Motor1B, HIGH);
  digitalWrite(Motor2B, HIGH);
}
void DcMotorsRight(void) {
  digitalWrite(Motor1F, HIGH);
  digitalWrite(Motor2F, LOW);
  digitalWrite(Motor1B, LOW);
  digitalWrite(Motor2B, HIGH);
}
void DcMotorsLeft(void) {
  digitalWrite(Motor1F, LOW);
  digitalWrite(Motor2F, HIGH);
  digitalWrite(Motor1B, HIGH);
  digitalWrite(Motor2B, LOW);
}
void DcMotorsStop(void) {
  digitalWrite(Motor1F, LOW);
  digitalWrite(Motor2F, LOW);
  digitalWrite(Motor1B, LOW);
  digitalWrite(Motor2B, LOW);

}


void R1Stop() {
  Serial.println("R1Stop\n");
  DcMotorsStop();
  server.send(200, "text/plain", "R1Stop");
}
void R2Stop() {
  Serial.println("R2Stop\n");
  ServoUD_Stop();
  server.send(200, "text/plain", "R2Stop");
}
void UpArrowButtonOnPressFunc() {
  Serial.println("OnPressUpArrow\n");
  ServoUD_U();
  server.send(200, "text/plain", "OnPressUpArrow");
}
void DownArrowButtonOnPressFunc() {
  Serial.println("OnPressDownArrow\n");
  ServoUD_D();
  server.send(201, "text/plain", "OnPressDownArrow");
}
void RightArrowButtonOnPressFunc() {
  Serial.println("OnPressRightArrow\n");
  DcMotorsRight();
  server.send(202, "text/plain", "OnPressRightArrow");
}
void LeftArrowButtonOnPressFunc() {
  Serial.println("OnPressLeftArrow\n");
  DcMotorsLeft();
  server.send(203, "text/plain", "OnPressLeftArrow");
}
void TriangleOnPressFunc() {
  Serial.println("OnPressTr\n");
  Buzzer();
  server.send(204, "text/plain", "OnPressTr");
}
void CircleOnPressFunc() {
  Serial.println("OnPressCircle\n");
  server.send(205, "text/plain", "OnPressCircle");
}
void XOnPressFunc() {
  Serial.println("OnPressX\n");
  DcMotorsForward();
  server.send(206, "text/plain", "OnPressX");
}
void SquareOnPressFunc() {
  Serial.println("OnPressSquare\n");
  DcMotorsBackward();
  server.send(207, "text/plain", "OnPressSquare");
}
void LTOnPressFunc() {
  Serial.println("OnPressLt\n");
  server.send(208, "text/plain", "OnPressLt");
}
void RTOnPressFunc() {
  Serial.println("OnPressRt\n");
  Shoot_Func();
  server.send(209, "text/plain", "OnPressRt");
}
void LBOnPressFunc() {
  Serial.println("OnPressLb\n");
  ServoLR_L();
  server.send(210, "text/plain", "OnPressLb");
}
void RBOnPressFunc() {
  Serial.println("OnPressRb\n");
  ServoLR_R();
  server.send(211, "text/plain", "OnPressRb");
}


void UpArrowButtonOnReleaseFunc() {
  Serial.println("OnReleaseUpArrow\n");
  ServoUD_Stop();
  server.send(217, "text/plain", "OnReleaseUpArrow");
}
void DownArrowButtonOnReleaseFunc() {
  Serial.println("OnReleaseDownArrow\n");
  ServoUD_Stop();
  server.send(218, "text/plain", "OnReleaseDownArrow");
}
void RightArrowButtonOnReleaseFunc() {
  Serial.println("OnReleaseRightArrow\n");
  DcMotorsStop();
  server.send(219, "text/plain", "OnReleaseRightArrow");
}
void LeftArrowButtonOnReleaseFunc() {
  Serial.println("OnReleaseLeftArrow\n");
  DcMotorsStop();
  server.send(220, "text/plain", "OnReleaseLeftArrow");
}
void TriangleOnReleaseFunc() {
  Serial.println("OnReleaseTr\n");
  server.send(221, "text/plain", "OnReleaseTr");
}
void CircleOnReleaseFunc() {
  Serial.println("OnReleaseCircle\n");
  server.send(222, "text/plain", "OnReleaseCircle");
}
void XOnReleaseFunc() {
  Serial.println("OnReleaseX\n");
  DcMotorsStop();
  server.send(223, "text/plain", "OnReleaseX");
}
void SquareOnReleaseFunc() {
  Serial.println("OnReleaseSquare\n");
  DcMotorsStop();
  server.send(224, "text/plain", "OnReleaseSquare");
}
void LTOnReleaseFunc() {
  Serial.println("OnReleaseLt\n");
  server.send(225, "text/plain", "OnReleaseLt");
}
void RTOnReleaseFunc() {
  Serial.println("OnReleaseRt\n");
  server.send(226, "text/plain", "OnReleaseRt");
}
void LBOnReleaseFunc() {
  Serial.println("OnReleaseLb\n");
  server.send(227, "text/plain", "OnReleaseLb");
}
void RBOnReleaseFunc() {
  Serial.println("OnReleaseRb\n");
  server.send(228, "text/plain", "OnReleaseRb");
}



void R1UpFunc() {
  Serial.println("R1Up\n");
  DcMotorsForward();
  server.send(234, "text/plain", "R1Up");
}
void R1DownFunc() {
  Serial.println("R1Down\n");
  DcMotorsBackward();
  server.send(235, "text/plain", "R1Down");
}
void R1RightFunc() {
  Serial.println("R1Right\n");
  server.send(236, "text/plain", "R1Right");
  DcMotorsRight();
}
void R1LeftFunc() {
  Serial.println("R1Left\n");
  server.send(237, "text/plain", "R1Left");
  DcMotorsLeft();
}

void R2UpFunc() {
  Serial.println("R2Up\n");
  ServoUD_U();
  server.send(238, "text/plain", "R2Up");
}
void R2DownFunc() {
  Serial.println("R2Down\n");
  ServoUD_D();
  server.send(239, "text/plain", "R2Down");
}
void R2RightFunc() {
  ServoLR_R();
  Serial.println("R2Right\n");
  server.send(240, "text/plain", "R2Right");
}
void R2LeftFunc() {
  Serial.println("R2Left\n");
  ServoLR_L();
  server.send(241, "text/plain", "R2Left");
}

 }

#endif 

and the ps4 controller python script code

import pygame
from esp_controller_functions import *
import time 

pygame.init()
pygame.joystick.init()


# Flags to track movement direction
R1moved_left = False
R1moved_right = False
R1moved_up = False
R1moved_down = False

R2moved_left = False
R2moved_right = False
R2moved_up = False
R2moved_down = False

RB_Moved = False
LB_Moved = False

def joy_Get_Init():
    get_init = pygame.joystick.get_init()
    if get_init == True:
        pass
    else:
        pass

def refresh():
    pygame.event.pump()



while True:
        # refresh()

        joystick = pygame.joystick.Joystick(0)
        joystick.init()
        events = pygame.event.get()
        for event in events:
            if event.type == pygame.JOYBUTTONDOWN:
                if joystick.get_button(Square):
                    SquareOnPressFunc()
                if joystick.get_button(X):
                    XOnPressFunc()
                if joystick.get_button(Circle):
                    CircleOnPressFunc()
                if joystick.get_button(Triangle):
                    TriangleOnPressFunc()
                if joystick.get_button(RT):
                    RtOnPressFunc()
                if joystick.get_button(LT):
                    LtOnPressFunc()
                if joystick.get_button(UpArrow):
                    UpArrowButtonOnPressFunc()
                if joystick.get_button(DownArrow):
                    DownArrowButtonOnPressFunc()
                if joystick.get_button(RightArrow):
                    RightArrowButtonOnPressFunc()
                if joystick.get_button(LeftArrow):
                    LeftArrowButtonOnPressFunc()
                if joystick.get_button(Share):
                    ShareOnPressFunc()
                if joystick.get_button(Ps):
                    PsOnPressFunc()
                if joystick.get_button(Options):
                    OptionsOnPressFunc()
                if joystick.get_button(R1Click):
                    R1ClickOnPressFunc()
                if joystick.get_button(R2Click):
                    R2ClickOnPressFunc()

            if event.type == pygame.JOYBUTTONUP:
                if event.button == (Square):
                    SquareOnReleaseFunc()
                if event.button == (X):
                    XOnReleaseFunc()
                if event.button == (Circle):
                    CircleOnReleaseFunc()
                if event.button == (Triangle):
                    TriangleOnReleaseFunc()
                if event.button == (RT):
                    RtOnReleaseFunc()
                if event.button == (LT):
                    LtOnReleaseFunc()
                if event.button == (UpArrow):
                    UpArrowButtonOnReleaseFunc()
                if event.button == (DownArrow):
                    DownArrowButtonOnReleaseFunc()
                if event.button == (RightArrow):
                    RightArrowButtonOnReleaseFunc()
                if event.button == (LeftArrow):
                    LeftArrowButtonOnReleaseFunc()
                if event.button == (Share):
                    ShareOnReleaseFunc()
                if event.button == (Ps):
                    PsOnReleaseFunc()
                if event.button == (Options):
                    OptionsOnReleaseFunc()
                if event.button == (R1Click):
                    R1ClickOnReleaseFunc()
                if event.button == (R2Click):
                    R2ClickOnReleaseFunc()

            if event.type == pygame.JOYAXISMOTION:
                axis = event.axis
                value = event.value


                R1x_axis = joystick.get_axis(R1Right_Left)  
                R1y_axis = joystick.get_axis(R1Up_Down)  
                R2x_axis = joystick.get_axis(R2Right_Left)  
                R2y_axis = joystick.get_axis(R2Up_Down) 
                RB_axis = joystick.get_axis(RB) 
                LB_axis = joystick.get_axis(LB) 

                if ((RB_axis > .5) and not RB_Moved):
                    RbOnPressFunc()
                    RB_Moved = True
        

                if RB_axis > .5 and not RB_Moved:
                    RB_Moved = True
                    RbOnPressFunc()
                elif RB_axis <= .5 and RB_Moved:
                    RB_Moved = False
                    RbOnReleaseFunc()

                if LB_axis > .5 and not LB_Moved:
                    LB_Moved = True
                    LbOnPressFunc()
                elif LB_axis <= .5 and LB_Moved:
                    LB_Moved = False
                    LbOnReleaseFunc()

                if R1x_axis < -0.5 and not R1moved_left:
                    R1LeftFunc()
                    R1moved_left = True
                elif R1x_axis > -0.1 and R1moved_left:
                    R1Stop()
                    R1moved_left = False

                # Detect movement to the right
                if R1x_axis > 0.5 and not R1moved_right:
                    R1RightFunc()
                    R1moved_right = True
                elif R1x_axis < 0.1 and R1moved_right:
                    R1Stop()
                    R1moved_right = False

                # Detect movement upwards
                if R1y_axis < -0.5 and not R1moved_up:
                    R1UpFunc()
                    R1moved_up = True
                elif R1y_axis > -0.1 and R1moved_up:
                    R1Stop()
                    R1moved_up = False

                # Detect movement downwards
                if R1y_axis > 0.5 and not R1moved_down:
                    R1DownFunc()
                    R1moved_down = True
                elif R1y_axis < 0.1 and R1moved_down:
                    R1Stop()
                    R1moved_down = False

                # Detect movement to the left
                if R2x_axis < -0.5 and not R2moved_left:
                    R2LeftFunc()
                    R2moved_left = True
                elif R2x_axis > -0.1 and R2moved_left:
                    R2Stop()
                    R2moved_left = False

                # Detect movement to the right
                if R2x_axis > 0.5 and not R2moved_right:
                    R2RightFunc()
                    R2moved_right = True
                elif R2x_axis < 0.1 and R2moved_right:
                    R2Stop()
                    R2moved_right = False

                # Detect movement upwards
                if R2moved_up == True :
                    R2DownFunc()
                    print("up")
                if R2moved_down == True :
                    R2UpFunc()
                    print("down")

                if R2y_axis < -0.5 and not R2moved_up:
                    R2UpFunc()
                    R2moved_up = True
                elif R2y_axis > -0.1 and R2moved_up:
                    R2Stop()
                    print("stop")
                    R2moved_up = False

                # Detect movement downwards
                if R2y_axis > 0.5 and not R2moved_down:
                    R2DownFunc()
                    R2moved_down = True
                elif R2y_axis < 0.1 and R2moved_down:
                    R2Stop()
                    print("stop")
                    R2moved_down = False

and the "esp_controller_functions" file code contains the ps4_buttons layout and functions to send requests

import urllib.request
import requests

def SendRequest(Request):
    Url = "http://192.168.1.4"
    try:
        urllib.request.urlopen(Url+Request)
    except Exception as e:
        try:
            pass
            urllib.request.urlopen(Url+Request)
        except Exception as e:
            print("Request failed:", e)```



by the way iam sending the requests twice because when i send in first time it fails and i dont know why

# Arrows OnPressFunctions
def UpArrowButtonOnPressFunc(event =1):
    SendRequest("/OnPressUpArrow")
def RightArrowButtonOnPressFunc(event =1):
    SendRequest("/OnPressRightArrow")
def LeftArrowButtonOnPressFunc(event =1):
    SendRequest("/OnPressLeftArrow")
def DownArrowButtonOnPressFunc(event =1):
    SendRequest("/OnPressDownArrow")

I moved your topic to a more appropriate forum category @osamaabdelmohsen.

The Nano ESP32 category you chose is only used for discussions directly related to the Arduino Nano ESP32 board.

In the future, please take the time to pick the forum category that best suits the subject of your question. There is an "About the _____ category" topic at the top of each category that explains its purpose.

Thanks in advance for your cooperation.

1 Like

And also i got only first two servo works the third one not working (whatever i changed the order)

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.