Умный санузел
- Войдите на сайт для отправки комментариев
Вс, 12/02/2017 - 18:10
Здравствуйте! Задался целью сделать автоматику против протечки в с/у и заодно прикрутить пару плюшек. Пока детали едут из Китая попробовал набросать скетч. Необходимо еще как то прикрутить обмен данными с NodeMCU по последовательному порту. С этим пока разбираюсь как вообще это происходит. Понимаю, что ужас полный, но это моя первая проба пера. Критика приветствуется.
#include <DHT.h> volatile int waterAl_1 = 2; // датчик протечки 1 volatile int waterAl_2 = 3; // датчик протечки 2 int waterAl_3 = 4; // датчик протечки 3 int light_WC = 5; // датчик освещенности в туалете int light_bath = 6; //датчик освещенности в ванной int higro = 7; // датчик температуры и влажности int relay_1 = 8; // реле1 ХВС int relay_2 = 9; // реле2 ГВС int relay_3 = 10; // реле3 вентилятора в ванной int relay_4 = 11; // реле4 вентилятора в туалете int ir_WC = 12; // датчик движения в туалете int ir_bath = 13; // датчик движения в ванной int time_in = 14; // получение времени (сигнал с1ч до4часов) int alarm_in = 15; // сигнал с дистанционки на выключение int alarm_out = 16;// сигнал на NodeMcu об аварии int gigro_out = 17; // данные температуры и влажности на NodeMcu float temp = 0; // переменная хранения теvпературы float hum = 0; // переменная хранения влажности int al_out = 0; // переменная значения протечки воды boolean lightOn = false; // переменная счетчика цикла влажности в ванной int hum_tmp = 50; // переменная начального значения влажности int hum_diff = 0; // переменная разницы влажности за отрезок времени boolean lightOnWC = false; // переменная счетчика времени в туалете boolean fanOnWC = false; // переменная для включения вентилятора в ванной unsigned long currentMillisLightBath = 0; //Текущее значение счетчика времени включениясвета в ванной unsigned long previousMillisLightBath = 0; //Начальное значение счетчика времени включениясвета в ванной unsigned long intervalLightBath = 180000; //Интервал времени включенного света в ванной мсек. unsigned long diffMillisWC = 60000; unsigned long currentMillisWC = 0; unsigned long previousMillisWC = 0; unsigned long perWaterMillis = 4200000000; // максимальное значение 4 294 967 295 unsigned long currentWaterMillis = 0; int timeNight = 0; // Надо как то получить с последовательного порта от NodeMcu int alarm = 0; DHT dht(higro, DHT22); // Создаем объект DHT void setup() { pinMode(waterAl_1, INPUT); // назначить выводу порт ввода датчика протечки 1 digitalWrite(waterAl_1, LOW); // включить подтягивающий резистор на землю pinMode(waterAl_2, INPUT); // назначить выводу порт ввода датчика протечки2 digitalWrite(waterAl_2, LOW); // включить подтягивающий резистор на землю pinMode(waterAl_3, INPUT); // назначить выводу порт ввода датчика протечки 3 digitalWrite(waterAl_3, LOW); // включить подтягивающий резистор на землю pinMode(light_WC, INPUT); // назначить выводу порт ввода датчика освещения туалета digitalWrite(light_WC, LOW); // включить подтягивающий резистор на землю pinMode(light_bath, INPUT); // назначить выводу порт ввода датчика освещения ванны digitalWrite(light_bath, LOW); // включить подтягивающий резистор на землю pinMode(higro, INPUT); // назначить выводу порт ввода датчика температуры и влажности digitalWrite(higro, LOW); // включить подтягивающий резистор на землю pinMode(ir_WC, INPUT); // назначить выводу порт ввода датчика движения в туалете digitalWrite(ir_WC, LOW); // включить подтягивающий резистор на землю pinMode(ir_bath, INPUT); // назначить выводу порт ввода датчика движения в ванной digitalWrite(ir_bath, LOW); // включить подтягивающий резистор на землю pinMode(relay_1, OUTPUT); // назначить выводу порт вывода реле 1 digitalWrite(relay_1, LOW); // подаем изначально низкое напряжение pinMode(relay_2, OUTPUT); // назначить выводу порт вывода реле 2 digitalWrite(relay_2, LOW); // подаем изначально низкое напряжение pinMode(relay_3, OUTPUT); // назначить выводу порт вывода реле 3 digitalWrite(relay_3, LOW); // подаем изначально низкое напряжение pinMode(relay_4, OUTPUT); // назначить выводу порт вывода реле 4 digitalWrite(relay_4, LOW); // подаем изначально низкое напряжение Serial.begin(9600); // Инициируем последовательный порт на скорости 9600 бит/с dht.begin(); // Вызов объекта dht attachInterrupt(2, waterAlarm, RISING); // Прерывание при срабатывании датчика протечки 1 attachInterrupt(3, waterAlarm, RISING); // Прерывание при срабатывании датчика протечки 2 } void loop() { waterAlarm(); DHT_Function(); fanBathHum(); fanWC(); Alarm(); } // Функция считывания и присвоения данных температуры и влажности переменным void DHT_Function() { // Даем название функции float hum = dht.readHumidity(); // Считываем влажность float temp = dht.readTemperature(); // Считываем температуру } //Функция работы с датчиками протечки и приводами кранов void waterAlarm() { // Даем имя функции if (digitalRead(waterAl_1) == HIGH || digitalRead(waterAl_2) == HIGH || digitalRead(waterAl_3) == HIGH || digitalRead(alarm_in) == HIGH) { // Если сработал какой то датчик протечки или сигнал на выключение, то digitalWrite(relay_1, LOW); // Выключаем реле крана ХВС digitalWrite(relay_2, LOW); // Выключаем реле крана ГВС digitalWrite(alarm_out, HIGH); // Даем на пин 16 сигнал об аварии для NodeMcu al_out = 1; // Даем переменной аварии значение 1 } else { // Иначе digitalWrite(relay_1, HIGH); // Включаем реле крана ХВС digitalWrite(relay_2, HIGH); // Включаем реле крана ГВС digitalWrite(alarm_out, LOW); // Даем на пин 16 сигнал об устранении аварии для NodeMcu al_out = 0; // Даем переменной аварии значение 0 } } // Функция включения вентилятора в ванной по повышению влажности void fanBathHum() { // Даем имя функции if (digitalRead(light_bath) == HIGH || lightOn == true) { // Если включен свет в ванной или принимали душ и вышли, то if (lightOn == false) { // Если счетчик цикла начальный, то hum_tmp = hum; // Записываем текущее значение влажности в буфер previousMillisLightBath = millis(); // Записываем текущее значение таймера работы программы } // Конец условия счетчик цикла равен нулю currentMillisLightBath = millis(); // Записываем текущее значение таймера работы программы if (currentMillisLightBath - previousMillisLightBath > intervalLightBath) { // Проверяем не прошел ли нужный интервал, если прошел то hum_diff = hum - hum_tmp; // Считаем изменение влажности за заданный интервал времени lightOn = false; // Обнуляем счетчик цикла } // Конец условия проверки заданного интервала else {lightOn = true;} // Меняем значение счетчика цикла на 1 } // Конец условия включенного света в ванной if (hum >= 80 || hum_diff >= 5) { // Если влажность более 80% или увеличение влажности более 5%, то digitalWrite(relay_3, HIGH); // Включаем реле вентилятора в ванной } // Конец условия проверки влажности 80% или разницы в 5% else { // Иначе, если влажность менее 80% или рост менее 5% if ( hum < 78 || hum_diff < -2){ // Если влажность менее 78% или падение влажности более 2% то digitalWrite(relay_3, LOW); // Вентилятор выключаем lightOn = false; } // Конец условия проверки влажности 78% или падения на 2% } // Конец условия "Иначе, если влажность менее 80% или рост менее 5%" } // Конец функции // Функция включения вентилятора в туалете по времени void fanWC(){ if (digitalRead(light_WC) == HIGH && digitalRead(ir_WC) == HIGH) { if (lightOnWC == false) { // Если счетчик цикла начальный, то previousMillisWC = millis(); // Записываем текущее значение таймера работы программы } // Конец условия счетчик цикла равен нулю currentMillisWC = millis(); // Записываем текущее значение таймера работы программы if (currentMillisWC - previousMillisWC > diffMillisWC) { // Проверяем не прошел ли нужный интервал, если прошел то lightOnWC = false; // Обнуляем счетчик цикла fanOnWC = true; } // Конец условия проверки заданного интервала else {lightOnWC = true;} // Меняем значение счетчика цикла на 1 } if (digitalRead(light_WC) == LOW && fanOnWC == true) { if (lightOnWC == false) { // Если счетчик цикла начальный, то previousMillisWC = millis(); // Записываем текущее значение таймера работы программы } // Конец условия счетчик цикла равен нулю currentMillisWC = millis(); // Записываем текущее значение таймера работы программы if (currentMillisWC - previousMillisWC > 180000) { // Проверяем не прошли ли 3 минуты, если прошли, то lightOnWC = false; // Обнуляем счетчик цикла fanOnWC =false; } // Конец условия проверки заданного интервала else {lightOnWC = true;} // Меняем значение счетчика цикла на 1 } if (fanOnWC == true) { digitalWrite(relay_4,HIGH); } else digitalWrite(relay_4,LOW); } // Функция сигнализации void Alarm(){ if (digitalRead(alarm_in) == HIGH && (digitalRead(light_WC) == HIGH || digitalRead(light_bath) == HIGH || digitalRead(ir_WC) == HIGH || digitalRead(ir_bath)) == HIGH) { alarm = 1;} else {alarm = 0;} } // Функция от закисания кранов. void WaterRelayDelay(){ currentWaterMillis = millis(); if (currentWaterMillis > perWaterMillis && timeNight == 1) { digitalWrite(relay_1, LOW); // Выключаем реле крана ХВС digitalWrite(relay_2, LOW); // Выключаем реле крана ГВС delay(60000); digitalWrite(relay_1, HIGH); // Включаем реле крана ХВС digitalWrite(relay_2, HIGH); // Включаем реле крана ГВС } }
ужас и есть.
делай 60000 говорит что в течение 60сек вернее минуты ваш счетч думает и в это время ничего не мониторить.
т.е. попадание потота в это момент его не остановит :)))
Это да, плохо. Но данная функция должна срабатывать раз в полтора месяца. А раз в полтора месяца остановка контроллера на минуту думаю не так уж и страшна. Тем более датчики протечки через прерывания должны сработать даже в этот момент.
А правда, что функция должна быть описана до ее вызова по листингу, или это как то несмертельно?
:)) не видел что она там у вас хз где вызвается.
и вы уверены что даже если она и гдето вызвается то миллис может эти полтора месяца насчитать.
у меня просто сомнение что 16МГц хватит разрядности для счета не говоря о том что она там обнуляется по кругу. надо почитать мануалы какое ее значение макс дял вашей платы
А правда, что функция должна быть описана до ее вызова по листингу, или это как то несмертельно?
вообще не факт! есть куча примеров когда описание функции позади вызова и все работает
А правда, что функция должна быть описана до ее вызова по листингу, или это как то несмертельно?
вообще не факт! есть куча примеров когда описание функции позади вызова и все работает
говорили же 100 раз, по стандарту положено раньше, некоторые версии иде позволяют писать и ниже, но чтобв скетч компилировался в любой версии нужно писать выше
пользуюсь 1.0.6 . в дальнейшем споре не вижу смысла