Currently, I'm working on a face-tracking webcam using a pan-tilt servo with PID controlling.
i have written the following code for Arduino and I'm sending the detected face center from Python code to Arduino. When I run the program for some initial time it's oscillating a lot and after a short time it is following the face and when I hold the face it tracks but slightly oscillates.
The main problem is that when I stop the execution of the program it moves to one of the extreme positions either 0 or 180 slowly. When I again run it repeats.
I have checked different P, I, and D parameters but not getting the result.
Note: My frame resolution is 640X480
#include <Servo.h>
#include <cvzone.h>
Servo panServo; // Create a servo object for the pan (horizontal) servo
Servo tiltServo; // Create a servo object for the tilt (vertical) servo
SerialData serialData(2, 3); //(numOfValsRec,digitsPerValRec)
int valsRec[2]; // array of int with size numOfValsRec
// Define the pins for the servo motors
int panPin = 3;
int tiltPin = 10;
// Define variables for PID control
double inputX, inputY; // Current position values received from Python
double outputX, outputY; // Output values to control the servos
double setpointX, setpointY; // Desired position values
// Define the PID constants
double kp = 0.4; // Proportional gain
double ki = 0.1; // Integral gain
double kd = 0.5; // Derivative gain
double prevErrorX = 0, prevErrorY = 0; // Previous error values for calculating the derivative term
double integralX = 0, integralY = 0; // Integral terms
void setup() {
// Attach the servos to their respective pins
panServo.attach(panPin);
tiltServo.attach(tiltPin);
// Set the initial setpoint to the current position
setpointX = 300;
setpointY = 200;
serialData.begin(9600);
}
void loop() {
// Receive position information from Python
receivePosition();
// Perform PID calculations for X-axis
double errorX = setpointX - inputX-10;
integralX += errorX;
double derivativeX = errorX - prevErrorX;
outputX = kp * errorX + ki * integralX + kd * derivativeX;
prevErrorX = errorX;
// Perform PID calculations for Y-axis
double errorY = setpointY - inputY;
integralY += errorY;
double derivativeY = errorY - prevErrorY;
outputY = kp * errorY + ki * integralY + kd * derivativeY;
prevErrorY = errorY;
Control the servos using the PID outputs
controlServos();
// Delay for a short interval before the next PID update
delay(10);
}
void receivePosition() {
// Reading the position information from Python
if (Serial.available() > 0) {
serialData.Get(valsRec);
// Read the position values
inputX = valsRec[0];
inputY = valsRec[1];
}
else if(Serial.available()<0){
panServo.write(90);
}}
void controlServos() {
// Mapping the PID outputs to servo angles
int panAngle = map(outputX, -100, 100, -45, 45);
int tiltAngle = map(outputY, -100, 100, -45, 45);
// Controlling the pan and tilt servos
panServo.write(90 + panAngle);
tiltServo.write(90 + tiltAngle);
}