How to limit integral sum error?
help with pid code
Ok, post what you have written and point out where you are having the issue(s).
How to limit integral sum error?
Isn't going to get you much positive response.
JIm
if(Isum < MAX) Isum++;
else Isum = MAX;
Do a search term for integrator windup This happens when the plant (ex: motor) can't keep up with the PID's commanded level, for example: at maximum deliverable power, torque, rpm, etc. The integrator keeps finding the setpoint is not being reached & increases its accumulated error (pos or neg), demanding ever-increasing fwd/rev power, torque, RPM, etc, which is useless, since no more is available. If this accumulation continues unabated, it takes a long long time for the PID commanded value to desaturate the plant command.
#include "complementary_filter.h"
uint8_t MPU6050_data[12];
volatile int acx,gyy,acx_lut_index,gyy_lut_index,acx_deg,gyy_deg,anglex;
void COMPFILT_Initialize()
{
TCCR2A = (WGM21);
//CTC 0 TO OCR2A
TCCR2B = (CS22) | (CS21) | (CS20);
//1024 PRESCALER
OCR2A = 10;
//1562.5 hz sample rate
TIMSK2 = (1 << OCIE2A);
//OCR2A COMAPARE INTTERUPT
}
ISR(TIMER2_COMPA_vect)
{
MPU6050_ReadByteS(ACXH,&MPU6050_data[0],6);
MPU6050_ReadByteS(GYXH,&MPU6050_data[6],6);
acx = MPU6050_data[0] << 8 | MPU6050_data[1];
gyy = MPU6050_data[8] << 8 | MPU6050_data[9];
//-----------------------------------------------------------------------------------------------------------------------
if (acx < 0)
acx_lut_index = -acx;
else
acx_lut_index = acx;
acx_lut_index = acx_lut_index >> 6;
acx_lut_index = acx_lut_index << 1;
acx_deg = (pgm_read_byte(&arcsinelut[acx_lut_index]) << 8 | pgm_read_byte(&arcsinelut[acx_lut_index + 1]));
if (acx < 0)
acx_deg = -acx_deg;
//----------------------------------------------------------------------------------------------------------------------------
if (gyy < 0)
gyy_lut_index = -gyy;
else
gyy_lut_index = gyy;
gyy_lut_index = gyy_lut_index >> 7;
gyy_lut_index = gyy_lut_index << 1;
gyy_deg = (pgm_read_byte(&gyrolut[gyy_lut_index]) << 8 | pgm_read_byte(&gyrolut[gyy_lut_index + 1]));
if (gyy < 0)
gyy_deg = -gyy_deg;
//-------------------------------------------------------------------------------------------------------------------------
anglex = multfix(anglex,0x00fd) + gyy_deg + multfix(acx_deg,0x0003);//00fb,0005//00fd,0003
//--------------------------------------------------------------------------------------------------------------------------
int speed,error,sum_error = 0,previous_error = 0,p_term,i_term,d_term;
//--------------------------------------------------------------------------------------------------------------------------
error = anglex - SETPOINT;
//---------------------------------------------------------------------------------------------------------------------------
if (error > P_ERROR_MAX)
{
p_term = PID_MAX_OUTPUT;
}
else if(error < -P_ERROR_MAX)
{
p_term = -PID_MAX_OUTPUT;
}
else
{
p_term = multfix(anglex,KP);
}
//---------------------------------------------------------------------------------------------------------------------------
if (sum_error + error > PID_MAX_OUTPUT)
{
sum_error = PID_MAX_OUTPUT;
i_term = PID_MAX_OUTPUT;
}
else if (sum_error + error < -PID_MAX_OUTPUT)
{
sum_error = -PID_MAX_OUTPUT;
i_term = -PID_MAX_OUTPUT;
}
else
{
if (sum_error + error > I_ERROR_MAX)
{
i_term = PID_MAX_OUTPUT;
}
else if (sum_error + error < -I_ERROR_MAX)
{
i_term = PID_MAX_OUTPUT;
}
else
{
i_term = multfix(KI,sum_error);
}
sum_error = sum_error + error;
}
//-------------------------------------------------------------------------------------------------------------------------------
if ((error - previous_error > PID_MAX_OUTPUT) || (error - previous_error > I_ERROR_MAX))
{
d_term = PID_MAX_OUTPUT;
}
else if((error - previous_error < -PID_MAX_OUTPUT) || (error - previous_error < -I_ERROR_MAX))
{
d_term = -PID_MAX_OUTPUT;
}
else
{
d_term = multfix(error-previous_error,KD);
}
previous_error = error;
//--------------------------------------------------------------------------------------------------------------------------------
if (p_term + i_term + d_term > PID_MAX_OUTPUT)
{
speed = PID_MAX_OUTPUT;
}
else if (p_term + i_term + d_term < -PID_MAX_OUTPUT)
{
speed = -PID_MAX_OUTPUT;
}
else
speed = p_term + i_term + d_term;
//-------------------------------------------------------------------------------------------------------------------------------
if (speed < 0)
{
speed = -speed;
speed = speed << 1;
MOTOR_Backward((uint8_t)(speed >> 8),(uint8_t)(speed >> 8));
}
else
{
speed = speed << 1;
MOTOR_Forward((uint8_t)(speed >> 8),(uint8_t)(speed >> 8));
}
}
This is the code
This is the code
So what....you neglect to say anywhere at all what you are observing. Should we assume everything is working great & others should add this to their code snip library?