To nigdy nie jest tak, że proste PID załatwia sprawę. Trzeba dodać kilka elementów nieliniowych aby algorytm numeryczny nie "wyszedł poza zakres"
Przykładowa implementacja:
void pid_calculate_output( void )
{
I64 calculation;
/* Calculate the error */
PidProcessing.error_p = PidProcessing.command - PidProcessing.feedback;
/* Apply error limits */
if(PidProcessing.error_p > PidSettings.max_error_p)
{
PidProcessing.error_p = PidSettings.max_error_p;
}
else if (PidProcessing.error_p < -(I32)PidSettings.max_error_p)
{
PidProcessing.error_p = -(I32)PidSettings.max_error_p;
}
/* Apply the deadband */
if (PidProcessing.error_p > PidSettings.deadband )
{
PidProcessing.error_p -= PidSettings.deadband ;
}
else if (PidProcessing.error_p < -(I32)PidSettings.deadband)
{
PidProcessing.error_p += PidSettings.deadband;
}
else
{
PidProcessing.error_p = 0;
}
/* If output is in limit, don't let integrator wind up */
if ( (PidProcessing.control_flags & PID_ANTI_WIND_UP_LOCK) == 0 )
{
/* Compute integral term */
PidProcessing.error_i += PidProcessing.error_p;
}
/* Apply integrator limits */
if (PidProcessing.error_i > PidSettings.max_error_i)
{
PidProcessing.error_i = PidSettings.max_error_i;
}
else if (PidProcessing.error_i< -(I32)PidSettings.max_error_i)
{
PidProcessing.error_i = -(I32)PidSettings.max_error_i;
}
/* Calculate derivative of error */
PidProcessing.error_d = (PidProcessing.error_p - PidProcessing.error_p_prev);
PidProcessing.error_p_prev = PidProcessing.error_p ;
/* Apply derivative limits */
if (PidProcessing.error_d > PidSettings.max_command_d )
{
PidProcessing.error_d = PidSettings.max_command_d ;
}
else if (PidProcessing.error_d< -(I32)PidSettings.max_command_d )
{
PidProcessing.error_d = -(I32)PidSettings.max_command_d ;
}
/* Calculate derivative of command */
PidProcessing.command_d = PidProcessing.command - PidProcessing.command_prev;
PidProcessing.command_prev = PidProcessing.command;
/* Apply derivative commands limits */
if (PidProcessing.command_d > PidSettings.max_error_d)
{
PidProcessing.command_d = PidSettings.max_error_d;
}
else if (PidProcessing.command_d < -(I32)PidSettings.max_error_d)
{
PidProcessing.command_d = -(I32)PidSettings.max_error_d;
}
/* Calculate derivative of feedback */
PidProcessing.feedback_d = PidProcessing.feedback - PidProcessing.feedback_prev;
PidProcessing.feedback_prev = PidProcessing.feedback;
/* Apply derivative feedback limits */
if (PidProcessing.feedback_d > PidSettings.max_feedback_d)
{
PidProcessing.feedback_d = PidSettings.max_feedback_d;
}
else if (PidProcessing.feedback_d < -(I32)PidSettings.max_feedback_d)
{
PidProcessing.feedback_d = -(I32)PidSettings.max_feedback_d;
}
/* Calculate the output value */
calculation = (I64)PidProcessing.error_p * (I64)PidSettings.p_gain +
(I64)PidProcessing.error_i * (I64)PidSettings.i_gain +
(I64)PidProcessing.error_d * (I64)PidSettings.d_gain +
(I64)PidProcessing.command * (I64)PidSettings.ff0_gain +
(I64)PidProcessing.command_d * (I64)PidSettings.ff1_gain +
(I64)PidProcessing.feedback_d * (I64)PidSettings.b_gain;
/* Cut fractional part */
calculation = calculation >> 16;
if (calculation > (I64)PidSettings.max_output )
{
PidProcessing.output = PidSettings.max_output ;
PidProcessing.control_flags |= PID_ANTI_WIND_UP_LOCK;
}
else if (calculation < -(I64)PidSettings.max_output)
{
PidProcessing.output = -(I32)PidSettings.max_output ;
PidProcessing.control_flags |= PID_ANTI_WIND_UP_LOCK;
}
else
{
PidProcessing.output = (I32)calculation;
}
}
Znaleziono 3 wyniki
- 03 lis 2008, 22:29
- Forum: Elektronika CNC
- Temat: Tani Enkoder
- Odpowiedzi: 40
- Odsłony: 18363
- 12 kwie 2007, 12:35
- Forum: Elektronika CNC
- Temat: Tani Enkoder
- Odpowiedzi: 40
- Odsłony: 18363
- 12 kwie 2007, 10:55
- Forum: Elektronika CNC
- Temat: Tani Enkoder
- Odpowiedzi: 40
- Odsłony: 18363