Главная chevron_right Наши уроки chevron_right Arduino chevron_right Arduino тыква — готовимся к Хэллоуину

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

Собираем Arduino-тыкву к Хэллоуину: датчик расстояния HC-SR04 определяет зону и запускает светозвуковую анимацию с NeoPixel и MP3-плеером

Видео-обложка запускается при наведении

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

В этом уроке мы создадим тематическое устройство, которое можно использовать как украшение стола, а именно 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-SR04

DFRobotDFPlayerMini 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-SR04

uint8_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 или нет;Если не истекло, то задаём режим работы светодиодных модулей;Если истекло, то гасим все светодиоды и сбрасываем флаг;

Ссылки:

Комплект для повторения проекта

Что понадобится

Это быстрый ориентир по основным модулям и деталям. Полный список для повторения проекта смотрите в самой статье.

9 позиций
Ультразвуковой дальномер HC-SR04 Сенсор определения расстояния до 4 м по отраженному звуковому сигналу Открыть в iArduino Arduino Uno R3 (USB ATmega16U2) Платформа c микроконтроллером ATmega328P на ядре AVR с чипом USB ATmega16U2 для разработки электронных устройств на языке C++ Открыть в iArduino Piranha Uno R3 Прямой аналог Arduino Uno c микроконтроллером ATmega328P на ядре AVR для разработки электронных устройств на языке C++ Открыть в iArduino Battery Shield (Li-po, 2300 мА·ч) Battery Shield Открыть в iArduino Trema Shield Плата расширения для удобного подключения периферийных устройств Открыть в iArduino NeoPixel (Trema-модуль) Модуль с четырьмя адресными RGB светодиодами, их «адресность» позволяет управлять цветом каждого светодиода Открыть в iArduino Mini MP3-плеер Компактный MP3-модуль, управляемый по UART Открыть в iArduino Динамик 40мм, 3W, 4Ом. Динамик Открыть в iArduino Конструктор ПВХ Чёрный «Пластина XL» Основа из которой можно вырезать любую деталь решетчатого конструктора Открыть в iArduino
Все уроки Arduino