[uquote="jcxz",url="/forum/viewtopic.php?p=4231089#p4231089"][uquote="Lum1noFor",url="/forum/viewtopic.php?p=4231012#p4231012"]Функция PID-регулятора вызывается по прерыванию таймера один раз в 10 миллисекунд.[/uquote]
Во-первых: Если функция вызывается периодически, с const периодом, то зачем
dt? Чтобы ещё больше затормозить и без того крайне тормозной код?
Выкинуть
dt отовсюду. За ненадобностью.
[uquote="Lum1noFor",url="/forum/viewtopic.php?p=4231012#p4231012"]Integral += error * dt;
I = Ki*Integral;[/uquote]
Во-вторых: Здесь интегральную составляющую лучше считать так:
Integral += error * Ki;
Далее - ограничение. Это и будет
I.
В-третьих: дифференциальная составляющая вам зачем? Думаете - возможны очень резкие изменения регулируемой величины??? Разве температура нагревателя в принципе может изменяться резко за .01 сек?
Выкинуть нафиг дифф.составляющую. Не загромождать и без того тормозной код ненужным хламом.
В-четвёртых: (как уже сказали выше) - ввести ограничение на интегральную составляющую (а не только на общий выход).
В-пятых: Использовать плавающую точку на CPU не имеющем FPU имеет смысл только там где это
реально необходимо. И то - стоит 10 раз подумать, прежде чем использовать её в алгоритмах реального времени. В вашем случае нет совершенно никакой надобности в плавающей точке, всё легко считается на фиксированной точке.
И в целом - код написан очень топорно, задней пяткой левой ноги.[/uquote]
Спасибо за критику! Задача именно попытаться разобраться, как сделать правильно. По поводу float'ов не беспокойтесь, я знаю, что их лучше не использовать без FPU. А здесь я это сделал по двум причинам: 1. МК не делает больше НИЧЕГО, кроме расчета PID-алгоритма. Все остальное работает на железках - SPI, детектор нуля, энкодер. 2) Я НЕ ПОНИМАЮ ВЫСШУЮ МАТЕМАТИКУ! Хочу понять, что такое интеграл, дифференциал, но я уже не в том возрасте, чтобы до меня легко доходило. Ну не понимаю и все тут. Буду дальше пытаться понять. И именно из-за этого полного непонимания смысла дифференциала и интеграла я и налепил float'ов, чтобы где-нибудь не вылезла какая-нибудь неизвестная мне математическая ошибка, типа мистического "разрыва функции регулирования". Например, мне не понятно, почему Вы говорите, что можно просто взять и убрать dt. Если есть время и возможность - объясните, пожалуйста! Еще раз благодарю!
Во-вторых: Здесь интегральную составляющую лучше считать так:
Integral += error * Ki;
Далее - ограничение. Это и будет I.
А почему именно так? Из соображений производительности, или есть какие-то другие причины? Почему не "в лоб", вот так:
Код: Выделить всё
Integral += error * dt;
if (Integral > max/Ki) {
Integral = max/Ki;
} else if (Integral < -max/Ki) {
Integral = -max/Ki;
}
I = Ki*Integral;