Следующая статья об автоматическом управлении сушильными камерами, где я подробно описываю реализацию одного из наших заказов.
Предыдущие статьи здесь, здесь, здесь, здесь и здесь.
Сегодня я расскажу об основной функции, в теле которой я разместил код управления заслонками в комнатах. Привожу в качестве примера код только для одной комнаты:
void rooms() {
cur_hum_1 = dht_1.readHumidity(); // присваиваем соответствующей переменной значение показаний датчика относительной влажности воздуха в первой комнате
cur_temp_1 = dht_1.readTemperature(); // то же самое с температурой в комнате
active_1 = digitalRead(45); // читаем состояние тумблера активации комнаты (включён/выключен)
hum_incr_time_1_ms = dryers.hum_incr_time_1 * 60000; // переменная выражает в миллисекундах время, значение которого мы задаём в минутах в меню
time_fresh_1_ms = dryers.time_fresh_1 * 60000; // переменная в миллисекундах, значение времени проветривания, которое мы задали в меню, выраженное в минутах
if (dryers.new_start_1 == 1) { // итак, наш алгоритм начинает работу. Если в меню мы нажали "Новый старт", то следующим переменным автоматически присваиваются значения по умолчанию:
dryers.top_hum_1 = 99; // верхний предел относительной влажности - 99%
dryers.dif_hum_1 = 5; // диапазон - 5%
dryers.bot_hum_1 = 94; // соответственно, нижний предел - 94%
dryers.temp_thres_1 = 45; // окончательно закроем заслонку при 45 градусах Цельсия
dryers.perc_down_1 = 5; // снижать диапазон относительной влажности будем на 5%
dryers.hum_incr_time_1 = 10; // если в течение 10 минут относительная влажность упадёт ниже нижнего предела,
dryers.time_close_1 = 0; // обнуляем счётчик времени закрытого состояния заслонки
dryers.hum_down_1 = 1; // при следующем прочтении скрипта снижаем верхний порог относительной влажности в комнате. Скорее всего эта опция отменится после прочтения процессором следующих строк кода.
Итак, значения присвоили, теперь можно и переменную "Новый старт" обнулить, чтобы при следующих прочтениях код те же операции снова и снова не выполнялись:
dryers.new_start_1 = 0;
}
После процесса сушки угля и дезактивации комнаты нам понадобится сначала проветрить комнату, открыв заслонку и выждав какое-то время (задаётся из меню), иначе внутри комнаты может быть слишком жарко и нужно остудить воздух, чтобы персонал мог зайти внутрь.
if (active_1 == 1) { // если комната активирована тумблером,
dryers.time_fresh_1 = 0; // обнуляем значение времени проветривания, которое мы задали из меню
dryers.incr_time_fresh_1 = 0; // обнуляем счётчик времени проветривания
}
if (active_1 == 0) { // если комната дезактивирована тумблером (например, после процесса сушки угля),
if (dryers.time_fresh_1 > 0) { // если при этом значение времени проветривания, которое мы задали из меню, больше нуля,
if (dryers.incr_time_fresh_1 >= time_fresh_1_ms) { // а также, если значение счётчика времени проветривания установилось больше или равным заданному времени проветривания, то, значит, проветривание окончено, поэтому
digitalWrite(2, HIGH); // закрываем заслонку ("0" значит "открыто", "1" значит "закрыто") - сделано так для того, чтобы при аварийном обесточивании цифровой части системы ("0" на всех выходах) все заслонки автоматически открывались
dryers.time_close_1 = 4200; // начинаем отсчёт на счётчике времени закрытого состояния заслонки, установив значение переменной равным 4,2 секунды до следующего прочтения скрипта. Ориентируясь на этот счётчик, код своевременно снизит верхний предел "коридора" относительной влажности в комнате
dryers.open_1 = 0; // сохраняем в переменной состояние заслонки в первой комнате (закрыта)
dryers.hum_down_1 = 0; // при следующем прочтении скрипта не понижаем верхний предел относительной влажности
dryers.time_fresh_1 = 0; // обнуляем значение времени проветривания, которое мы задали из меню,
dryers.incr_time_fresh_1 = 0; // обнуляем счётчик времени открытого состояния заслонки
} else { // если же значение счётчика времени проветривания меньше заданного времени проветривания, то, значит, проветривание ещё не закончено, поэтому
digitalWrite(2, LOW); // оставляем заслонку открытой ("0" = открыть),
dryers.time_close_1 = 0; // обнуляем счётчик времени закрытого состояния заслонки (она же открыта),
dryers.open_1 = 1; // сохраняем в переменной состояние заслонки в первой комнате (открыта),
dryers.incr_time_fresh_1 += 4200; // к значению счётчика времени закрытого состояния заслонки прибавляем 4,2 секунды, через 4,2 секунды скрипт снова прочётся
}
} else { // если при этом значение времени проветривания, которое мы задали из меню, равно нулю (меньше нуля быть не может), значит мы не проветриваем, поэтому
digitalWrite(2, HIGH); // закрываем заслонку
dryers.time_close_1 = 4200; // начинаем отсчёт на счётчике времени закрытого состояния заслонки, установив значение переменной равным 4,2 секунды до следующего прочтения скрипта
dryers.open_1 = 0; // сохраняем в переменной состояние заслонки в первой комнате (закрыта),
dryers.hum_down_1 = 0; // при следующем прочтении скрипта не понижаем верхний предел относительной влажности
dryers.incr_time_fresh_1 = 0; // обнуляем счётчик времени открытого состояния заслонки
}
} else // если комната активирована
if (cur_hum_1 < dryers.bot_hum_1 && cur_temp_1 <= dryers.temp_thres_1) { // если же относительная влажность в комнате ниже нижнего порога относительной влажности и при этом температура в комнате ниже или равна значению порога, который мы установили,
digitalWrite(2, HIGH); // закрываем заслонку,
dryers.time_close_1 = 0; // обнуляем счётчик времени закрытого состояния заслонки,
dryers.open_1 = 0; // сохраняем в переменной состояние заслонки в первой комнате (закрыта),
dryers.hum_down_1 = 0; // при следующем прочтении скрипта не понижаем верхний предел относительной влажности
} else
if (cur_hum_1 < dryers.bot_hum_1 && cur_temp_1 > dryers.temp_thres_1) { // если же относительная влажность в комнате ниже нижнего порога относительной влажности и при этом температура в комнате выше порога, который мы установили,
digitalWrite(2, HIGH); // закрываем заслонку,
dryers.time_close_1 += 4200; // к значению счётчика времени закрытого состояния заслонки прибавляем 4,2 секунды,
dryers.open_1 = 0; // сохраняем в переменной состояние заслонки в первой комнате (закрыта),
dryers.hum_down_1 = 0; // при следующем прочтении скрипта не понижаем верхний предел относительной влажности,
} else
if (cur_hum_1 > dryers.top_hum_1 && cur_temp_1 <= dryers.temp_thres_1) { // если же относительная влажность в комнате выше верхнего порога относительной влажности и при этом температура в комнате ниже или равна значению порога, который мы установили,
digitalWrite(2, HIGH); // закрываем заслонку,
dryers.time_close_1 = 0; // обнуляем счётчик времени закрытого состояния заслонки,
dryers.open_1 = 0; // сохраняем в переменной состояние заслонки в первой комнате (закрыта),
dryers.hum_down_1 = 0; // при следующем прочтении скрипта не понижаем верхний предел относительной влажности
} else
if (cur_hum_1 > dryers.top_hum_1 && cur_temp_1 > dryers.temp_thres_1) { // если же относительная влажность в комнате выше верхнего порога относительной влажности и при этом температура в комнате выше порога, который мы установили,
digitalWrite(2, LOW); // открываем заслонку,
dryers.time_close_1 = 0; // обнуляем счётчик времени закрытого состояния заслонки,
dryers.open_1 = 1; // сохраняем в переменной состояние заслонки в первой комнате (открыта),
dryers.hum_down_1 = 1; // при следующем прочтении кода необходимо будет снизить верхнюю границу диапазона относительной влажности на величину диапазона, установленного в меню,
} else
if (dryers.hum_down_1 == 1 && cur_temp_1 <= dryers.temp_thres_1) { // если верхний предел относительной влажности в комнате пора понизить, и при этом температура в комнате ниже или равна значению порога, который мы установили,
digitalWrite(2, HIGH); // закрываем заслонку до окончания сушки,
dryers.time_close_1 = 0; // обнуляем счётчик времени закрытого состояния заслонки,
dryers.open_1 = 0; // сохраняем в переменной состояние заслонки в первой комнате (закрыта),
dryers.hum_down_1 = 0; // при следующем прочтении скрипта не понижаем верхний предел относительной влажности,
} else
if (dryers.hum_down_1 == 1 && cur_temp_1 > dryers.temp_thres_1) { // если верхний предел относительной влажности в комнате нужно понизить, и при этом температура в комнате выше порога, который мы установили,
digitalWrite(2, LOW); // открываем заслонку,
dryers.time_close_1 = 0; // обнуляем счётчик времени закрытого состояния заслонки,
dryers.open_1 = 1; // сохраняем в переменной состояние заслонки в первой комнате (открыта),
} else
if (cur_temp_1 <= dryers.temp_thres_1) { // если температура в комнате упала ниже предела, который мы установили,
digitalWrite(2, HIGH); // закрываем заслонку до окончания сушки,
dryers.time_close_1 = 0; // обнуляем счётчик времени закрытого состояния заслонки,
dryers.open_1 = 0; // сохраняем в переменной состояние заслонки в первой комнате (закрыта),
} else { // в остальных случаях
digitalWrite(2, HIGH); // закрываем заслонку,
dryers.time_close_1 += 4200; // к значению счётчика времени закрытого состояния заслонки прибавляем 4,2 секунды,
dryers.open_1 = 0; // сохраняем в переменной состояние заслонки в первой комнате (закрыта)
}
if (dryers.time_close_1 > hum_incr_time_1_ms) { // если значение счётчика времени закрытого состояния заслонки больше, чем значение периода времени (в миллисекундах), установленного нами с помощью меню,
dryers.top_hum_1 = dryers.top_hum_1 - dryers.perc_down_1; // понизим значение верхнего предела "коридора" относительной влажности на значение переменной, в которой записано, на сколько процентов мы хотим снизить верхний предел (это значение по умолчанию равно 5%, мы можем его менять с помощью меню)
dryers.time_close_1 = 4200; // начинаем отсчёт на счётчике времени закрытого состояния заслонки, установив значение переменной, равное 4,2 секунды, до следующего прочтения скрипта
}
Постепенно снижаясь, значения верхнего и нижнего порога влажности могут уехать в отрицательные значения. Чтобы этого не случилось, такую ситуацию мы отслеживаем и исправляем:
if (dryers.top_hum_1 < 15) { // если верхний предел меньше 15%
dryers.top_hum_1 = 15; // установим верхний предел равным 15%
dryers.bot_hum_1 = 10; // а нижний предел - равным 10%
} else { // если же верхний предел по-прежнему больше 15%
dryers.bot_hum_1 = dryers.top_hum_1 - dryers.dif_hum_1; // верхний предел не трогаем, а нижний установим, вычтя из значения верхнего предела значение диапазона ("коридора")
}
if (dryers.bot_hum_1 < 10) { // если в результате вычитания значение нижнего порога окажется ниже 10% (например верхний предел 18%, его не трогали, диапазон, скажем был равен 10%, то, вычитая, получили 18%-10%=8%),
dryers.bot_hum_1 = 10; // установим нижний предел равным 10%
}
} // конец функции void rooms()
Так выглядит алгоритм работы заслонки в одной комнате. Написание кода заняло довольно продолжительное время, так как нужно было просчитать все возможные ситуации в процессах, происходящих в сушильной комнате, подружить между собой большое количество переменных. В довершение всего, после старта устройства на производстве нам поступили пожелания персонала о создании дополнительных настроек в системе, что влекло за собой новые пункты меню, новые переменные и новые взаимосвязи между ними. В коде, описанном выше, все новые переменные уже добавлены:)
В следующей статье не менее содержательное описание кода нашего устройства, в том числе управление включением и выключением компрессора, откачивающего влажный воздух из комнаты:)