Релейное управление – самое простое из возможных, ведь у нас есть только два состояния – вкл и выкл. В этом уроке рассмотрим алгоритмы, которые сделают регулирование более плавным, позволят сохранить "здоровье" реле и повысят точность управления. Начнём с самого простого и очевидного - порог переключения.
Порог переключения #
Здесь всё просто: если текущее значение (value
) меньше заданного (setpoint
) - включить реле, если больше - выключить:
// "нагрев"
if (value < setpoint) relayOn();
else relayOff();
Это в случае прямого управления (нагреватель). Для обратного (холодильник, вентилятор) логика будет обратная, т.е.
// "охлаждение"
if (value > setpoint) relayOn();
else relayOff();
Условный пример для Arduino, нагрев до 50 градусов:
void loop() {
float temp = 0; // получили с датчика
if (temp < 50.0) digitalWrite(relayPin, HIGH);
else digitalWrite(relayPin, LOW);
// или просто
// digitalWrite(relayPin, temp < 50.0);
}
Дребезг #
Если вызывать данный код со скоростью loop
, как в примере - получим жуткий дребезг в момент включения и выключения реле, так как шумы измерений будут постоянно менять результат условия вокруг порогового значения:
Зелёный график - как раз состояние реле. Ужас! Значения "температуры" надо фильтровать, это сильно увеличит стабильность системы. Фильтры мы подробно разбирали в уроке про фильтры.
Даже если входной сигнал отфильтрован и меняется плавно, частый опрос приведёт к частым переключениям реле около порогового значения, особенно если система "быстрая". Такая система будет стараться удерживать температуру как можно точнее к заданной, даже если она колеблется в диапазоне +-0.001 градус - недостижимая и избыточная точность, такую даже не получится измерить термометром:
Если реле обычное электромагнитное, то оно имеет ресурс на количество переключений. Такой регулятор очень быстро износит реле.
Период опроса #
Самым простым шагом к созданию более стабильного релейного регулятора является период работы - его можно реализовать как задержкой, так и таймером на миллис. Период 1 секунда:
void loop() {
float temp = 0; // получили с датчика
digitalWrite(relayPin, temp < 50.0);
delay(1000);
}
Ситуация в корне изменится: реле станет принудительно переключаться реже, соответственно ухудшится точность регулирования и появятся более видимые колебания, но реле будет меньше щёлкать и проживёт дольше:
Пример для Arduino:
uint32_t tmr;
void loop() {
if (millis() - tmr >= 1000) {
tmr = millis();
float temp = 0; // получили с датчика
digitalWrite(relayPin, temp < 50.0);
}
}
Гистерезис #
Второй способ – гистерезис, тоже позволяет уменьшить количество переключений, но без периода опроса - это повышает скорость реакции системы на изменения, сохранив при этом хорошую устойчивость к помехам. Гистерезис имеет два порога переключения, которые разделяют область значения на 3 зоны:
- Ниже
(порог - гистерезис)
- Между
(порог - гистерезис, порог + гистерезис)
- Выше
(порог + гистерезис)
Логика работы такова, что мы включаем ниже нижнего порога и выключаем выше верхнего. То есть образуется область, внутри которой система движется по инерции от последнего переключения и меняет состояние только при выходе из этой области. Понятное дело, что добавление гистерезиса сильно уменьшает не только количество переключений, но и точность - мы буквально задаём область, точность внутри которой нам безразлична (как и шумы измерения):
В коде гистерезис можно реализовать так:
if (value < setpoint - hyster) relayOn();
else if (value > setpoint + hyster) relayOff();
Отлично! Теперь нам не страшны шумы и износ реле, система реагирует быстро, но мы фактически "раскачали" систему, заставляя её включаться чуть ниже заданной температуры, а выключаться - чуть выше. Пример для Arduino:
// порог 50, гистерезис 2
void loop() {
float temp = 0; // получили с датчика
if (temp < 50 - 2) digitalWrite(relayPin, HIGH);
else if (temp > 50 + 2) digitalWrite(relayPin, LOW);
}
Алгоритм с опережением #
Для увеличения стабильности системы с гистерезисом можно ввести предсказывание значения на основе скорости его изменения. Это позволит удерживать значение более точно и лучше реагировать на внезапные изменения, а также использовать релейный регулятор для управления более сложными и быстрыми процессами. Например, подобный алгоритм используется в космических аппаратах: задача такой системы - включать двигатели ориентации максимально редко и эффективно, избегая перерегулирования, которое неизбежно при обычном гистерезисе. Т.е. такой регулятор выключит реле заранее и регулируемое значение уже по инерции дойдёт до заданного, в идеале не превышая его.
Реализуется это довольно просто - в алгоритме с гистерезисом нужно сравнивать не текущее значение, а предсказанное, которое получается как текущее + скорость изменения значения, умноженная на некоторый коэффициент. Этот коэффициент и будет задавать вес предсказания в сравнении - значение подбирается экспериментально от 0
, максимальное зависит от конкретной системы:
// dt - время между измерениями в секундах
rate = (value - prev) / dt; // производная (скорость)
prev = value; // предыдущее значение
signal = value + rate * k; // предсказанное значение
// обычный гистерезис
if (signal < setpoint - hyster) relayOn();
else if (signal > setpoint + hyster) relayOff();
Пример для Arduino:
const int relayPin = 2; // пин реле
const int period = 100; // период опроса в мс
float k = 0.5; // коэффициент
float setpoint = 30; // уставка
float hyster = 2; // гистерезис (в одну сторону)
float prev = 0; // пред. значение
void loop() {
float temp = 0; // прочитать температуру
float rate = (temp - prev) / (period / 1000.0); // скорость
prev = temp;
float signal = temp + rate * k; // предсказанное значение
if (signal < setpoint - hyster) digitalWrite(relayPin, HIGH);
else if (signal > setpoint + hyster) digitalWrite(relayPin, LOW);
delay(period);
}
При правильной настройке гистерезиса и коэффициента данный алгоритм работает гораздо лучше, чем просто порог по таймеру. Особенно хорошо это становится заметно при наличии непостоянного внешнего воздействия: розовая линия на графиках ниже - условная "внешняя температура", которая влияет на процесс нагрева. Регулятор с моделью опережения (второй график) удерживает температуру гораздо лучше, чем просто порог по таймеру (первый график), имея +- такое же количество переключений:
Видео #
Дополнительно #
Дополнительный контент доступен владельцам набора GyverKIT и по подписке, подробнее читай здесь. Блок содержит:
- Интерактивный график
Полезные страницы #
- Набор GyverKIT – наш большой стартовый набор Arduino, продаётся в России
- Каталог ссылок на дешёвые Ардуины, датчики, модули и прочие железки с AliExpress
- Обратная связь – сообщить об ошибке в уроке или предложить дополнение по тексту ([email protected])
- Поддержать автора за работу над уроками
