Ночник с управлением жестами, на базе адресных светодиодов
Ночник с управлением жестами, на базе адресных светодиодов
Уроки и проекты /Общие сведения:
В этом уроке мы создадим ночник с управлением адресными светодиодами через датчик жестов.
Выполнив один из жестов, которые распознаёт датчик, вы сможете управлять режимом работы ночника, его яркостью, цветом и скоростью анимации.
Видео:
Нам понадобится:
- 1х Arduino / Piranha UNO;
- 1х Battery Shield;
- 1х Trema Shield;
- 8х Trema-модуль Адресный светодиод NeoPixel;
- 1х Trema-модуль Датчик жестов, приближения, освещённости, цвета;
- 6х ПВХ-конструктор;
Для реализации проекта нам необходимо установить библиотеки:
- SparkFun_APDS9960 — для работы с датчиком движений;
- iarduino_NeoPixel — для работы с адресными светодиодами NeoPixel;
- Wire — библиотека входит в базовый набор Arduino IDE и не требует установки;
О том, как устанавливать библиотеки, Вы можете ознакомиться на странице Wiki - Установка библиотек в Arduino IDE.
Описание работы ночника:
После подачи питания ночник готов к работе.
Для включения ночника проведите рукой над датчиком вправо или влево, после чего ночник включит один из режимов работы:
- Перелив всеми цветами радуги;
- Случайное включение случайным цветом;
- Смена одного цвета на другой;
- Имитация пламени свечи;
- Один цвет на выбор по порядку(красный, зелёный, синий, жёлтый, фиолетовый, голубой, белый);
Для того, чтобы увеличить или уменьшить скорость анимации, достаточно провести рукой вверх (ускорить) или вниз (замедлить) над датчиком.
Для того, чтобы изменить уровень яркости ночника достаточно приблизить руку к датчику и плавно её отдалить - ночник перейдёт в режим настройки:
- При входе в режим настройки яркости ночник однократно моргнёт светодиодами белого цвета, после чего в течении времени, заданном в переменной
waiting_time
, будет принимать команды настройки яркости; - Приближая или отдаляя руку к/от датчика яркость будет плавно меняться от меньшего (приближая) к большему (отдаляя);
- По истечении времени ночник вновь однократно моргнёт светодиодами белого цвета и выйдет из режима настройки яркости;
Для того, чтобы выключить ночник, достаточно поднести руку над датчиком на расстоянии 10-15 см и плавно её приблизить. После этого ночник выключится.
Схема сборки:
Arduino / Piranha UNO:
Batery Shield:
Установите Battery Shield на Arduino / Piranha UNO:
Во время установки Battery Shield должен быть в выключенном состоянии.
Trema Shield:
На Battery Shield установите Trema Shield:
Датчик жестов:
Подключите Trema-модуль Датчик жестов к Trema Shield:
Адресные светодиоды:
Подключите адресные светодиоды NeoPixel к Trema Shield:
Все используемые в уроке Trema-модули NeoPixel соединены друг c другом, а первый модуль можно подключить к любому выводу Arduino. Номер вывода указывается в скетче (в примере используется вывод D10
). Чем больше модулей в цепи, тем больше тока она потребляет, по этому в схеме используется стабилизированный источник питания Battery Shield на 5В постоянного тока.
Код программы (скетч):
// Подключаем библиотеки: #include <Wire.h>// Для работы с шиной I2C #include <SparkFun_APDS9960.h>// Для работы с датчиком APDS-9960 #include <iarduino_NeoPixel.h>// Подключаем библиотеку iarduino_NeoPixel для работы со светодиодами NeoPixel uint8_t neo_pin = 10;// Вывод, к которому подключены модули NeoPixel uint16_t modul_number = 8;// Количество модулей iarduino_NeoPixel led(neo_pin, modul_number*4 );// Объявляем объект LED указывая (№ вывода Arduino к которому подключён модуль NeoPixel, количество используемых светодиодов) SparkFun_APDS9960 apds = SparkFun_APDS9960();// Определяем объект apds, экземпляр класса SparkFun_APDS9960 // Объявляем переменные: uint8_t j;// Объявляем переменную для хранения значения сдвига спектра цветов для всех светодиодов (от 0 до 255) uint8_t k;// Объявляем переменную для хранения положения сдвига спектра цвета для каждого светодиода на спектре j (зависит от количества светодиодов) uint8_t r, g, b;// Объявляем переменную для хранения цветов RGB для каждого светодиода uint8_t z = 1;// Определяем константу указывающую задержку в мс (чем выше значение, тем медленнее перелив цветов) uint8_t flg, setting = 0;// Флаг включения/выключения света uint8_t mode = 0;// Флаг режима работы светодиодов uint8_t proximityData = 0;// Переменная, хранящая значение расстояния до модуля APDS9960 uint8_t brightness = 255;// Переменная значения яркости uint32_t waiting_time = 7000;// Время ожидания при настройке яркости uint32_t work_time;// Счётчик времени при настройке яркости byte on_off = 0;// Триггер включения/выключения светаvoid setup() {// Инициализируем адресные светодиоды: led.begin();// Инициализируем модуль жестов: apds.init();// Если инициализация модуля жестов прошла успешно, то ...// Устанавливаем коэффициент усиления приёмника: // Доступные значения: 1х, 2х, 4х, 8х (GGAIN_1X, GGAIN_2X, GGAIN_4X, GGAIN_8X). Чем выше коэффициент тем выше чувствительность apds.setGestureGain(GGAIN_4X);// Если установлен коэффициент усиления приёмника в режиме обнаружения жестов, то ...// Устанавливаем силу тока драйвера ИК-светодиода: // Доступные значения: 100мА, 50мА, 25мА, 12.5мА (LED_DRIVE_100MA, LED_DRIVE_50MA, LED_DRIVE_25MA, LED_DRIVE_12_5MA). Чем выше сила тока, тем выше чувствительность. apds.setGestureLEDDrive(LED_DRIVE_100MA);// Если устанавлена сила тока драйвера (яркость) ИК-светодиода для обнаружения жестов, то ...// Разрешаем режим обнаружение жестов: apds.enableGestureSensor(false);// Если инициализация режима обнаружения жестов прошла успешно, то led.setColor(NeoPixelAll,0, 0, 0);// Выключаем светодиоды led.write();// // Ждём завершение инициализации и калибровки: delay(500);// Задержка 0,5с }void loop() {// Проверяем наличие движенияif (apds.isGestureAvailable()) {// Если зафиксировано движение, то ...switch (apds.readGesture()) {// Сверяем значение соответствующее жесту ...// Проверяем жест: //==========================================================//// "СЕВЕР" - УВЕЛИЧЕНИЕ СКОРОСТИ АНИМАЦИИcase DIR_UP:if(z>=1 && z <=11){z += 5;} else// Если параметр скорости задан от 1мс до 11мс, то шаг равен 5мсif(z > 11 && z <=101) {z += 20;}else// Если параметр скорости задан от 11мс до 101мс, то шаг равен 20мсif(z > 101 && z <=500){z += 50;}else// Если параметр скорости задан от 101мс до 500мс, то шаг равен 50мсif(z > 500){z = 1;}// При превышении значения шаг сбрасываетсяbreak; //==========================================================// // "ЮГ" - УМЕНЬШЕНИЕ СКОРОСТИ АНИМАЦИИcase DIR_DOWN:if(z<1){z = 500;}else// При выходе из заданного промежутка значений шаг сбрасываетсяif(z >=1 && z <=11){z -= 5;} else// Если параметр скорости задан от 1мс до 11мс, то шаг равен 5мсif(z > 11 && z <= 101){z -= 20;}else// Если параметр скорости задан от 1мс до 11мс, то шаг равен 5мсif(z > 101 && z <=500){z -= 50;}// Если параметр скорости задан от 1мс до 11мс, то шаг равен 5мсbreak; //==========================================================//// "ЗАПАД" - ЛИСТАЕМ РЕЖИМЫ ВНИЗcase DIR_LEFT: mode--;// Уменьшаем номер режима на единицуif(mode < 1){mode = 11;}// Если значение меньше допустимого, то переходим к максимально большому значениюbreak; //==========================================================// // "ВОСТОК" - ЛИСТАЕМ РЕЖИМЫ ВВЕРХcase DIR_RIGHT: mode++;// Увеличиваем номер режима на единицуif(mode > 11){mode = 1;}// Если значение больше допустимого, то переходим к минимальному значениюbreak; //==========================================================// // "ОТДАЛЕНИЕ" - ПЕРЕХОД В РЕЖИМ ЯРКОСТИcase DIR_FAR: setting = 1;// Ставим флаг перехода в режим настройки яркости flg = 1;// Ставим флаг смены работы режима датчика жестов - с чтения жестов на чтение приближения work_time = millis();// Обновляем счётчикbreak; //==========================================================// // "ПРИБЛИЖЕНИЕ" - ПЕРЕХОД В РЕЖИМ ВЫКЛЮЧЕНИЯ СВЕТАcase DIR_NEAR: mode = 12;// Устанавливаем режим выключения светаbreak;}}// РЕЖИМЫ РАБОТЫ СВЕТОДИОДОВ:switch (mode) {// Сверяем значение соответствующее режиму работы //==========================================================// // ПЕРЕЛИВ ВСЕХ ЦВЕТОВ РАДУГИcase 1: j++;// Смещаем спектр цветов для всех светодиодовfor(uint16_t i=0; i<led.count(); i++){// Проходим по всем светодиодам k=((uint16_t)(i*256/led.count())+j);// Определяем положение очередного светодиода на смещённом спектре цветовif(k<85) { b=0; r=k*3; g=255-r;}else// Перелив от зелёного к красному, через жёлтыйif(k<170){k-=85; g=0; b=k*3; r=255-b;}else// Перелив от красного к синему , через фиолетовый{k-=170; r=0; g=k*3; b=255-g;}// Перелив от синего к зелёному, через голубой led.setColor(i,// Устанавливаем выбранный цвет для очередного светодиода map(r, 0, 255, 0, brightness),// Задаём зависимость яркости красного от параметра brightness, который определяется в настройках яркости map(g, 0, 255, 0, brightness),// Задаём зависимость яркости зелёного от параметра brightness, который определяется в настройках яркости map(b, 0, 255, 0, brightness));// Задаём зависимость яркости синего от параметра brightness, который определяется в настройках яркости} led.write();// Записываем цвета в светодиоды delay(z);// Устанавливаем задержкуbreak; //==========================================================// // ВКЛЮЧЕНИЕ СЛУЧАЙНЫМ ЦВЕТОМcase 2:for(uint16_t t=0; t<led.count(); t++){// Проходим по всем светодиодамint8_t i=random(3);// Определяем какой из трех составляющих цветов будет отсутствовать R, G, или Bif(i==0){r=0;}else{r=random(0xFF);}// Определяем случайное значение для переменной rif(i==1){g=0;}else{g=random(0xFF);}// Определяем случайное значение для переменной gif(i==2){b=0;}else{b=random(0xFF);}// Определяем случайное значение для переменной b led.setColor(t,// Устанавливаем цвет r,g,b для случайного светодиода map(r, 0, 255, 0, brightness),// Задаём зависимость яркости красного от параметра brightness, который определяется в настройках яркости map(g, 0, 255, 0, brightness),// Задаём зависимость яркости зелёного от параметра brightness, который определяется в настройках яркости map(b, 0, 255, 0, brightness));// Задаём зависимость яркости синего от параметра brightness, который определяется в настройках яркости} led.write();// Записываем цвета в светодиоды delay(z);// Устанавливаем задержкуbreak; //==========================================================// // ВСЕ СВЕТОДИОДЫ ЗАЖИГАЮТСЯ ОДНИМ ЦВЕТОМcase 3:uint16_t f;// Определяем переменную как коэффициент яркостиif(f==0){f=42; }else// f=60° (0 ... 42 ... 255 = 0° ... 60° ... 360°)if(f==42 ){f=85; }else// f=120° (0 ... 85 ... 255 = 0° ... 120° ... 360°)if(f==85 ){f=127;}else// f=180° (0 ... 127 ... 255 = 0° ... 180° ... 360°)if(f==127){f=170;}else// f=240° (0 ... 170 ... 255 = 0° ... 240° ... 360°)if(f==170){f=212;}else// f=300° (0 ... 212 ... 255 = 0° ... 300° ... 360°)if(f==212){f=0;}// f=360° (0 ... 255 ... 255 = 0° ... 360° ... 360°)if(f<85) { b=0; r=f*3; g=255-r;}else// Перелив от зелёного к красному, через жёлтыйif(f<170){f-=85; g=0; b=f*3; r=255-b;}else// Перелив от красного к синему , через фиолетовый{f-=170; r=0; g=f*3; b=255-g;}// Перелив от синего к зелёному, через голубой led.setColor(NeoPixelAll,// Устанавливаем выбранный цвет для очередного светодиода map(r, 0, 255, 0, brightness),// Задаём зависимость яркости красного от параметра brightness, который определяется в настройках яркости map(g, 0, 255, 0, brightness),// Задаём зависимость яркости зелёного от параметра brightness, который определяется в настройках яркости map(b, 0, 255, 0, brightness));// Задаём зависимость яркости синего от параметра brightness, который определяется в настройках яркости led.write();// Записываем цвета в светодиоды delay(z*10);// Устанавливаем задержкуbreak; //==========================================================//// ГОРИТ СВЕЧАcase 4:for(uint16_t m=0; m<led.count(); m++){// Проходим по всем светодиодамif(m%2==0){// Каждый второй светодиод настраиваем гореть красным r = random(10,50);// Определяем случайное значение яркости красного led.setColor(m,// Устанавливаем выбранный цвет для очередного светодиода map(r, 0, 255, 0, brightness),// Задаём зависимость яркости красного от параметра brightness, который определяется в настройках яркости0,// Устанавливаем зелёный равным 00);// Устанавливаем синий равным 0}else {// Оставшиеся светодиоды настраиваем гореть жёлтым r = random(50,256); g = r;// Определяем случайное значение яркости жёлтого led.setColor(m,// Устанавливаем выбранный цвет для очередного светодиода map(r, 0, 255, 0, brightness),// Задаём зависимость яркости красного от параметра brightness, который определяется в настройках яркости map(g, 0, 255, 0, brightness),// Задаём зависимость яркости зелёного от параметра brightness, который определяется в настройках яркости0);// Устанавливаем синий равным 0}} led.write();// Записываем цвета в светодиоды delay(random(10,100));// Устанавливаем случаное значение времени задержки для имитации горенияbreak; //==========================================================//// ГОРИТ КРАСНЫМcase 5: r = 255; g = 0; b = 0;// Выставляем значение RGB-спектра в красный цвет led.setColor(NeoPixelAll,// Устанавливаем выбранный цвет для всех светодиодов map(r, 0, 255, 0, brightness),// Задаём зависимость яркости красного от параметра brightness, который определяется в настройках яркости g,// Устанавливаем зелёный равным 0 b);// Устанавливаем синий равным 0 led.write();// Записываем цвета в светодиодыbreak; //==========================================================//// ГОРИТ ЗЕЛЁНЫМcase 6: r = 0; g = 255; b = 0;// Выставляем значение RGB-спектра в зелёный цвет led.setColor(NeoPixelAll,// Устанавливаем выбранный цвет для всех светодиодов r,// Устанавливаем красный равным 0 map(g, 0, 255, 0, brightness),// Задаём зависимость яркости зелёного от параметра brightness, который определяется в настройках яркости b);// Устанавливаем синий равным 0 led.write();// Записываем цвета в светодиодыbreak; //==========================================================//// ГОРИТ СИНИМcase 7: r = 0; g = 0; b = 255;// Выставляем значение RGB-спектра в синий цвет led.setColor(NeoPixelAll,// Устанавливаем выбранный цвет для всех светодиодов r,// Устанавливаем красный равным 0 g,// Устанавливаем зелёный равным 0 map(b, 0, 255, 0, brightness));// Задаём зависимость яркости синего от параметра brightness, который определяется в настройках яркости led.write();// Записываем цвета в светодиодыbreak; //==========================================================//// ГОРИТ ЖЁЛТЫМcase 8: r = 255; g = 255; b = 0;// Выставляем значение RGB-спектра в жёлтый цвет led.setColor(NeoPixelAll,// Устанавливаем выбранный цвет для всех светодиодов map(r, 0, 255, 0, brightness),// Задаём зависимость яркости красного от параметра brightness, который определяется в настройках яркости map(g, 0, 255, 0, brightness),// Задаём зависимость яркости зелёного от параметра brightness, который определяется в настройках яркости b);// Устанавливаем синий равным 0 led.write();// Записываем цвета в светодиодыbreak; //==========================================================//// ГОРИТ ФИОЛЕТОВЫЙcase 9: r = 255; g = 0; b = 255;// Выставляем значение RGB-спектра в фиолетовый цвет led.setColor(NeoPixelAll,// Устанавливаем выбранный цвет для всех светодиодов map(r, 0, 255, 0, brightness),// Задаём зависимость яркости красного от параметра brightness, который определяется в настройках яркости g,// Устанавливаем зелёный равным 0 map(b, 0, 255, 0, brightness));// Задаём зависимость яркости синего от параметра brightness, который определяется в настройках яркости led.write();// Записываем цвета в светодиодыbreak; //==========================================================//// ГОРИТ ГОЛУБЫМcase 10: r = 0; g = 255; b = 255;// Выставляем значение RGB-спектра в голубой цвет led.setColor(NeoPixelAll,// Устанавливаем выбранный цвет для всех светодиодов r,// Устанавливаем красный равным 0 map(g, 0, 255, 0, brightness),// Задаём зависимость яркости зелёного от параметра brightness, который определяется в настройках яркости map(b, 0, 255, 0, brightness));// Задаём зависимость яркости синего от параметра brightness, который определяется в настройках яркости led.write();// Записываем цвета в светодиодыbreak; //==========================================================//// ГОРИТ БЕЛЫМcase 11: r = 255; g = 255; b = 255;// Выставляем значение RGB-спектра в красный цвет led.setColor(NeoPixelAll,// Устанавливаем выбранный цвет для всех светодиодов map(r, 0, 255, 0, brightness),// Задаём зависимость яркости красного от параметра brightness, который определяется в настройках яркости map(g, 0, 255, 0, brightness),// Задаём зависимость яркости зелёного от параметра brightness, который определяется в настройках яркости map(b, 0, 255, 0, brightness));// Задаём зависимость яркости синего от параметра brightness, который определяется в настройках яркости led.write();// Записываем цвета в светодиодыbreak; //==========================================================//// ВЫКЛЮЧЕНОcase 12: r = 0; g = 0; b = 0;// Выставляем значение RGB-спектра в чёрный цвет (включено) led.setColor(NeoPixelAll,// Устанавливаем выбранный цвет для всех светодиодов r,// Устанавливаем красный равным 0 g,// Устанавливаем зелёный равным 0 b);// Устанавливаем синий равным 0 led.write();// Записываем цвета в светодиодыbreak;} //==========================================================//// РЕЖИМ НАСТРОЙКИ ЯРКОСТИ:if(setting){// Если стоит флаг входа в режим настройки, то проверяем...if(work_time+waiting_time > millis()){// с момента входа в режим настройки не прошло ли время waiting_time, и если не прошло то...if(flg){// проверяем, стоит ли флаг смены режима работы датчика жестов. Если стоит, то flg = 0;// сбрасываем флаг, apds.disableGestureSensor(); delay(500); // выключаем режим чтения жестов, ждём 0,5с, apds.enableProximitySensor(false);// включаем режим чтения приближения, led.setColor(NeoPixelAll,0 ,0 ,0 ); led.write(); delay(
Станьте первым!