Делаю подсветку в коридор

viktor001
Offline
Зарегистрирован: 31.12.2016
 
Здравствуйте! Хочу сделать подсветку в коридор. Выключатели расположены крайне неудобно и постоянно приходится идти на ощупь :( Нашёл в интернете код который при срабатывании датчика движения сравнивает состояние входа АЦП от фоторезистора и если всё ОК то включает реле на заданное время к примеру 5 сек. По истечению этого времени проверяется состояние входа от PIR датчика и если есть движение то - повтор заданного времени работы. В принципе всё отлично, но как то скучно. Моих познаний хватило лишь на добавление нескольких каналов на выход, последовательное их включение/выключение и начальная яркость пока выбрана -100 (потом подберу более оптимальну).
Помогите пожалуйста добавить ещё один функционал.
В основном мы просто пересекаем коридор и редко когда нужен полный накал свечения ламп/лед лент, поэтому было бы не плохо что бы ленты загорались к примеру в пол накала, а если задержались то после повторной проверки присутствия разгорались бы так же последовательно уже на полную мощность.
int const Pot = A5; //Потенцинометр 10к:
int const Light = A7; //Датчик света:
int const Led1 = 4;
int const Led2 = 5;
int const Led3 = 9;
int const Led4 = 10;
int const Pirsens = 3; // Цифровой датчик движения:

int const pause = 5000; // время работы 5 сек.
long unsigned int lowIn;
boolean lockLow = true;
boolean takeLowTime;

void setup() {
// Определяем входы и выходы:
pinMode(Pirsens, INPUT);
pinMode(Led1, OUTPUT);
pinMode(Led2, OUTPUT);
pinMode(Led3, OUTPUT);
pinMode(Led4, OUTPUT);
// определяем состояние:
digitalWrite(Led1, HIGH);
digitalWrite(Led2, HIGH);
digitalWrite(Led3, HIGH);
digitalWrite(Led4, HIGH);

}

void loop() {

int pirsensVal = digitalRead(Pirsens);
int lightVal = analogRead(Light);
int potVal = analogRead(Pot);
int lightLimit = map(potVal, 0, 1023, 200, 500);

if (pirsensVal == HIGH && lightVal < lightLimit) {
if (lockLow) {
lockLow = false;
analogWrite(Led1, 100);
delay(100);
analogWrite(Led2, 100);
delay(100);
analogWrite(Led3, 100);
delay(100);
analogWrite(Led4, 100);
delay(100);
}
takeLowTime = true;

} else {
if (takeLowTime) {
lowIn = millis();
takeLowTime = false;
}

if (!lockLow && millis() - lowIn > pause) {
lockLow = true;
digitalWrite(Led1, HIGH);
delay (100);
digitalWrite(Led2, HIGH);
delay (100);
digitalWrite(Led3, HIGH);
delay (100);
digitalWrite(Led4, HIGH);

}
}
}

 

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

Код написал но не проверял

/*viktor001.ino
#1
датчик движения ->3 (Pirsens_pin) 1 есть движение / нет

Датчик света -> A7 (Light_pin)  опред дня/ночи
потенциометр -> A5 (Pot_pin) задает с какого уровня нужна подсветка
#2
светодиод 1 -> 4 (Led1_pin) 1 погашено/ аналог горит по уровню
светодиод 2 -> 5 (Led1_pin)
светодиод 3 -> 6 (Led1_pin)
светодиод 4 -> 7 (Led1_pin)

*/

//#1
const int Pirsens_pin = 3; // Цифровой датчик движения:
int Pirsens;
const int Light_pin = A7; //Датчик света:
const int Pot_pin = A5; //Потенцинометр 10к:
//#2
const int Led1_pin = 4; // управление яркостью с помощью ШИМ
int Led1;// 0 - горит / 1 горит в полнакала / 2 горит полностью
const int Led1_time = 0; // время задержи зажигания
//#3
const int Led2_pin = 5;
int Led2;// 0 - горит / 1 горит в полнакала / 2 горит полностью
const int Led2_time = 0; // время задержи зажигания
//#4
const int Led3_pin = 9;
int Led3;// 0 - горит / 1 горит в полнакала / 2 горит полностью
const int Led3_time = 0; // время задержи зажигания
//#5
const int Led4_pin = 10;
int Led4;// 0 - горит / 1 горит в полнакала / 2 горит полностью
const int Led4_time = 300; // время задержи зажигания

void Out_Led(int Led_pin, int Led) { // фунция зажеч с нужным уровнем
  const int light0 = 0; // уровень не горит
  const int light50 = 100; // уровень  горит 50%
  const int light100 = 255; // уровень горит 100%
  switch (Led) {
    case 0:
      analogWrite(Led1_pin, light0);
      break;
    case 2:
      analogWrite(Led1_pin, light50);
      break;
    default:
      analogWrite(Led1_pin, light100);
  }
}
void setup() {
  //#1
  pinMode(Pirsens_pin, INPUT);
  //#2
  pinMode(Led1_pin, OUTPUT);
  Out_Led(Led1_pin, Led1 = 0);
  //#3
  pinMode(Led2_pin, OUTPUT);
  Out_Led(Led2_pin, Led2 = 0);
  //#4
  pinMode(Led3_pin, OUTPUT);
  Out_Led(Led3_pin, Led3 = 0);
  //#5
  pinMode(Led4_pin, OUTPUT);
  Out_Led(Led4_pin, Led4 = 0);
}

void loop() {
  //#1
  Pirsens = digitalRead(Pirsens_pin) && analogRead(Light_pin) < map(analogRead(Pot_pin), 0, 1023, 200, 500);
  //#2
  static uint32_t past_1 = 0 ;
  if (Led1 = 3 &&  millis() - past_1 >= 60000) { // 60сек
    if (! Pirsens) Out_Led(Led1_pin, Led1 = 2);
    past_1 = millis() ;
  }
  if (Led1 = 2 &&  millis() - past_1 >= 60000) { // 60сек
    if (Pirsens) Out_Led(Led1_pin, Led1 = 0);
    else  Out_Led(Led1_pin, Led1 = 3);
    past_1 = millis() ;
  }
  if (Led1 = 1 &&  millis() - past_1 >= 500) {// 0.5 сек
    Out_Led(Led1_pin, Led1 = 2);
    past_1 = millis() ;
  }
  if (Led1 = 0 && Pirsens) {
    Led1 = 1;
    past_1 = millis() ;
  }
  //#3
  // подобно коду в #2
  //#4
  // подобно коду в #2
  //#5
  // подобно коду в #2
}

 

viktor001
Offline
Зарегистрирован: 31.12.2016

С Новым Годом! Спасибо за помощь, но программа не работает. При включении загораются Led1, 3, и 4.  Горят постоянно и никакой реакции на движения. 

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

Ну там ошибки. Надо тестировать на железе. Попробуйте протестировать и разобраться в этом коде. Он рабочий.

/*viktor001_cl.ino
#1
кнопка -> 2 (btn1_pin) 0 нажата/ 1 нет
#2
светодиод 1 -> 3 (Led1_pin) 1 погашено/ аналог горит по уровню
светодиод 2 -> 5 (Led2_pin)
светодиод 3 -> 6 (Led3_pin)
светодиод 4 -> 9 (Led4_pin)
Принцип кода: чем дольше держишь кнопку, тем ярче горят светодиоды(50%,100%)
*/
class Cl_Led {
  public:
    Cl_Led(int _pin, uint32_t _time_1, uint32_t _time_2);
    void setup();
    void loop(int _btn);
  private:
    int pin;// нога на светодиод
    int Led;// величина на светодиоде
    const int light0 = 0; // уровень не горит
    const int light50 = 50; // уровень  горит 50%
    const int light100 = 100; // уровень горит 100%
    void Out_Led(int _Led);
    uint32_t past_led;
    uint32_t time_1; // задержка времени вкл light0->light50 и обратно
    uint32_t time_2; // задержка времени вкл light50->light100 и обратно
};
Cl_Led::Cl_Led(int _pin, uint32_t _time_1, uint32_t _time_2) {
  pin = _pin;
  time_1 = _time_1;
  time_2 = _time_2;
}
void  Cl_Led::Out_Led(int _Led) { // функция  управ.свет с нужным уровнем
  switch (Led = _Led) {
    case 0:
      analogWrite(pin,  light0);
      break;
    case 1:
      analogWrite(pin,  light0);
      break;
    case 2:
      analogWrite(pin,  light50);
      break;
    default:
      analogWrite(pin,  light100);
  }
}
void  Cl_Led::setup() {
  past_led = 0;
  Out_Led(0);
}
void Cl_Led::loop(int _btn) {
  if (Led == 3 &&  millis() - past_led >= time_2) {
    past_led = millis() ;
    if ( _btn)
      Out_Led( 2);
  }
  if (Led == 2 &&  millis() - past_led >= time_2 ) {
    past_led = millis() ;
    if (_btn)
      Out_Led(0);
    else
      Out_Led(3);
  }
  if (Led == 1 &&  millis() - past_led >= time_1 ) {
    past_led = millis() ;
    Out_Led(2);
  }
  if (Led == 0 && ! _btn) {
    past_led = millis() ;
    Led = 1;
  }
}
//#1
const int btn1_pin = 2; //нога кнопки
bool btn1;// инверс сост кнопки 1 нажата /0 нет
//#2
const int Led1_pin = 3; // управление яркостью с помощью ШИМ
Cl_Led Led1(Led1_pin, 500, 3000); // 0,1 - негорит / 2 горит в полнакала / 3 горит полностью

const int Led2_pin = 5; // управление яркостью с помощью ШИМ
Cl_Led Led2(Led2_pin, 700, 3000); // 0,1 - негорит / 2 горит в полнакала / 3 горит полностью

const int Led3_pin = 6; // управление яркостью с помощью ШИМ
Cl_Led Led3(Led3_pin, 1000, 3000); // 0,1 - негорит / 2 горит в полнакала / 3 горит полностью

const int Led4_pin = 9; // управление яркостью с помощью ШИМ
Cl_Led Led4(Led4_pin, 1500, 3000); // 0,1 - негорит / 2 горит в полнакала / 3 горит полностью
void setup() {
  //#1
  pinMode(btn1_pin, INPUT_PULLUP);
  //#2
  Led1.setup();
  Led2.setup();
  Led3.setup();
  Led4.setup();
}

void loop() {
  //#1
  btn1 =  digitalRead(btn1_pin);
  //#2
  Led1.loop(btn1);
  Led2.loop(btn1);
  Led3.loop(btn1);
  Led4.loop(btn1);
}

 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016
/*viktor001_v2_cl
#1
датчик движения ->2 (Pirsens_pin) 1 есть движение / нет
Датчик света -> A7 (Light_pin)  опред дня/ночи
потенциометр -> A5 (Pot_pin) задает с какого уровня нужна подсветка

убрана (кнопка -> 2 (btn1_pin) 0 нажата/ 1 нет)
#2
светодиод 1 -> 3 (Led1_pin) 1 погашено/ аналог горит по уровню
светодиод 2 -> 5 (Led2_pin)
светодиод 3 -> 6 (Led3_pin)
светодиод 4 -> 9 (Led4_pin)
Принцип кода: чем дольше держишь кнопку, тем ярче горят светодиоды(50%,100%)
*/
class Cl_Led {
  public:
    Cl_Led(int _pin, uint32_t _time_1, uint32_t _time_2);//(нога, время 0->50% ,время 50->100% )
    void setup();
    void loop(int _btn);
  private:
    int pin;// нога на светодиод
    int Led;// величина на светодиоде
    const int light0 = 0; // уровень не горит
    const int light50 = 50; // уровень  горит 50%
    const int light100 = 100; // уровень горит 100%
    void Out_Led(int _Led);
    uint32_t past_led;
    uint32_t time_1; // задержка времени вкл light0->light50 и обратно
    uint32_t time_2; // задержка времени вкл light50->light100 и обратно
};
Cl_Led::Cl_Led(int _pin, uint32_t _time_1, uint32_t _time_2) { //(нога, время 0->50% ,время 50->100% )
  pin = _pin;
  time_1 = _time_1;
  time_2 = _time_2;
}
void  Cl_Led::Out_Led(int _Led) { // функция  управ.свет с нужным уровнем
  switch (Led = _Led) {
    case 0:
      analogWrite(pin,  light0);
      break;
    case 1:
      analogWrite(pin,  light0);
      break;
    case 2:
      analogWrite(pin,  light50);
      break;
    default:
      analogWrite(pin,  light100);
  }
}
void  Cl_Led::setup() {
  past_led = 0;
  Out_Led(0);
}
void Cl_Led::loop(int _btn) {
  if (Led == 3 &&  millis() - past_led >= time_2) {
    past_led = millis() ;
    if ( _btn)
      Out_Led( 2);
  }
  if (Led == 2 &&  millis() - past_led >= time_2 ) {
    past_led = millis() ;
    if (_btn)
      Out_Led(0);
    else
      Out_Led(3);
  }
  if (Led == 1 &&  millis() - past_led >= time_1 ) {
    past_led = millis() ;
    Out_Led(2);
  }
  if (Led == 0 && ! _btn) {
    past_led = millis() ;
    Led = 1;
  }
}
//#1
const int Pirsens_pin = 2; // Цифровой датчик движения:
bool Pirsens;
const int Light_pin = A7; //Датчик света:
const int Pot_pin = A5; //Потенцинометр 10к:

//const int btn1_pin = 2; //нога кнопки
//bool btn1;// инверс сост кнопки 1 нажата /0 нет
//#2
const int Led1_pin = 3; // управление яркостью с помощью ШИМ
Cl_Led Led1(Led1_pin, 500, 3000); // (нога, время 0->50% ,время 50->100% )

const int Led2_pin = 5; // управление яркостью с помощью ШИМ
Cl_Led Led2(Led2_pin, 700, 3000); // (нога, время 0->50% ,время 50->100% )

const int Led3_pin = 6; // управление яркостью с помощью ШИМ
Cl_Led Led3(Led3_pin, 1000, 3000); // (нога, время 0->50% ,время 50->100% )

const int Led4_pin = 9; // управление яркостью с помощью ШИМ
Cl_Led Led4(Led4_pin, 1500, 3000); //(нога, время 0->50% ,время 50->100% )
void setup() {
  //#1
  pinMode(Pirsens_pin, INPUT);
  //  pinMode(btn1_pin, INPUT_PULLUP);
  //#2
  Led1.setup();
  Led2.setup();
  Led3.setup();
  Led4.setup();
}

void loop() {
  //#1
  Pirsens = digitalRead(Pirsens_pin) && analogRead(Light_pin) < map(analogRead(Pot_pin), 0, 1023, 200, 500);
 // btn1 =  digitalRead(btn1_pin);
  //#2
  Led1.loop(! Pirsens);
  Led2.loop(! Pirsens);
  Led3.loop(! Pirsens);
  Led4.loop(! Pirsens);
}
viktor001
Offline
Зарегистрирован: 31.12.2016

Светодиоды загораются независимо от освещённости. С циклом примерно три секунды становятся ярче, потом темнее и затем тухнут. Так как датчик движения держит на выходе высокий уровень минимум 5 сек. то заменил в коде время с 3000 на 6000. Теперь разгорается на 6 сек. и если нет движения то гаснет, если есть движение то увеличивается яркость. Затем ждём пока истечёт время и светодиоды должны последовательно потухнуть, но выключение происходит сначала понижением яркости, а потом уж окончательным. Ещё один момент. Повторно активировать включение возможно тольке после паузы. И иногда код ведёт себя крайне не стабильно. Тоесть при явном движении может потухнуть, не отработать некоторые светодиоды. 

Nosferatu
Offline
Зарегистрирован: 04.11.2012

viktor001 пишет:

Светодиоды загораются независимо от освещённости. С циклом примерно три секунды становятся ярче, потом темнее и затем тухнут. Так как датчик движения держит на выходе высокий уровень минимум 5 сек. то заменил в коде время с 3000 на 6000. Теперь разгорается на 6 сек. и если нет движения то гаснет, если есть движение то увеличивается яркость. Затем ждём пока истечёт время и светодиоды должны последовательно потухнуть, но выключение происходит сначала понижением яркости, а потом уж окончательным. Ещё один момент. Повторно активировать включение возможно тольке после паузы. И иногда код ведёт себя крайне не стабильно. Тоесть при явном движении может потухнуть, не отработать некоторые светодиоды. 

Думаю, что дело в засветке подсветкой датчика света.

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

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

замените цифры 500,700,1000,1500 на 0 и светодиоды будут реагировать сразу на движение. Или малыми величинами. Большие величины просто делают веселье в подсветке, какое вы и хотели, когда открыли тему.

viktor001 пишет:
Нашёл в интернете код который при срабатывании датчика движения сравнивает состояние входа АЦП от фоторезистора и если всё ОК то включает реле на заданное время к примеру 5 сек. По истечению этого времени проверяется состояние входа от PIR датчика и если есть движение то - повтор заданного времени работы. В принципе всё отлично, но как то скучно. Моих познаний хватило лишь на добавление нескольких каналов на выход, последовательное их включение/выключение и начальная яркость пока выбрана -100 (потом подберу более оптимальну).

viktor001
Offline
Зарегистрирован: 31.12.2016

Да с этими цифрами то всё нормально. Их можно опытным путём подобрать. Проблема в другом. 1) Срабатывает при любом освещении. 2) Если освещение 100% то гаснет сначала на 50% и потом через паузу до 0%. Если бы гасла без паузы то было бы очень замечательно, но так как эта же пауза заявлена и на разгорание то тут просто изменить константы не прокатит. 3) В режиме выключения иногда (чаще всего) 3 и 4 лед гаснут сразу в 0% - выглядит не симпатично. 4) После выключения код выдерживает паузу в 4-5 секунд. Только по истечении этой паузы можно опять активировать включение лед. В практическом применении это совсем плохо, можно оказаться в полной темноте. 

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

Ну так "обрабатывай напильником". У меня нет вашего "железа" , так что практика и еще практика. 

на 1- отработайте работу на кнопке. А потом сведите ваши датчики к иммтации работы кнопки.# Замечание нажатие кнопки 0

на 2- так и предусмотрено. 0-50-100-50-0

на 3  там все светодиоды равноцены. А класс даже стирает отличия подностью

на 4 . это вы путаете. то у вас см пунк 2, то смотри пунк 4

ПС: Я выложил эволюцию развития такого скетча(3 варианта). Разбирайтесь сами. Программирование это не только залить "чужой скетч", но и наладка под ваши условия и поиск глюков в чужом скетче. Приехать я к вам лично не смогу, даже если у меня было бы желание.

ПС2: А еще выкрутите ваш пирометр на мин паузу. Это пауза тоже сбивает работу.

viktor001
Offline
Зарегистрирован: 31.12.2016
Хорошо, буду разбираться. Когда есть желание собрать некое устройство и пару вариантов кода то как то проще вникать в суть языка программирования и всего что с этим связано чем просто читать книжку о программировании. Но тем не менее без непонятных моментов не обходится, что-то можно из книжек вычитать, а что-то нуждается в более детальном объяснении. Большое спасибо за помощь, надеюсь, что Вы мне ещё что-нибудь подскажите.
 
ПС: А с кодом, что я выкладывал нельзя ничего сделать? Или его тоже надо глобально переписывать?
qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

viktor001 пишет:

ПС: А с кодом, что я выкладывал нельзя ничего сделать? Или его тоже надо глобально переписывать?

Ну здесь мои глюки. Я пишу в своем стиле и под свою концепцию программирования. Не потому что не могу иначе, а потому что надо развивать именно эту.  Попробуй разобраться со своим вариантом. Направление я указал, осталась ваша реализация. Может другие предложат другое. Я не возражаю, тем более это ваша тема, а не моя. Да и форум тоже не мой. Я такой же как и вы, приходящий.

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014

Попробуйте такой код. Может его Вам будет проще понять 

int const Pot = A5; //Потенцинометр 10к:
int const Light = A7; //Датчик света:
int const Led1 = 4;
int const Led2 = 5;
int const Led3 = 9;
int const Led4 = 10;
int const Pirsens = 3; // Цифровой датчик движения:

//int const pause = 5000; // время работы 5 сек.
boolean lockLow ;
boolean takeLow;
uint8_t nakal;

void setup()
{
    // Определяем входы и выходы:
    pinMode(Pirsens, INPUT);
    pinMode(Led1, OUTPUT);
    pinMode(Led2, OUTPUT);
    pinMode(Led3, OUTPUT);
    pinMode(Led4, OUTPUT);
    // определяем состояние:
    digitalWrite(Led1, LOW);
    digitalWrite(Led2, LOW);
    digitalWrite(Led3, LOW);
    digitalWrite(Led4, LOW);
    //Serial.begin(9600);

}

unsigned long currentPause[1];   //массив данных. Количество элементов - количеству таймеров
bool fl_pause[1];//массив данных. Количество элементов - количеству таймеров

//Функция дребезга или паузы

boolean my_pausa(unsigned long time, byte nomer)   //функция таймер, time-время задержки, nomer-номер таймера
{
    bool x = 0;
    if (fl_pause[nomer] == 0)currentPause[nomer] = millis(), fl_pause[nomer] = 1;
    if (millis() - currentPause[nomer] >= time) x = 1, fl_pause[nomer] = 0;
    return x;
}

void vklucenie(uint8_t led, uint16_t vel)
{
    analogWrite(led, vel);
}

void loop()
{
    static bool _lockLow;
    int pirsensVal = digitalRead(Pirsens);
    int lightVal = analogRead(Light);
    int potVal = analogRead(Pot);
    int lightLimit = map(potVal, 0, 1023, 200, 500);
    
    static char var = 1;
    static char nul = 0;
    static unsigned char sto = 100;
    
    if (pirsensVal == HIGH && lightVal < lightLimit)//Движение, освещенность
    {
        if (!lockLow)
        {
            lockLow = 1;
            _lockLow = lockLow;
        }
    }
    else if(pirsensVal == LOW)
    {
        if(nakal > 210) lockLow = 0;
        else if(nakal >= 100)lockLow = 0;
    }



    if(lockLow && nakal <= 210)
    {
        takeLow=0;
        if(my_pausa(125, 0))
        {
            switch (var)
            {
            case 1:
                vklucenie(Led1, nakal += 10);
                if(nakal >= sto)var++, nakal = nul;
                break;
            case 2:
                vklucenie(Led2, nakal += 10);
                if(nakal >= sto)var++, nakal = nul;
                break;
            case 3:
                vklucenie(Led3, nakal += 10);
                if(nakal >= sto)var++, nakal = nul;
                break;
            case 4:
                vklucenie(Led4, nakal += 10);
                if(nakal >= sto)
                {
                    var = 1;
                    nul= 110;
                    sto=220;
                }
                break;
            }
        }
    }

    else if(lockLow != _lockLow && nakal >= 10)
    {
        if(!takeLow)
        {
            if(nakal == 100)sto = 0, nul = 100;
            else if(nakal > 200)sto=110, nul= 220;
            takeLow=1;
        }

        if(my_pausa(125, 0))
        {
            switch (var)
            {
            case 1:
                vklucenie(Led1, nakal -= 10);
                if(nakal <= sto)var++, nakal = nul;
                break;
            case 2:
                vklucenie(Led2, nakal -= 10);
                if(nakal <= sto)var++, nakal = nul;
                break;
            case 3:
                vklucenie(Led3, nakal -= 10);
                if(nakal <= sto)var++, nakal = nul;
                break;
            case 4:
                vklucenie(Led4, nakal -= 10);
                if(nakal <= sto)
                {
                    var = 1;
                    nul = 110;
                    sto = 0;
                }
                if(nakal == 0)_lockLow = lockLow;
                break;
            }
        }

    }

}