GyverPID - библиотека PID регулятора для Arduino
- Время одного расчёта около 70 мкс
- Режим работы по величине или по её изменению (для интегрирующих процессов)
- Возвращает результат по встроенному таймеру или в ручном режиме
- Встроенные калибровщики коэффициентов
- Режим работы по ошибке и по ошибке измерения
- Встроенные оптимизаторы интегральной суммы
Совместима со всеми Arduino платформами (используются Arduino-функции)
К библиотеке есть расширенная документация
- Библиотеку можно найти по названию GyverPID и установить через менеджер библиотек в:
- Arduino IDE
- Arduino IDE v2
- PlatformIO
- Скачать библиотеку .zip архивом для ручной установки:
- Распаковать и положить в C:\Program Files (x86)\Arduino\libraries (Windows x64)
- Распаковать и положить в C:\Program Files\Arduino\libraries (Windows x32)
- Распаковать и положить в Документы/Arduino/libraries/
- (Arduino IDE) автоматическая установка из .zip: Скетч/Подключить библиотеку/Добавить .ZIP библиотеку… и указать скачанный архив
- Читай более подробную инструкцию по установке библиотек здесь
- Рекомендую всегда обновлять библиотеку: в новых версиях исправляются ошибки и баги, а также проводится оптимизация и добавляются новые фичи
- Через менеджер библиотек IDE: найти библиотеку как при установке и нажать "Обновить"
- Вручную: удалить папку со старой версией, а затем положить на её место новую. "Замену" делать нельзя: иногда в новых версиях удаляются файлы, которые останутся при замене и могут привести к ошибкам!
// Можно инициализировать объект тремя способами:
GyverPID regulator; // инициализировать без настроек (всё по нулям, dt 100 мс)
GyverPID regulator(kp, ki, kd); // инициализировать с коэффициентами. dt будет стандартно 100 мс
GyverPID regulator(kp, ki, kd, dt); // инициализировать с коэффициентами и dt (в миллисекундах)
Смотри документацию
datatype setpoint = 0; // заданная величина, которую должен поддерживать регулятор
datatype input = 0; // сигнал с датчика (например температура, которую мы регулируем)
datatype output = 0; // выход с регулятора на управляющее устройство (например величина ШИМ или угол поворота серво)
datatype getResult(); // возвращает новое значение при вызове (если используем свой таймер с периодом dt!)
datatype getResultTimer(); // возвращает новое значение не ранее, чем через dt миллисекунд (встроенный таймер с периодом dt)
void setDirection(boolean direction); // направление регулирования: NORMAL (0) или REVERSE (1)
void setMode(boolean mode); // режим: работа по входной ошибке ON_ERROR (0) или по изменению ON_RATE (1)
void setLimits(int min_output, int max_output); // лимит выходной величины (например для ШИМ ставим 0-255)
void setDt(int16_t new_dt); // установка времени дискретизации (для getResultTimer)
float Kp = 0.0;
float Ki = 0.0;
float Kd = 0.0;
Остальные примеры смотри в examples!
/*
Пример работы ПИД регулятора в автоматическом режиме по встроенному таймеру
Давайте представим, что на 3 пине у нас спираль нагрева, подключенная через мосфет,
управляем ШИМ сигналом
И есть какой то абстрактный датчик температуры, на который влияет спираль
*/
// перед подключением библиотеки можно добавить настройки:
// сделает часть вычислений целочисленными, что чуть (совсем чуть!) ускорит код
// #define PID_INTEGER
// режим, при котором интегральная составляющая суммируется только в пределах указанного количества значений
// #define PID_INTEGRAL_WINDOW 50
#include "GyverPID.h"
GyverPID regulator(0.1, 0.05, 0.01, 10); // коэф. П, коэф. И, коэф. Д, период дискретизации dt (мс)
// или так:
// GyverPID regulator(0.1, 0.05, 0.01); // можно П, И, Д, без dt, dt будет по умолч. 100 мс
void setup() {
regulator.setDirection(NORMAL); // направление регулирования (NORMAL/REVERSE). ПО УМОЛЧАНИЮ СТОИТ NORMAL
regulator.setLimits(0, 255); // пределы (ставим для 8 битного ШИМ). ПО УМОЛЧАНИЮ СТОЯТ 0 И 255
regulator.setpoint = 50; // сообщаем регулятору температуру, которую он должен поддерживать
// в процессе работы можно менять коэффициенты
regulator.Kp = 5.2;
regulator.Ki += 0.5;
regulator.Kd = 0;
}
void loop() {
int temp; // читаем с датчика температуру
regulator.input = temp; // сообщаем регулятору текущую температуру
// getResultTimer возвращает значение для управляющего устройства
// (после вызова можно получать это значение как regulator.output)
// обновление происходит по встроенному таймеру на millis()
analogWrite(3, regulator.getResultTimer()); // отправляем на мосфет
// .getResultTimer() по сути возвращает regulator.output
}
- v1.1 - убраны дефайны
- v1.2 - возвращены дефайны
- v1.3 - вычисления ускорены, библиотека облегчена
- v2.0 - логика работы чуть переосмыслена, код улучшен, упрощён и облегчён
- v2.1 - integral вынесен в public
- v2.2 - оптимизация вычислений
- v2.3 - добавлен режим PID_INTEGRAL_WINDOW
- v2.4 - реализация внесена в класс
- v3.0
- Добавлен режим оптимизации интегральной составляющей (см. доку)
- Добавлены автоматические калибровщики коэффициентов (см. примеры и доку)
- v3.1 - исправлен режиме ON_RATE, добавлено автоограничение инт. суммы
- v3.2 - чуть оптимизации, добавлена getResultNow
- v3.3 - в тюнерах можно передать другой обработчик класса Stream для отладки
При нахождении багов создавайте Issue, а лучше сразу пишите на почту alex@alexgyver.ru
Библиотека открыта для доработки и ваших Pull Request'ов!
При сообщении о багах или некорректной работе библиотеки нужно обязательно указывать:
- Версия библиотеки
- Какой используется МК
- Версия SDK (для ESP)
- Версия Arduino IDE
- Корректно ли работают ли встроенные примеры, в которых используются функции и конструкции, приводящие к багу в вашем коде
- Какой код загружался, какая работа от него ожидалась и как он работает в реальности
- В идеале приложить минимальный код, в котором наблюдается баг. Не полотно из тысячи строк, а минимальный код