How to apply autotune


#include <Servo.h>

// 180 horizontal MAX
Servo horizontal; // Servo object for horizontal movement
int servoh = 90; // Initial horizontal servo position
int servohLimitHigh = 180; // Horizontal servo upper limit
int servohLimitLow = 0; // Horizontal servo lower limit

Servo vertical; // Servo object for vertical movement
int servov = 45; // Initial vertical servo position
int servovLimitHigh = 180; // Vertical servo upper limit
int servoLimitLow = 0; // Vertical servo lower limit

// Joystick and switch pin definitions
const int joystickXPin = A4; // Joystick X-axis pin
const int joystickYPin = A5; // Joystick Y-axis pin
const int switchPin = 2; // Switch pin

bool joystickMode = false; // Joystick mode flag
bool switchPressed = false; // Switch pressed flag

// PID control variables
float integralV = 0, integralH = 0; // Integral terms for vertical and horizontal
float previousErrorV = 0, previousErrorH = 0; // Previous error terms for vertical and horizontal
float kp = -0.04, ki = -0.0005, kd = -0.0001; // PID coefficients
float integralMax = 100.0, integralMin = -100.0; // Integral clamping limits

bool autoTuneMode = false;

void autoTuneVertical() {
  // Implement Ziegler-Nichols tuning for the vertical servo
  // ...
}

void autoTuneHorizontal() {
  // Implement Ziegler-Nichols tuning for the horizontal servo
  // ...
}

void setup() {
  Serial.begin(9600); // Initialize serial communication
  horizontal.attach(9); // Attach horizontal servo to pin 9
  vertical.attach(10); // Attach vertical servo to pin 10
  horizontal.write(90); // Initial horizontal position
  vertical.write(45); // Initial vertical position

  pinMode(switchPin, INPUT_PULLUP); // Set switch pin mode

  delay(3000); // Initial delay
}

void loop() {
  int switchState = digitalRead(switchPin); // Read switch state

  // Toggle joystick mode on switch press
  if (switchState == LOW && !switchPressed) {
    joystickMode = !joystickMode; // Toggle joystick mode
    switchPressed = true;
    if (!joystickMode) {
      // Return to initial position
      horizontal.write(90);
      vertical.write(45);
      delay(1000); // Wait before moving to light sensor positions
    }
    delay(300); // Debounce delay
  } else if (switchState == HIGH) {
    switchPressed = false; // Reset switch pressed flag
  }

  if (joystickMode) {
    // Read joystick values
    int joystickX = analogRead(joystickXPin);
    int joystickY = analogRead(joystickYPin);

    // Map joystick values to servo positions
    servoh = map(joystickX, 0, 1023, servohLimitLow, servohLimitHigh);
    servov = map(joystickY, 0, 1023, servoLimitLow, servovLimitHigh);

    horizontal.write(servoh);
    vertical.write(servov);

  } else {
    int dtime = 10; // Delay time
    int tol = 50; // Tolerance
    int lt = analogRead(0); // Light sensor top-left
    int rt = analogRead(1); // Light sensor top-right
    int ld = analogRead(2); // Light sensor bottom-left
    int rd = analogRead(3); // Light sensor bottom-right

    int avt = (lt + rt) / 2; // Average of top sensors
    int avd = (lt + rd) / 2; // Average of bottom sensors
    int avl = (lt + ld) / 2; // Average of left sensors
    int avr = (rt + rd) / 2; // Average of right sensors

    int dvert = avt - avd; // Vertical difference
    int dhoriz = avl - avr; // Horizontal difference

    // PID control for vertical servo
    integralV += dvert; // Integral term for vertical

    // Clamp the integrator
    if (integralV > integralMax) {
      integralV = integralMax;
    } else if (integralV < integralMin) {
      integralV = integralMin;
    }

    float derivativeV = dvert - previousErrorV; // Derivative term for vertical
    float outputV = kp * dvert + ki * integralV + kd * derivativeV; // PID output for vertical
    previousErrorV = dvert; // Update previous error for vertical

    if (-1 * tol > dvert || dvert > tol) {
      servov += outputV;
      if (servov > servovLimitHigh) {
        servov = servovLimitHigh;
      } else if (servov < servoLimitLow) {
        servov = servoLimitLow;
      }
      vertical.write(servov);
      delay(20);
    }

    // PID control for horizontal servo
    integralH += dhoriz; // Integral term for horizontal

    // Clamp the integrator
    if (integralH > integralMax) {
      integralH = integralMax;
    } else if (integralH < integralMin) {
      integralH = integralMin;
    }

    float derivativeH = dhoriz - previousErrorH; // Derivative term for horizontal
    float outputH = kp * dhoriz + ki * integralH + kd * derivativeH; // PID output for horizontal
    previousErrorH = dhoriz; // Update previous error for horizontal

    if (-1 * tol > dhoriz || dhoriz > tol) {
      servoh += outputH;
      if (servoh > servohLimitHigh) {
        servoh = servohLimitHigh;
      } else if (servoh < servohLimitLow) {
        servoh = servohLimitLow;
      }
      horizontal.write(servoh);
      delay(20);
    }

    // Print important values to the serial monitor
    Serial.print("dvert: ");
    Serial.print(dvert);
    Serial.print(", dhoriz: ");
    Serial.print(dhoriz);
    Serial.print(", servov: ");
    Serial.print(servov);
    Serial.print(", servoh: ");
    Serial.print(servoh);
    Serial.print(", integralV: ");
    Serial.print(integralV);
    Serial.print(", integralH: ");
    Serial.print(integralH);
    Serial.print(", outputV: ");
    Serial.print(outputV);
    Serial.print(", outputH: ");
    Serial.println(outputH);
  }

  delay(100); // Main loop delay
}

Could you please enclose your whole program in code tags?

Check now

As your topic does not indicate a problem with IDE 1.x it has been moved to a more suitable location on the forum.

What do you mean?

Your topic is about autotune (whatever that is). So that has nothing to do with IDE problems. Hence it was moved.

I assume the following code is not implementing autotune, could someone help me with the the code below???

#include <Servo.h>

// 180 horizontal MAX
Servo horizontal; // Servo object for horizontal movement
int servoh = 90; // Initial horizontal servo position
int servohLimitHigh = 180; // Horizontal servo upper limit
int servohLimitLow = 0; // Horizontal servo lower limit

Servo vertical; // Servo object for vertical movement
int servov = 45; // Initial vertical servo position
int servovLimitHigh = 180; // Vertical servo upper limit
int servoLimitLow = 0; // Vertical servo lower limit

// Joystick and switch pin definitions
const int joystickXPin = A4; // Joystick X-axis pin
const int joystickYPin = A5; // Joystick Y-axis pin
const int switchPin = 2; // Switch pin

bool joystickMode = false; // Joystick mode flag
bool switchPressed = false; // Switch pressed flag

// PID control variables
float integralV = 0, integralH = 0; // Integral terms for vertical and horizontal
float previousErrorV = 0, previousErrorH = 0; // Previous error terms for vertical and horizontal
float kp = -0.04, ki = -0.0005, kd = -0.0001; // PID coefficients
float integralMax = 100.0, integralMin = -100.0; // Integral clamping limits

bool autoTuneMode = false;

void autoTuneVertical() {
  // Implement Ziegler-Nichols tuning for the vertical servo
  // ...
}

void autoTuneHorizontal() {
  // Implement Ziegler-Nichols tuning for the horizontal servo
  // ...
}

void setup() {
  Serial.begin(9600); // Initialize serial communication
  horizontal.attach(9); // Attach horizontal servo to pin 9
  vertical.attach(10); // Attach vertical servo to pin 10
  horizontal.write(90); // Initial horizontal position
  vertical.write(45); // Initial vertical position

  pinMode(switchPin, INPUT_PULLUP); // Set switch pin mode

  delay(3000); // Initial delay
}

void loop() {
  int switchState = digitalRead(switchPin); // Read switch state

  // Toggle joystick mode on switch press
  if (switchState == LOW && !switchPressed) {
    joystickMode = !joystickMode; // Toggle joystick mode
    switchPressed = true;
    if (!joystickMode) {
      // Return to initial position
      horizontal.write(90);
      vertical.write(45);
      delay(1000); // Wait before moving to light sensor positions
    }
    delay(300); // Debounce delay
  } else if (switchState == HIGH) {
    switchPressed = false; // Reset switch pressed flag
  }

  if (joystickMode) {
    // Read joystick values
    int joystickX = analogRead(joystickXPin);
    int joystickY = analogRead(joystickYPin);

    // Map joystick values to servo positions
    servoh = map(joystickX, 0, 1023, servohLimitLow, servohLimitHigh);
    servov = map(joystickY, 0, 1023, servoLimitLow, servovLimitHigh);

    horizontal.write(servoh);
    vertical.write(servov);

  } else {
    int dtime = 10; // Delay time
    int tol = 50; // Tolerance
    int lt = analogRead(0); // Light sensor top-left
    int rt = analogRead(1); // Light sensor top-right
    int ld = analogRead(2); // Light sensor bottom-left
    int rd = analogRead(3); // Light sensor bottom-right

    int avt = (lt + rt) / 2; // Average of top sensors
    int avd = (lt + rd) / 2; // Average of bottom sensors
    int avl = (lt + ld) / 2; // Average of left sensors
    int avr = (rt + rd) / 2; // Average of right sensors

    int dvert = avt - avd; // Vertical difference
    int dhoriz = avl - avr; // Horizontal difference

    // PID control for vertical servo
    integralV += dvert; // Integral term for vertical

    // Clamp the integrator
    if (integralV > integralMax) {
      integralV = integralMax;
    } else if (integralV < integralMin) {
      integralV = integralMin;
    }

    float derivativeV = dvert - previousErrorV; // Derivative term for vertical
    float outputV = kp * dvert + ki * integralV + kd * derivativeV; // PID output for vertical
    previousErrorV = dvert; // Update previous error for vertical

    if (-1 * tol > dvert || dvert > tol) {
      servov += outputV;
      if (servov > servovLimitHigh) {
        servov = servovLimitHigh;
      } else if (servov < servoLimitLow) {
        servov = servoLimitLow;
      }
      vertical.write(servov);
      delay(20);
    }

    // PID control for horizontal servo
    integralH += dhoriz; // Integral term for horizontal

    // Clamp the integrator
    if (integralH > integralMax) {
      integralH = integralMax;
    } else if (integralH < integralMin) {
      integralH = integralMin;
    }

    float derivativeH = dhoriz - previousErrorH; // Derivative term for horizontal
    float outputH = kp * dhoriz + ki * integralH + kd * derivativeH; // PID output for horizontal
    previousErrorH = dhoriz; // Update previous error for horizontal

    if (-1 * tol > dhoriz || dhoriz > tol) {
      servoh += outputH;
      if (servoh > servohLimitHigh) {
        servoh = servohLimitHigh;
      } else if (servoh < servohLimitLow) {
        servoh = servohLimitLow;
      }
      horizontal.write(servoh);
      delay(20);
    }

    // Print important values to the serial monitor
    Serial.print("dvert: ");
    Serial.print(dvert);
    Serial.print(", dhoriz: ");
    Serial.print(dhoriz);
    Serial.print(", servov: ");
    Serial.print(servov);
    Serial.print(", servoh: ");
    Serial.print(servoh);
    Serial.print(", integralV: ");
    Serial.print(integralV);
    Serial.print(", integralH: ");
    Serial.print(integralH);
    Serial.print(", outputV: ");
    Serial.print(outputV);
    Serial.print(", outputH: ");
    Serial.println(outputH);
  }

  delay(100); // Main loop delay
}

Here's how it works:

Please, do not create multiple topics with the same subject.

Please, do not create multiple topics with the same subject.

https://forum.arduino.cc/t/how-to-apply-autotune-in-order-to-get-best-pid-controller/1282599/2

Please do not cross post, it wastes peoples time.
Please do not post in "Uncategorized"; see the sticky topics in https://forum.arduino.cc/c/using-arduino/uncategorized/184.

Your topics on the same subject have been merged.

Please read How to get the best out of this forum.

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