Умный санузел
- Войдите на сайт для отправки комментариев
Вс, 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 . в дальнейшем споре не вижу смысла