====== Новогодняя SMS-ёлка ====== {{ :projects:christmastree:christmastree_overview.jpg?nolink&700 |}} * Платформы: Iskra Neo * Языки программирования: Arduino (C++) * Тэги: Merry Christmas, WS2811, GPRS, гирлянда, адресная светодиодная лента RGB, ёлка, IP-камера ===== Что это? ===== Ни один Новый Год не обходится без ёлки, гирлянды и подарков. Мы расскажем как прокачать вашу ёлку так, что она будет удивлять и ослеплять всех ваших гостей. Сделаем гирлянду, цвет свечения которой может изменить каждый с помощью SMS. В сообщении достаточно отправить число от 0 до 360, которое определяет оттенок (Hue) по цветовому кругу, по модели HSV. {{ :projects:christmastree:christmastree_hsv.png?nolink |}} Приняв сообщение, устройство переведёт цвет в нужное для ленты RGB-значение и с помощью незамысловатой анимации изменит цвет на новый. ===== Что нам понадобится? ===== {{ :projects:christmastree:christmastree_parts2.jpg?nolink&700 |}} - [[amp>product/iskra-neo?utm_source=proj&utm_campaign=ny2016&utm_medium=wiki | Iskra Neo]] - [[amp>product/arduino-gprs-shield?utm_source=proj&utm_campaign=ny2016&utm_medium=wiki | GPRS Shield]] - [[amp>product/ws2811-led-strip-sealed?utm_source=proj&utm_campaign=ny2016&utm_medium=wiki | Адресная светодиодная лента RGB]] - [[amp>product/structor-mega?utm_source=proj&utm_campaign=ny2016&utm_medium=wiki | Пластина мега (#Структор)]] - [[amp>product/21mm-jack?utm_source=proj&utm_campaign=ny2016&utm_medium=wiki | Штекер питания 2,1 мм]] - [[amp>product/wire-mm?utm_source=proj&utm_campaign=ny2016&utm_medium=wiki | Соединительные провода «папа-папа»]] - SIM-карта - Блок питания (12 В, 12,5 А) - Влагозащищенный корпус - Евровилка сетевая с выключателем - Герметичный разъём (розетка + вилка) 4pin - Многожильный монтажный провод с сечением не менее 3×2,5 мм² (1 метр) - Многожильный монтажный провод с сечением не менее 1 мм² (2 шт. разного цвета) ===== Как собрать? ===== - Вставьте сим-карту в GPRS Shield и установите его на платформу Iskra Neo.{{ :projects:christmastree:christmastree_build1.jpg?nolink&700 |}} - Установите в герметичный корпус блок питания (12 В, 12,5 А) и «бутерброд» из платы Iskra Neo и GPRS Shield’a, используя мегапластину от #структора.{{ :projects:christmastree:christmastree_build2.jpg?nolink&700 |}} - Сделайте два отверстия в корпусе и установите через них евровилку и герметичный разъём (розетка).{{ :projects:christmastree:christmastree_build3.jpg?nolink&700 |}} - Соедините клеммы входного напряжения блока питания ''L'' и ''N'' с евровилкой, используя монтажные провода из кабеля 3×2,5. А клеммы выходного напряжения ''−V'' и ''+V'' — с герметичным разъёмом для питания светодиодной ленты.{{ :projects:christmastree:christmastree_build4.jpg?nolink&700 |}} - Соедините цифровой пин ''6'' платформы Iskra Neo с герметичным разъёмом. По нему будут передаваться данные для контроллеров светодиодной ленты.{{ :projects:christmastree:christmastree_build5.jpg?nolink&700 |}} - Подключите выходное напряжение ''−V'' и ''+V'' от блока питания к плате Iskra Neo через внешний разъём, используя монтажные провода и штекер питания 2,1 мм.{{ :projects:christmastree:christmastree_build6.jpg?nolink&700 |}} - Используя многожильный монтажный провод с сечением 3×2,5 мм² и герметичный разъём (вилка), сделайте шнур для подключения RGB-ленты к блоку управления, по которому будет подаваться питание и данные для адресной светодиодной ленты: - питание ''+V'' — коричневый; - земля ''−V'' — синий; - сигнальный — зелёный.{{ :projects:christmastree:christmastree_build7.jpg?nolink&700 |}} - Далее соедините полученные проводники с адресной светодиодной лентой через клеммы. - В заключении подключите сетевой шнур в евровилку, а герметичный разъём со шнуром (вилка) — в герметичный разъём в корпусе (розетка) {{ :projects:christmastree:christmastree_build8.jpg?nolink&700 |}} {{:продукты:magic-fogg.png?nolink |}}**//Внимание!//** Если необходимо подключить несколько светодиодных лент, недостаточно подключить вторую ленту к первой последовательно. В таком случае первая лента может перегреваться, так как её токопроводящие дорожки рассчитаны на ток одной ленты. Перегрев в свою очередь значительно сокращает срок службы светодиодов. Правильный вариант – выходной сигнальный провод первой ленты оставить соединённым с входным сигналом второй ленты, а выводы питания и земли каждой ленты подключить непосредственно к выводам блока питания. {{ :projects:christmastree:christmastree_scheme.png?nolink |}} ===== Алгоритм ===== * Сразу после подачи питания проверяем есть ли связь с GPRS устройством. * Если связи нет, повторяем запрос снова и ждём подтверждения связи. * Ожидаем приём новых сообщений. * Если их нет, повторяем запрос снова и снова. * Читаем сообщение и проверяем содержимое его текста: * Если в тексте число 0–360, меняем по сегментам цвет гирлянды по шкале ''HSV'' и отчитываемся об изменении обратным смс. * Если текст не распознан, отправляем обратное смс об ошибке распознавания команды. ===== Исходный код ===== // библиотека для эмуляции Serial-порта // она нужна для работы библиотеки GPRS_Shield_Arduino #include // библиотека для работы с GPRS устройством #include // библиотека для работы с адресной RGB-лентой #include // номер пина, к которому подключен сигнальный провод ленты #define PIXEL_PIN 6 // количество сегментов в ленте #define PIXEL_COUNT 200 // текст сообщения, об удачном изменении цвета ленты #define MESSAGE_OK "Well done! "\ "You are hacked our Christmas Tree. Happy New Year 2016!" // текст сообщения, об ошибки ввода смс #define MESSAGE_ERROR "Whoops! Something wrong."\ "Your attempt is failed." // текст сообщения, о включении секретного режима #define MESSAGE_BONUS "You are hacked our Christmas Tree."\ "Secret mod has been activated. Happy New Year 2016!" // длина входящего сообщения сообщения #define MESSAGE_LENGTH 160 // массив текста сообщения char message[MESSAGE_LENGTH]; // номер, с которого пришло сообщение char phone[16]; // дата отправки сообщения char datetime[24]; // создаём объект класса GPRS и передаём в него объект Serial1 GPRS gprs(Serial1); // можно указать дополнительные параметры — пины PK и ST // по умолчанию: PK = 2, ST = 3 // GPRS gprs(Serial1, 2, 3); // если используете плату Arduino Uno или Arduino Mega2560 // прочтите внимательно статью о GPRS Shield, что бы сделать некоторые исправления // создаём объект класса Adafruit_NeoPixel Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, NEO_BRG + NEO_KHZ800); // переменные, содержащие насыщенность красного, синего и зелёного цветов int r, g, b; void setup() { // инициализация светодиодной ленты strip.begin(); strip.show(); // включаем GPRS шилд gprs.powerOn(); // проверяем, есть ли связь с GPRS-устройством while (!gprs.init()) { // если связи нет, ждём 1 секунду // процесс повторяется в цикле, // пока не появится ответ от GPRS устройства delay(1000); } // заполняем RGB-ленту по сегментам «бегущий огонь» colorWipe(strip.Color(190, 0, 255), 50); // гасим RGB-ленту по сегментам «бегущая тень» colorWipe(strip.Color(0, 0, 0), 50); } void loop() { // если пришло новое сообщение if (gprs.ifSMSNow()) { // сохраняем текст, номер с которого пришло и дату приёмки в переменные gprs.readSMS(message, phone, datetime); // проверяем подходит ли текст сообщения по нужный формат if (checkSMS() == 0) { // если нет, отправляем на номер с которого пришло сообщение // о неправильном формате смс gprs.sendSMS(phone, MESSAGE_ERROR); // возвращаемся в функцию loop и ожидаем нового сообщения return; } // переводим текст сообщения в целочисленную переменную int value = atoi(message); // проверка входит ли число в диапазон шкалы «HSV» if (value >= 0 && value <= 360) { // если да, отправляем на номер с которого пришло сообщение // об удачном смене цвета гирлянды gprs.sendSMS(phone, MESSAGE_OK); // переводим значение цвета из шкалы «HSV» в «RGB» f_HSV_to_RGB(value, 255, 255); // заполняем RGB-ленту по сегментам выбранным пользователем цветом colorWipe(strip.Color(r, g, b), 50); } else if (value == 2016) { // если число оказалось лотерейным // отправляем на номер с которого пришло сообщение // о включении секретного режима гирлянды gprs.sendSMS(phone, MESSAGE_BONUS); // включаем мигающий градиент цветов theaterChaseRainbow(50); // возвращаем предыдущий цвет RGB-ленты colorWipe(strip.Color(r, g, b), 50); } else { // если число не попало не в один диапазон чисел // отправляем на номер с которого пришло сообщение // о неправильном формате смс gprs.sendSMS(phone, MESSAGE_ERROR); } } } // функция проверки формата смс-сообщения bool checkSMS() { // создаём переменную и присваиваем ей длину текста сообщения int len = strlen(message); // если длина смс больше 4 символов или равна 0 if (len == 0 || len > 4) { // выходим из функции и возвращаем «ложь» return false; } // проверка всех символов текста смс for (int i = 0; i < len; i++) { // если в тексте есть хотя бы одна не цифра if (message[i] < '0' || message[i] > '9') { // выходим из функции и возвращаем «ложь» return false; } } // если все условия выполнеы возвращаем «истину» return true; } // функция перевода цвета из шкалы «HSV» в «RGB» void f_HSV_to_RGB(int hue, int sat, int val) { int base; if (sat == 0) { r = val; g = val; b = val; } else { base = ((255 - sat) * val) >> 8; switch (hue / 60) { case 0: { r = val; g = (((val - base) * hue) / 60) + base; b = base; break; } case 1: { r = (((val - base) * (60 - (hue % 60))) / 60) + base; g = val; b = base; break; } case 2: { r = base; g = val; b = (((val - base) * (hue % 60)) / 60) + base; break; } case 3: { r = base; g = (((val - base) * (60 - (hue % 60))) / 60) + base; b = val; break; } case 4: { r = (((val - base) * (hue % 60)) / 60) + base; g = base; b = val; break; } case 5: { r = val; g = base; b = (((val - base) * (60 - (hue % 60))) / 60) + base; break; } case 6: { r = val; g = 0; b = base; break; } } } } // функция заполнения каждого сегмента void colorWipe(uint32_t c, uint8_t wait) { for (uint16_t i = 0; i < strip.numPixels(); i++) { // заполняем текущий сегмент выбранным цветом strip.setPixelColor(i, c); strip.show(); // ждём delay(wait); } } // функция эффекта радуги void theaterChaseRainbow(uint8_t wait) { for (int j = 0; j < 256; j++) { for (int q = 0; q < 3; q++) { for (int i = 0; i < strip.numPixels(); i = i + 3) { // включаем каждый третий сегмент strip.setPixelColor(i + q, wheel((i+j) % 255)); } strip.show(); // ждём delay(wait); for (int i = 0; i < strip.numPixels(); i = i + 3) { // выключаем каждый третий сегмент strip.setPixelColor(i+q, 0); } } } } uint32_t wheel(byte wheelPos) { wheelPos = 255 - wheelPos; if (wheelPos < 85) { return strip.Color(255 - wheelPos * 3, 0, wheelPos * 3); } if (wheelPos < 170) { wheelPos -= 85; return strip.Color(0, wheelPos * 3, 255 - wheelPos * 3); } wheelPos -= 170; return strip.Color(wheelPos * 3, 255 - wheelPos * 3, 0); } Для компиляции скетча вам понадобятся библиотеки [[https://github.com/amperka/gprs-shield|GPRS-shield]] и [[https://github.com/adafruit/Adafruit_NeoPixel|Adafruit_NeoPixel]]. ===== Демонстрация работы устройства ===== {{youtube>SCqW3nglgIU?large}} ===== Что дальше? ===== Заменив в своём проекте [[amp>product/arduino-gprs-shield?utm_source=proj&utm_campaign=ny2016&utm_medium=wiki | GPRS Shield]] на [[amp>product/troyka-sound-loudness-sensor?utm_source=proj&utm_campaign=ny2016&utm_medium=wiki | датчик шума]] вы дадите уши своему проекту. И получите из RGB-ленты — светомузыкальную установку.