#include <ESP32Servo.h>
// Define pin connections
const int joyXPin1 = 34; // Joystick 1 X-axis (for servo 1 in/out) - Use ADC1 pins (32-39)
const int joyYPin1 = 35; // Joystick 1 Y-axis (not used) - Use ADC1 pins (32-39)
const int joyXPin2 = 32; // Joystick 2 X-axis (for servo 2 rotation) - Use ADC1 pins (32-39)
const int joyYPin2 = 33; // Joystick 2 Y-axis (not used) - Use ADC1 pins (32-39)
const int servoInOutPin = 14; // Servo 1 pin (in/out movement)
const int servoRotatePin = 15; // Servo 2 pin (rotation)
// Servo objects
Servo servoInOut;
Servo servoRotate;
// Servo position limits and mapping ranges
const int servoInOutMin = 0; // Minimum position for in/out servo
const int servoInOutMax = 180; // Maximum position for in/out servo
const int servoRotateMin = 0; // Minimum rotation for rotation servo
const int servoRotateMax = 180; // Maximum rotation for rotation servo
const int joyMin = 0; // Minimum joystick reading (theoretical)
const int joyMax = 4095; // Maximum joystick reading (12-bit ADC)
// Dead zone for joystick
const int deadZone = 150; // Adjust as needed, now based on 12-bit ADC
// Number of samples for averaging joystick readings
const int numAvgSamples = 5;
// Variables for averaging
int joyX1Samples[numAvgSamples];
int joyX2Samples[numAvgSamples];
int sampleIndex = 0;
bool samplesFilled = false;
void setup() {
// Initialize servos using ESP32Servo
ESP32PWM::allocateTimer(0); //important to allocate a timer to the esp32servo library, we are using the first of 4 timers here
ESP32PWM::allocateTimer(1);
ESP32PWM::allocateTimer(2);
ESP32PWM::allocateTimer(3);
servoInOut.setPeriodHertz(50); // Standard 50Hz servo
servoRotate.setPeriodHertz(50);
servoInOut.attach(servoInOutPin, 500, 2400); // (pin, min pulse width, max pulse width in microseconds)
servoRotate.attach(servoRotatePin, 500, 2400);
// Initialize serial communication for debugging (optional)
Serial.begin(115200);
}
int readJoystickAvg(int joyPin, int samples[], int numSamples) {
// Shift existing samples
for (int i = numSamples - 1; i > 0; i--) {
samples[i] = samples[i - 1];
}
// Read new sample
samples[0] = analogRead(joyPin);
// Calculate average
long sum = 0;
int count = samplesFilled ? numSamples : sampleIndex+1;
for (int i = 0; i < count; i++) {
sum += samples[i];
}
return (int)(sum / count);
}
void loop() {
// Read joystick values with averaging
int joyX1 = readJoystickAvg(joyXPin1, joyX1Samples, numAvgSamples);
int joyX2 = readJoystickAvg(joyXPin2, joyX2Samples, numAvgSamples);
// Update sample index and flag
sampleIndex = (sampleIndex + 1) % numAvgSamples;
if (sampleIndex == 0) {
samplesFilled = true;
}
// --- Control in/out servo with joystick 1 X-axis ---
if (abs(joyX1 - (joyMax/2)) > deadZone) {
int servoInOutPos = map(joyX1, joyMin, joyMax, servoInOutMax, servoInOutMin);
servoInOutPos = constrain(servoInOutPos, servoInOutMin, servoInOutMax);
servoInOut.write(servoInOutPos);
// Debugging
Serial.print("Joystick 1 X: ");
Serial.print(joyX1);
Serial.print("\tServo In/Out: ");
Serial.println(servoInOutPos);
}
// --- Control rotation servo with joystick 2 X-axis ---
if (abs(joyX2 - (joyMax/2)) > deadZone) {
int servoRotatePos = map(joyX2, joyMin, joyMax, servoRotateMin, servoRotateMax);
servoRotatePos = constrain(servoRotatePos, servoRotateMin, servoRotateMax);
servoRotate.write(servoRotatePos);
// Debugging
Serial.print("Joystick 2 X: ");
Serial.print(joyX2);
Serial.print("\tServo Rotate: ");
Serial.println(servoRotatePos);
}
}
esp:0
esp:2
esp:4
esp:5
esp:12
esp:13
esp:14
esp:15
esp:16
esp:17
esp:18
esp:19
esp:21
esp:22
esp:23
esp:25
esp:26
esp:27
esp:32
esp:33
esp:34
esp:35
esp:3V3
esp:EN
esp:VP
esp:VN
esp:GND.1
esp:D2
esp:D3
esp:CMD
esp:5V
esp:GND.2
esp:TX
esp:RX
esp:GND.3
esp:D1
esp:D0
esp:CLK
servo1:GND
servo1:V+
servo1:PWM
servo2:GND
servo2:V+
servo2:PWM
Kick (rotate) Servo
Move Rod (push/pull) Servo
joystick1:VCC
joystick1:VERT
joystick1:HORZ
joystick1:SEL
joystick1:GND
joystick2:VCC
joystick2:VERT
joystick2:HORZ
joystick2:SEL
joystick2:GND
vcc1:VCC
gnd1:GND
Move Rod
Kick
External Power Supply