Снова всем здравствуйте!
После довольно долгого периода молчания решил таки выложить хоть часть того что я уже успел сделать. А сделано, как мне кажется, уже немало. Ну во первых сделал полностью готовый проект управления освещением и подогрева курятника с мониторингом и управлением через интернет. Устройство полностью собрано, установлено и работает. Материал уже подготавливаю. А во-вторых, брат попросил сделать такое же устройство, только вот не захотел он управление через интернет и вообще сделать проще- управлять просто освещением, без подогрева. Цена такого вопроса- смешная, поэтому решил сделать все «по быстрому» но… опять всякие форс- мажоры и получилось так что буквально 3 недели пришлось урывками программировать и вот наконец- первый результат готов! Поэтому просто переходим ниже и изготавливаем такое устройство. Поверьте- вещь просто необходимая.
Но прежде чем перейдем напрямую к изготовлению автомата освещения для кур я хотел бы описать из каких изначальных данных мне пришла в голову данная идея. После постройки курятника, проведения в него электричества остро встала нужда во включении/ отключении освещения т.к. для кур оптимальным считается 12 часовой световой день. Т.е. им нужно около 12 часов светлого времени для нормального периода яйценоскости. Можно укоротить период освещенности до 10 часов, но это- минимум, можно увеличить до 14- и это максимум. Но желательно чтобы у кур был довольно жесткий распорядок- в этом случае достигается максимальная отдача яиц. Поэтому решение с изготовлением автомата освещения курятника- довольно нужное решение. Мной уже используется автомат с такими установками:
- включение освещения- 6.00
- отключение по достижению определенного значения фоторезистора (отключение освещения утром)
- включение по достижению определенного значения фоторезистора (включение освещения вечером)
- отключение освещения- 21.00
В моем блоке кроме мониторинга и управлением освещением также присутствует модуль управлением подогрева курятника т.к. оптимальная температура для кур держится в пределе 13-17 градусов Цельсия. Кстати значения времени включения/ отключения а так же верхних и нижних пределов температуры можно изменять оперативно прямо с телефона или планшета, который я повесил дома вместо всех выключателей. Систему управления я назвал СУКА (Система Управления Курятником Автоматизированная). Как бы это неординарно не звучало. Ну а брату сделаю младшую версию данного аппарата. Итак, приступаем.
Для сборки данного устройства вам понадобится:
- Ардуино. Можно использовать любые версии ардуино, все зависит от размеров корпуса в который вы после сборки вложите собственно сам контроллер. Можно прошить отдельно микроконтроллер (МК) и, таким образом, немного сэкономить. Единственное условие- размер памяти МК. Скетч занимает около 14 кБ, поэтому необходимо взять атмегу хотя бы 168 серии со 16 кБ памяти на борту.
- RTC модуль DS1307. Можно любой другой часовой модуль, если часы будут сильно убегать/ отставать- перепаяйте кварцевый резонатор.
- Блок реле на 5В с одним реле.
- Валкодер. Можно конечно сделать кнопочное управление но валкодер, по моему мнению, лучшее решение в данном устройстве.
- Индикатор TM1637. Выбран из за того что занимает мало места, светодиодный, т.е., по сравнению с ЖК, на холоде он будет корректно работать а не притормаживать показания при работе и вообще информации на вывод мало и этот блок отлично справится со всеми возложенными задачами.
- Фоторезистор.
- Радиорассыпуха (БП на 5В (старый зарядник от телефона с выходным током около 500мА), подстроечный резистор на 10кОм, провода, коробка под корпус и т.д.)
Основное место в памяти МК естественно занимают библиотеки всех подключаемых устройств. Плюс еще пришлось подключить библиотеку ЕЕПРОМ для занесения в память времени включения/ отключения лампы освещения после пропадания напряжения и Serial. Можно конечно убрать библиотеку ЕЕПРОМ и жестко прописать время включения + настраивать НО. Если пропадет напряжение (а это обычно и происходит) то придется настраивать время включения/ отключения заново а это не совсем удобно. Схема данного устройства приведена ниже.
Возможно после сборки регулировка валкодером будет зеркальная. В этом случае поменяйте выводы CLK и DT местами. Будьте осторожны при сборке, на БП и коммутируемых цепях будет находится опасное напряжение 220В! Все устройство целесообразно собрать на макетной плате и разместить в электрической распределительной коробке подходящего размера. Фоторезистор следует расположить так чтобы избежать попадания как прямого так и отраженного света от любых поверхностей т.к. это может вызвать ложные срабатывания МК. Предел срабатывания датчика освещения регулируется подстроечным резистором R2. На схеме присутствует 2 выключателя. S1 отключает всю схему вместе с лампой. S2 позволяет включать освещение независимо от времени и степени освещенности. Так называемый байпасс. Кстати S1 можно перенести за провод идущий на лампу. В этом случае отключаться будет только автоматика а ручное управление освещением останется.
Принцип работы следующий:
- При включении проверяются ячейки ЕЕПРОМ на значение 255 (строки 56-68). Это значит что у вас новая Nano. Если МК чистый то в нужные ячейки ЕЕПРОМ записываются значения по умолчанию- 6 часов утра на включение и 21.00 на выключение освещения. При следующих включениях данные из ячеек будут присваиваться переменным. Значения времени работы можно изменять и значения в ячейках также будут автоматически изменяться.
- Затем проверяется нажат ли валкодер (строка 73). Если не нажат- просто отображаем время. Об этом говорят мигающие точки. Если нажат то переходим в меню настройки. Т.к. индикатор 7 сегментный то вывести названия настраиваемого параметра довольно проблематично. Поэтому я решил сделать так: при первом нажатии просто остается текущее время и гаснут точки (листинг страницы timeNastr.h , строки 7-39)- значит зашли в настройки текущего времени. Регулируем часы, нажимаем валкодер, регулируем минуты, опять нажимаем валкодер (в данных действиях включена полностью вкладка timeNastr.h командой в строке 75, функция encod с параметрами, строки 139-167 ). Таким образом установили текущее время и оно уже начало свой отсчет. Дальше опять загорятся точки на дисплее- это значит что регулируем время включения освещения. Тоже выбираем часы, нажимаем валкодер, выбираем минуты, нажимаем валкодер. Переходим в последний пункт- время выключения. Опять гаснут точки- значит время выключения. Опять регулируем часы, нажимаем, минуты, нажимаем. Все. Автомат настроен и уже работает.
- Настроить автомат только на часы довольно просто. Но вот с минутами… Пришлось написать довольно большой обработчик для обработки включения именно часов и минут (строки 101-126).
- п.3. просто дает разрешение на включение освещения, а дополнительный модуль на освещенность позволяет отключать освещение при достаточной яркости света днем и включать при недостаточной освещенности вечером (строки 128-135).
Сам скетч с библиотеками можно скачать. Листинг приведен ниже.
// скетч курятника для брата на RTC и 1637 #define pin_SW_SDA 3 // Назначение любого вывода Arduino для работы в качестве линии SDA программной шины I2C. #define pin_SW_SCL 4 // Назначение любого вывода Arduino для работы в качестве линии SCL программной шины I2C. #define tm_CLK 5 // для тм1637 #define tm_DIO 6 // #define en_CLK 7 // энкодер #define en_DT 8 // энкодер #define en_SW 9 // энкодер #define hr_ON 6 // час включения по умолчанию #define mm_ON 0 // минуты включения по умолчанию #define hr_OFF 21 // час выключения по умолчанию #define mm_OFF 0 // минуты выключения по умолчанию #define rl 13 // выход на реле #define rl_on 0 // активный уровень реле #define rl_of 1 // пассивный уровень реле int hh; // часы текущие int mm; // минуты текущие int hhm; // часы включения утренние int mmm; // минуты включения утренние int hhe; // часы выключения вечерние int mme; // минуты выключения вечерние int p_lgt = 400; // уровень срабатывания датчика analogRead(A0); int e_hon = 1; // ячейка ЕЕПРОМ для часов включения int e_mon = 2; // ячейка ЕЕПРОМ для минут включения int e_hoff = 3; // ячейка ЕЕПРОМ для часов выключения int e_moff = 4; // ячейка ЕЕПРОМ для минут выключения byte b_pnt = 0; // для отображения точки при работающих часах byte b_nast = 0; // для цикла настройки byte b_nast1 = 0; // для выхода из функции encod byte swl = 0; // признак работы света (0- отключен, 1- включен) int t_sw = 100; // дельта для предотвращения переключения // подключаем библиотЭки #include <GyverEncoder.h> #include "GyverTM1637.h" #include <EEPROM.h> #include <Wire.h> Encoder enc1(en_CLK, en_DT, en_SW); GyverTM1637 disp(tm_CLK, tm_DIO); #include <iarduino_RTC.h> // Подключаем библиотеку iarduino_RTC для работы с модулями реального времени. iarduino_RTC watch(RTC_DS1307); void setup() { enc1.setType(TYPE2); // тип энкодера TYPE1 одношаговый, TYPE2 двухшаговый. Если ваш энкодер работает странно, смените тип delay(300); // Ждем готовности модуля отвечать на запросы. // Serial.begin(9600); // Инициируем передачу данных в монитор последовательного порта на скорости 9600 бод. watch.begin(); // Инициируем работу с модулем. disp.brightness(4); pinMode(rl, OUTPUT); // выход на реле // проверка ЕЕПРОМ на наличие данных и присваивание времени включения/отключения if (EEPROM.read(e_hon) == 255 && EEPROM.read(e_hoff) == 255) // проверка по часам включения/ отключения (если 255- новая) { EEPROM.write(e_hon, hr_ON); // записываем в ЕЕПРОМ часы/ минуты включения/ отключения EEPROM.write(e_mon, mm_ON); EEPROM.write(e_hoff, hr_OFF); EEPROM.write(e_moff, mm_OFF); } hhm = EEPROM.read(e_hon); // считываем из ЕЕПРОМ часы/ минуты включения/ отключения mmm = EEPROM.read(e_mon); hhe = EEPROM.read(e_hoff); mme = EEPROM.read(e_moff); } void loop() { enc1.tick(); // Опрашиваем энкодер if (enc1.isClick()) // если был нажат энкодер { //НАСТРОЙКА #include "timeNastr.h" } if (b_nast == 0) { // РАБОТА if (millis() % 1000 == 0) // Если прошла 1 секунда. { hh= atoi (watch.gettime("H")); // Получаем часы mm= atoi (watch.gettime("i")); // Получаем минуты if (b_pnt == 1) { disp.point(1); // вкл точки b_pnt = 0; } else { disp.point(0); // выкл точки b_pnt = 1; } disp.displayClock(hh, mm); // выводим время delay(1); // Приостанавливаем скетч на 1 мс } } // срабатывание по датчику освещения if (hh < hhm) // если не достигли даже часа включения { swl = 0; } if (hh == hhm && mm >= mmm) // достигли времени включения { swl = 1; // указываем что свет зажегся } if (hh > hhm && hh <= hhe) // работа между установленными часами { swl = 1; // указываем что свет зажегся } if ( hh == hhe && mm >= mme) // достигли времени отключения { swl = 0; // указываем что свет погашен } if ( hh > hhe ) // выше заданного часа отключаем { swl = 0; // указываем что свет погашен } if ((analogRead(A0) < p_lgt) && swl == 1) // зажигаем освещение при недостаточной яркости на улице и гасим при достаточной { if ((analogRead(A0)<p_lgt-t_sw)) digitalWrite (rl, rl_on); // если освещенность ниже нижнего предела p_lgt-t_sw то включаем освещение } else { digitalWrite (rl, rl_of); } } // функция настройки VALUE- значение, maxim- максимальное значение, hm- регулировка часов при 1, иначе- минуты, h- часы, m- минуты int encod(int value, int maxim, int hm, int h, int m) { b_nast1++; while (b_nast1 > 0) { // Serial.println(value); enc1.tick(); if (enc1.isRight()) value++; // если был поворот направо, увеличиваем на 1 if (enc1.isLeft()) value--; // если был поворот налево, уменьшаем на 1 if (value < 0) value = 0; if (value > maxim) value = maxim; if (hm == 1) { disp.displayClock(value, m); } else { disp.displayClock(h, value); } if (enc1.isClick()) { b_nast1 = 0; // выход из цикла b_nast++; // переходим на следующий пункт меню return value; } } }
Страница timeNastr.h
b_nast++; while (b_nast != 0) { delay(100); enc1.tick(); Serial.println(b_nast); switch (b_nast) { case 1: // настройка текущего времени disp.point(0); // выкл точки hh = encod(hh, 23, 1, hh, mm); watch.settime(0, 0, hh); case 2: disp.point(0); // выкл точки mm = encod(mm, 59, 0, hh, mm); watch.settime(0, mm); // настройка времени включения case 3: disp.point(1); // вкл точки disp.displayClock(hhm, mmm); // выводим время hhm = encod(hhm, 23, 1, hhm, mmm); EEPROM.write(e_hon, hhm); // записываем в ЕЕПРОМ данные case 4: disp.point(1); // вкл точки mmm = encod(mmm, 59, 0, hhm, mmm); EEPROM.write(e_mon, mmm); // записываем в ЕЕПРОМ данные case 5: disp.point(0); // выкл точки (настройка времени выключения) disp.displayClock(hhe, mme); // выводим время hhe = encod(hhe, 23, 1, hhe, mme); EEPROM.write(e_hoff, hhe); // записываем в ЕЕПРОМ данные case 6: disp.point(0); // выкл точки mme = encod(mme, 59, 0, hhe, mme); EEPROM.write(e_moff, mme); // записываем в ЕЕПРОМ данные case 7: b_nast = 0; // выходим из настройки } }
Кстати по этому же скетчу можно легко сделать часы на Ардуино и TM1637. Если подключать другие библиотеки и индикаторы- то вообще можно сделать отличные часы.
Буду рад всем положительным и отрицательным отзывам, советам, предложениям. Спасибо за внимание.
Здравствуйте, а что делать с timeNastr.h и как ее залить? Спасибо!
Хороший вопрос, я как то упустил этот момент, думал что все знают тоже что и я. Все на самом деле проще чем вы думаете. Для того чтобы не плодить слишком длинный код многие программисты вставляют функцию # include «название вкладки.h«. Затем делают вкладку с таким же названием и, если вкладка в этом же проекте, все что написали в этой вкладке просто вписывается в исходный код. Т.е. Вы можете просто скопировать весь код из вкладки timeNastr.h и вставить вместо 75 строки. Т.е #include «timeNastr.h» удаляете и вставляете весь код из timeNastr.h. Это самый простой вариант. А чтобы было удобнее самому разбираться то делаете следующее: под кнопкой Монитор порта есть кнопка с треугольником, нажимаете ее, выбираете Новая вкладка или жмете комбинацию Ctrl+Shift+N, вводите название вкладки timeNastr.h. Можете заметить что у вас появляется 2 вкладки вверху. Одна по названию файла проекта и вторая- именно та что вы только что создали. Копируете в нее весь указанный код. Теперь программа доходит до #include «timeNastr.h» и переходит в указанную вкладку, пробегает весь код в ней и, по окончании вкладки, возвращается опять в основное тело программы. Все очень просто.
Здравствуйте. Понравилось Ваше устройство. Хочу попробовать повторить, но не скачиваются по ссылке скетч и библиотеки.
Перенастроил, все должно работать. Спасибо за отзыв
Здравствуйте! Спасибо за ссылку. Попытался сам найти все библиотеки и скетч перенести в программу ардуино и всё получилось. Все, так же как и в Вашем скетче. У меня вопрос. По описанию алгоритма работы устройства от датчика освещённости получается, что освещение будет включаться при снижении освещённости (вечером) и отключаться при увеличении освещённости (утром). Я так понял? А можно внести коррективы в скетч, чтобы освещение включалось от датчика освещённости (вечером) а отключалось от установленного в таймере времени. Через час два или три.
Можно и так. Нужно закомментировать код со 102 строки по 127 и в условии на срабатывании от датчика освещения поставить условие на срабатывание по таймеру. Но зачем?. Устройство сделано так что, например, освещение может включиться в 7 утра, затем отключится по датчику освещенности, затем обратно включится по тому же датчику освещенности и, наконец, отключит освещение по указанному времени. Не обязательно устанавливать время на всю ночь. Например время включения в 21.00, отключение- 7.00. Можно поставить наоборот: включение- 7.00, отключение- 21.00. Но уж если захотелось сделать устройство со срабатыванием по датчику освещенности и отключением по таймеру- тут уж и модуль часов и индикатор не нужны. Просто условие на срабатывание и таймер на отключение. Да тут скетч вообще в Атмегу 8 влезет и даже в 85.
Здравствуйте. Собрал таймер по Вашей схеме. Работает как таймер нормально. Поменял в скетче активный уровень реле с «0» на «1». Единственное не срабатывает от датчика освещённости. Не подскажете, в может быть причина?
1- проверьте как настроен подстроечный резистор (возможно движок резистора вывернут на максимум или минимум)- подключите вольтметр между общим проводом и точкой соединения между фоторезистором и переменным резистором, должно быть какое то напряжение и оно должно меняться от количества попадающего на фоторезистор света (можете бвстренько накидать скетч в Ардуино ИДЕ или вообще взять скетч из примеров той же ИДЕ, по моему называется AnalogRead, подправите его и можно обойтись без вольтметра и посмотреть какие значения подаются на аналоговый вход)
2- введите дополнительные переменные между строк 128-135 в основном блоке и выведите их в монитор порта (раскомментируйте 49 строку // Serial.begin(9600); ), например
Таким образом мы узнаем в мониторе порта значение приходящее на порт А0. Нужно понять- доходит ли команда до этой строки.
Здравствуйте. Долго не отвечал недавно приехал с командировки. Спасибо за подсказку. Разобрался. Оказывается, подстроечники были бракованные. Заказывал на алиэкспрес 5 штук. Два оказалось в обрыве. Не звонятся вообще.
Бывает. Можно было поставить простой делитель и уже в скетче поправить пороги срабатывания.
Здравствуйте! Вот опять обращаюсь к Вам. Проявился такой вот дефект. Первый месяц таймер отработал нормально. Потом стали сбивать часы. Изначально стоял модуль DS1307 с батарейкой. Батарейка нормальная. Модуль, к сожалению, был один. Потом взял у знакомого модуль DS3231. Тоже с батарейкой. Какой-то период проработали нормально. Потом опять стали сбиваться. Даже логику не пойму могут и три четыре дня проработать, не сбиваясь, а могут за сутки два раза. Кинул отдельную линию на таймер от щита, чтобы на этой линии не было других потребителей. Приеду с работы, попробую какой нибудь фильтр соорудить. Не подскажете, в чем может быть проблема.
Здравствуйте. Очень интересная проблема… С таким я еще не встречался. Знаю что на Атмега контроллерах стоит внутренний таймер, который при переполнении подвешивает сам микроконтроллер. Это происходит где то раз в 30-40 дней. В Вашем случае может быть несколько причин:
1- Плохие контакты (окисленные в том числе), напряжение работы довольно низкое и, возможно, неконтакт приводит к глюкам.
2- БП (блок питания). Емкости подсохли и пролетают пульсации в сам мк. Лечится заменой БП или проверкой и заменой конденсаторов в БП.
3- Брак деталей. Ну тут уже довольно сложно определить что сломалось и проблема будет решаться 2 способами- а- поочередной заменой деталей (займет много времени), б- ведение учета ошибок (для этого надо уже подключать SD карту и писать в нее логи по каким либо событиям, например по времени: мк берет текущее время и прибавляет 1 секунду, значит следующее время будет на секунду больше, наступает следующая секунда и, если время не равно высчитанному, проверять какие то данные с записью в SD- карту). Оба способа довольно проблематичные и долгие по времени. Поэтому я бы начал с БП т.к. деталь очень подвержена временным факторам.
PS* Если сбивается все таки время- то вероятнее всего что то с модулем времени т.к. время берется именно с модуля часов.