автоматизация фитолампы
Растут у меня красивые растения Адениум обесум, но пока маленькие и некрасивые. 😉 Холодной и хмурой зимой хочется даль больше света и тепла малявкам, а для этого на выручку — придёт фитолампа, у меня длинная над подоконником висит и питается 12В.
Конечно же автоматизировать процесс включения и отключения. Для этого на Алике мною было приобретено реле с датчиком света:
с помощью проводов с разъёмами на 12В я собрал простенькую схему для подключения в разрыв цепи
примерно так:
И в процессе тестов мои подозрения подтвердились, в момент переключения реле начинает щёлкать, безостановочно то включаясь, то отключаясь. Почему так происходило? Темнеет очень плавно, когда наступает пороговое значение — датчик освещенности дает сигнал на включение фитолампы, общая освещенность помещения немного увеличивается, но этого достаточно, чтобы сработал датчик и выключил лампу и так по кругу. Такой процесс происходит длительный период, переключая туда-сюда по несколько раз в секунду.
Правильно, для света и тепла использовать датчики с двумя порогами и разносить точки включения и отключения, создавая петлю Гистерезиса.
С текущим устройством реализовать подобную схему не получится, пороговая точка одна. К сожалению, разбираем и думаем другое решение.
Новый проект
А с решением мне помог мой коллега Дмитрий, он подсказал, что проще всего привязаться ко времени восхода и захода солнца.
Приступаем:
- самое главное — синхронизация времени
- график включения/отключения для нашей полосы
Остановил свой выбор на ESP8266 с WiFi модулем Nodemcu-CP2102.
Алгоритм следующий: подключились к wifi, синхронизировали время с ntp сервером, и с определенной периодичностью проверяем вхождение времени в массивы вкл/откл.
Я проверил время восходов и закатов из года в год примерно одинаковое, ± 1 минута, что не существенная погрешность. Используем готовые массивы, которые можно получить из онлайн калькуляторов для своего местоположения (в примере для Москвы).
Схема подключения очень простая, в качестве ключа я использовал мосфет 30N06, благо, в своё время куплено их было много
Он спокойно работает с напряжением 12В и током 1А, и переключается рабочим напряжением 3,3В с ноги ардуино.
Схема подключения взята из ролика Алекса Гайвера
Питание 12В я подал на разъём VIN и GND, а управление повесил на ногу D1.
Ниже сам код, в комментариях я постарался максимально подробно расписать механизмы
#include <NTPClient.h>
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
const char *ssid = "wifi_name";
const char *password = "wifi_password";
char buf[6];
// массивы с временем в формате день:месяц-часы:минуты, дополненные нулями
String time_lamp_off[366] = { "01.01-09:00", "02.01-09:00", "03.01-08:59", "04.01-08:59", "05.01-08:59", "06.01-08:58", "07.01-08:57", "08.01-08:57", "09.01-08:56", "10.01-08:55", "11.01-08:54", "12.01-08:54", "13.01-08:53", "14.01-08:52", "15.01-08:51", "16.01-08:49", "17.01-08:48", "18.01-08:47", "19.01-08:46", "20.01-08:44", "21.01-08:43", "22.01-08:42", "23.01-08:40", "24.01-08:39", "25.01-08:37", "26.01-08:35", "27.01-08:34", "28.01-08:32", "29.01-08:30", "30.01-08:29", "31.01-08:27", "01.02-08:25", "02.02-08:23", "03.02-08:21", "04.02-08:19", "05.02-08:17", "06.02-08:15", "07.02-08:13", "08.02-08:11", "09.02-08:09", "10.02-08:07", "11.02-08:05", "12.02-08:03", "13.02-08:00", "14.02-07:58", "15.02-07:56", "16.02-07:54", "17.02-07:51", "18.02-07:49", "19.02-07:47", "20.02-07:44", "21.02-07:42", "22.02-07:40", "23.02-07:37", "24.02-07:35", "25.02-07:32", "26.02-07:30", "27.02-07:27", "28.02-07:25", "29.02-07:25", "01.03-07:23", "02.03-07:20", "03.03-07:18", "04.03-07:15", "05.03-07:12", "06.03-07:10", "07.03-07:07", "08.03-07:05", "09.03-07:02", "10.03-07:00", "11.03-06:57", "12.03-06:54", "13.03-06:52", "14.03-06:49", "15.03-06:47", "16.03-06:44", "17.03-06:41", "18.03-06:39", "19.03-06:36", "20.03-06:33", "21.03-06:31", "22.03-06:28", "23.03-06:26", "24.03-06:23", "25.03-06:20", "26.03-06:18", "27.03-06:15", "28.03-06:12", "29.03-06:10", "30.03-06:07", "31.03-06:04", "01.04-06:02", "02.04-05:59", "03.04-05:57", "04.04-05:54", "05.04-05:51", "06.04-05:49", "07.04-05:46", "08.04-05:44", "09.04-05:41", "10.04-05:39", "11.04-05:36", "12.04-05:33", "13.04-05:31", "14.04-05:28", "15.04-05:26", "16.04-05:23", "17.04-05:21", "18.04-05:18", "19.04-05:16", "20.04-05:14", "21.04-05:11", "22.04-05:09", "23.04-05:06", "24.04-05:04", "25.04-05:02", "26.04-04:59", "27.04-04:57", "28.04-04:55", "29.04-04:52", "30.04-04:50", "01.05-04:48", "02.05-04:46", "03.05-04:43", "04.05-04:41", "05.05-04:39", "06.05-04:37", "07.05-04:35", "08.05-04:33", "09.05-04:31", "10.05-04:29", "11.05-04:27", "12.05-04:25", "13.05-04:23", "14.05-04:21", "15.05-04:19", "16.05-04:18", "17.05-04:16", "18.05-04:14", "19.05-04:12", "20.05-04:11", "21.05-04:09", "22.05-04:08", "23.05-04:06", "24.05-04:05", "25.05-04:03", "26.05-04:02", "27.05-04:00", "28.05-03:59", "29.05-03:58", "30.05-03:57", "31.05-03:55", "01.06-03:54", "02.06-03:53", "03.06-03:52", "04.06-03:51", "05.06-03:51", "06.06-03:50", "07.06-03:49", "08.06-03:48", "09.06-03:48", "10.06-03:47", "11.06-03:47", "12.06-03:46", "13.06-03:46", "14.06-03:46", "15.06-03:45", "16.06-03:45", "17.06-03:45", "18.06-03:45", "19.06-03:45", "20.06-03:45", "21.06-03:45", "22.06-03:45", "23.06-03:46", "24.06-03:46", "25.06-03:46", "26.06-03:47", "27.06-03:47", "28.06-03:48", "29.06-03:49", "30.06-03:49", "01.07-03:50", "02.07-03:51", "03.07-03:52", "04.07-03:53", "05.07-03:54", "06.07-03:55", "07.07-03:56", "08.07-03:57", "09.07-03:58", "10.07-03:59", "11.07-04:01", "12.07-04:02", "13.07-04:03", "14.07-04:05", "15.07-04:06", "16.07-04:08", "17.07-04:09", "18.07-04:11", "19.07-04:12", "20.07-04:14", "21.07-04:15", "22.07-04:17", "23.07-04:19", "24.07-04:21", "25.07-04:22", "26.07-04:24", "27.07-04:26", "28.07-04:28", "29.07-04:29", "30.07-04:31", "31.07-04:33", "01.08-04:35", "02.08-04:37", "03.08-04:39", "04.08-04:40", "05.08-04:42", "06.08-04:44", "07.08-04:46", "08.08-04:48", "09.08-04:50", "10.08-04:52", "11.08-04:54", "12.08-04:56", "13.08-04:58", "14.08-05:00", "15.08-05:02", "16.08-05:04", "17.08-05:06", "18.08-05:07", "19.08-05:09", "20.08-05:11", "21.08-05:13", "22.08-05:15", "23.08-05:17", "24.08-05:19", "25.08-05:21", "26.08-05:23", "27.08-05:25", "28.08-05:27", "29.08-05:29", "30.08-05:31", "31.08-05:33", "01.09-05:35", "02.09-05:37", "03.09-05:39", "04.09-05:40", "05.09-05:42", "06.09-05:44", "07.09-05:46", "08.09-05:48", "09.09-05:50", "10.09-05:52", "11.09-05:54", "12.09-05:56", "13.09-05:58", "14.09-06:00", "15.09-06:02", "16.09-06:03", "17.09-06:05", "18.09-06:07", "19.09-06:09", "20.09-06:11", "21.09-06:13", "22.09-06:15", "23.09-06:17", "24.09-06:19", "25.09-06:21", "26.09-06:23", "27.09-06:25", "28.09-06:27", "29.09-06:28", "30.09-06:30", "01.10-06:32", "02.10-06:34", "03.10-06:36", "04.10-06:38", "05.10-06:40", "06.10-06:42", "07.10-06:44", "08.10-06:46", "09.10-06:48", "10.10-06:50", "11.10-06:52", "12.10-06:54", "13.10-06:56", "14.10-06:58", "15.10-07:00", "16.10-07:02", "17.10-07:04", "18.10-07:06", "19.10-07:08", "20.10-07:11", "21.10-07:13", "22.10-07:15", "23.10-07:17", "24.10-07:19", "25.10-07:21", "26.10-07:23", "27.10-07:25", "28.10-07:27", "29.10-07:29", "30.10-07:31", "31.10-07:34", "01.11-07:36", "02.11-07:38", "03.11-07:40", "04.11-07:42", "05.11-07:44", "06.11-07:46", "07.11-07:48", "08.11-07:51", "09.11-07:53", "10.11-07:55", "11.11-07:57", "12.11-07:59", "13.11-08:01", "14.11-08:03", "15.11-08:05", "16.11-08:07", "17.11-08:09", "18.11-08:11", "19.11-08:13", "20.11-08:15", "21.11-08:17", "22.11-08:19", "23.11-08:21", "24.11-08:23", "25.11-08:25", "26.11-08:27", "27.11-08:29", "28.11-08:30", "29.11-08:32", "30.11-08:34", "01.12-08:35", "02.12-08:37", "03.12-08:39", "04.12-08:40", "05.12-08:42", "06.12-08:43", "07.12-08:45", "08.12-08:46", "09.12-08:47", "10.12-08:48", "11.12-08:50", "12.12-08:51", "13.12-08:52", "14.12-08:53", "15.12-08:54", "16.12-08:55", "17.12-08:56", "18.12-08:56", "19.12-08:57", "20.12-08:58", "21.12-08:58", "22.12-08:59", "23.12-08:59", "24.12-09:00", "25.12-09:00", "26.12-09:00", "27.12-09:00", "28.12-09:00", "29.12-09:00", "30.12-09:00", "31.12-09:00" };
String time_lamp_on[366] = { "01.01-16:07", "02.01-16:08", "03.01-16:10", "04.01-16:11", "05.01-16:12", "06.01-16:14", "07.01-16:15", "08.01-16:17", "09.01-16:18", "10.01-16:20", "11.01-16:21", "12.01-16:23", "13.01-16:25", "14.01-16:27", "15.01-16:28", "16.01-16:30", "17.01-16:32", "18.01-16:34", "19.01-16:36", "20.01-16:38", "21.01-16:40", "22.01-16:42", "23.01-16:44", "24.01-16:46", "25.01-16:48", "26.01-16:50", "27.01-16:52", "28.01-16:54", "29.01-16:56", "30.01-16:58", "31.01-17:01", "01.02-17:03", "02.02-17:05", "03.02-17:07", "04.02-17:09", "05.02-17:11", "06.02-17:14", "07.02-17:16", "08.02-17:18", "09.02-17:20", "10.02-17:22", "11.02-17:25", "12.02-17:27", "13.02-17:29", "14.02-17:31", "15.02-17:33", "16.02-17:36", "17.02-17:38", "18.02-17:40", "19.02-17:42", "20.02-17:44", "21.02-17:46", "22.02-17:48", "23.02-17:51", "24.02-17:53", "25.02-17:55", "26.02-17:57", "27.02-17:59", "28.02-18:01", "29.02-18:02", "01.03-18:03", "02.03-18:05", "03.03-18:08", "04.03-18:10", "05.03-18:12", "06.03-18:14", "07.03-18:16", "08.03-18:18", "09.03-18:20", "10.03-18:22", "11.03-18:24", "12.03-18:26", "13.03-18:28", "14.03-18:30", "15.03-18:32", "16.03-18:34", "17.03-18:36", "18.03-18:38", "19.03-18:40", "20.03-18:42", "21.03-18:44", "22.03-18:46", "23.03-18:48", "24.03-18:50", "25.03-18:52", "26.03-18:54", "27.03-18:56", "28.03-18:58", "29.03-19:00", "30.03-19:02", "31.03-19:04", "01.04-19:06", "02.04-19:08", "03.04-19:10", "04.04-19:12", "05.04-19:14", "06.04-19:16", "07.04-19:18", "08.04-19:20", "09.04-19:22", "10.04-19:24", "11.04-19:26", "12.04-19:29", "13.04-19:31", "14.04-19:33", "15.04-19:35", "16.04-19:37", "17.04-19:39", "18.04-19:41", "19.04-19:43", "20.04-19:45", "21.04-19:47", "22.04-19:49", "23.04-19:51", "24.04-19:53", "25.04-19:55", "26.04-19:57", "27.04-19:59", "28.04-20:01", "29.04-20:03", "30.04-20:05", "01.05-20:07", "02.05-20:09", "03.05-20:11", "04.05-20:13", "05.05-20:15", "06.05-20:17", "07.05-20:19", "08.05-20:21", "09.05-20:23", "10.05-20:25", "11.05-20:27", "12.05-20:29", "13.05-20:30", "14.05-20:32", "15.05-20:34", "16.05-20:36", "17.05-20:38", "18.05-20:40", "19.05-20:42", "20.05-20:43", "21.05-20:45", "22.05-20:47", "23.05-20:48", "24.05-20:50", "25.05-20:52", "26.05-20:53", "27.05-20:55", "28.05-20:56", "29.05-20:58", "30.05-20:59", "31.05-21:01", "01.06-21:02", "02.06-21:04", "03.06-21:05", "04.06-21:06", "05.06-21:07", "06.06-21:08", "07.06-21:10", "08.06-21:11", "09.06-21:12", "10.06-21:12", "11.06-21:13", "12.06-21:14", "13.06-21:15", "14.06-21:16", "15.06-21:16", "16.06-21:17", "17.06-21:17", "18.06-21:18", "19.06-21:18", "20.06-21:19", "21.06-21:19", "22.06-21:19", "23.06-21:19", "24.06-21:19", "25.06-21:19", "26.06-21:19", "27.06-21:19", "28.06-21:19", "29.06-21:19", "30.06-21:18", "01.07-21:18", "02.07-21:17", "03.07-21:17", "04.07-21:16", "05.07-21:16", "06.07-21:15", "07.07-21:14", "08.07-21:13", "09.07-21:12", "10.07-21:11", "11.07-21:10", "12.07-21:09", "13.07-21:08", "14.07-21:07", "15.07-21:06", "16.07-21:05", "17.07-21:03", "18.07-21:02", "19.07-21:01", "20.07-20:59", "21.07-20:58", "22.07-20:56", "23.07-20:54", "24.07-20:53", "25.07-20:51", "26.07-20:49", "27.07-20:48", "28.07-20:46", "29.07-20:44", "30.07-20:42", "31.07-20:40", "01.08-20:38", "02.08-20:36", "03.08-20:34", "04.08-20:32", "05.08-20:30", "06.08-20:28", "07.08-20:26", "08.08-20:24", "09.08-20:22", "10.08-20:20", "11.08-20:17", "12.08-20:15", "13.08-20:13", "14.08-20:11", "15.08-20:08", "16.08-20:06", "17.08-20:04", "18.08-20:01", "19.08-19:59", "20.08-19:57", "21.08-19:54", "22.08-19:52", "23.08-19:49", "24.08-19:47", "25.08-19:44", "26.08-19:42", "27.08-19:39", "28.08-19:37", "29.08-19:34", "30.08-19:32", "31.08-19:29", "01.09-19:27", "02.09-19:24", "03.09-19:22", "04.09-19:19", "05.09-19:16", "06.09-19:14", "07.09-19:11", "08.09-19:09", "09.09-19:06", "10.09-19:03", "11.09-19:01", "12.09-18:58", "13.09-18:55", "14.09-18:53", "15.09-18:50", "16.09-18:47", "17.09-18:45", "18.09-18:42", "19.09-18:39", "20.09-18:37", "21.09-18:34", "22.09-18:32", "23.09-18:29", "24.09-18:26", "25.09-18:24", "26.09-18:21", "27.09-18:18", "28.09-18:16", "29.09-18:13", "30.09-18:10", "01.10-18:08", "02.10-18:05", "03.10-18:02", "04.10-18:00", "05.10-17:57", "06.10-17:55", "07.10-17:52", "08.10-17:50", "09.10-17:47", "10.10-17:44", "11.10-17:42", "12.10-17:39", "13.10-17:37", "14.10-17:34", "15.10-17:32", "16.10-17:29", "17.10-17:27", "18.10-17:24", "19.10-17:22", "20.10-17:20", "21.10-17:17", "22.10-17:15", "23.10-17:12", "24.10-17:10", "25.10-17:08", "26.10-17:05", "27.10-17:03", "28.10-17:01", "29.10-16:59", "30.10-16:56", "31.10-16:54", "01.11-16:52", "02.11-16:50", "03.11-16:48", "04.11-16:46", "05.11-16:44", "06.11-16:42", "07.11-16:40", "08.11-16:38", "09.11-16:36", "10.11-16:34", "11.11-16:32", "12.11-16:30", "13.11-16:28", "14.11-16:27", "15.11-16:25", "16.11-16:23", "17.11-16:22", "18.11-16:20", "19.11-16:18", "20.11-16:17", "21.11-16:15", "22.11-16:14", "23.11-16:13", "24.11-16:11", "25.11-16:10", "26.11-16:09", "27.11-16:08", "28.11-16:07", "29.11-16:05", "30.11-16:04", "01.12-16:04", "02.12-16:03", "03.12-16:02", "04.12-16:01", "05.12-16:00", "06.12-16:00", "07.12-15:59", "08.12-15:59", "09.12-15:58", "10.12-15:58", "11.12-15:57", "12.12-15:57", "13.12-15:57", "14.12-15:57", "15.12-15:57", "16.12-15:57", "17.12-15:57", "18.12-15:57", "19.12-15:57", "20.12-15:58", "21.12-15:58", "22.12-15:59", "23.12-15:59", "24.12-16:00", "25.12-16:00", "26.12-16:01", "27.12-16:02", "28.12-16:03", "29.12-16:04", "30.12-16:05", "31.12-16:06" };
// переопределяем +3 часа к Гринвичу
const long utcOffsetInSeconds = 10800;
// задаем частоту синхронизации 1 час
const long UpdateIntervalInMilliseconds = 3600000;
// Определение NTP-клиента для получения времени
WiFiUDP ntpUDP;
// синхронизируем время с ntp сервером pool.ntp.org
NTPClient timeClient(ntpUDP, "pool.ntp.org", utcOffsetInSeconds, UpdateIntervalInMilliseconds);
// функция дополнения числа нулём
String c2d (byte i) {
// добавляю ноль перед числом до 10 и преобразовываю в строку
String str = (String)i;
if (i < 10) str = '0' + str;
return str;
}
void setup() {
Serial.begin(115200);
// Подготовка GPIO
pinMode(5, OUTPUT);
digitalWrite(5, 0);
WiFi.begin(ssid, password);
while ( WiFi.status() != WL_CONNECTED ) {
delay ( 500 );
Serial.print ( "." );
}
Serial.println("");
Serial.println("WiFi connected");
// в случае обрыва соединения Wifi - автоматически переподключаемся
WiFi.setAutoReconnect(true);
WiFi.persistent(true);
timeClient.begin();
}
void loop()
{
timeClient.update();
// считываем часы и минуты
int currentHour = timeClient.getHours();
int currentMinute = timeClient.getMinutes();
time_t epochTime = timeClient.getEpochTime();
struct tm *ptm = gmtime ((time_t *)&epochTime);
// считываем число и месяц
int monthDay = ptm->tm_mday;
int currentMonth = ptm->tm_mon;
// формируем строку в соответствие с форматом в массивах для последующего сравнения
String currentDateTime = c2d(monthDay)+"."+c2d(currentMonth+1)+"-"+c2d(currentHour)+":"+c2d(currentMinute);
Serial.println(currentDateTime);
// проходим в цикле значения массива отключения и в случае совпадения - отключаем лампу
for (int i = 0; i < 366; i++) {
if (time_lamp_off[i] == currentDateTime) {
Serial.println("Off lamp");
digitalWrite(5, 0);
break;
}
}
// проходим в цикле значения массива включения и в случае совпадения - включаем лампу
for (int i = 0; i < 366; i++) {
if (time_lamp_on[i] == currentDateTime) {
Serial.println("On lamp");
digitalWrite(5, 1);
break;
}
}
// пауза - 20 сек. проверку осуществляем 3 раза в минуту, в случае, если что-то один раз сбоит - перепроверим еще пару раз, просто добавляем надёжности
delay(20000);
}
Собрано было в компактный корпус, тоже с Алика
Теперь всё работает как часы, в прямом и переносном смысле 😅