Tengo un PID que controla un motor de CC. Estoy intentando controlar la velocidad del motor con mucha precisión. Mi controlador me permite cambiar la dirección del motor y darle un pwm para la velocidad. Por lo tanto, tengo un PID que tiene un máximo y un mínimo de más y menos. Con el fin de acelerar el dispositivo y ralentizar el dispositivo lo suficientemente rápido. La salida del PID es para el pwm y, por lo tanto, es un valor absoluto del PID, simplemente cambiando un pin de dirección cuando PID < 0. Estoy usando la dirección opuesta del motor solo como sistema de frenado. Por lo tanto, el motor siempre debe ir en una dirección, pero debe desacelerarse más rápido al aplicar un par de reversa.
Estoy escribiendo firmware C en MCUXpresso. Los gráficos provienen del envío de datos a través de UART a un Arduino para graficar datos fácilmente.
Mi problema es que, a veces, cuando la variable de proceso llega a 0 o cerca de ella, el PID se invierte y necesita ser negativo, por lo que hace girar el motor a toda velocidad en la dirección opuesta. Las dos imágenes a continuación muestran los casos concretos de cuando sucedió. La línea roja es el punto de ajuste y la línea azul es la variable de proceso.
El código que controla el dispositivo y el PID está debajo.
Me cuesta entender por qué el PID se escaparía de esta manera. Cualquier ayuda sería increíble. ¡Gracias!
Control principal
int dir = FORWARD; //Controls direction of motor
motorPID.setpoint = vehicleSpeed;
motorPID.input = SM_GetRPM();
motorPID.input = motorPID.input * speedConversion;
UART_SendPID((uint8_t)motorPID.input, (uint8_t)motorPID.setpoint);
PID_Compute(&motorPID);
if(motorPID.output < 0){
dir = BACKWARD;
}
if(motorPID.setpoint == 0){
motorPID.output = 0;
}
if(motorPID.input > 60){
MC_SetMotorSpeed(0, dir);
int test = 0;
}
MC_SetMotorSpeed(abs(motorPID.output),dir);
Código PID
//Find all error variables
self->lastError = self->error;
double input = self->input; //Only so input can't change during compute
self->error = self->setpoint - input;
self->integral += self->error;
double derivative = self->error - self->lastError;
//Anti-integral Windup
if(self->integral > self->Outmax)
self->integral = self->Outmax;
else if(self->integral < self->Outmin)
self->integral = self->Outmin;
//Calculate PID
self->output = (self->Kp*self->error) + (self->Ki * self->integral) + (self->Kd * derivative);
//Set limits
if(self->output > self->Outmax)
self->output = self->Outmax;
else if(self->output < self->Outmin)
self->output = self->Outmin;
EDITAR: Resulta que esto fue un error combinado del problema descrito y un problema de hardware.