WS2812B + APDS9960 = управляемый жестами светильник на Arduino
Всем привет!!!
Я рад , что могу снова показать Вам свои наработки.
На этот раз я собрал светильник на ардуино управляемый жестами.
Данный проект отнял у меня очень много времени, которого у меня и так всегда не хватает. Первый вариант светильника я собрал очень быстро и он прекрасно работал у меня на макетной плате, но когда я перенес его на постоянное место в корпус, вот тут все и началось, вылезли все проблемы с подвисаниями, ложными срабатываниями и прочими неприятностями. Погуглив в интернете, я нашел на иностранных сайтах, множество жалоб связанных с проблемами датчика 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
Скачать скетч светильника
Итоги
Светильник в живую выглядит лучше чем на видео. Теперь все кто увидел его у меня, просят собрать им такой же. На данный момент мне не нравится как работает регулировка яркости, но я над этим работаю. Не обещаю, что скоро, но уже в разработке следующая версия светильника.
Спасибо, что дочитали статью до конца! Если у Вас остались вопросы, можете задать в комментарии под статьей, регистрация не требуется.
20 комментариев
Подскажите, а Вы на продажу не собираете такие светильники?
duino-led-lamp:47:3: error: 'set_color' was not declared in this scope. В чем причина?
И второй вопрос где можно скачать библиотеку avr-wdt.h
Функцию ’set_color’ компилятор не находит
Это был ответ на второй вопрос
exit status 1
Adafruit NeoPixel.h: No such file or directory. Вот такая ошибка.