if(Meas == ME_DONE) //процесс измерения закончен
{
//преобразование кода АЦП в ток излучателя:
GetI = Heater * ADC_KI / (ADC_MAX * 3L * N_Int);
if(Pid_HKi && SetI) //если PID включен,
GetHPwm = HPid(SetI, GetI); //вычисление PID,
else GetHPwm = SetHPwm; //иначе ручное управление
OCR1B = GetHPwm; //установка PWM излучателя
Meas = ME_WAIT; //запуск измерителя
}
//Параметры регулятора:
//Pid_KpH - коэффициент пропорциональный
//Pid_KiH - коэффициент интегральный
//Pid_KdH - коэффициент дифференциальный
//ref - установленное значение
//inp (X) - измеренное значение
//out (Y) - воздействие
int HPid(int ref, int inp)
{
static int Yp = 0; //предыдущее значение out
static int Xp = 0; //предыдущее значение inp
static int Xpp = 0; //пред-предыдущее значение inp
long Y;
//вычисляем ошибку:
int e = ref - inp;
//учитываем пропорциональную составляющую:
Y = Yp - (long)Pid_HKp * (inp - Xp) / 100;
//учитываем интегральную составляющую:
Y = Y + (long)Pid_HKi * e / 100;
//учитываем дифференциальную составляющую:
Y = Y - (long)Pid_HKd * (inp - 2 * Xp + Xpp) / 100;
//ограничиваем выходное значение:
if(Y > PWM_MAX) Y = PWM_MAX;
if(Y < 0) Y = 0;
//обновляем значения:
Yp = Y; Xpp = Xp; Xp = inp;
return(Y);
}