Вам нужно решить две проблемы:
- арифметическое переполнение
- интегратор windup
Арифметическое переполнение довольно просто - всякий раз, когда вы выполняете целочисленную математику, убедитесь, что вы используете промежуточные значения большей ширины: например, если a
и b
16-битные, и вы добавляете / вычитаете их, используйте 32-битное промежуточное значение значение, и ограничьте его диапазоном 16-битного значения (от 0 до 65535 для без знака, от -32768 до 32767 для со знаком) перед приведением к 16 битам. Если вы абсолютно уверены, что вы никогда не получите переполнение, потому что вы абсолютно уверены в диапазонах входных переменных, тогда вы можете пропустить этот шаг, но будьте осторожны.
Проблема с запуском интегратора более тонкая. Если у вас есть большая ошибка в течение длительного периода времени, так что вы достигнете предела насыщения выходного сигнала вашего контроллера, но ошибка все еще не равна нулю, то интегратор будет продолжать накапливать ошибку, возможно, становясь намного больше, чем он должен достичь устойчивое состояние. Как только контроллер выходит из насыщения, интегратору приходится возвращаться вниз, вызывая ненужную задержку и, возможно, нестабильность реакции вашего контроллера.
На другой ноте:
Я настоятельно рекомендую (да, я знаю, что этому вопросу исполнилось 18 месяцев, так что вы, вероятно, выполнили свою задачу, но для удобства читателей притворимся, что это не так), чтобы вы вычислили интегральный термин по-другому: вместо Ки * (интегрированная ошибка), вычислить интеграл от (Ki * error).
Есть несколько причин для этого; Вы можете прочитать их в блоге, который я написал о том, как правильно реализовать PI-контроллеры .
<stdint.h>
дляuint8_t
иuint16_t
, а неunsigned int
иunsigned char
.