Vga писал(а):А какие есть?
Вы прямо как на базаре. Не стыдно? Не получается тот или иной алгоритм - спросите помощи. А так Вы хотите всё и сразу, причем непонятно для чего.
Vga писал(а):В первую очередь интересен разумеется алгоритм термостабилизации. От ввода значения через АЦП и до вывода в ШИМ (или что там).
АЦП работает с периодом дискретизации T_SYS = 500 мкс. Поток данных с выхода АЦП поступает на цифровой FIR-фильтр с прямоугольным окном. Длительность окна TSAMPLE = 100 мс. Фильтр производит децимацию, период дискретизации на выходе фильтра 100 мс. С таким периодом работает PID-регулятор. Сначала производится преобразование кода измеренного значения AdcCode в микровольты Vtc с учетом коэффициента передачи усилителя термопары и опорного напряжения:
Vtc = (AdcCode * ADC_REF / ADC_RES) / (FIR_N * GAIN)
Далее производится проверка этого напряжения с целью определения обрыва термопары. Если оно выше V_BRK = 24000, то ошибка. Затем вычисляется эквивалентное напряжение холодного спая Vcj на основе показаний tcj термометра DS18B20. Так как диапазон температур холодного спая невелик, вычисление производится по линейному закону с коэффициентом TCJ_K = 40.0 мкВ/°C:
Vcj = tcj * TCJ_K
Затем вычислятся выходное напряжение термопары с компенсацией холодного спая:
Vhj = Vtc + Vcj
Затем производится табличная лианеризация показаний термопары. Элементы таблицы Lin[TC_POINTS] рассчитаны с шагом 1000 мкВ. Находится элемент таблицы, меньший или равный измеренному напряжению. Индекс таблицы дает температуру ttab. Затем между точками таблицы проводится линейная интерполяция:
thj = ttab + DeltaV * DeltaT / 1000
Далее полученная температура подвергается процедуре цифровой калибровки:
t = thj * Gain / GAIN_NOM + Shift
Полученное значение температуры t поступает на PID-регулятор. Регулятор реализован в дифференциальной форме, т.е. пропорциональная составляющая превращается в дифференциальную, интегральная - в пропорциональную, а дифференциальная - во вторую производную. На выходе получаем дифференциал воздействия. Такой подход позволяет избавится от интегральной составляющей вместе с проблемой ее ограничения:
dP = Kp * (t[i] - t[i - 1]) - Ki * (tset - t[i]) + Kd * (t[i] - 2 * t[i - 1] + t[i -2])
Из дифференциала мощности и предыдущего значения мощности получаем текущее значение мощности, которую нужно подать на нагреватель:
P[i] = P[i-1] - dP
Управление нагревателем может осуществляться в фазовом режиме или в режиме Delta-Sigma модулятора. В любом случае требуется привязка к сети по фазе. Она реализована с помощью цифровой петли PLL. Импульсы с детектора перехода через ноль (ZCD) поступают на вход захвата ICP таймера 1. Используется спад импульса, так как он имеет большую крутизну. Схема захвата имеет аппаратный подавитель шумов, который включен с помощью бита ICNC1. В прерывании по захвату вычисляется текущая ошибка фазы:
dPh = ICR1 + Delay
Она является входной величиной для PI-регулятора, который служит петлевым фильтром PLL:
Period[i] = Period[i-1] - Kp * (dPh[i - 1] - dPh[i]) + Ki * dPh[i]
Выходной сигнал PI-регулятора представляет собой текущий период таймера 1, который загружается в регистр OCR1A. Таймер работает в режиме очистки по сравнению (CTC), причем TOP = OCR1A. В результате работа таймера оказывается синхронизированной с сетью с точностью до фазы (если точнее, с удвоенной частотой сети). PLL позволяет получить постоянный сдвиг Delay относительно сигнала ZCD, который позволяет скомпенсировать конечную длительность импульса ZCD и задержку срабатывания ZCD.
При работе в режиме фазового управления для управления ключом служит канал B аппаратного PWM, значение которого загружается в регистр OCR1B, а выходная последовательность формируется на выводе OC1B. Загрузка регистра OCR1B должна осуществляться как при изменении желаемого угла открывания ключа, так и при подстройке периода таймера (в прерывании по захвату). Регистры OCR1A и OCR1B имеют double buffering, поэтому их перезагрузка не нарушает текущий цикл управления ключом.
Желаемая мощность P задается в процентах от максимальной с дискретностью 0.1%. Далее эта мощность должна быть преобразована в угол открытия ключа, который и представляет собой код регистра OCR1B с точностью до постоянного множителя. При фазовом управлении мощность зависит от угла нелинейно: для угла f нормализованная мощность равна интегралу от f до pi от sin^2(x)dx, деленному на pi/2. Или
Pnorm = 1 - f / pi + sin(2 * f) / (2 * pi)
Если угол A задается в градусах, то f = A * pi / 180
Аналитическое выражения для угла в зависимости от требуемой мощности я найти не смог. И это не arccos, как вычисляют в некоторых фазовых регуляторах. Поэтому численными методами была сгенерирована таблица с шагом по мощности 1%. Между точками таблицы производится линейная интерполяция:
angle = A[p] + DeltaP * DeltaA / 10
Найденный угол преобразуется в код для загрузки регистра OCR1B:
OCR1B = Half_Period * angle / MAX_ANGLE;
При работе в режиме Delta-Sigma модулятора мощность зависит от кода линейно, никакой специальной линеаризации не требуется. Частота дискретизации Delta-Sigma модулятора равна частоте сравнений COMPA таймера 1. Модулятор реализован следующим образом:
квантование:
if(Sigma > MAX_POW) { Delta = -MAX_POW; OutOn(); }
else { Delta = 0; OutOff(); }
суммирование:
Sigma = Sigma + Power + Delta;
Ну как-то так.
Vga писал(а):Но, возможно, у вас там еще какая-нибудь изюминка есть?
Нет.