Светильник управляемый жестами на Arduino

    image

    Всем привет!!!
    Я рад, что снова могу показать Вам свою новую поделку.
    На этот раз я собрал светильник на ардуино управляемый жестами.

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

    И так, все по порядку.

    Описание светильника


    Основной упор в этом светильнике я сделал не на визуализацию, а на управление жестами, все остальные функции второстепенные.

    Включается светильник жестами влево или вправо, а так же можно включить и жестом на себя, но это не совсем удобно. Далее жестами влево и вправо можно перелистывать световые эффекты. Если начать листать вправо, то лампа сначала будет менять свои цвета от белого до красного, включая все основные цвета и переходы между ними.

    Если после включения лампы начнем листать влево, то увидим динамические световые эффекты, такие как «Огонь», «Матрица», «Лава лампа», «Радуга», «Конфетти», «Искры», «Огненный светильник». Если Вам нужно вернуться на обычный светильник, то вместо перелистывания, можно выключить лампу жестом от себя и включить любым из трех жестов.
    Выключение производится жестом от себя.



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

    Я не уделял особого внимания визуальным эффектам, так как планирую сделать вторую версию лампы на контроллере Wemos D1 mini. В которой планирую довести все до идеала. По этой же причине я пока использую только одну линейку светодиодов, состоящую из 4 планок ws2812b, вместо четырех.

    Прерывания APDS9960


    Собственно основные проблемы светодиодной лампы связаны именно с ним. Прерывания в apds9960 живут своей жизнью, может сработать от чего угодно например от ЭМ помехи или от нахождения рядом с датчиком человека, от пульсации по питанию и возможно от чего то еще.



    Сначала попробовал исправить проблему изменениями в железе. Фильтрация питания не помогла, даже от аккумулятора 18650 датчик все равно продолжал жить своей жизнью. Попробовал переключить нагрузочный резистор сигнала INT на +5В и это тоже не принесло успеха.

    По мере изучение пришло понимание от чего происходят ложные срабатывания прерываний. Основная проблема — это случайные отражения ИК сигнала. Производитель рекомендует покрыть датчик и все вокруг него черным резиновым напылением. У меня нет такой краски и я не стал с этим заморачиваться. Хотя наверняка это могло бы немного уменьшить число ложных срабатываний.

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

    Определение жеста


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

    Для того, что бы улучшить стабильность распознавания жестов, так же пришлось в библиотеке уменьшить чувствительность приемника. Для этого нужно в файле SparkFun_APDS9960.h заменить строку:

    if( !setLEDBoost(LED_BOOST_300) )
    на
    if( !setLEDBoost(LED_BOOST_150) )

    Если Вы скачали библиотеку из этой статьи, то ничего делать не нужно, там уже все исправлено.
    Я так же экспериментальным путем подобрал ток светодиода 50 мА, при котором жесты определяются наиболее стабильно и нет надобности насиловать инфракрасный светодиод, током 100 мА.

    А так же я допустил ошибку, разместив микроконтроллер в нижней части светильника, а датчик жестов в верхней крышке. Из-за этого, для соединения arduino и apds9960, пришлось использовать провода длинной 30 см. Что тоже добавило дополнительной нестабильности работы датчика. В итоге я программным путем победил все эти проблемы.

    Схема




    Для питания устройства я использую зарядное устройство от моего смартфона, с напряжением выхода 5В и током 2А. Но на самом деле светильник при включенном белом свете на максимальной яркости, не потребляет выше 1,3 А. По этому подойдет любой источник питания с выходным током не менее 1,3А.

    Стабилизатор dc-dc mini360, можно заменить на любой другой понижающий преобразователь напряжения, с выходным током не менее 150 мА.

    В нижеприведенной схеме я не использую преобразователь логических уровней, но это мое личное решение. И поэтому я заранее снимаю с себя ответственность, в том случаи если, у вас выйдет из строя сенсор APDS9960, подключенный без преобразователя TTL уровней.

    Вместо Ардуино Нано можно использовать контроллер Arduino UNO или его клоны.

    Обязательно проверьте на датчике жестов наличие перемычек, они отмечены красным цветом на фотографии ниже. В случаи их отсутствия следует паяльником на эти контактные дорожки, нанести и разогреть припой до образования однородной капли. Сейчас китайцы поставляют эти датчики без перемычек. Без указанных перемычек работа датчика не гарантируется.



    Используемые компоненты


    Arduino Nano — 1 шт.
    Датчик жестов APDS9960 — 1 шт.
    Светодиодные планки ws2812b — 4 шт.
    Преобразователь понижающий mini360 — 1 шт.
    Соединительные провода — 1 комплект.

    Программный код для Ардуино


    Код разбит на две части. В первой части находится основной код, который работает с сенсором, а во второй части находится код всех световых эффектов.

    Вы можете сами добавить любой эффект по аналогии с моим кодом, но главное не забудьте добавить функцию выхода по жесту из зацикленного эффекта. Для этого нужно добавить в конце цикла, следующую строку if(check_int()) return;

    Описание основных функций программы
    processingGesture() обрабатывает прерывания от датчика жестов.
    processingProximity() обрабатывает прерывания от датчика приближения.
    gesture_int() — обработчик прерывания от датчика жестов.
    proximity_int() — обработчик прерывания от датчика приближения.

    Описание констант


    APDS9960_INT — вход для внешнего прерывания. В Arduino Nano и UNO всего два таких входа, 2 и 3.

    PIN — здесь нужно указать выход на светодиодную ленту. Можно указывать любой цифровой пин к которому подключены планки ws2812b.

    NUM_PIX — здесь указываем количество адресных светодиодов в используемой ленте.
    range — предел погрешности от 0 до 10. Если при регулировке яркости зафиксировать руку над датчиком на 2 сек, то показания должны сохраниться, если же показания не сохраняются, то увеличивайте постепенно предел погрешности.

    Скачать библиотеку APDS9960
    Скачать скетч светильника

    Видео демонстрирующее работу светильника



    Итоги


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

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

    P.S.


    Идеей лампы вдохновился здесь
    Основные эффекты брал тут

    Similar posts

    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 37

      0
      Не думали о применении esp8266? Она компактнее слегка и там WiFi есть, можно было бы в систему умного дома встроить. Это сейчас, мне кажется, очень модно)
        0
        Я в статье написал о том, что следующая версия будет на wemos d1 mini
          +1
          Проглядел! Хороший выбор)
        +1

        Хорошая работа!

          0
          Спасибо!
          0
          А сам корпус светильника на али заказывали?
            0
            В Леруа покупал за 900р. Потом видел такой же в Ашане за 700р. Еще можно использовать вазу из Ikea, дешевле выходит
              0

              Вот инструкция по сборке https://youtu.be/771-Okf0dYs

                +1
                У Гайвера нет жестов, просто ёмкостная кнопка (и кстати не очень стабильно определяющая двойное нажатие). Но суть очень похожая, да.
                  0
                  Идеей лампы вдохновился здесь
                  Судя по дате: 10 окт. 2015 г, Гайвер тоже взял эту идею у Cine-Lights за основу.
                  Эффекты я брал тут
                  0

                  А чем обусловлен выбор отдельного датчика? Не пробовали самостоятельно собрать на ИК светодиоде и ИК фотодиода?

                    0
                    На ИК датчике препятствий, невозможно измерять расстояние. В светильнике регулировка яркости использует датчик приближения.
                    А так же для управления жестами в двух плоскостях, понадобится 4 фотодиода и ИК светодиод, а это влечет за собой увеличение размеров.
                      0
                      а это влечет за собой увеличение размеров
                      Мне кажется, вверху лампы предостаточно места. Можно хоть датчик жестов сделать и дополнительно датчик расстояния.
                        0

                        Но датчик то представляет собой ту же самую пару — ИК диод, ИК фотодиод, ну насколько я могу судить по фотографиям. Да и насколько я знаком с такими парами расстояние замерить тоже возможно путем измерения падения напряжения на фотодиоде (чем дальше препятствие, тем больше падение, т.к. фотодиод приоткрыт не полностью). Просто возиться с таким привередливым датчиком так себе занятие...

                          +1
                          APDS9960 намного более сложный датчик. Там целая матрица фотодиодов под линзой, наличие которой и позволяет определять жесты в трёх направлениях. А кроме этого, расстояние, освещённость, цвет.
                          0
                          На самом деле немного не так. ИК-датчик прекрасно позволяет измерять расстояние. Что касается двух плоскостей, ну не знаю, дело вкуса.

                          Я лампу делал на ИК-датчике Sharp GP2Y0A21YK, режимы переключаются по кольцу (потому что датчик, конечно, не имеет полноценного распознавания жестов), когда проводишь рукой над датчиком в горизонтальной плоскости. Яркость, оттенок регулируются в вертикальной плоскости, как раз по контролю расстояния до ладони.
                            0
                            Учитывая стоимость apds9960, то не вижу смысла в самодельном датчике.
                              0
                              Я и не говорил ничего о самодельном датчике. Sharp GP2Y0A21YK — это промышленный датчик. Но дело даже не в этом, просто вы почему-то считаете, что ИК не позволяет определять расстояние, вот и все.
                        0

                        Если станешь использавать ESP8266, тогда не подключай WI FI, иначе динамическое отображение эфектов станет прерывчато, по причине требования ресурсов микроконтроллера для обслуживания функций WIFI. Нужно использовать двухядерную ESP32, где второе ядро самостоятельно обслуживает WIFI.

                          0
                          Спасибо, учту этот факт
                            0
                            Если станешь использовать ESP8266, тогда не подключай WI FI, иначе динамическое отображение эффектов станет прерывисто, по причине требования ресурсов микроконтроллера для обслуживания функций WIFI.

                            поди библиотека NeoPixel? У нее на esp8266 импульсы для WS2812 софтварно генерируются. Можно попробовать задействовать I2S с DMA или UART1 аппаратным FIFO, тогда никаких рывков не будет.

                            Нужно использовать двухядерную ESP32, где второе ядро самостоятельно обслуживает WIFI.

                            Для esp32 некоторые версии NeoPixel используют аппаратную часть — RMI для генерирования импульсов для WS2812, второе ядро тут совсем ни причем.
                            А вот если поддержку RMI выключить то на esp32 оно даже работает без заеданий, пока не начинаешь делать что то тяжёлое — например декодировать и воспроизводить mp3, тогда вместо красивой гирлянды получаем непонятный стробоскоп.
                            0

                            Но если для управления нужно протягивать руку в сторону светильника. — почему не протянуть ее чуть-чуть дальше? Можно вместо датчика движения взять сенсорные кнопки, это надёжнее. Можно поставить их 20 шт, управлять светом в одно нажатие удобнее.

                              –1

                              Заглянул в код библиотеки. Он показался знакомым (тоже игрался с датчиком) обилием подобных фрагментов:


                                  if( !setMode(POWER, 1) ) {
                                      return false;
                                  }
                              
                                  return true;

                              Лёгким движением руки 5 строчек превращаются в одну:


                              return !!setMode(POWER, 1);
                                –1
                                НИКОГДА так не делайте.
                                  +1
                                  Можно узнать почему?
                                    +1
                                    Потому что перевод целого в булево при помощи двойного отрицания — это:
                                    1. Ненаглядно и не очевидно для читателя.
                                    2. Компиляторо-зависимо
                                    3. И (что прикольно) медленнее исполняется.
                                  0
                                  Наверное тогда уж так:
                                  return setMode(POWER, 1);

                                  Зачем две подряд логические инверсии? Чтобы именно true/false на выходе получить? Но это не нужно. false = 0, true !=0
                                    –1
                                    true/false на выходе получить? Но это не нужно.

                                    Согласен, здесь совершенно не нужно. Машинально написал.
                                    Бывают ситуации, когда нужно что-то явно привести к bool, а "!!" известное сокращение для этого.

                                      0

                                      "Бывают ситуации, когда нужно что-то явно привести к bool"


                                      Оно и так приведется. В потрохах системных include есть конструкция


                                      define true 1
                                      define false 0

                                      '"!!" известное сокращение для этого.'


                                      Вряд ли. Если хочется подчеркнуть, что тут приведение к bool, лучше так:


                                      return (bool)setMode(POWER, 1);

                                  0

                                  Предположу что если поставить несколько датчиков то вероятность что случайные прерывания у них совпадут будет весьма низкой.
                                  Что скажите о такой идее?

                                    –3

                                    Когда же прекратят называть схемой, то что ей не является.

                                      0
                                      Я же не написал, что это принципиальная схема. Это общая схема.
                                      Если Вы считаете специалистом в этом вопросе, то разъясните пожалуйста?
                                        –1
                                        Приведенный в статье рисунок соединения разноцветными проводками, это даже не общая схема. На Хабре есть статья по типам электрических схем.
                                        А в целом получилось хорошее изделие.
                                          0

                                          Такие схемы рисуют в программе Fritzing. Не по ГОСТу, но своеобразный стандарт.

                                            +2
                                            У вас в статье все схемы электрические, а у автора схема в общем понимании этого слова (или я пропустил момент когда она потеряла «электрическая»)

                                            Схема — изложение, изображение, представление чего-либо в самых общих чертах, упрощённо
                                              –3
                                              В статье идет описание электронного устройства, следовательно, схема должна быть не эфемерная, а связанная с электронным устройством (электрическая, структурная и т.д.). А в статье приведена картинка разноцветная.

                                      Only users with full accounts can post comments. Log in, please.