====== Новогодняя 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-ленты — светомузыкальную установку.