четверг, 9 июля 2015 г.

Управление освещением для кухни с датчиком движения на Arduino(часть 3)

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




Алгоритма программы:


      Maxbrightness = 180 - максимальная яркость свечения светильников. При значении 255 (макс. сигнал на выходе Arduino) канал мосфета полностью открыт, и 18.5В поступает на светильник. Ток светильников при этом  больше полуампера. Значение 180 выбрано такое, при котором ток через светильники примерно 300мА. При помощи переключателя можно переключать яркость освещения: 180, 120 и 40.

Скетч для Arduino:


 /*********************************************************************************************************
 *                       Программа для управления освещением с датчиком движения.                         *
 *********************************************************************************************************/
 
 /*****           Назначение выводов Arduino              *****/

        int OutLight = 6;    // Силовой блок управления лампами(мосфет) подключен к цифровому выводу 6
      int switchTIME = 1;  // Переключатель времени свечения подключен к аналоговом выводу 1 (А1)
      int INlighting =3;   // Фоторезистор подключен к аналоговом выводу 3 (А3)
      int inPIR = 4;       // Выход датчика движения подключен к к цифровому выводу 4

 /*****           Описание переменных              *****/
      int Maxbrightness = 180; // переменная максимальной яркости свечения (Max 255). 
        int Minbrightness = 0; // переменная минимальной яркости свечения (min 0).
      int LimitLight = 1; // Предел чувствительности 55-900, 0 выкл.
      int inmotion = 0; //переменная для хранения состояния датчика PIR
      int TimeWait = 120; // переменная для хранения времени свечения (120 - 1мин, 360 - 3 мин 0 -выкл)
      int LightTIME = 0; // переменная для хранения времени свечения
        int LedOUT = HIGH; // состояние светильников HIGH - включно, LOW выключено
        int CurrentBright = 0; // Текущая яркость свечения (0 - выкл.)
        int tmp = 0; //Временная переменная
void setup() {

  Serial.begin(115200); // Для настройки - скорость порта для вывода на ПК промежуточных значений
pinMode (inPIR, INPUT); // Датчик движения подключен ко входу Arduino
pinMode(OutLight, OUTPUT);// инициализируем наш пин как выход

}
void LightON (int time) // Функция плавного включения
{
for  (int i=Minbrightness; i<=Maxbrightness; i++)
{
  analogWrite (OutLight, i);
  CurrentBright = i;
  delay (time);
}
}

void LightOFF (int time) // Функция плавного выключения time - время выключения
{
for  (int i=Maxbrightness; i>-1; i--)
{
  analogWrite (OutLight, i);
    CurrentBright = i;
  delay (time);
}
}

/*
void inTimeWait (int tw) // Функция опроса выкл. времени свечения 
{
  if (tw > 800)
 TimeWait = 150;
 else
 TimeWait = 50;
 if (tw == 0) TimeWait = 0;
 }
 }
*/

void brightness (int tw) // Функция опроса выкл. времени свечения 
{
  if (tw > 800)
 Maxbrightness = 40;
 else
 Maxbrightness = 180;
 if (tw == 0) Maxbrightness = 120;
 }
 
void LimLight (int LL) // 0 - откл. 1 вкл. 2 много света
{
//  Serial.println(LL);
  if (LL > 180) LimitLight = 2;
  if (LL <= 160) LimitLight = 1;
  if (LL ==0) LimitLight =0;  
 
}

void correctbrightness (int CB) // Функция корректировки яркости свечения 
{
while (CurrentBright != Maxbrightness)
{
if (CurrentBright > Maxbrightness) CurrentBright--;
if (CurrentBright < Maxbrightness) CurrentBright++;
//Serial.println(CurrentBright);
  analogWrite (OutLight, CurrentBright);
  delay (20);
 }
}
void loop() {
/***** Опрос датчиков ****/
   inmotion = digitalRead(inPIR);
//   inTimeWait(analogRead (switchTIME)); // Получение TimeWait (Время свечения после сигнала PIR)
   brightness(analogRead (switchTIME)); // Получение Maxbrightness (Яркость свечения с выключателя)
   LimLight(analogRead (INlighting)); // Получение LimitLight (датчик освещенности)

if (inmotion == HIGH) {  LightTIME = TimeWait; } // Если есть сигнал с PIR-датчика - обнулить время свечения.
if (LightTIME > 0 && LimitLight < 2) LedOUT = HIGH; else LedOUT = LOW; 

if (CurrentBright == 0 && LedOUT == HIGH) { Minbrightness = 0; LightON(50); }// Если не горит, а должен - тогда включить 
if (CurrentBright == Maxbrightness && LedOUT == LOW) LightOFF(15); // Если горит, а не должен - тогда выключить
if (CurrentBright != Maxbrightness && CurrentBright != 0) correctbrightness(CurrentBright); // При переключении яркости откорректировать свечение

LightTIME --; // Уменьнить время свечения на 1

//Serial.println(LightTIME);
//Serial.println(CurrentBright);
//Serial.println( LimitLight);
//Serial.println(Maxbrightness);
delay (500); // Задержка 0,5 сек
}
Скачать скетч можно здесь.

12 комментариев:

  1. Подскажите в какой строке устанавливается чувствительность фоторезистора. Пробовал в этой int LimitLight = 1; // Предел чувствительности 55-900, 0 выкл.
    результата никакого

    ОтветитьУдалить
    Ответы
    1. Чувствительность задается переменной LL здесь:
      void LimLight (int LL) // 0 - откл. 1 вкл. 2 много света
      {
      if (LL > 180) LimitLight = 2; // Если LL>180 - свет не включать - день
      if (LL <= 160) LimitLight = 1;// Если LL<160 - Свет включать по движению - ночь
      if (LL ==0) LimitLight =0; // Если LL=0 датчик освещения отключен (не опрашивается)
      }

      Удалить
  2. Подскажите еще пожалуйста, где в коде выставить длительность свечения после обнаружения PIR датчиком. Нужно 30сек

    ОтветитьУдалить
    Ответы
    1. Время свечения задается в полусекундах строкой:
      int TimeWait = 120;
      Т.е. чтоб установить время свечения после срабатывания PIR датчика равное 30сек, нужно переменной задать значение 60.

      Удалить
  3. Добрый день Вячеслав.
    Как добавить функцию,чтобы при включенной подсветке не опрашивался фоторезистор? А то как то неудобно выносить фоторезистор куда то, чтобы на него не попадал свет от ламп.

    ОтветитьУдалить
  4. После строки
    LimLight(analogRead (INlighting)); // Получение LimitLight (датчик освещенности)
    Добавьте
    if (LedOUT == HIGH) LimitLight = 0; // Если свет включен - считать что датчик освещения отключен

    ОтветитьУдалить
  5. Еще раз огромное Вам спасибо за помощь. Отличный проект.

    ОтветитьУдалить
  6. Вячеслав, а за что отвечают эти закомментированные строки?
    /*

    void inTimeWait (int tw) // Функция опроса выкл. времени свечения
    {
    if (tw > 800)
    TimeWait = 150;
    else
    TimeWait = 50;
    if (tw == 0) TimeWait = 0;
    }
    }
    */

    и вот эта часть разкомментированных

    void brightness (int tw) // Функция опроса выкл. времени свечения
    {
    if (tw > 800)
    Maxbrightness = 40;
    else
    Maxbrightness = 180;
    if (tw == 0) Maxbrightness = 120;
    }

    ОтветитьУдалить
    Ответы
    1. В схеме стоит клавишный переключатель SW1 на 2 положения с отключением (вот такой: http://voron.ua/files/pic/knopki/kod/KCD1-103-2.jpeg). При помощи этого переключателя устанавливается определенное напряжение на аналоговом входе А1. Данные функции опрашивают вход А1 и в зависимости от уровня сигнала на нем выполняют действия.
      Функция inTimeWait задавала время свечения после поступления сигнала с датчика движения, но на практике это оказалось непрактично и я ее убрал, а вместо нее используется функция brightness.
      Фунция brightness задает ЯРКОСТЬ свечения, в зависимости от положения переключателя. Т.е. я в любой момент могу нажать на переключать и изменить яркость освещения.

      Удалить
  7. Дорогой друг а если человек не будет шевелится то датчик выключит свет так получается ?

    ОтветитьУдалить
    Ответы
    1. Да, если человек не будет двигаться более 1-3 минут, свет выключится

      Удалить