9 — Умный дом на Ардуино. Глава IV — Освещение. Часть 1 — Ванная. Ночная подсветка

Автоматическую ночную подсветку в ванной будем делать с использованием датчика движения и датчика света(фоторезистора). В качестве светящегося элемента будем использовать светодиодную ленту 12v

Профиль со светодиодной лентой
IMG_8144.JPG в боксе
IMG_8147.JPG (временный монтаж)
IMG_8155.JPG

Алгоритм управления довольно простой. Если темно и сработал датчик движения — включаем подсветку на некоторое время.
Также необходимо предусмотреть случай, когда выходишь из ванной и выключаешь основной свет. В этот момент подсветка включится, т.к. датчик движения будет активным. Для исключения этих ложных срабатываний необходимо добавить задержку включения ночной подсветки после выключения основного света.

Итак Алгоритм:

  1. Ждем состояния, когда основной свет выключен
  2. Ждем задержку после выключения основного света
  3. Ждем срабатывания датчика движения
  4. Включаем ночную подсветку
  5. Ждем некоторое время
  6. Выключаем ночную подсветку

В нашей схеме умного дома добавились датчик движения, , полевой транзистор — для плавного управления светодиодной лентой, и резистор номиналом 4.7кОм.

controller 2_light_night_bath.png light_bath.png

Кусок скетча с алгоритмом автоматической ночной подсветки в ванной(полный скетч по ссылке в конце статьи)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
void set_light_night_bath()//управление ночной подсветкой в ванной
{
 if ((param_light_night_bath[0] & 1)==1)//если автоматический режим
  { 
    if (!f_light_bath)//если выключен свет
     {  
 
          if((digital_value & 1)==1)//если сработал датчик движения
           {
              if (my_timer(6000,5,0,0))//задержка после выключения света
              {
                if ((param_light_night_bath[0]&2)==0)
                {
                 //плавно включаем подсветку
                  noInterrupts();//отключаем прерывание
                  int br=0;
                  while (br<255)
                  {
                    analogWrite(pin_light_night_bath,br);                  
                    delay(10);
                    br++;
                  }
                  interrupts();//включаем прерывание
                } 
                  digitalWrite(pin_light_night_bath,HIGH);  
                  my_timer(0,4,1,1);//обнуляем таймер выключения
                  param_light_night_bath[0]=((param_light_night_bath[0]>>2)<<2) xor 3;//записываем состояние подсветки "вкл"
              }
           } else {
             //ожидаем задержку выключения
              if (my_timer(param_light_night_bath[1]*1000l*60l,4,0,1)==true)//задержка выключения
              {
                 //выключаем подсветку
                 digitalWrite(pin_light_night_bath,LOW);
                 param_light_night_bath[0]=((param_light_night_bath[0]>>2)<<2) xor 1;//записываем состояние подсветки "выкл" 
              }
           }
         
     } else 
       {
          digitalWrite(pin_light_night_bath,LOW);
          param_light_night_bath[0]=((param_light_night_bath[0]>>2)<<2) xor 1;//записываем состояние подсветки "выкл" 
       }
 
 
  }else digitalWrite(pin_light_night_bath, (param_light_night_bath[0] & 2)>0);//если ручной режим, то устанавливаем выставленное вручную значение вкл/выкл
}
void set_light_night_bath()//управление ночной подсветкой в ванной
{
 if ((param_light_night_bath[0] & 1)==1)//если автоматический режим
  { 
    if (!f_light_bath)//если выключен свет
     {  

          if((digital_value & 1)==1)//если сработал датчик движения
           {
              if (my_timer(6000,5,0,0))//задержка после выключения света
              {
                if ((param_light_night_bath[0]&2)==0)
                {
                 //плавно включаем подсветку
                  noInterrupts();//отключаем прерывание
                  int br=0;
                  while (br<255)
                  {
                    analogWrite(pin_light_night_bath,br);                  
                    delay(10);
                    br++;
                  }
                  interrupts();//включаем прерывание
                } 
                  digitalWrite(pin_light_night_bath,HIGH);  
                  my_timer(0,4,1,1);//обнуляем таймер выключения
                  param_light_night_bath[0]=((param_light_night_bath[0]>>2)<<2) xor 3;//записываем состояние подсветки "вкл"
              }
           } else {
             //ожидаем задержку выключения
              if (my_timer(param_light_night_bath[1]*1000l*60l,4,0,1)==true)//задержка выключения
              {
                 //выключаем подсветку
                 digitalWrite(pin_light_night_bath,LOW);
                 param_light_night_bath[0]=((param_light_night_bath[0]>>2)<<2) xor 1;//записываем состояние подсветки "выкл" 
              }
           }
         
     } else 
       {
          digitalWrite(pin_light_night_bath,LOW);
          param_light_night_bath[0]=((param_light_night_bath[0]>>2)<<2) xor 1;//записываем состояние подсветки "выкл" 
       }


  }else digitalWrite(pin_light_night_bath, (param_light_night_bath[0] & 2)>0);//если ручной режим, то устанавливаем выставленное вручную значение вкл/выкл
}

Скетч измененного таймера с функцией принудительного обнуления

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
unsigned long millis_old[6]={0,0,0,0,0,0};//массив для хранения последних данных о времени срабатывания таймера.Количество элементов соответствует количеству таймеров
boolean my_timer(unsigned long time, byte nomer, boolean clear_t, boolean auto_clear)//функция таймер, time-время задержки, nomer-номер таймера, clear_t обнуление
{
  if (clear_t==1) //если необходимо обнулить
    millis_old[nomer]=0;//обнуляем таймер
  else {
      unsigned long current_millis;//текущее значение миллисекунды
      current_millis=millis();
      if (millis_old[nomer]==0) millis_old[nomer]=current_millis;//если таймер обнулен, то записываем текущее время
      if (current_millis-millis_old[nomer]>time) //если время срабатывания таймера наступило
      {
        if (auto_clear==1) millis_old[nomer]=0;//перезаписываем время последнего срабатывания таймера
        return true;//возвращаем true
      } else if (current_millis<millis_old[nomer])//произошло переполнение таймера
      {
        for (int i=1; i <= 5; i++) millis_old[i]=0; //обнуляем массив всех таймеров
      } else return false;//возвращаем false
  }
}
unsigned long millis_old[6]={0,0,0,0,0,0};//массив для хранения последних данных о времени срабатывания таймера.Количество элементов соответствует количеству таймеров
boolean my_timer(unsigned long time, byte nomer, boolean clear_t, boolean auto_clear)//функция таймер, time-время задержки, nomer-номер таймера, clear_t обнуление
{
  if (clear_t==1) //если необходимо обнулить
    millis_old[nomer]=0;//обнуляем таймер
  else {
      unsigned long current_millis;//текущее значение миллисекунды
      current_millis=millis();
      if (millis_old[nomer]==0) millis_old[nomer]=current_millis;//если таймер обнулен, то записываем текущее время
      if (current_millis-millis_old[nomer]>time) //если время срабатывания таймера наступило
      {
        if (auto_clear==1) millis_old[nomer]=0;//перезаписываем время последнего срабатывания таймера
        return true;//возвращаем true
      } else if (current_millis<millis_old[nomer])//произошло переполнение таймера
      {
        for (int i=1; i <= 5; i++) millis_old[i]=0; //обнуляем массив всех таймеров
      } else return false;//возвращаем false
  }
}

Также необходимо внести изменения в скетч на местер-контроллере и WEB-интерфейсе. Демо-веб интерфейса

Все файлы проекта

Добавить комментарий