Доброго времени суток уважаемые посетители сайта www.samosdel.ru. Надеюсь данное устройство вам пригодится в Вашем доме. Приступаем.
Предыстория. Столкнулся я с такой ситуацией что у меня под навесом находится 3 прохода, через которые приходится входить/ выходить. Задумался я об освещении. Чтоб можно было включить и выключить его с любой точки. Сейчас у меня ПОКА свет под навесом включается из дома что не совсем удобно, т.к. когда приходишь , например, с работы, уже темно и приходится открывать дом в потемках (свет то включается дома и на весь день его включать… слишком много электричества улетит впустую) что вообще ни разу не удобно. Посмотрел стоимость проходных выключателей. Ужаснулся. Да и выключить свет тоже можно забыть. Решил сделать автомат освещения на известном микроконтроллере Ардуино. Сказано- начал делать.
Во первых подумал что куда подсоединить. Решил поставить кнопки а не выключатели, и их подключить к аналоговому порту т.к. он может принимать значения не только 0 и 1 но и что то среднее между ними, что при большой длине провода до кнопки может вызвать несрабатывание кнопки, аналоговый вход более чувствителен к уровню, но он также чувствителен и к наводке от сети 50 Гц, поэтому на плате я бы порекомендовал поставить между входом А0 и Gnd конденсатор на 0,01-0,1 мкФ (на схеме не показан) дабы наводки стекали с сигнального провода на землю. Кнопок включения можно ставить сколько угодно. Светодиоды тоже планировал ставить над кнопками, чтобы в темноте они светились и указывали местоположение кнопок. Если провода для проходных выключателей нужно ставить трехжильные и сечением 1,5 мм² не менее, а он довольно дорогой, то для кнопок и светодиодов достаточно витой пары, которой везде просто валяется целые кучи. Для светодиодов предусмотрел транзистор. Он предохранит выход контроллера от перегрузки по току при большом количестве светодиодов. Резистор на светодиоды придется подобрать в зависимости от количества светодиодов. Реле- покупное для Ардуино на 5В KY-019. Блок питания- самый маленький что найдете на 5В. Можно зарядник от телефона, но есть блоки питания гораздо меньшие по размеру и потреблению.
Теперь разберемся с алгоритмом работы данного автомата:
- При включении должны загореться светодиоды, указывающие местоположение кнопок включения.
- При коротком нажатии включается выдержка (настраивается индивидуально в зависимости от дальности кнопки до входа в дом), светодиоды гаснут, включается реле на заданное время. По истечении выдержки отключается реле, включаются светодиоды. Это автоматический режим.
- При длительном нажатии (> 1 сек) происходит тоже самое как и в п.2 только выдержки нет. Т.е. включается свет до тех пор пока повторно не нажмется любая из кнопок, т.е. как будто включили и не выключаем выключатель. Например ждем гостей и они могу не знать что и как включать. При таком режиме светодиоды продолжают гореть, что указывает на данный режим работы. Повторное нажатие любой из кнопок отключает данный режим. Это ручной режим.
- Так же должно быть принудительное отключение при любом из режимов нажатием любой из кнопок для экономии электричества.
Приступаем к написанию скетча. Я, конечно, до предлагаемого материала посидел несколько дней при разработке и нашел много тонкостей и ошибок. О процессе написания и отладке я остановлюсь подробно дабы Вы и сами могли понять что и как я делал и что получил в итоге. Для начала я попробовал найти 2 режима работы на одной кнопке. Нашел. Разобрался но… он меня не устроил и я решил написать полностью свой обработчик. Поэтому сначала я просто написал скетч на включение/ отключение реле и светодиода при нажатии на одну кнопку. Если будете копировать скетч то после вставки в Arduino IDE нажмите комбинацию клавиш Ctrl+T (английская). Скетч выстроится корректно и удобно для чтения и редактирования.
uint32_t last_millis; // длительность нажатия кнопки int iTime = 1; // длительность удержания кнопок при длительном включении в секундах byte bLongTime = 0; int iTimeWork = 10; // время работы при однократном нажатии в секундах byte bSwitch = 0; void setup() { pinMode(13, OUTPUT); // 13 вывод для индикации светодиодов pinMode(7, OUTPUT); // 7 вывод для реле digitalWrite(13, LOW); // включаем светодиоды digitalWrite(7, HIGH); // выключаем реле (активный уровень- низкий) } void loop() { if (analogRead(A0) > 100) { delay (200); if (bSwitch == 0) { bSwitch = 1; digitalWrite(13, HIGH); digitalWrite(7, LOW); // включаем реле (активный уровень- низкий) } else // отключаем принудительно { bSwitch = 0; digitalWrite(13, LOW); digitalWrite(7, HIGH); // выключаем реле (активный уровень- низкий) } }
В нем все понятно. При старте контроллер ждет нажатия кнопки. При нажатии на аналоговом порту А0 появляется напряжение выше нуля (analogRead(A0) > 100), это вызывает срабатывание логического переключателя. Смотрим на нижнюю часть условия else и понимаем что это и есть готовый вариант принудительного отключения! Поэтому сносим его подальше вниз по скетчу и принимаемся дописывать верхнюю часть.
uint32_t last_millis; // длительность нажатия кнопки int iTime = 1; // длительность удержания кнопок при длительном включении в секундах byte bLongTime = 0; int iTimeWork = 10; // время работы при однократном нажатии в секундах byte bSwitch = 0; void setup() { Serial.begin(9600); pinMode(13, OUTPUT); // 13 вывод для индикации светодиодов pinMode(5, OUTPUT); // 7 вывод для реле digitalWrite(13, HIGH); // включаем светодиоды digitalWrite(7, HIGH); // выключаем реле (активный уровень- низкий) } void loop() { if (analogRead(A0) > 100) { delay (200); if (bSwitch == 0) { bSwitch = 1; digitalWrite(13, LOW); digitalWrite(7, LOW); // включаем реле (активный уровень- низкий) last_millis = millis(); // начало отсчета времени bType = 1; //указываем что короткое включение Serial.println(«Short ON«); while (analogRead(A0) > 100) { if (last_millis + iTime * 1000 > millis()) //длительное нажатие { digitalWrite(13, HIGH ); // зажигаем светодиоды- индикация что работать будет до нажатия кнопки digitalWrite(7, LOW); // включаем реле (активный уровень- низкий) bType = 0; //указываем что длительное включение Serial.println(«Long ON«); } } } else // отключаем принудительно { bSwitch = 0; digitalWrite(13, HIGH); digitalWrite(7, HIGH); // выключаем реле (активный уровень- низкий) Serial.println(«All OFF«); } } delay (200); if ( bSwitch == 1 && (last_millis + iTimeWork * 1000) < millis() && bType == 1) //отключение через заданное время при коротком нажатии { bSwitch = 0; digitalWrite(13, HIGH); digitalWrite(7, HIGH); // выключаем реле (активный уровень- низкий) Serial.println(«Short OFF«); } }
Это вторая часть моего получившегося скетча. Принцип работы следующий: при нажатии на кнопку проверяется состояние логического переключателя bSwitch, и если оно равно нулю то присваиваем ему 1 (означает срабатывание устройства на включение), гасим светодиод и включаем реле (у KY-019 активный уровень- низкий) т.е. запускаем автоматический режим работы (bType =1). Затем идет цикл, который продолжает отслеживать нажатие кнопки и, если удерживать её дольше iTime * 1000 миллисекунд то произойдет переключение в ручной режим (bType =0). Но это еще полдела. В данном куске кода был решен только выход из ручного и принудительное завершение автоматического режимов. Поэтому ниже дописал секцию по значениям которой происходит отключение через iTimeWork *1000 миллисекунд. Все довольно сносно работало при значении iTimeWork до 30. Затем начались вообще непонятные глюки. Ставлю 180 секунд. Автомат сразу включается и отключается. Я всю голову изломал пока не догадался посмотреть тип переменной millis(). Она оказалась unsigned long. Как я понял, методом подбора значений, выше 32 секунд я вводить значения не могу т.к. при складывания типа unsigned long и прибавления умноженного на 1000 типа integer общее значение (last_millis + iTimeWork * 1000) принимает тип integer и практически моментально переключает автоматический режим обратно в отключенное состояние. Тут получается ошибка совместимости типов и поэтому программа просто вылетала. После того как я присвоил переменной iTimeWork тип unsigned long программа начала корректно исполнятся. Заключительный вид скетча выглядит так:
uint32_t last_millis; // длительность нажатия кнопки int iTime = 1; // длительность удержания кнопок при длительном включении в секундах byte bType = 0; unsigned long ulTimeWork = 180; // время работы при однократном нажатии в секундах byte bSwitch = 0; #define lgt 13 // вывод светодиодов #define rel 7 // вывод реле void setup() { pinMode(lgt, OUTPUT); // 13 вывод для индикации светодиодов pinMode(rel, OUTPUT); // 7 вывод для реле digitalWrite(lgt, HIGH); // включаем светодиоды digitalWrite(rel, HIGH); // выключаем реле (активный уровень- низкий) } void loop() { if (analogRead(A0) > 100) { delay (200); if (bSwitch == 0) { bSwitch = 1; digitalWrite(lgt, LOW); digitalWrite(rel, LOW); // включаем реле (активный уровень- низкий) last_millis = millis(); // начало отсчета времени bType = 1; //указываем что короткое включение while (analogRead(A0) > 100) { if (last_millis + iTime * 1000 > millis()) //длительное нажатие { digitalWrite(lgt, HIGH ); // зажигаем светодиоды- индикация что работать будет до нажатия кнопки digitalWrite(rel, LOW); // включаем реле (активный уровень- низкий) bType = 0; //указываем что длительное включение } } } else // отключаем принудительно { bSwitch = 0; digitalWrite(lgt, HIGH); digitalWrite(rel, HIGH); // выключаем реле (активный уровень- низкий) } } delay (200); if ( bSwitch == 1 && (last_millis + ulTimeWork * 1000) < millis() && bType == 1) //отключение через заданное время при коротком нажатии { bSwitch = 0; digitalWrite(lgt, HIGH); digitalWrite(rel, HIGH); // выключаем реле (активный уровень- низкий) } }
Хочу обратить внимание на название переменной iTimeWork в предыдущем скетче и переменно ulTimeWork в данном скетче. Как я говорил очень удобно указывать в названии переменной её тип. Поэтому тут я переименовал переменную iTimeWork (расшифровывается как integer Time Work переменная времени работы TimeWork с типом integer) в ulTimeWork (unsigned long переменная времени работы TimeWork). Данный скетч занимает всего 1572 байта и можно использовать не Ардуино а, например, ATMEGA8. Для этого я применил оператор #define который подставляет в строках кода вместо переменной её значение. Т.е если написано #define lgt 13 и встречается команда digitalWrite(lgt, LOW); то вместо lgt в команде digitalWrite(lgt, LOW); вставляется её значение, т.е. 13. Получается команда digitalWrite(13, LOW); Данный прием особенно эффективен при больших проектах или, как в нашем случае, когда необходимо поменять назначение выводов сразу во всем скетче. Для этого достаточно одной команды и правильного написания кода чтоб сделать глобальные изменения а не прыгать по каждому оператору. Так что для прошивки в ATMEGA8 достаточно посмотреть даташит на неё, выбрать нужные выводы и объявить их в соответствующих секциях #define!
Например приведу распиновку 328 Атмеги (она такая же как и ATMEGA8). В нашем случае подключаться напрямую к микросхеме нужно будет так: порт А0- 23 нога, светодиоды- 19 и реле- 13 ноги контроллера. ATMEGA8 отдельно стоит около 50-60 руб в Китае что почти в 10 раз дешевле Arduino UNO и в 2-3 дешевле Arduino NANO. Поэтому имеет смысл для постоянных проектов иметь в запасе пару тройку таких контроллеров вместо ардуин. Достаточно просто купить программатор за те же 100 руб или использовать как программатор собственно Ардуину. Для совсем небольших проектов, можно купить контроллеры Attiny. Они бывают 25, 45 и 85 серии где первая цифра указывает объем её памяти в килобайтах. Например Attiny45 имеет всего 8 выводов и 4 кБ памяти. В нашем случае достаточно было бы Attiny25 т.к. объем занимаемой памяти 1,5 кБ и выводов хватит на все. Все очень просто!
Теперь можно перейти к дополнительному функционалу. Ну во первых можно поставить датчик освещенности на фоторезисторе. Конечно можете сказать- проще поставить датчик движения и все… Но в нашем случае появляется более гибкое устройство. У Вас может возникнуть вопрос- как регулировать порог срабатывания? Можно жестко ввести в скетче значения и датчик будет срабатывать по достижению этих значений. А можно сделать регулируемый датчик. Для этого необходимо будет всего один переменный на 10 кОм и один постоянный резисторы на 1 кОм. Переменный резистор подключаем крайними выводами к + и -5В. Ползунок через сопротивление 1 кОм подключаем к аналоговому входу, например А1. Не забываем подключить фоторезистор к другому порту, например А2. Считываем значения из А1, сравниваем со значением А2 и, например, при достаточной освещенности не даем включать реле. Таким образом мы будем экономить электричество в дневное время + защита от случайного нажатия днем. Но и это еще не все! Для тех кто выезжает за город только по выходным данное устройство будет просто находкой. Если подключить к контроллеру модуль GSM и передавать ему различные команды то можно добиться эффекта присутствия хозяина дома. Т.е. мы частично делаем уже небольшое не охранное а предупредительное устройство. Можно конечно подключить блок часов реального времени и включать по времени, но включение в одно и тоже время может указывать на отсутствие хозяев или на их просто дикую пунктуальность. Можно вообще завести охранную сигнализацию на контроллер и при получении аварийного сигнала будет выполнятся дозвон или отправляться СМС на указанный номер. Вобщем, нам бы это только суметь…
Ну а по поводу установки в доме данного автомата скажу следующее. Сам блок включу через выключатель в доме т.к. летом темнеет поздно и рассветает рано. Как только отпадет надобность в автомате- просто выключаю его и все. Давайте посчитаем. Вроде потребляемая мощность и небольшая, всего 2-3 Ватта НО. В день на холостом режиме (не считаем включения ламп) потребляется 3*24=72 Ватта, в месяц 72*30= 2160 Ватт или 2 кВт. Уже много. Поэтому все равно есть смысл иногда отключать автомат освещения. Но это все равно меньше чем свет попросту горит на улице. Дальше, у меня 3 точки где необходимо установить кнопочный пост со светодиодами. Поэтому я довольно дешево перекрываю все точки просто протянув витую пару до нужных точек. Опять же безопасность. По витой паре будет идти максимум 5 Вольт. Думаю данный автомат можно использовать и на лестничном освещении в многоэтажных домах. А если использовать вместе с фоторезистором то экономия будет очень существенная!
Автомат уличного освещения готов! Оставляйте свои отзывы по конструкции и функционалу автомата. Буду рад любым предложениям и критике.
Вторая версия более доработанного автомата освещения находится ЗДЕСЬ.