Управление вытяжкой в санузле.

A.K.
Offline
Зарегистрирован: 20.12.2021

Здравствуйте, уважаемые!

Как говорится, первый пост, сильно не пинайте.... Пинайте, но не сильно. Пытаюсь для единственной тёщи. Задача - управлять вытяжкой в санузле.

Не могу разобраться с работой по времени.

Техзадание, сформулированное для себя.

0. Регистрация включения-выключения освещения фоторезистором, регистрация влажности датчиком DHT11
1. Включение вентиляции по отключению света в ванной на 10 мин
2. Включение вентиляции по отключению света при влажности > 70%, до её снижения ниже порога, но не более 30 мин.
3. При повторном включении света во время работы вентилятора - перезапуск его с п.1
4. Возможность принудительного запуска/остановки вентиляции без дополнительных выключателей - приятная плюшка, пока не придумал как 

Значения влажности и длительность работы вентилятора - величины условные, будут подбираться по мере отладки.

Собственно, код:

#include <iarduino_DHT.h>                 // подключаем библиотеку для работы с датчиком DHT
iarduino_DHT sensor(10);                  // объявляем  переменную для работы с датчиком DHT, указывая номер цифрового вывода к которому подключён датчик
int Light(3);                            // объявляем переменную для датчика света на (X) pin
int Relay(12);                            // объявляем переменную для реле на (X) pin
int Timer = 0;                            // объявляем переменную таймера,

void lightOff()                            // функция, вызываемая освещением 
{  Timer = 20;
}

void setup()
 { attachInterrupt(1, lightOff, FALLING);  // аппаратное прерывание по освещению;
   Serial.begin(9600);                     // открываем последовательный порт на скорости 9600 бод
   delay(1000);                            // выполняем задержку для перехода датчика в активное состояние
   pinMode(12, OUTPUT);                    // Set Pin12 as output
   digitalWrite(12, 0);                    // Set Pin12 Low
   pinMode(Light, INPUT);                 // declare pushbutton as input
   Timer = 0;                              // устанавливаем таймер в 0
 }

void loop()
{ switch (sensor.read())                  // читаем показания датчика
  { case DHT_OK:               Serial.println((String) "CEHCOР: " + sensor.hum + "% - " + sensor.tem + "*C");     break;
    case DHT_ERROR_CHECKSUM:   Serial.println(         "CEHCOP: HE PABEHCTBO KC");                                break;
    case DHT_ERROR_DATA:       Serial.println(         "CEHCOP: OTBET HE COOTBETCTB. CEHCOPAM 'DHT'");            break;
    case DHT_ERROR_NO_REPLY:   Serial.println(         "CEHCOP: HET OTBETA");                                     break;
    default:                   Serial.println(         "CEHCOP: ERROR");                                          break;

    int val = digitalRead(Light);      // читаем кнопку
  }


 if ((digitalRead(Light) == 1)            // проверяем: освещение включено
      or (sensor.hum < 60.0))             // сравниваем влажность с произвольным эталоном
  { Serial.println(Timer);                //выводим значение счетчика на экран
    digitalWrite(Relay, 0);               // отключаем реле
  }
 
  else if ((Timer > 0)
          and (sensor.hum > 60.0))
  { Serial.println(Timer);                //выводим значение счетчика на экран
    Timer --;                             // увеличиваем таймер
    digitalWrite(Relay, 1);               // включаем реле
  }
  
  sensor.read();                          // чтение показаний датчика
  sensor.hum;                             // показания влажности
  delay(300);
}

Направьте, пожалуйста, мысли в нужную сторону.

Спасибо!

Дим-мычъ
Offline
Зарегистрирован: 20.03.2021

Может "техзадание" сложновато? Я бы, для начала, сделал с двумя опциями:

1 - автомат. включение/выключение по влажности

2.-ручное включение/выключение.(возможно, варианты с таймером)

А где две , там и десять)). Хотя смысла добавлять что-то ещё как бы и не вижу(но это уже хозяин-барин)...

b707
Offline
Зарегистрирован: 26.05.2017

A.K., приветсвую.

Какие проблемы со временем? предположу, что срабатывает один раз и все? это связано с тем , что вы в коде переменную Timer уменьшаете до нуля, но больше нигде не устанавливаете.

И еще - строчки 29 и 47 абсолютно бессмысленны, обратите внимание.

A.K.
Offline
Зарегистрирован: 20.12.2021

Уважаемый Дим-мычъ! Ваше предложение - не вариант. Просто и потому не интересно!

Уважаемый b707! Спасибо за подсказку!

На текущий момент код несколько изменён. Чтобы здесь не перегружать, привожу по частям:

1. Таймер устанавливается в зависимости от влажности на 3 или на 7 "попугаев", работает правильно

void lightOff()                           // функция, вызываемая освещением
{ if (sensor.hum <= 60.0)
  { Timer = 3;
  }
  else if (sensor.hum > 60.0)
  { Timer = 7;
  }
}

2. Проблемная часть. Отключение реле происходит только по таймеру и не зависит от влажности, т.е. при снижении влажности ниже порога таймер продолжает считать.

if      ((digitalRead(Light) == 1)   // проверяем: освещение вкл
          or (Timer <= 0))            // проверяем таймер
  { Timer = 0;                       // обнуляем таймер 
    digitalWrite(Relay, 0);          // отключаем реле
  }
  
else if ((Timer > 0)                 // проверяем таймер
           or (sensor.hum > 60.0))   // проверяем датчик
  {  Timer --;                       // считаем таймер 
     digitalWrite(Relay, 1);         // включаем реле
  }

В чём ошибка?

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Как вариант можно посмотреть сюда

// avtomat
const int ledPin =  LED_BUILTIN;
const long interval = 1000;
//
int state = LOW;
unsigned long past = 0;
void stand(int s) {
  past = millis();
  state = s;
  switch (state) {
    case LOW:
      digitalWrite(ledPin, LOW);
      break;
    case HIGH:
      digitalWrite(ledPin, HIGH);
      break;
  }
}
void run() {
  switch (state) {
    case LOW:
      if (millis() - past >= interval)stand(HIGH);
      break;
    case HIGH:
      if (millis() - past >= interval)stand(LOW);
      break;
  }
}
//-------------------
void setup() {
  pinMode(ledPin, OUTPUT);
  stand(LOW);
}
void loop() {
  run();
}

 

Дим-мычъ
Offline
Зарегистрирован: 20.03.2021
if      ((digitalRead(Light) == 1)   // проверяем: освещение вкл
          || (Timer <= 0) || (sensor.hum < 60) )            // проверяем таймер
  { Timer = 0;                       // обнуляем таймер 
    digitalWrite(Relay, 0);          // отключаем реле
  }
  
else if ((Timer > 0)                 // проверяем таймер
           or (sensor.hum > 60.0))   // проверяем датчик
  {  Timer --;                       // считаем таймер 
     digitalWrite(Relay, 1);         // включаем реле
  }

Может так?

A.K.
Offline
Зарегистрирован: 20.12.2021

Тогда не работает "короткая" часть кода, т.е. безусловное включение реле после света.

lilik
Offline
Зарегистрирован: 19.10.2017

A.K. пишет:

4. Возможность принудительного запуска/остановки вентиляции без дополнительных выключателей - приятная плюшка, пока не придумал как 

 
:-)
Без хлопков в ладоши, без ИК пульта, без голосовых команд "включись-отключись", без кнопок в приложении на смартфоне или ПК????.... тогда как !?!?
Дим-мычъ
Offline
Зарегистрирован: 20.03.2021

A.K. пишет:

Тогда не работает "короткая" часть кода, т.е. безусловное включение реле после света.

Пробуйте убрать else перед  if, возможно "свет" блокирует

A.K.
Offline
Зарегистрирован: 20.12.2021

lilik Например, по двойному переключению освещения в течение 5-7 сек, нет? Но пока строится основная часть.

A.K.
Offline
Зарегистрирован: 20.12.2021

Дим-мычъ, тогда работает только по влажности

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

A.K. пишет:

lilik Например, по двойному переключению освещения в течение 5-7 сек, нет?

Ну это уже Вам придется вызывать платного шамана на дом. Такую программу вы не только не напишите, но и не отладите.

A.K.
Offline
Зарегистрирован: 20.12.2021

qwone пишет:

 ... вызывать платного шамана ...

А научиться шаманить не возбраняется? ;)

lilik
Offline
Зарегистрирован: 19.10.2017

A.K. пишет:

lilik Например, по двойному переключению освещения в течение 5-7 сек, нет? Но пока строится основная часть.

Аааа..., ну это не принудительно, а по условию-стечения обстоятельств :-)

A.K.
Offline
Зарегистрирован: 20.12.2021

lilik, спасибо за уточнение! И правда, в этом случае - по условию.

A.K.
Offline
Зарегистрирован: 20.12.2021

Доброго здоровья!

Спасибо всем участникам обсуждения! Основная задача решена. Пока не реализована последняя задача, буду придумывать. Вместе с тем понимаю, что код далеко не идеален. 

Буду рад любым советам по улучшению кода.

 

#include <iarduino_DHT.h>                 // библиотека для работы с датчиком DHT
iarduino_DHT sensor(3);                   // переменная для работы с датчиком DHT, на (Х) pin
int Light(2);                             // переменная для датчика света на (X) pin
int Relay(12);                            // переменная для реле на (X) pin
int Timer = 0;                            // переменная таймера освещения
byte Flag = 0;                            // переменная вариантов откл. вентилятора

void lightOff()                           // функция, вызываемая освещением
{ if (sensor.hum <= 60.0)                 // проверяем влажность
  { Timer = 180;                            // Назначаем длительность короткого таймера
    Flag = 1;                             // назначаем вариант откл. вентилятора
  }
  else if (sensor.hum > 60.0)
  { Timer = 600;
    Flag = 2;
  }
}

void setup()
{ attachInterrupt(0, lightOff, FALLING);  // аппаратное прерывание по освещению;
  Serial.begin(9600);                     // открываем последовательный порт на скорости 9600 бод
  delay(1000);                            // выполняем задержку для перехода датчика в активное состояние
  pinMode(12, OUTPUT);                    // Set Pin12 as output
  digitalWrite(12, 0);                    // Set Pin12 Low
  pinMode(Light, INPUT);                  // declare pushbutton as input
}

void loop()
{ switch (sensor.read())                  // читаем показания датчика
                                          // далее выводим показания датчика
  { case DHT_OK:               Serial.println((String) "CEHCOР: " + sensor.hum + "%");                  break;
    case DHT_ERROR_CHECKSUM:   Serial.println(         "CEHCOP: HE PABEHCTBO KC");                      break;
    case DHT_ERROR_DATA:       Serial.println(         "CEHCOP: OTBET HE COOTBETCTB. CEHCOPAM 'DHT'");  break;
    case DHT_ERROR_NO_REPLY:   Serial.println(         "CEHCOP: HET OTBETA");                           break;
    default:                   Serial.println(         "CEHCOP: ERROR");                                break;
  }

switch (Flag)
  { case 1: if (Timer > 0)                               // проверяем таймер
                  { Timer --;                            // считаем таймер 
                    digitalWrite(Relay, 1);              // включаем реле                                 
                  }
            else digitalWrite(Relay, 0);                 // отключаем реле
      break;
    case 2: if ((Timer > 0) and (sensor.hum > 60.0))     // проверяем таймер и влажность
                  { Timer --;                            // считаем таймер 
                    digitalWrite(Relay, 1);              // включаем реле                                 
                  }                                                                   
            else  { digitalWrite(Relay, 0);              // отключаем реле
                    Timer = 0;                           // обнуляем таймер 
                  };  
       break;
    default: if (Timer <= 0)                              // проверяем таймер
                  { digitalWrite(Relay, 0);               // отключаем реле
                  }; 
       break;
  }
 sensor.read();                          // чтение показаний датчика
  delay(975);
  Serial.println(Timer);                  //выводим значение таймер влажн на экран
}

 

Дим-мычъ
Offline
Зарегистрирован: 20.03.2021

Как по мне, норм. для новичка.  Я тоже вроде как новичёк ещё, скоро год, как увлекаюсь ардуино.

Вот набросал тоже. Не скажу,что лучше, но без прерываний и, главное без делей.  Если что-то нужно будет







#include <iarduino_DHT.h>                 // подключаем библиотеку для работы с датчиком DHT
iarduino_DHT sensor(10);                  // объявляем  переменную для работы с датчиком DHT, указывая номер цифрового вывода к которому подключён датчик
int Light(3);                            // объявляем переменную для датчика света на (X) pin
int Relay(12);                            // объявляем переменную для реле на (X) pin
int Timer_n = 0;                            // объявляем переменную таймера,

unsigned long last_millis = 0;
bool Light_flg = false;
bool Light_flg_last = false;
bool Hum_flg = false;
bool Hum_flg_last = false;
bool Timer_flg = false;

bool ON = false;

void setup()
{
  
  Serial.begin(9600);                     // открываем последовательный порт на скорости 9600 бод
  delay(1000);                            // выполняем задержку для перехода датчика в активное состояние
  pinMode(12, OUTPUT);                    // Set Pin12 as output
  digitalWrite(12, 0);                    // Set Pin12 Low
  pinMode(Light, INPUT);                 // declare pushbutton as input
  digitalWrite(Light, LOW);               // без подтяжки
  Timer_n = 0;                              // устанавливаем таймер в 0
}




void read_IN() {
  if ((digitalRead(Light) == 1)) { //читаем датчики
    Light_flg = true;
  }
  else {
    Light_flg = false;
  }
  if (sensor.hum > 60.0) {
    Hum_flg = true;
  }
  else {
    Hum_flg = false;
  }
}

void control() {
  if (!Light_flg ) { //если свет погашен
    if (Light_flg != Light_flg_last) { //только что

      Timer_n = 40; //3000 10 минут включение по выключению света
      Timer_flg = true; //запуск таймера
      ON = true;    // без других условий
      // даже если влажность в норме
    
      if (Hum_flg) { //если влажность превысила
          Timer_n = 80;//9000 30 мин
          ON = false;
        Timer_flg = true; //запуск таймера
      }
    }
    if ((!Hum_flg) && (!ON)) { //если влажность норм и
      if(Timer_n > 40){//если не прошло 10 мин
      Timer_n = (40 - (80 - Timer_n));//добавить до 10 мин
      ON = true;
      }
      else{    
      Timer_n = 0; // не происходит вентиляция по выкл. света
      ON = false;
    }
    }
    if (Timer_n > 0) {
      digitalWrite(Relay, 1);
    }
    else {
      digitalWrite(Relay, 0);
    }
  }
}

void Timer() {
  if (Timer_flg) {
    Timer_n--;
    if (Timer_n <= 0) {
      Timer_n = 0;
      Timer_flg = false;
      ON = false;
    }
  }
  else {
    Timer_n = 0;
  }
}

void loop() {
  if (millis() - last_millis >= 200) {
    last_millis = millis();
    Serial.println(Timer_n);
    // читаем показания датчика
    switch (sensor.read())
    { case DHT_OK:               Serial.println((String) "CEHCOР: " + sensor.hum + "% - " + sensor.tem + "*C");     break;
      case DHT_ERROR_CHECKSUM:   Serial.println(         "CEHCOP: HE PABEHCTBO KC");                                break;
      case DHT_ERROR_DATA:       Serial.println(         "CEHCOP: OTBET HE COOTBETCTB. CEHCOPAM 'DHT'");            break;
      case DHT_ERROR_NO_REPLY:   Serial.println(         "CEHCOP: HET OTBETA");                                     break;
      default:                   Serial.println(         "CEHCOP: ERROR");                                          break;

       
    }

    Timer();
    read_IN();
    control();
    Light_flg_last = Light_flg;
    
  }
}

добавить, не будет блокировать.

Возможно, немного допилить придётся))

P.S. Но  всё равно, если я всё правильно понял, в Вашем алгоритме есть недостаток(может я не прав?)

Допустим , идёт большая и долгая стирка, и никто не включает/выключает свет.

Тогда вентилятор сам не включится.

Поэтому, я, всё же останусь при своём мнении (#1),  что лучше "дёшево и сердито"))

Если ванная исключается, то да, почему бы и нет, для любимой тёщи?

P.P.S. И ещё. В коде из #15 если выключаем свет при повышенной влажности, и ,допустим, через минуту влажность придёт в норму, реле выключит вытяжку. Т.е. вентилятор не отработает свои минимальные 10мин?

 

 

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Для санузла логичнее включать вентиляцию при включении освещения (кто в потёмках то «дела» делает?). И любой таймер, чтобы ещё минут 20-30 после выключения освещения вентиляция работала. Всё.

Rumata
Rumata аватар
Offline
Зарегистрирован: 29.03.2019

BOOM пишет:

Для санузла логичнее включать вентиляцию при включении освещения (кто в потёмках то «дела» делает?). И любой таймер, чтобы ещё минут 20-30 после выключения освещения вентиляция работала. Всё.

Функционал абсолютно любого бытового вытяжного вентилятора...

A.K.
Offline
Зарегистрирован: 20.12.2021

Уважаемый Дим-мычъ!

Попробовал залить Вашу версию прошивки и огорчился - не работает. Т.е., алгоритм из ТЗ не выполняется, а что и как выполняется, разобраться не получилось, увы! Иногда реле включается вне границ влажности и  без связи с освещением. :(

Кстати, чем Вас смущает deley? Его можно и вовсе исключить: 1. экспериментально оценить длительность работы программы и задать соотв. значения таймеров, или 2. ввести millis с нужным "обвесом".  Если Вы заметили, в последней версии кода millis исключены, т.к. были взяты из чужого кода.
Понятно, что в первом случае не будет точного времени, но он с такой точностью для такой задачи, ИМХО, и требуется.

Но и в моём коде (#15) есть недоработка. между 57 и 58 строками нужно добавить

if ((digitalRead(Light) == 1)or (Timer <= 0)) // проверяем освещ и таймер
                  { digitalWrite(Relay, 0);   // отключаем реле
                  }

После этого добавления первые 3 пункта ТЗ отрабатываются корректно.

Ещё на Хабре есть хорошая статья на эту тему, но там уж совсем красиво, по богатому и с яндексовой Алисой:  https://habr.com/ru/post/597023/

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

BOOM пишет:

Для санузла логичнее включать вентиляцию при включении освещения (кто в потёмках то «дела» делает?). И любой таймер, чтобы ещё минут 20-30 после выключения освещения вентиляция работала. Всё.

Может у ТС вентилятор шумный. Думать мешает.

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

A.K. пишет:

Попробовал залить Вашу версию прошивки и огорчился - не работает. Т.е., алгоритм из ТЗ не выполняется,

А у вас ТЗ логически не полное.

Цитата:

2. Включение вентиляции по отключению света в ванной на 10 мин
3. Включение вентиляции по отключению света при влажности > 70%, до её снижения ниже порога, но не более 30 мин.

- Вот если при выключении света влажность была > 70% но снизилась ниже порога меньше чем за 10 минут, то надо следовать п.3 или п.2?

- Чему равен порог?

- Почему в ТЗ упоминается 70% влажности, а в коде этого нет?

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

asam пишет:

BOOM пишет:

Для санузла логичнее включать вентиляцию при включении освещения (кто в потёмках то «дела» делает?). И любой таймер, чтобы ещё минут 20-30 после выключения освещения вентиляция работала. Всё.

Может у ТС вентилятор шумный. Думать мешает.

Ну значит запускать таймер после «думных дел» )))

Дим-мычъ
Offline
Зарегистрирован: 20.03.2021

A.K. пишет:

Попробовал залить Вашу версию прошивки и огорчился - не работает.

В Протеусе работает. Возможно уже переназначили пины. Если что, Pro Mini 8MHz.

Ну а про делей- ясно дело, зацикливает работу процессора. Говорили ведь, что ещё планируете опции добавлять...

 

P.S. Ещё, как только выложил, в течении часа исправил ошибку. Не сказал, потому что не было ответа, думал Вас нет на форуме

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

A.K. пишет:

Иногда реле включается вне границ влажности и  без связи с освещением. :(

 

Подобные вещи удобно делать с использованием State Machine. Вот, набросал, правда не отлаживал.

#include <iarduino_DHT.h>

#define REL_PIN 12
#define LIGHT_PIN 2
#define REL_OFF (digitalWrite(REL_PIN, 0))
#define REL_ON  (digitalWrite(REL_PIN, 1))
#define TIME_ON   600000  //10 min
#define TIME_HUM 1800000  //30 min
#define HUM_ON  60.0

iarduino_DHT sensor(3);
enum states {V_off, V_time, V_hum};
states State = V_off;
float Hum = 0;
long StartTime;

void lightOff()
{
  StartTime = millis();
  REL_OFF;
  State = V_time;
}

void setup() {
  attachInterrupt(0, lightOff, FALLING);  // аппаратное прерывание по освещению;
  Serial.begin(9600);                     // открываем последовательный порт на скорости 9600 бод
  pinMode(REL_PIN, OUTPUT);               // Set Relay as output
  REL_OFF;
  pinMode(LIGHT_PIN, INPUT);              // declare light sensor pin as input

}

void loop() {
  delay(1000);
  long Time = millis();
  { switch (sensor.read())                  // читаем показания датчика
      // далее выводим показания датчика
    { case DHT_OK:               Serial.println((String) "CEHCOР: " + sensor.hum + "%"); Hum = sensor.hum; break;
      case DHT_ERROR_CHECKSUM:   Serial.println("CEHCOP: HE PABEHCTBO KC");                      break;
      case DHT_ERROR_DATA:       Serial.println("CEHCOP: OTBET HE COOTBETCTB. CEHCOPAM 'DHT'");  break;
      case DHT_ERROR_NO_REPLY:   Serial.println("CEHCOP: HET OTBETA");                           break;
      default:                   Serial.println("CEHCOP: ERROR");                                break;
    }
  }
  switch (State)
  {
    case V_off:
      REL_OFF;
      break;
    case V_time:
      if ((Time - StartTime) > TIME_ON) State = V_hum;
      break;
    case V_hum:
      if ((Time - StartTime) > TIME_HUM) State = V_off;
      if (Hum < HUM_ON) State = V_off;
  }
  Serial.print((String) "State = " + State + "  ");
  if (State != V_off) Serial.print((String) "TimeOn = " + (Time - StartTime) / 1000 + "sec");
  Serial.println();
}

При подобном подходе прикрутить включение/выключение по двойному миганию света - пара пустяков.

nik182
Offline
Зарегистрирован: 04.05.2015

У друга ещё в 80-х на двух концевиках и реле с задержкой было сделано и нормально работало. 

Дим-мычъ
Offline
Зарегистрирован: 20.03.2021

A.K. пишет:

После этого добавления первые 3 пункта ТЗ отрабатываются корректно.

Если выключили свет(при повышенной влажности), и через минуту, влажность придёт в норму - вентилятор проработает минуту.

Надо корректировать таймер

В моём случае макс. время 80 у.е.)) мин. - 40. Т.е если прошло 3у.е. из 80 надо добавить 37 до 40

 ну или просто добавить 40 а не просто обнулить

                

Morroc
Offline
Зарегистрирован: 24.10.2016

nik182 пишет:

У друга ещё в 80-х на двух концевиках и реле с задержкой было сделано и нормально работало. 


Это потому что у друга в 80х ардуины не было )

nik182
Offline
Зарегистрирован: 04.05.2015

Morroc пишет:
nik182 пишет:

У друга ещё в 80-х на двух концевиках и реле с задержкой было сделано и нормально работало. 

Это потому что у друга в 80х ардуины не было )

Это да. Не было. Зато были прямые руки не из жопы и голова светлая. Без форумов и советов обошёлся. 

A.K.
Offline
Зарегистрирован: 20.12.2021

nik182 пишет:

У друга ещё в 80-х на двух концевиках и реле с задержкой было сделано и нормально работало. 

Я дико извиняюсь, а контроль влажности - был? Ни в коей мере не умаляю пряморукости, а равно и мыслительных способностей Вашего друга. Для 80-х такое решение было, да что там решение! - сама мысль была весьма достойной! Но наши-то с Вами возможности, кажется, отличаются от 80-х? Так что, если можете, передайте Вашему другу моё восхищение! Он опередил нас с Вами в формулировке проблемы.

A.K.
Offline
Зарегистрирован: 20.12.2021

Дим-мычъ пишет:

[Если выключили свет(при повышенной влажности), и через минуту, влажность придёт в норму - вентилятор проработает минуту.

 А что Вас смущает? В формулировке ТЗ я отталкивался от следующих соображений.
Когда человек принимает ванну или моется в душе поток воздуха, пусть даже небольшой, способен снизить температуру поверхности тела (люди - теплокровны), значит "сквозняка" быть не должно.
После дефекации запах должен быть ослаблен/удалён, а вводить датчик органики, как у профессионалов с Хабра, я сейчас не готов.
Настроить время работы вытяжки проще, чем менять алгоритм. Случай с затяжной влажностью можно быстро допилить звуковой тревогой.
Кажется, для первого "самостоятельного" проекта достаточно. Dixi.

P.S. Тестировал ранее предложенный Вами код на железе: Arduino Nano + датчики и реле из китайского набора Keystudio.

Дим-мычъ
Offline
Зарегистрирован: 20.03.2021

A.K. пишет:

 А что Вас смущает?

Уважаемый А.К.! Наоборот, я рад, что у Вас получилось! И, спасибо за то , что дали пример для тренировки))

nik182
Offline
Зарегистрирован: 04.05.2015

A.K. пишет:

nik182 пишет:

У друга ещё в 80-х на двух концевиках и реле с задержкой было сделано и нормально работало. 

Я дико извиняюсь, а контроль влажности - был? Ни в коей мере не умаляю пряморукости, а равно и мыслительных способностей Вашего друга. Для 80-х такое решение было, да что там решение! - сама мысль была весьма достойной! Но наши-то с Вами возможности, кажется, отличаются от 80-х? Так что, если можете, передайте Вашему другу моё восхищение! Он опередил нас с Вами в формулировке проблемы.

Я не понимаю необходимости контроля влажности в туалете. В ванной да, когда моешься влажность подпрыгивает. В туалете не видел ни разу подъёма влажности. Вытяжка постоянно подсасывает воздух из квартиры, который у меня выше 35% влажности не бывает с постоянно включенным увлажнителем. В туалете нет источника влажности что бы перебороть влажность комнат, соотношение объёмов туалета и комнат таково, что даже при открытии - закрытии двери воздух внутри становится такой же как в комнате.  

Дим-мычъ
Offline
Зарегистрирован: 20.03.2021

A.K. пишет:

 Тестировал ранее предложенный Вами код на железе: Arduino Nano + датчики и реле из китайского набора Keystudio.

P.S. Наконец дошло, почему мой код не работал)) То что для меня само-собой разумеется, кому-то может быть не понятно.  Так что извините, что не разъяснил.

Для меня как 2х2то, что если кнопка активна лог1, то "подтягиваем" пин к земле. А если лог0, то к +питания.

Это видно из логики кода, но новичку может и не видно. Я должен был сказать. У меня кнопка , активна при лог1. "Подтянута к земле" резистором 12,1кОм.(можно 5-15кОм) Со стороны питания ограничительный резистор(необязательно) 382 Ом.

Если этого не сделать, то на пине будут наводки, и работа схемы будет непредсказуемой.

 

A.K.
Offline
Зарегистрирован: 20.12.2021

Уважаемый nik812!

В "географии" санузла есть тонкость, которую я не упомянул и которая, должно быть, критически влияет на ТЗ. Санузел организован "трамвайчиком", т.е. вход в туалет - через ванную. Соответственно, свет при входе в туалет включается сразу и в ванной. Разумеется, влажность контролируется только в ванной. Поток вентиляции настраивается "диафрагмами" вентиляционной системы и затейливым учётом локальных условий, касающихся притока-оттока воздуха. Опять же, загляните на Хабр, в статью из #19, там красиво и 100% правильно. Я затачивал ТЗ под свои хотелки, ну или тёщины потребности (иногда бываю убедителен). Я - великий маркетолог!(шутка, никакого отношения, чур меня!) 

A.K.
Offline
Зарегистрирован: 20.12.2021

Дим-мычъ пишет:

... мой код не работал)) То что для меня само-собой разумеется, кому-то может быть не понятно. 

Уважаемый Дим-мычъ !

Спасибо Вам за диалог! я пока слаб в программной части, но, благодаря Вашим советам, надеюсь научиться.

nik182
Offline
Зарегистрирован: 04.05.2015

Посмотрел статью. Как всё слишком обще описано. Подобная система у меня уже несколько лет работает, завязанная на blynk. По крайней мере blynk выдаёт данные всех датчиков за последние 2 года. Прикольнее всего следить за СО2. Возможно это особенность моей квартиры, но влажность прыгает в ванной и коридоре около только если кто-нибудь принимает душ. В остальное время быстро приходит в норму. Была тоже идея включать вытяжку по влажности, но парадигма включение вентилятора руками в нужные моменты победила после полугода автоматического управления светом в туалете. Оказалось что всем удобнее самим включать - выключать. Уж не знаю почему, но отношение к автоматике с задержками отключения через какое то время от состояния прикольно перешла а состояние  - нервирует. Сейчас остались только датчики и панели с индикацией.    

Green
Offline
Зарегистрирован: 01.10.2015

Подтверждаю. У меня на входе всего лишь выключатель с задержкой отключения. Мы как то сразу привыкли, а вот посторонние и даже родственники... Постоянно норовят пощёлкать выключателем, сколько им не говори.)

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Green пишет:
...выключатель с задержкой отключения.

Если реакция устройства на внешнее воздействие происходит с ощутимой задершкой, это, абычна, провоцирует у людей, лишонных яиц, панику и ступор, они почему-то сразу думают, что сделали что-то не так и пытаются сделать это снова и "так".   Задершка - зло (по крайней мере, в моем доме).  Я пытался, канеш, выдрессировать глупых самок, но швабра по коленям - очень ощутимый аргумент против, я отступился.  

v258
v258 аватар
Offline
Зарегистрирован: 25.05.2020

Дык свет и не нужно с задержкой отключать. Задержка нужна только вентилятору ))

SLKH
Offline
Зарегистрирован: 17.08.2015

Дим-мычъ пишет:

P.S. Наконец дошло, почему мой код не работал)) То что для меня само-собой разумеется, кому-то может быть не понятно.  Так что извините, что не разъяснил.

Для меня как 2х2то, что если кнопка активна лог1, то "подтягиваем" пин к земле. А если лог0, то к +питания.

Это видно из логики кода, но новичку может и не видно. Я должен был сказать. У меня кнопка , активна при лог1. "Подтянута к земле" резистором 12,1кОм.(можно 5-15кОм) Со стороны питания ограничительный резистор(необязательно) 382 Ом.будет непредсказуемой.

Мне вот непонятно. Чем не устраивает INPUT_PULLUP без обвешивания доп. резисторами?

Дим-мычъ
Offline
Зарегистрирован: 20.03.2021

SLKH пишет:

Мне вот непонятно. Чем не устраивает INPUT_PULLUP без обвешивания доп. резисторами?

  input_pullup всем устраивает, но не всегда ведь нужен активный низкий уровень?

 Да и "подтяжка" иногда нужна побольше (напр.1-wire 5кОм нужно)

А в этом случае - просто привычка. Мне проще раз поставить резистор, и знать, что есть напряжение-лог1

нет-лог0 (упрощённо конечно), чем всё время "переворачивать" кнопку в голове))

 

Green
Offline
Зарегистрирован: 01.10.2015

Дим-мычъ пишет:
...чем всё время "переворачивать" кнопку в голове))

Ужос.( Есть же куча способов что бы отделить физику от логики и не страдать фигнёй. Простейший вариант:

#define get_key()  !digitalRead(KEY)      //физика
#define led_on()   digitalWrite(LED, LOW)

  if (get_key()) //логика
    led_on();

Для того что бы поменять активный уровень KEY и/или LED правится только в одном месте, а вся логика остаётся ВООБЩЕ без изменений. И в голове ничего переворачивать не надо. Описал физику и всё. Напрочь о ней забыл!

Дим-мычъ
Offline
Зарегистрирован: 20.03.2021

Green пишет:

 Описал физику и всё. Напрочь о ней забыл!

Спасибо, буду теперь знать!

Green
Offline
Зарегистрирован: 01.10.2015

А если любите Ардуино, можно описать активность каждого.

#define KEY_ACTIVE LOW
#define LED_ACTIVE LOW

if (digitalRead(KEY) == KEY_ACTIVE)
  digitalWrite(LED, LED_ACTIVE);
else
  digitalWrite(LED, !LED_ACTIVE);

 

Дим-мычъ
Offline
Зарегистрирован: 20.03.2021

Green пишет:

А если любите Ардуино, можно описать активность каждого.

#define KEY_ACTIVE LOW
#define LED_ACTIVE LOW

if (digitalRead(KEY) == KEY_ACTIVE)
  digitalWrite(LED, LED_ACTIVE);
else
  digitalWrite(LED, !LED_ACTIVE);

 

Спасибо за примеры, буду пробовать применять.

А к Ардуино да, не равнодушен, есть такое...