Arduino тыква — готовимся в Хэллоуину

Arduino тыква — готовимся в Хэллоуину

Уроки и проекты /

Общие сведения:

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

У датчика существует 2 зоны чувствительности (в зависимости от расстояния от датчика), попав в каждую из которых будет выполняться светозвуковая анимация.

Видео:

Нам понадобится:

    Для реализации проекта нам необходимо установить библиотеки:

    О том, как устанавливать библиотеки, Вы можете ознакомиться на странице Wiki - Установка библиотек в Arduino IDE.

    Описание работы устройства:

    После подачи питания Arduino-тыква готова к работе.

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

    Схема сборки:

    Arduino / Piranha UNO:

    Batery Shield:

    Установите Battery Shield на Arduino / Piranha UNO:
    Во время установки Battery Shield должен быть в выключенном состоянии.

    Trema Shield:

    На Battery Shield установите Trema Shield:

    MP3-плеер:

    Подключите MP3-плеер к Trema Shield и динамик к MP3-плееру:

    Так как выводы 0 и 1 зарезервированы под RX и TX, перед загрузкой скетча необходимо отключить плеер от платы, а после загрузки и перед использованием подключить обратно.

    Датчик расстояния

    Подключите датчик расстояния HC-SR04 к Trema Shield:

    Адресные светодиоды:

    Подключите адресные светодиоды NeoPixel к Trema Shield:

    Все используемые в уроке Trema-модули NeoPixel соединены друг c другом, а первый модуль можно подключить к любому выводу Arduino. Номер вывода указывается в скетче (в примере используется вывод D5). Чем больше модулей в цепи, тем больше тока она потребляет, поэтому в схеме используется стабилизированный источник питания Battery Shield на 5В постоянного тока.

    Код программы (скетч):

    #include <DFRobotDFPlayerMini.h>//  подключаем библиотеку для работы с MP3-плеером #include <iarduino_NeoPixel.h>//  подключаем библиотеку для работы со светодиодами NEoPixel #include <iarduino_HC_SR04_int.h>//  подключаем библиотеку для работы с датчиком расстояния HC-SR04DFRobotDFPlayerMini myDFPlayer;//  объявляем объект myDFPlayer для работы с плееромuint8_t       neo_pin      = 5;//  указываем вывод, к которому подключены светодиоды NeoPixel uint16_t      modul_number = 4;//  указываем количество модулей в цепи iarduino_NeoPixel led(neo_pin, modul_number * 4 );//  объявляем объект led для работы со светодиодами NeoPixel iarduino_HC_SR04_int sensor(3, 2);//  объявляем объект sensor для работы с датчиком расстояния HC-SR04uint8_t       j;//  Объявляем переменную для хранения значения сдвига спектра цветов для всех светодиодов (от 0 до 255) uint8_t       r, g, b;//  Объявляем переменную для хранения цветов RGB для каждого светодиода uint32_t      timer1, timer2;//  счётчики времени при срабатывании анимации uint32_t      timer3;//  счётчик времени при включении светодиодной подсветки тыквы uint32_t      hcsr_waiting_time_far   = 600000;//  время ожидания повтора анимации ДВИЖЕНИЕ ВДАЛЕКЕ uint32_t      hcsr_waiting_time_near  = 60000;//  время ожидания повтора анимации ДВИЖЕНИЕ ВБЛИЗИ uint32_t      action_time             = 10000;//  время работы анимации uint8_t       flg_near, flg_far;//  флаги для включения анимации uint8_t       rev_flg;//  флаг включения реверса при счёте uint8_t       p;//  переменная для хранения номера светодиода при сдвиге uint8_t       l;//  переменная для хранения значения яркости светодиодовvoid setup() {Serial.begin(9600);//  инициируем работу Монитора последовательного порта на скорости 9600бод   myDFPlayer.begin(Serial);//  указываем последовательный порт для общения с MP3-плеером   led.begin();//  инициализируем адресные светодиоды   led.setColor(NeoPixelAll, 0, 0, 0);//  указываем всем светодиодам погаснуть   led.write();//  выключаем светодиоды   randomSeed(analogRead(0));//  инициируем генератор псевдослучайных чисел   sensor.distance();//  запрашиваем значение расстояния   delay(500);//  задержка 0.5сек }void loop() {//====================================================================//  //====================================================================//  if (sensor.distance() >= 1 && sensor.distance() <= 15) {//  Проверяем, если расстояние до препятствия от 1 до 15см, тоif(millis() > timer1 + hcsr_waiting_time_near || flg_near ==0){//  проверяем, прошло ли заданное время после последней сработки, или сброшен ли флаг при первом запуске, и если да, то         flg_near = true;//  ставим флаг,         timer1 = millis();//  обновляем значение таймера,         myDFPlayer.volume(20);//  выставляем уровень громкости плеера         myDFPlayer.play(4);//  указываем плееру включить 4 трек}}if (sensor.distance() >= 30 && sensor.distance() <= 70) {//  Проверяем, если расстояние до препятствия от 30 до 70 см, тоif(millis() > timer2 + hcsr_waiting_time_far || flg_far ==0){//  проверяем, прошло ли заданное время после последней сработки, или сброшен ли флаг при первом запуске, и если да, то         flg_far = true;//  ставим флаг,         timer2 = millis();//  обновляем значение таймера,         myDFPlayer.volume(15);//  выставляем уровень громкости плеера         myDFPlayer.play(5);//  указываем плееру включить 5 трек         l = 0;//  обнуляем переменную для изменения значения яркости светодиодов}}//====================================================================// //====================================================================// if (flg_near) {//  Если был установлен флаг ПРЕПЯТСТВИЕ БЛИЗКО, тоif(millis() < timer1 + action_time){//  проверяем, прошло ли заданное время на выполнение анимации, и если нет, то//============================================================//  //  БЛОК РАБОТЫ ВНУТРЕННЕЙ ПОДСВЕТКИif (millis() > timer3 + 500) {//  Проверяем, прошло ли время с момента последнего выполнения блока, и если нет, то         timer3 = millis();//  обновляем значение таймера,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;}//  перелив от синего   к зелёному, через голубойfor (uint8_t t = 0; t < 8; t++) {led.setColor(t, r, g, b);}//  устанавливаем выбранный цвет для очередного светодиода}//============================================================//  //  БЛОК РАБОТЫ "ГЛАЗ" - эффект "бегающих" по кругу глаз         p++;//  увеличиваем значение переменной на 1 при каждом выполнении циклаif (p == 4) p = 0;//  при превышении значения сбрасываем его         led.setColor(8 + p, 255, 0, 0);//  указываем указанному светодиоду на левом модуле гореть красным         led.setColor(12 + p, 255, 0, 0);//  указываем указанному светодиоду на правом модуле гореть красным         led.setColor(7 + (p ? p : 4), 127, 127, 127);//  указываем всем остальным светодиодам на левом модуле гореть белым         led.setColor(11 + (p ? p : 4), 127, 127, 127);//  указываем всем остальным светодиодам на правом модуле гореть белым//============================================================//         led.write();//  записываем указанные цвета в модули         delay(100);//  задержка 100мс} else {//  Если время выполнения анимации закончилось, то       flg_near = false;//  Сбрасываем флаг       led.setColor(NeoPixelAll, 0, 0, 0);//  устанавливаем цвет всех светодиодов в чёрный(гасим)       led.write();//  записываем указанный цвет в модули}}//====================================================================//  //====================================================================//  else if (flg_far) {//  Если был установлен флаг ПРЕПЯТСТВИЕ ДАЛЕКО, тоif(millis() < timer2 + action_time){//  проверяем, прошло ли заданное время на выполнение анимации, и если нет, тоif (!rev_flg) {//  проверяем, установлен флаг реверса, и если нет, то         l++;//  увеличиваем значение яркости на 1 при кажом выполнении цикла         r = l; g = 0; b = 0;//  устанавливаем светодиодам внутри красный цвет, и задаём яркостьfor (uint8_t e = 0; e < 8; e++) {//  проходим по указанным светодиодам (установленным внутри)           led.setColor(e, r, g, b);//  задаём указанным светодиодам яркость и цвет}         led.write();//  записываем указанный цвет и яркость в модули         delay(19);//  задержка 19мсif (l == 255) rev_flg = 1;//  при достижении максимального значения яркости устанавливаем флаг реверса} else {//  Если установлен флаг реверса, то           l--;//  уменьшаем значение яркости на 1 при каждом выполнении цикла           r = l; g = 0; b = 0;//  устанавливаем светодиодам внутри красный цвет, и задаём яркостьfor (uint8_t e = 0; e < 8; e++) {//  проходим по указанным светодиодам (установленным внутри)             led.setColor(e, r, g, b);//  задаём указанным светодиодам яркость и цвет}           led.write();//  записываем указанный цвет и яркость в модули           delay(19);//  задержка 19мсif (l == 0) rev_flg = 0;//  при достижении минимального значения яркости сбрасываем флаг реверса}} else {//  Если время выполнения анимации закончилось, то       flg_far = false;//  Сбрасываем флаг       led.setColor(NeoPixelAll, 0, 0, 0);//  устанавливаем цвет всех светодиодов в чёрный(гасим)       led.write();//  записываем указанный цвет в модули}} }

    Алгоритм работы скетча:

    До кода void setup() определяются переменные, подключаются необходимые библиотеки.

    В коде void setup() инициализируется MP3-плеер, адресные светодиоды NeoPixel, датчик расстояния, выключаются светодиоды, если до этого они горели.

    Код void loop() делится 2 части:

    • Проверяется, обнаружил ли датчик расстояния препятствие в одной из 2 указанных зон:
      • Если препятствие находится вблизи, то запускается трек 4, ставится флаг наличия препятствия flg_near в данной зоне, обнуляется счётчик времени timer1, фиксирующий наступление события, чтобы в следующий раз оно сработало через время hcsr_waiting_time_near;
      • Если препятствие находится вдалеке, то запускается трек 5, ставится флаг наличия препятствия flg_far в данной зоне, обнуляется счётчик времени timer2, фиксирующий наступление события, чтобы в следующий раз оно сработало через время hcsr_waiting_time_far;
    • Проверяется, был ли установлен флаг наличия препятствия:
      • Если препятствие было обнаружено вблизи (установлен флаг flg_near):
        • Проверяем, истекло время выполнения анимации timer1 + action_time или нет;
          • Если не истекло, то задаём режим работы светодиодных модулей;
          • Если истекло, то гасим все светодиоды и сбрасываем флаг;
      • Если препятствие было обнаружено вдалеке (установлен флаг flg_far):
        • Проверяем, истекло время выполнения анимации timer2 + action_time или нет;
          • Если не истекло, то задаём режим работы светодиодных модулей;
          • Если истекло, то гасим все светодиоды и сбрасываем флаг;

      Ссылки:

      Теги: logani 0


      Станьте первым!

      Пожалуйста, авторизуйтесь или зарегистрируйтесь для комментирования!