Hi,
So I was trying to tune the PID control for my DC motor (set to the desired speed and get to that speed) but I didn't really get the response I want.
For these parameters: Kp = 10/3, Ki = 290/300, Kd = 10/300; this is the response I got.
It does not really get to the set point and there's a fair bit of overshoot.
For these parameters: Kp = 10/3, Ki = 300/300, Kd = 10/300; this is the response I got.
This time, it overshoots the setpoint and takes forever to go back.
I'm looking for somewhat less overshoot and actually reach the setpoint. The response time can be NOT instant to accommodate these requirements.
Any ideas how should I go about finding the correct parameters?
This is the code if it's helpful at all.
///////////////////////////// Library /////////////////////////////
#include <Encoder.h>
#include <PID_v1.h>
///////////////////////////// DC motors /////////////////////////////
const int int3 = A2; // motor 1
const int int4 = A3;
const int enB = 3;
/////////////////////////////
Encoder enc1(6, 7);
float countPerRotation = 2797.0;
/////////////////////////// PID ////////////////////////////
struct motorPID_parameter {
double Setpoint;
double Input;
double Output;
};
float Kp = 10/3, Ki = 290/300, Kd = 10/300;
struct motorPID_parameter motor1;
float pwm1 = 0;
PID motorPID1(&motor1.Input, &motor1.Output, &motor1.Setpoint, Kp, Ki, Kd, DIRECT);
////////////////// For keeping track of time ////////////////
unsigned long start0 = 0;
unsigned int elapsedTime0 = 0;
int time_frame0 = 100;
///////////////// For calculate displacement ///////////////
long int displacement1 = 0;
long int posPrevious1 = 0;
float speed1 = 0;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
pinMode(int3, OUTPUT);
pinMode(int4, OUTPUT);
pinMode(enB, OUTPUT);
analogWrite(enB, 0);
// PID1 initialize
motorPID1.SetMode(AUTOMATIC);
motorPID1.SetTunings(Kp, Ki, Kd);
motorPID1.SetOutputLimits(-255,255);
motorPID1.SetSampleTime(100);
motor1.Setpoint = -30;
start0 = millis();
}
void loop() {
// put your main code here, to run repeatedly:
elapsedTime0 = millis() - start0;
if (elapsedTime0 > time_frame0) {
start0 = millis();
displacement1 = (enc1.read() - posPrevious1);
posPrevious1 = enc1.read();
speed1 = (displacement1 / countPerRotation) / (time_frame0 / 1000.0) * 60; // rpm
Serial.print(speed1);
Serial.print(" ");
Serial.println(motor1.Setpoint);
motor1.Input = speed1;
motorPID1.Compute();
pwm1 = motor1.Output;
if (pwm1 > 0) {
digitalWrite(int3, 1);
digitalWrite(int4, 0);
analogWrite(enB, pwm1);
} else {
digitalWrite(int3, 0);
digitalWrite(int4, 1);
analogWrite(enB, -pwm1);
}
}
}
speed_test3.ino (2.2 KB)