Четыре состояния - двумя реле.
- Войдите на сайт для отправки комментариев
Ср, 20/03/2013 - 22:24
Термостат.
Есть три нагревателя с состоянием включен, выключен.
Управляются тремя реле. Пин в HIGH - реле выкл.
Нагреватели включаются постепенно. Ниже температура, больше нагревателей.
Для задержки между включениями введен признак включения flag для каждого реле.
if (time_act > time_eco_end && time_act <= time_eco_bg)
{
ust = 23;
}
else
{
ust = 22;
}
if (celsius >= ust && flag == true)
{
digitalWrite(4, HIGH);
flag = false;
}
else if (celsius < (ust - 0.2) && flag == false)
{
digitalWrite(4, LOW);
flag = true;
}
if (celsius > (ust - 1) && flag2 == true)
{
digitalWrite(3, HIGH);
flag2 = false;
}
else if (celsius < (ust - 1.2) && flag2 == false)
{
digitalWrite(3, LOW);
flag2 = true;
}
if (celsius > (ust - 1.5) && flag3 == true)
{
digitalWrite(2, HIGH);
flag3 = false;
}
else if (celsius < (ust - 1.7) && flag3 == false)
{
digitalWrite(2, LOW);
flag3 = true;
}
Код работает.
Однако, при этом используются три реле. Хотя четыре необходимых состояния можно обеспечить двумя.
Всё выключено. Включен один. Включены два. Включены все, 2+1.
И будто бы ничего сложного, но какой-то паралич мысли, "все говорит о наличии отсутствия опыта" :)
Подтолкните мыслю, пожалуйста.
Можно и с двумя реле, но двумя дополнительными логическими элементами. Oдин OR и один AND.
Два сигнала на пинах SWLow и SWHigh
Реле 1 управляется по (SWLow || SWHigh)
Реле 2- SWHigh
Реле 3 - (SWLow && SWHigh)
Код вроде несложно подправить.
Вот тут я засел....:( и ту-плю! Или просто нужно отдохнуть?
if (celsius >= ust && flag == true) { digitalWrite(3, HIGH); digitalWrite(4, HIGH); flag = false; } else if (celsius >= (ust - 0.99) && celsius <= (ust - 0.2)) && flag == false) { digitalWrite(3, LOW); digitalWrite(4, HIGH); flag = true; } if (celsius >= (ust - 1) && celsius <= (ust - 0.95)) && flag2 == true) { digitalWrite(3, HIGH); digitalWrite(4, LOW); flag2 = false; } else if (celsius < (ust - 1.1) && flag2 == false) { digitalWrite(3, HIGH); digitalWrite(4, LOW); flag2 = true; } if ((celsius >=(ust - 1.3)&&celsius <=(ust - 1.2)) && flag3 == true) { digitalWrite(3, LOW); digitalWrite(4, HIGH); flag3 = false; } else if (celsius < (ust - 1.4) && flag3 == false) { digitalWrite(3, LOW); digitalWrite(4, LOW); flag3 = true; }.............. :))) оно? В смысле похоже? Только чур, не подсказывать!
Немного непонятно что вы хотите. Сказали что у вас "четыре необходимых состояния" и тут же перечислили пять состоний ("2+1" это что?)
А когда "мозга забастовали", так решение - тоже известно. Дробите задачу на подзадачи. Вначале выясняйте сколько реле вам нужно включить, а потом отдельно включайте. И не нужно никаких флагов.
Просто введите доп переменню в которой храните сколько реле нужно включить.
Примерно так
byte heats=0; // тут храним сколько реле нужно включить // выясняем сколько реле нам нужно if(celc<10) heats=2 // два реле нужно если меньше 10 градусов else if(celc<20) heats=1 // от 10 до 20 градусов хватит и одного else heats=0; // если больше 10-ти вообще ничего не нужно // а теперь включаем реле switch(heats){ case 2: digitalWrite(RELE1,LOW); // если LOW - включает нагреватель digitalWrite(RELE2,LOW); break; case 1: digitalWrite(RELE1,LOW); // если LOW - включает нагреватель digitalWrite(RELE2,HIGH); // выключили второе break; default: digitalWrite(RELE1,HIGH); // выключили первое digitalWrite(RELE2,HIGH); // выключили второе }Вообщем-то switch можно свернуть и две строчки. Используя битовые операции, но раз "мозги баструют", то решил дать хоть и более громоздкий, но более прямодушный вариант :)
А еще задержка вам нужна... ну это опять-таки отдельно. Нечего все в один огород городить внутрь ифов.
byte prevHeats=0; loop(){ .... тут код из прошлого поста, вычисляем/включаем релешки... if(prevHeats!=heats){ // количество включенных реле изменилось delay(200); // значит нужно чуток подуплить } prevHeats=heats; // запомнили сколько у нас реле включено }Можно и с двумя реле, но двумя дополнительными логическими элементами. Oдин OR и один AND.
....
Реле 3 - (SWLow && SWHigh)
Забавно ;)
Ага, с двумя пинами, конечно -)
Количество реле в любом случае определяется количеством термостатов.
Спасибо, друзья! :) Интересное решение с кейсами.
Виноват. Очень бестолково описал задачу. Даже телепаты бессильны.:( Виноват!
Постараюсь поконкретней. Итак, управлять с помощью двух реле тремя нагревателями.
Может быть четыре состояния.
Выключены все. (оба реле выключены).
Включен один. (Реле 1).
Включены два. (Реле 2. Внимание! Реле 2 включает сразу два нагревателя)
Включены оба реле. (Реле1 и Реле2. В работе три нагревателя. Реле 1 - один, Реле 2 - 2 итого 3)
В первом сообщении в коде кусок:
if (celsius >= ust && flag == true) { digitalWrite(4, HIGH); flag = false; } else if (celsius < (ust - 0.2) && flag == false) { digitalWrite(4, LOW); flag = true; }включение нагревателя не сразу после того, как температура падает меньше установленной на величину разрешения температурного датчика, а после понижения на 0.2 градуса. Задержка во времени неодинаковая, в зависимости от того, насколько быстро произойдет остывание. Почему не delay() ? delay() в цикле конечно есть потому, что используется DS18b20. Но в цикле кроме этого есть обновление дисплея с часами, хотя и без секунд. И DS18b20 при всем его 0.06 разрешении, все равно "качается" (23 - 22.94 - 23 - 22.94.....) чтобы реле не "хлопали" на этих ненужных сотках и сделана задержка по понижению на пару десяток градуса.
Из-за чего сыр бор? Релюшки в блоках по две штуки... (Ну, и вот. Если три релюхи, то два блока, а это четыре реле. Жаба начинает свою песню... Ну и просто поискать возможное решение. :)
Так понятно, но вообщем-то принципиально не меняет идею изложенную в #3. А идея такова: разбивайте на блоки:
1. Блок выяснение сколько должно быть включенно (и кстати тестить его тогда можно даже без реле, простыми Serial.print)
2. Блок включения реле (блок исполнения решений)
3. Блок обеспечения задержки.
И чем меньше они связанны между собой - тем лучше. Их тогда можно будет потом вынести в отдельные функции. Сделать код более причесанным.
При переходе к "два реле - три нагревателя" - в блоке два - принципиально ничего не меняется. Просто в switch пропишите что-бы на "case 2:" включалось нужно реле, а не оба, а на "case 3" - оба.
"Без delay()" - ну тоже не очень сложно. Просто изначально небыло про "что-то еще происходит", поэтому его было проще, но и без делай не сумпер сложно
unsigned long lastHeatsChangedTime=0; loop(){ if(millis()-lastHeatsChangedTime>500){ // с прошлого включения прошло достаточно времени // тут идет логика сколько выключателей нужно включать, само включение и ит.п. // вообщем из #3 if(prevHeats!=heats) lastHeatsChangedTime=millis(); // запомнили когда последний раз переключили реле } prevHeats=heats; }А гистерезис сделать, что-бы на границах температур не "щелкало" - чуть-чуть изменить if-выснения сколько реле нужно
Вот так при температуре от 10 до 11, от 15 до 16 и от 20 до 21 - heats не будет менять свое значение.
Скажем если температура растет 9 (включились 3), 9.5,10,10.5 (по прежнему три),11,11.5(один выключился), 12, 11, 10.5 (по прежнему два), 10, 9.5 (опять три).
Вообщем в этих "промежутках" у вас количество включенных будет зависить от того "сверху" или "снизу" мы пришли. В точности как digitalRead решает логическая единица у нас или ноль при промежуточных значениях вольтажа на пине.
Только сам byte heats , нужно будет объявить не внутри loop, а как глобальную переменную, что-бы ее значение тоже сохранялось между проходами loop() (или объявить ее статической).