Неужели никто ничего подобного не делал?
На данный момент работает функция:
TempL=OCR0B;
if (Nout>Nin) {TempL=(TempL-((Nout-Nin)*S_fact)); if (TempL<0) TempL=0;}
else {TempL=(TempL+((Nin-Nout)*S_fact)); if (TempL>255) TempL=255;}
OCR0B=TempL;
(Nin, Nout - unsigned int заданный и измеренный параметры. TempL - float)
Причём работает довольно коряво. S_fact имеет значение 0,08, при более высоком система заводится и идёт вразнос. Всё это крутится в прерывании с частотой ~1600Гц, частота ШИМ ~47кГц (12МГц/256). С выхода ШИМ сигнал поступает на R-C-R-C интегратор (номиналы резисторов по 10кОм, конденсаторов по 10мкФ).
Подскажите, пожалуйста, что-нибудь более добротное в качестве следящей функции.
А МК успевает отработать в прерывании float ? Вообще в прерывании float - плохой тон, я думаю. Попробовать табличным способом, если свободный объем флеши позволяет. Там можно организовать и более сложную обратную связь - с гистерезисом, с насыщением и пр. И вообще, говорят - ПИД регулятор рулит... Тут по нему серьезные спецы есть, я не из них.
И вообще - может, это не на МК схема, а управляет большой ПК ?
Здравствуйте. Подскажите пожалуйста, при попытке подцепить lcd экран к atmega 8 через PORTC codevision выдает ошибки
в файле проекта с расширением .asm
ниже код программы и на месте, что ругается
Подскажите, пожалуйста насчет файла spi.h, который содержится CVavr 3.12. Как я понял, судя по его содержанию, он реализует аппаратную поддержку SPI для контроллеров ATxmega. И у меня с ATmega328p аппаратный SPI не работает...
ELcat, Вы уверены, что Вам именно ПИД нужен ? В большинстве случаев достаточно 2-ух звеньев - "П" и "И".
Ну а вообще, там ничего сложного. П (пропорциональная составляющая) - это разность между уставкой и текущем значением обратной связи. Она же - ошибка или рассогласование. И (интегральная составляющая) - сумма этих самых ошибок за всё время работы регулятора. Нужна для установки на выходе некой постоянной составляющей, при которой ошибка равна нулю, или близка к нему.
Ну а Д (дифференциальная составляющая) - это разница между текущей ошибкой и предыдущей. Нужна для того, чтобы следить за скоростью изменения ошибки. Т.е. смягчать слишком быстрые изменения.
Ну и у каждой составляющей есть свои коэффициенты, которыми они настраиваются, или отключаются вовсе.
Pink-Pank писал(а):В Гугле полно примеров ПИД-регуляторов на СИ
На Си, к сожалению, не нашёл. Попадались в основном курсовые работы с мудрёным математическим изложением.
Аlex писал(а):ELcat, Вы уверены, что Вам именно ПИД нужен ? В большинстве случаев достаточно 2-ух звеньев - "П" и "И".
Ну а вообще, там ничего сложного.
Уверенным можно быть только тогда, когда чётко понимаешь о чём идёт речь. У меня такового понимания нет, поскольку столкнулся с этим впервые. Тем более я далёк от АСУ, да и знакомых нет, кто работает в этой сфере. Но "краем уха" слыхал, что есть нечто под названием "ПИД", как чудодейственная панацея на все случаи жизни.
В ходе самостоятельных экспериментов пришёл к формуле:
unsigned int Nout, Nin;
float TempL;
#define S_fact 0.01
...
if (Nout>Nin) {TempL=(TempL-((Nout-Nin)*S_fact)); if (TempL<0) TempL=0;}
else {TempL=(TempL+((Nin-Nout)*S_fact)); if (TempL>255) TempL=255;}
OCR0B=TempL;
, которая имеет и пропорциональную составляющую, и ведёт накопление ошибки. На данный момент величины R уменьшены до 200 Ом, система работает стабильно и практически без нареканий. Захват параметра и его удержание стабильные. Самовозбуждение пока ещё есть, но лишь на одном маленьком участке. Думаю устранить правкой аппаратной части.
А главное был получен бесценный опыт.
Последний раз редактировалось ELcat Пн ноя 17, 2014 10:09:18, всего редактировалось 1 раз.
Странные какие-то проверки на больше/меньше. Для чего ? Ошибка может быть и отрицательной, ничего страшного. Хотя бы для того, чтобы интегральная составляющая могла уменьшаться. Ну или получалось на выходе отрицательное значение, если регулятор инверсный.
Классический ПИ-регулятор :
int PI(int out_val, int in_val ){
int E; // Ошибка
static long I; // Сумма ошибок
long out; // Выходное значение
E = in_val - out_val;
E*=kP;
I+=E;
out= E + I*kI;
if(out>MAX_OUT) out=MAX_OUT;
if(out<MIN_OUT) out = MIN_OUT;
return (int)out;
}
Аlex писал(а):
И (интегральная составляющая) - сумма этих самых ошибок за всё время работы регулятора. Нужна для установки на выходе некой постоянной составляющей, при которой ошибка равна нулю, или близка к нему.
Статическая ошибка сводится к нулю, но за счет колебательного режима около точки нулевого рассогласования.
Мне кажется, я тоже самое сказал
Скажем "равна нулю", конечно, грубо сказано, не будет такого никогда. Но было сказано для понимания человеком играющей роли интегральной составляющей. Она стремится сравнять уставку с выходным значением ОС (т.е., как Вы сказали - свести ошибку к нулю).
Тем более, я подчеркнул - "или близка к нему"
Может, потому, что Вы настроили его мастером, а ножки контроллера настроили как для слейва?
Ну мне надо что бы МК был мастером. Соответственно в байте SPCR бит MSTR=1. А ножки PB3 и PB5, который являются, соответственно, MOSI и SCK, я делаю выходами, т. е. DDRB=0b00101000. Так?
Спасибо, передача пошла, и на осциллографе все выглядит правильно, но микросхема 74hc595, на которую я передаю байт, выдает у себя на выходах то, что я посылаю, но сдвигом вправо. Код выглядит вот так:
ARV с знаковыми и беззнаковыми разберусь. А вот целочисленно считать... Как же тогда будет вестись накопление при крутизне 0,01? Или всё выражение умножать на 1000 и считать в long?