ОБНОВЛЕНИЯ
- v2.1 — исправлена getResultTimer
ТЕОРИЯ
Это библиотека не для модулей реле (им не нужны библиотеки), это библиотека для релейного регулятора, т.е. реализация релейного закона регулирования с гистерезисом и обратной связью по скорости изменения величины через коэффициент усиления. Что позволяет делать релейный регулятор:
- Управлять какой-то величиной, включая и выключая орган управления (температура – обогреватель или холодильник, влажность – увлажнитель, и так далее)
- Гистерезис – “окно” вокруг установленного значения, чтобы уменьшить количество включений/выключений реле (управляющего устройства)
- Обратная связь (ОС) по изменению – в библиотеку встроено автоматическое вычисление производной измеряемой величины. Подобрав коэффициент усиления ОС можно добиться максимальной стабильности и точности удержания заданной величины: обратная связь по изменению позволяет отключать управляющее устройство до перехода через заданную величину снизу, и заранее включать при приближении к ней сверху
БИБЛИОТЕКА
Библиотека классического релейного регулятора для Arduino
- Обратная связь по скорости изменения величины
- Настройка гистерезиса, коэффициента усиления ОС, направления регулирования
- Возвращает результат по встроенному таймеру или в ручном режиме
Поддерживаемые платформы: все Arduino (используются стандартные Wiring-функции)
УСТАНОВКА
- Библиотеку можно найти и установить через менеджер библиотек по названию GyverRelay в:
- Arduino IDE (Инструменты/Управлять библиотеками)
- Arduino IDE v2 (вкладка «Library Manager»)
- PlatformIO (PIO Home, вкладка «Libraries»)
- Про ручную установку читай здесь
ДОКУМЕНТАЦИЯ
Документация
Инициализация
Можно создать объект с указанием направления регулированияGyverRelay regulator(REVERSE);
Можно просто
GyverRelay regulator;
Настройка
Основные параметры регулятора можно читать и изменять напрямую как члены класса:input
- входная величина, например температураsetpoint
- установка (к чему регулятор будет стремиться привести входную величину)output
- выход (0 или 1) для управления реле (например черезdigitalWrite()
). Менять его не нужно, этим занимается библиотека!
hysteresis
- ширина окна (петли) гистерезиса. Гистерезис уменьшает количество переключений реле, но дестабилизирует систему.k
- коэффициент обратной связи по скорости (по первой производной), подбирается вручную (0.01 ~ 100). При нулевом значении ОС отключается. ОС по скорости изменения позволяет стабилизировать систему, см. картинку в начале статьи.dT
- время итерации для режима работы по встроенному таймеру.setDirection(dir)
- установить направление работы регулятора:NORMAL
- включаем нагрузку при переходе через значение снизу (пример: охлаждение),REVERSE
- включаем нагрузку при переходе через значение сверху (пример: нагрев).
Управление
Работа релейного регулятора завязана на времени между измерениями, особенно в режиме с ОС, поэтому период расчёта должен строго соблюдаться. Библиотека имеет три функции для расчёта состояния реле, все функции возвращают состояние 0 или 1, а также изменяют состояниеoutput
, которое можно использовать в коде для чтения:
compute(dt)
- моментальный расчёт. Принимаетdt
в секундах для режима с ОС. Можно не передаватьdt
, тогда ОС не будет работать. Функция сделана для работы напрямую с расчётом, т.е. вы сами контролируете период вызова функции и передаёте его ей в миллисекундах (если нужна ОС). Демо-пример, вариант 3;getResult()
- моментальный расчёт. Встроенный таймер для режима с ОС. При вызове данной функции программа сама вычисляет время с предыдущего вызова с передаёт dt в расчёт. Таким образом нужно просто позаботиться о периодичности вызова этой функции, dt в расчёт она передаёт сама. Демо-пример, вариант 1;getResultTimer()
- расчёт по встроенному таймеру, самый простой в использовании вариант: делает расчёт и возвращает новое значение по своему собственному таймеру, а пока таймер не сработал - возвращает результат предыдущего расчёта. Т.е. эту функцию можно вызывать постоянно, новое значение она отдаст только когда придёт время. Демо-пример, вариант 2.
Список функций
GyverRelay(boolean direction = REVERSE); // NORMAL - включаем нагрузку при переходе через значение снизу (пример: охлаждение) // REVERSE - включаем нагрузку при переходе через значение сверху (пример: нагрев) // расчёт возвращает состояние для управляющего устройства (реле, транзистор) (1 вкл, 0 выкл) boolean compute(float dt = 0); // моментальный расчёт. Принимает dt в секундах для режима с ОС boolean getResult(); // моментальный расчёт. Встроенный таймер для режима с ОС boolean getResultTimer(); // расчёт по встроенному таймеру void setDirection(boolean dir); // направление регулирования (NORMAL, REVERSE) float input = 0; // сигнал с датчика (например температура, которую мы регулируем) float setpoint = 0; // заданная величина, которую должен поддерживать регулятор (температура) boolean output = 0; // выход регулятора (0 или 1) float hysteresis = 0; // ширина окна гистерезиса float k = 0; // коэффициент усиления по скорости (по умолч. 0) int16_t dT = 1000; // время итерации, мс (по умолч. секунда)
ПРИМЕРЫ
Остальные примеры смотри в папке examples библиотеки, также примеры можно открыть из Arduino IDE/Файл/Примеры
Демо - все возможности библиотеки с комментариями
/* Пример работы релейного регулятора в автоматическом режиме по встроенному таймеру Давайте представим, что на 3 пине у нас спираль нагрева, подключенная через реле И есть какой то абстрактный датчик температуры, на который влияет спираль */ #include "GyverRelay.h" // установка, гистерезис, направление регулирования GyverRelay regulator(REVERSE); // либо GyverRelay regulator(); без указания направления (будет REVERSE) void setup() { pinMode(3, OUTPUT); // пин реле regulator.setpoint = 40; // установка (ставим на 40 градусов) regulator.hysteresis = 5; // ширина гистерезиса regulator.k = 0.5; // коэффициент обратной связи (подбирается по факту) //regulator.dT = 500; // установить время итерации для getResultTimer } // вариант с delay void loop() { int temp; // например читаем с датчика температуру regulator.input = temp; // сообщаем регулятору текущую температуру // getResult возвращает значение для управляющего устройства digitalWrite(3, regulator.getResult()); // отправляем на реле (ОС работает по своему таймеру) delay(100); } /* // вариант со встроенным таймером void loop() { int temp; // например читаем с датчика температуру regulator.input = temp; // сообщаем регулятору текущую температуру // getResult возвращает значение для управляющего устройства digitalWrite(3, regulator.getResultTimer()); // отправляем на реле // также можно получить значение с выхода регулятора // regulator } */ /* // вариант со своим таймером void loop() { static uint32_t myTimer = 0; if (millis() - myTimer > 2000) { // свой таймер на миллис, 2 секунды myTimer = millis(); int temp; // например читаем с датчика температуру regulator.input = temp; // сообщаем регулятору текущую температуру // getResult возвращает значение для управляющего устройства digitalWrite(3, regulator.compute(2)); // отправляем на реле. Время передаём вручную, у нас 2 секунды } } */
Симуляция (см. через плоттер порта)
/* Симуляция работы реле. Обнули k и увидишь, как регулятор перестанет справляться с инерционной системой */ #include "GyverRelay.h" GyverRelay regulator(REVERSE); void setup() { Serial.begin(9600); regulator.setpoint = 40; regulator.hysteresis = 5; regulator.k = 0.5; } boolean state = 0; float value = 0; void loop() { process(); regulator.input = value; state = regulator.getResult(); Serial.print(value); Serial.print(' '); Serial.print(regulator.setpoint - 5 / 2); Serial.print(' '); Serial.print(regulator.setpoint + 5 / 2); Serial.print(' '); Serial.println(regulator.setpoint); delay(100); } void process() { static float coef = 0; coef += state ? 0.3 : -0.6; if (coef > 2.0) coef = 2.0; if (coef < -3.0) coef = -3; value += coef; }
ВИДЕО
ПОДДЕРЖАТЬ
Вы можете поддержать меня за создание доступных проектов с открытым исходным кодом, полный список реквизитов есть вот здесь.
0
0
голоса
Рейтинг статьи