=DeaD= писал(а):RoboTok писал(а):Короче для управления скоростью ПИД не шибко подходит...
А для плавного старта и нету в ПИД регуляторе функции...
А ты не меняй резко команду и всё
передавай в пид команду', и пресэмплинг:
если команда-команда'>епсилон, тогда команда'=команда'+епсилон
иначеесли команда-команда'<-епсилон, тогда команда'=команда'-епсилон
иначе команда'=команда
Вот эта штука обычно и зовется acceleration/deceleration ramp generator или rate limiter. Выполнять через регулярные интервалы времени, обычно вместе с регулятором, но можно реже. Для плавности требует большей разрядности числа для команда', чем для самой команды. Мы его звали генератор темпа. Просто ограничитель темпа нарастания/спадания скорости. Причем скокрости - именно команды на скорость. А после этой штуки - ПИД или ПИ. Тогда коэффициентами ПИ/ПИД достигаем оптимального регулирования скорости, а генератором темпа - нужного темпа. Вот код для примера - 16-разрядный ПИ для АВРки, правда работало это на довольно медленной системе и ШИМ-выходы авр шли на ПЧ типа Lenze, который управлял мотором. Там 2 канала было, но это не важно. ПИ-регулятор обеспечивал ОС по скорости, сигналом ОС были метки с вращаемой системы. Несмотря на 16 разрядов использовались реально 8.
Да. Задачи оптимизации по времени выполнения или размеру не стояло, так что написано максимально прозрачно.
Функции регулятора и рампы (числа отфонарные, совпадение с реальными изделиями случайно
)
- Код: Выделить всё • Развернуть
#define PI_KOEFF_P 50
#define PI_KOEFF_I 100
typedef struct
{
long ival;
short min;
short max;
short err;
short out;
} TPIReg;
typedef struct
{
long ival;
long rate;
} TRate;
short StepRate(TRate *rate, short inval)
{
long delta;
delta = ((long)inval << 16) - rate->ival;
if (delta < -rate->rate) delta = -rate->rate;
else if (delta > rate->rate) delta = rate->rate;
rate->ival += delta;
return rate->ival >> 16;
}
short StepPIReg(TPIReg *reg, short err)
{
short res;
reg->err = err;
reg->ival += ((long)err)*PI_KOEFF_I;
res = reg->ival >> 16;
if (res<reg->min) {
res = reg->min;
reg->ival = ((long)res)<<16;
}
else if (res>reg->max)
{
res = reg->max;
reg->ival = ((long)res)<<16;
}
res += ((long)err*PI_KOEFF_P)>>8;
if (res<reg->min) {
res = reg->min;
}
else if (res>reg->max)
{
res = reg->max;
}
reg->out = res;
return res;
}
Как применять (инициализация)
- Код: Выделить всё • Развернуть
TPIReg MyReg;
TRate MyRate;
PIReg1.ival = 0x50000;
PIReg1.min = 5;
PIReg1.max = 254;
RateIn.rate = 0x800; //0x400;
RateIn.ival = 0x2000;
и само тело цикла регулирования:
- Код: Выделить всё • Развернуть
OCR1A = StepPIReg(&MyReg, StepRate(&MyRate, command) - feedback);
ну тут command - это команда скорости, feedback - измеренная скорость откуда-нибудь из другой части проги - из считалки импульсов.
Поле err в структуре ПИ - чисто отладочное, для расчета не нужно, а вот по уарту его выплевывать и смотреть в виде графика - полезно. Вообще для настройки регулятора жутко полезно иметь возможность смотреть на графики как минимум команды и реальной скорости, наложенных на друга.
Почему min и max - переменные, а коэффициенты - константы - не спрашивайте, не помню уже