Автоматическая подсветка лестницы

Тема в разделе "Глядите, что я сделал", создана пользователем ИгорьК, 19 сен 2013.

  1. Megakoteyka

    Megakoteyka Оракул Модератор

    Если сигналы лежат в пределах логических "0" и "1", то ничего страшного.
    На дальнем конце 150-метрового кабеля прием идет? Если идет, то на просадки и помехи можно не обращать внимания.
    Если очень хочется длинный кабель и высокую надежность, используйте RS-485. У него еще и помехозащищенность поприличней будет.
     
    ИгорьК нравится это.
  2. fr0ster

    fr0ster Гик

    Видимо у вас не 150 метров или скорость обмена данными по шине не критична.
    А у I²C ограничение определяется емкостью шины и скоростью обмена данными.
    Так что никак не 1,5 метра дальность I²C.

    ЗЫ А вообще много чего было открыто потому, что открывший не знал почему это невозможно :)
     
    Tomasina нравится это.
  3. fr0ster

    fr0ster Гик

    Все же это если скорость не критична. Ну и какое то количество 0 вместо 1 и наоборот допустимо.
     
  4. ИгорьК

    ИгорьК Гуру

    Ряд товарищей, повторяющих подсветку, просит сделать зажигание ступенек "как у Лукьянова".
    Надеюсь, этот код им поможет:
    Код (C):
    // Скетч для датчика  SEN136B5B и  ArduinoMega 2560 - у нее 15 PWM ног.
    #define sensorPin A0                    // Нога для фоторезистора включается в A0 http://goo.gl/9gupvj;
    #define ledNight 24                        // Нога для LED - показывает включение ночного режима;
    unsigned int sensorValue = 0;            // Переменная для снятия показаний сенсора освещенности;
    boolean night = 0;                        // Если 1 - то ночь;
    byte OutPins[15] = {2,3,4,5,6,7,8,9,10,11,12,13,44,45,46}; // Массив PWM ног, сюда включаются входы http://goo.gl/ZM3xCw;
    int i;                                    // Счетчик для зажигания и тушения диодов, определения день/ночь;
    #define pingPin00 30                    // SEN00 - нижний ультрасоник http://goo.gl/Nrwwk7 ; PWM Выход на ноге 30;
    #define pingPin01 32                    // SEN01 - верхний ультрасоник http://goo.gl/Nrwwk7; PWM Выход на ноге 32;
    #define LedUltra 25                        // Нога светодиода - в ночном режиме показывает что любой ультрасоник схватил дистанцию, в дневном режиме просто светится;
    unsigned int Distance=0;                // Дистанция с ультрасоника;

    //************************* Все что ниже - определить самостоятельно ************************************************
    unsigned int sensorRef = 1010;            // Референсное значение сенсора освещенности, выше которого считается ночь;
    #define timer 20                        // Таймер для задержек при включении/выключении последовательности ступенек;
    #define SwitchOffDelay 15000            // Задержка выключения посветки, милисекунды (здесь 15 секунд) ;
    #define SwitchOnBright 180                // Яркость включенных ступенек, максимально - 255;
    #define NightBright  30                    // Яркость подсвеченных ступенек в ночном режиме (первая, последняя);
    //int timeForBlink = 100;                    // Число циклов мерцания включенной подсветки;
    #define bottomDistance 140                // Расстояние в см для срабатывания нижнего ультрасоника
    #define topDistance 55                    // Расстояние в см для срабатывания верхнего ультрасоника
    #define smoothSwitchDelayStep 5            // Скорость нарастания яркости ступеньки мс., чем меньше тем быстрее нарастает;
    //*******************************************************************************************************************
    void setup() {
      //Serial.begin(9600);
      pinMode(ledNight, OUTPUT);            // Ночной диод  ;
      pinMode(LedUltra, OUTPUT);            // Диод, индикатор "день" а ночью - чтобы видно было как действует ультрасоник;
      digitalWrite(LedUltra,LOW);

      for(i=0; i<15; i++) {                    // Режим работы PWM ног - выход;
        pinMode(OutPins[i], OUTPUT);
      }
    }

    //===================================================================================================================
    void loop() {
        NightIn();                            // Получаем данные День/Ночь;
        //Serial.print(night);
        //Serial.print(" - boolean night");
        //Serial.println();

        if(1 == night) {                    // Если ночь;
            getDistance(pingPin00);            // Опрашиваем нижний ультрасоник;
            //Serial.print(Distance);
            //Serial.print(" - First Distance");
            //Serial.println();
            //delay(1000);
            if(Distance < bottomDistance) {    // Проверка дистанции для нижнего ультрасоника;
                SwitchOnSmoothly(0);        // Включаем подсветку снизу вверх;
            }

            getDistance(pingPin01);            // Опрашиваем верхний ультрасоник;
            //Serial.print(Distance);
            //Serial.print(" - Second Distance");
            //Serial.println();
            //delay(1000);

            if(Distance < topDistance) {    // Проверка дистанции для верхнего ультрасоника;
                SwitchOnSmoothly(1);        // Включаем подсветку сверху вниз;
            }
      }
    }
    //===========================================================================================
    unsigned int getDistance(byte pingPin) {// Чтение ультрасоника - получение дистанции;
        unsigned int duration = 0;
        pinMode(pingPin, OUTPUT);
        digitalWrite(pingPin, LOW);
        delayMicroseconds(2);
        digitalWrite(pingPin, HIGH);
        delayMicroseconds(15);
        digitalWrite(pingPin, LOW);
        delayMicroseconds(20);
        pinMode(pingPin, INPUT);
        duration = pulseIn(pingPin, HIGH);
        Distance = duration / 29 / 2;

        return Distance;
    }
    //===========================================================================================
    boolean NightIn() {                                        // Чтение день или ночь;
        sensorValue = 0;
        unsigned int a = 0, b = 0;                            // Счетчики превышения сенсора над референсным значанием и значением минус гистерезис

        for(i = 0; i < 50; i++) {
            sensorValue = analogRead(sensorPin);            // Чтение показаний датчика;
            if (sensorValue > sensorRef) a++;                // Увеличиваем а, если темнее референсного значения;
            if (sensorValue > (sensorRef - 25)) b++;        // Увеличиваем b, если темнее чем референсное значение минус допуск на гистерезис;
        }

        if ((night == 0) && (a > 49)) {                        // Если сейчас режим день и 50 раз значение датчика оказалось выше референсного,
                                                            // то переключаемся в ночной режим, включаем дежурную подсветку ступенек.
            digitalWrite(ledNight, HIGH);
            digitalWrite(LedUltra, LOW);
            analogWrite(2,NightBright);
            analogWrite(46,NightBright);
            night = 1;
        }

        if ((night == 1) && (b == 0)) {                        // Если сейчас режим ночь, и 50 раз значение датчика оказалось ниже референсного за
                                                            // вычетом запаса на гистерезис - включаем режим "день", гасим подсветку ступенек.
            digitalWrite(ledNight, LOW);
            digitalWrite(LedUltra, HIGH);
            analogWrite(2,0);
            analogWrite(46,0);
            night = 0;
        }

        return night;
    }
    //===========================================================================================
    //void blink (int timeForBlink) {                            // Мерцание во время задержки
        //unsigned char brightness = 0;
        //for (int a = 0; a < timeForBlink; a++) {            // Цикл определяет длительность мерцания;
            //for(i = 1; i < 15; i++) {                        // Мерцаем диодами;
                //brightness = random((SwitchOnBright-25), SwitchOnBright);
                //analogWrite(OutPins[i], brightness);
                //delay(2);                                    // Маленькая задержка;
            //}
        //}
        //
        //for(i = 1; i < 15; i++) {                            // Восстанавливаем свечение лестницы;
            //analogWrite(OutPins[i], SwitchOnBright);
        //}
        //return;
    //}
    //===========================================================================================
    void SwitchOnSmoothly(bool direction) {                    // Включаем/выключаем в указанном направлении ;
        int brightness;
        digitalWrite(LedUltra, HIGH);

        if (!direction) {
            for (i=0; i<16; i++) {
                for (brightness = 0; brightness < SwitchOnBright; brightness++) {
                    analogWrite(OutPins[i], brightness);
                    delay(smoothSwitchDelayStep);
                }
            }
            delay(SwitchOffDelay);
            //blink (timeForBlink);                            // Померцаем;

            for (i=0; i<16; i++) {
                for (brightness = SwitchOnBright; brightness >= 0; brightness--) {
                    analogWrite(OutPins[i], brightness);
                    delay(smoothSwitchDelayStep);
                }
            }

        }
        else {
            for (i=15; i>=0; i--) {
                for (brightness = 0; brightness < SwitchOnBright; brightness++) {
                    analogWrite(OutPins[i], brightness);
                    delay(smoothSwitchDelayStep);
                }
            }
            delay(SwitchOffDelay);
            //blink (timeForBlink);                            // Померцаем;

            for (i=15; i>=0; i--) {
                for (brightness = SwitchOnBright; brightness >= 0; brightness--) {
                    analogWrite(OutPins[i], brightness);
                    delay(smoothSwitchDelayStep);
                }
            }
        }

            analogWrite(2,NightBright);               // Включим первую и последнюю ступеньки.
            analogWrite(46,NightBright);
    }
     
     
    Последнее редактирование: 4 мар 2014
  5. ИгорьК

    ИгорьК Гуру

    А также скетч для народного датчика hc-sr04. Много вопросов в личку и на почту о том, как его присоединить. Вот скетч, работоспособность не проверял по причине отсутствия датчиков. Кто сделает - отпишитесь как работает.
    Код (C):
    // Скетч для датчика hc-sr04 и ArduinoMega 2560 - у нее 15 PWM ног.
    #define sensorPin A0                    // Нога для фоторезистора включается в A0 http://goo.gl/9gupvj;
    #define ledNight 24                        // Нога для LED - показывает включение ночного режима;
    unsigned int sensorValue = 0;            // Переменная для снятия показаний сенсора освещенности;
    boolean night = 0;                        // Если 1 - то ночь;
    byte OutPins[15] = {2,3,4,5,6,7,8,9,10,11,12,13,44,45,46}; // Массив PWM ног, сюда включаются входы http://goo.gl/ZM3xCw;
    int i;                                    // Счетчик для зажигания и тушения диодов, определения день/ночь;
    #define pingPin00 30                    // SEN00 - нижний ультрасоник, PWM Выход на ноге 30;
    #define trigPin00 31                    // сюда присоединяем тригерную ногу нижнего ультрасоника;
    #define pingPin01 32                    // SEN01 - верхний ультрасоник, PWM Выход на ноге 32;
    #define trigPin01 33                    // сюда присоединяем тригерную ногу верхнего ультрасоника;
    #define LedUltra 25                        // Нога светодиода - в ночном режиме показывает что любой ультрасоник схватил дистанцию, в дневном режиме просто светится;
    unsigned int Distance=0;                // Дистанция с ультрасоника;

    //************************* Все что ниже - определить самостоятельно ************************************************
    unsigned int sensorRef = 1010;            // Референсное значение сенсора освещенности, выше которого считается ночь;
    #define timer 20                        // Таймер для задержек при включении/выключении последовательности ступенек;
    #define SwitchOffDelay 15000            // Задержка выключения посветки, милисекунды (здесь 15 секунд) ;
    #define SwitchOnBright 180                // Яркость включенных ступенек, максимально - 255;
    #define NightBright  80                    // Яркость подсвеченных ступенек в ночном режиме (первая, последняя);
    //int timeForBlink = 100;                    // Число циклов мерцания включенной подсветки;
    #define bottomDistance 140                // Расстояние в см для срабатывания нижнего ультрасоника
    #define topDistance 55                    // Расстояние в см для срабатывания верхнего ультрасоника
    #define smoothSwitchDelayStep 3            // Скорость нарастания яркости ступеньки мс., чем меньше тем быстрее нарастает;
    //*******************************************************************************************************************
    void setup() {
      //Serial.begin(9600);
      pinMode(ledNight, OUTPUT);            // Ночной диод  ;
      pinMode(LedUltra, OUTPUT);            // Диод, индикатор "день" а ночью - чтобы видно было как действует ультрасоник;
      digitalWrite(LedUltra,LOW);
      pinMode(trigPin00,OUTPUT);
      pinMode(trigPin01,OUTPUT);
      pinMode(pingPin00,INPUT);
      pinMode(pingPin01,INPUT);

      for(i=0; i<15; i++) {                    // Режим работы PWM ног - выход;
        pinMode(OutPins[i], OUTPUT);
      }
    }

    //===================================================================================================================
    void loop() {
        NightIn();                            // Получаем данные День/Ночь;
        //Serial.print(night);
        //Serial.print(" - boolean night");
        //Serial.println();

        if(1 == night) {                    // Если ночь;
            getDistance(trigPin00, pingPin00);            // Опрашиваем нижний ультрасоник;
            //Serial.print(Distance);
            //Serial.print(" - First Distance");
            //Serial.println();
            //delay(1000);
            if(Distance < bottomDistance) {    // Проверка дистанции для нижнего ультрасоника;
                SwitchOnSmoothly(0);        // Включаем подсветку снизу вверх;
            }

            getDistance(trigPin01, pingPin01);            // Опрашиваем верхний ультрасоник;
            //Serial.print(Distance);
            //Serial.print(" - Second Distance");
            //Serial.println();
            //delay(1000);

            if(Distance < topDistance) {    // Проверка дистанции для верхнего ультрасоника;
                SwitchOnSmoothly(1);        // Включаем подсветку сверху вниз;
            }
      }
    }
    //===========================================================================================
    unsigned int getDistance(byte trig, byte ping) {// Чтение ультрасоника - получение дистанции;
        unsigned int duration = 0;
        digitalWrite(trig, LOW);
        delayMicroseconds(2);
        digitalWrite(trig, HIGH);
        delayMicroseconds(10);
        digitalWrite(trig, LOW);
        duration = pulseIn(ping,HIGH);
        Distance = duration/29/2;
     
        return Distance;
    }
    //===========================================================================================
    boolean NightIn() {                                        // Чтение день или ночь;
        sensorValue = 0;
        unsigned int a = 0, b = 0;                            // Счетчики превышения сенсора над референсным значанием и значением минус гистерезис

        for(i = 0; i < 50; i++) {
            sensorValue = analogRead(sensorPin);            // Чтение показаний датчика;
            if (sensorValue > sensorRef) a++;                // Увеличиваем а, если темнее референсного значения;
            if (sensorValue > (sensorRef - 25)) b++;        // Увеличиваем b, если темнее чем референсное значение минус допуск на гистерезис;
        }

        if ((night == 0) && (a > 49)) {                        // Если сейчас режим день и 50 раз значение датчика оказалось выше референсного,
                                                            // то переключаемся в ночной режим, включаем дежурную подсветку ступенек.
            digitalWrite(ledNight, HIGH);
            digitalWrite(LedUltra, LOW);
            analogWrite(2,20);
            analogWrite(46,20);
            night = 1;
        }

        if ((night == 1) && (b == 0)) {                        // Если сейчас режим ночь, и 50 раз значение датчика оказалось ниже референсного за
                                                            // вычетом запаса на гистерезис - включаем режим "день", гасим подсветку ступенек.
            digitalWrite(ledNight, LOW);
            digitalWrite(LedUltra, HIGH);
            analogWrite(2,0);
            analogWrite(46,0);
            night = 0;
        }

        return night;
    }
    //===========================================================================================
    //void blink (int timeForBlink) {                            // Мерцание во время задержки
    //   unsigned char brightness = 0;
    //    for (int a = 0; a < timeForBlink; a++) {            // Цикл определяет длительность мерцания;
    //       for(i = 1; i < 15; i++) {                        // Мерцаем диодами;
    //           brightness = random((SwitchOnBright-25), SwitchOnBright);
    //           analogWrite(OutPins[i], brightness);
    //           delay(2);                                    // Маленькая задержка;
    //       }
    //    }

    //   for(i = 1; i < 15; i++) {                            // Восстанавливаем свечение лестницы;
    //       analogWrite(OutPins[i], SwitchOnBright);
    //    }
    //   return;
    //}
    //===========================================================================================
    void SwitchOnSmoothly(bool direction) {                    // Включаем/выключаем в указанном направлении ;
        int brightness;
        digitalWrite(LedUltra, HIGH);

        if (!direction) {
            for (i=0; i<16; i++) {
                for (brightness = 0; brightness < SwitchOnBright; brightness++) {
                    analogWrite(OutPins[i], brightness);
                    delay(smoothSwitchDelayStep);
                }
            }
            delay(SwitchOffDelay);
            //blink (timeForBlink);                            // Померцаем;

            for (i=0; i<16; i++) {
                for (brightness = SwitchOnBright; brightness >= 0; brightness--) {
                    analogWrite(OutPins[i], brightness);
                    delay(smoothSwitchDelayStep);
                }
            }

        }
        else {
            for (i=15; i>=0; i--) {
                for (brightness = 0; brightness < SwitchOnBright; brightness++) {
                    analogWrite(OutPins[i], brightness);
                    delay(smoothSwitchDelayStep);
                }
            }
            delay(SwitchOffDelay);
            //blink (timeForBlink);                            // Померцаем;

            for (i=15; i>=0; i--) {
                for (brightness = SwitchOnBright; brightness >= 0; brightness--) {
                    analogWrite(OutPins[i], brightness);
                    delay(smoothSwitchDelayStep);
                }
            }
        }
       
    analogWrite(2,NightBright); // Включим первую и последнюю ступеньки.
    analogWrite(46,NightBright);

    }
     
     
    Последнее редактирование: 11 мар 2014
  6. vist

    vist Нуб

    Немного странно.
    unsignedint sensorRef =1010; в этом значении вообще никак не реагирует, при уменьшении до 610, и ниже если включена настольная лампа - зажигаются LED 2,46, и LED24?, активируя сенсор на 30-31, медленно загорается и через некоторое время гаснет с ШИМом, а вот при активации сенсора на 32-33, загорается и стоит в таком состоянии пока не перегрузишь, при отключенной настольной лампе вообще тишина.
     
  7. ИгорьК

    ИгорьК Гуру

    1. Думаю, Вам надо точнее разобраться с электрическим соединением. Никто на проблему датчика света не жаловался, да и Вы сами видите на видео - все работает. Смотрите что и как соединено. Скорее всего, у Вас с ростом освещенности значение датчика не падает, а увеличивается.
    Начните с того, что напишите отдельную программу вывода значения датчика в com-порт компьютера и поймите как все это работает.
    К сожалению с hc-sr04 я не могу лично ничего повторить.
    2. Проверьте код еще раз. В нем была ошибка, но я ее исправил где-то в течение часа. Возможно Вы успели подхватить ошибочный. Это может касается реакции на датчик.
     
    Последнее редактирование: 3 мар 2014
  8. ИгорьК

    ИгорьК Гуру

    В продолжение темы. Дальнейшая работа идет по трем направлениям.
    1. Нет простою в 15 секунд, когда светится лестница. Каждое срабатывание датчика в это время увеличивает время подсветки на 7 секунд.
    2. Во время выключения датчики проверяются. Если датчик срабатывает, выключение сменяется включением. Выглядит вот так:


    3. Это цветная лента. С ней железом все еще не определился.
     
    woloooodjaj нравится это.
  9. ИгорьК

    ИгорьК Гуру

    Исправлен последний код для датчика hc-sr04. Скетч вел себя неадекватно вот из-за чего.
    1. В установках счетчик i был объявлен как byte. Изменение на int решило все проблемы. Скетч должен работать - отпишитесь, пожалуйста.
    2. Кроме этого, в скетче, по недосмотру, был оставлен вызов подпрограммы мерцания, которая не предназначена для работы с ним. Приношу всем извинения за невнимательность.
    В чем же коренная суть проблемы byte и int мне самому не ясно. Может кто из более сведущих подскажет?
     
    Последнее редактирование: 4 мар 2014
  10. rav_75

    rav_75 Гик

    Код (Text):
    byte i;
    for (i=15; i>=0; i--){}
    Вот здесь Ваша ошибка. В какой-то из соседних веток вроде недавно рассматривалось. При i=0 декремент i-- дает значение i=255, таким образом условие i>=0 продолжает выполняться и программа уходит в бесконечный цикл. Вроде как-то так.
     
    ИгорьК нравится это.
  11. ИгорьК

    ИгорьК Гуру

    Дошло. Видимо в этом случае компилятор организует дело так, что проверяется последнее соответствие не на равенство нулю ("i>=0" как записано в коде), а на "i > -1" больше минус единицы, которой в byte не может быть по определению.
    Всегда для счетчиков автоматом выбирал int и не обращал внимание на этот факт.
     
    Последнее редактирование: 4 мар 2014
  12. Megakoteyka

    Megakoteyka Оракул Модератор

    Не совсем. Цикл работает так:
    -проверили условие.
    - выполнили тело.
    - отняли счетчик.
    - проверили условие...
    Получается, что условие 0 == 0 проходит, выполняется тело цикла, затем убавляется счетчик (до 0xFF) затем снова проверяется условие. И вот тут-то и происходит облом - счетчик снова больше нуля.
    Давеча acos как раз подобную проблему описывал.
     
    Последнее редактирование: 4 мар 2014
    ИгорьК нравится это.
  13. vist

    vist Нуб

    Уважаемый ИгорьК!
    Опять неувязочка!
    При первом включении LEDs 2,46 мерцают, горит 24, через 1 секунду загорается LED25 активируется нижний датчик 30,31 , соответственно загораются и гаснут в обратном порядке LEDs со 2 по 46 с ШИМом.
    После прохождения этого цикла все входит в норму, горят LEDs24,25 ждут команды-все остальные погашены,т.е LEDs 2,46 не мерцают. При активации датчиков программа все четко отрабатывает.Нажимаешь на плате RESET все повторяется сначала.
    При замене int i;на byte i;(счетчик), все тоже самое. что описывал, датчик при активации 30,31 работает нормально, а вот 32-33(верхний), загорается и не гаснет мерцает 4LED при нарастании от 46 ко 2LEDs.
     
  14. vist

    vist Нуб

    Датчика hc-sr04 очень чувствителен
    #define bottomDistance 20 // Расстояние в см для срабатывания нижнего ультрасоника
    #define topDistance 15
    уменьшал, т.к. срабатывали постоянно и не понятно было, что влияет на активацию. Чисто для таких нубов как я.
     
  15. kusto

    kusto Нуб

    Уважаемый ИгорьК
    Код отличный, ошибки исправлены . Спасибо !
    С датчиками hc-sr04 проблем пока не обнаружено.

    #define bottomDistance 60
    #define topDistance 60
     
  16. lexalex08

    lexalex08 Нуб

    в скетче для hc-sr04 пропущены две строчки в конце
    analogWrite(2,NightBright); // Включим первую и последнюю ступеньки.
    analogWrite(46,NightBright);
    без них перестают светиться первая и последняя ступени, а так все работает уже 2 день без проблем
     
  17. ИгорьК

    ИгорьК Гуру

    Добавил.
     
  18. ИгорьК

    ИгорьК Гуру

    Версия beta три для народного датчика hc-sr04.
    1. Код переписан заново. Включение плавное. Ультрасоники во время включения не проверяются.
    2. При включенной лесенке не стоим в delay(), а читаем ультрасоники. Если происходит срабатывание, время начинает течь заново;
    3. Во время выключения проверяются ультрасоники. При срабатывании режим выключения меняется на режим включения.
    4. Уровень подсветки включенных ступенек менять можно (не смотря на то что написано в скетче) в меньшую сторону но кратно 5.
    Как и ранее, этих ультрасоников у меня нет. Кому интересно повторить - отпишитесь.
     

    Вложения:

    Последнее редактирование: 11 мар 2014
  19. Nikolay

    Nikolay Нуб

    Игорь, Большое спасибо за проделанную работу. Для меня программирование очень далеко. Повторить, спаять - нет проблем. Сначала встал в тупик, где ledNight и LedUltra. Запустил, увидел - эта функция перешла на 2 и 46 выходы. Работает супер. Единственное - нет возможности уменьшить яркость включённых ступенек. Готовлюсь к дачному сезону.
    P.S. Предыдущий скетч работал с большой ошибкой, не успел видео снять.
    Ещё раз спасибо.
     
  20. vist

    vist Нуб

    Добрый вечер, ИгорьК!
    Спасибо, оба кода работают, как Вы описали.