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")