КОРЗИНА
магазина
8 (499) 500-14-56 | ПН. - ПТ. 12:00-18:00
ЛЕСНОРЯДСКИЙ ПЕРЕУЛОК, 18С2, БЦ "ДМ-ПРЕСС"

Урок 36. Гирлянда из Trema-модулей NeoPixel

В этом уроке мы создадим гирлянду из Trema-модулей NeoPixel. Каждый модуль состоит из четырёх адресных светодиодов и имеет один вход и один выход. Модули можно соединять друг с другом (выход одного модуля подключается ко входу другого), получив гирлянду из модулей. Управление цветами каждого светодиодов, происходит с использованием всего одного вывода Arduino.

Собираемая нами схема состоит из 30 модулей (количество указывается в скетче), по 4 адресных светодиода в каждом, значит всего 120 светодиодов. Каждый светодиод может потреблять до 45 мА (при белом свечении), значит вся гирлянда может потреблять до 5,4 А (120 x 45 мА). Разумеется это максимум и по алгоритму скетча мы его не достигнем, но для сборки гирлянды потребуются провода с большим сечением, как у проводов из набора МАМА-МАМА 20AWG.

Меняя значения четырёх констант скетча Вы можете изменить: номер вывода Arduino, количество используемых Trema-модулей NeoPixel, количество модулей между шарами и время на которое будет устанавливаться очередное состояние гирлянды.

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

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

  • iarduino_NeoPixel для работы с адресными светодиодами.

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

Видео:


Схема подключения:

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

Ёлочная гирлянда на адресных светодиодах

Алгоритм работы:

Работа адресных светодиодов:
  • На выходе Arduino формируется последовательность импульсов:
    • короткий импульс означает, что бит равен 0.
    • длинный импульс означает, что бит равен 1.
  • Светодиод подключенный первым к выводу Arduino «берёт» себе первые сформированные 24 бита (3 байта) указывающие яркость трёх цветов GBR. А все остальные биты светодиод пропускает, передавая их на свой выход, к которому подключён вход следующего светодиода.
  • Второй светодиод, так же, «берёт» себе первые полученные им 24 бита (3 байта) которые пропустил первый светодиод. Но на самом деле это вторые 3 байта которые сформировались на выходе Arduino, т.к. первые 3 байта «забрал» первый светодиод.
  • Как только импульсы перестали формироваться на выходе Arduino, светодиоды ждут до 50 мкс, после чего устанавливают полученный (взятый из потока данных) ими цвет.
  • Светодиоды находящиеся в модуле подключённом первым к выводу Arduino имеют номера 0-3, в следующем 4-7 и т.д.
Работа с библиотекой iarduino_NeoPixel:
  • После подключения библиотеки нужно объявить объект, указав номер вывода Arduino и количество используемых светодиодов.
  • В коде setup() необходимо инициировать работу с адресными светодиодами вызвав функцию begin() объекта библиотеки.
  • Вызывая функцию setColor(,R,G,B) объекта библиотеки, можно установить любой цвет для любого светодиода, но эта функция не передаёт цвет светодиоду, а сохраняет его в памяти. Номер светодиода должен находиться в пределах от 0 до 65534, а каждое из значений составляющих цвет (RGB) в пределах от 0 до 255. Если вместо номера указать NeoPixelAll, то цвет установится для всех светодиодов.
  • Вызов функции write() объекта библиотеки приведёт к передачи всех установленных ранее цветов во все используемые светодиоды. Именно после вызова данной функции светодиоды меняют свои цвета.

Все функции библиотеки iarduino_NeoPixel описаны в разделе Wiki - Адресные светодиоды, модули NeoPixel.

Работа скетча:
  • В начале скетча определены четыре константы pinNum, modSum, modShift и durationState. Меняя их значение Вы можете изменить: номер вывода Arduino, количество используемых Trema-модулей NeoPixel, количество модулей между шарами и время на которое будет устанавливаться очередное состояние гирлянды (в секундах).
  • Далее подключается библиотека iarduino_NeoPixel, объявляется объект библиотеки, а также используемые переменные и функции.
  • Код loop() состоит из оператора switch() в котором выполняется только тот участок кода, который совпадает с номером состояния в переменной garlandState. А после оператора switch() имеется код который меняет значение переменной garlandState через каждые durationState секунд.
  • В конце кода определены три функции:
    • Функция setColorModule(,R,G,B) выполняет то же самое что и функция setColor(,R,G,B) объекта библиотеки iarduino_NeoPixel, но принимает не номер светодиода, а номер Trema-модуля NeoPixel, устанавливая цвет для всех его светодиодов.
    • Функция setColorBall(,R,G,B) выполняет то же самое что и функция setColor(,R,G,B) объекта библиотеки iarduino_NeoPixel, но принимает не номер светодиода, а номер шара с Trema-модулем NeoPixel, устанавливая цвет для всех его светодиодов.
    • Функция getColorDeg(угол) принимает одно значение - угол, но не в градусах от 0 до 360, а в виде значения от 0 до 255. Если нарисовать радужный круг с переливом цветов (зелёный > красный > синий), то функция возвращает цвет (в переменные colR, colG и colB) на который указывает угол из центра этого круга.

Код программы:

/*  Скетч для работы гирлянды состоящей из Trema-модулей NeoPixel.
 *  Общее количество используемых Trema-модулей указывается в константе modSum.
 *  Номер вывода Arduino к которому подключена гирлянда указывается в константе pinNum.
 *  Гирлянда состоит из чередующихся игрушек (Trema-модулей в шарах) и Trema-модулей без шаров.
 *  Между каждым шаром должно быть одинаковое количество Trema-модулей (указывается в константе modShift).
 *  Гирлянда не может начинаться с шара.
 *  Состояние гирлянды (режим её работы) постоянно меняется через время указанное в константе durationState (в секундах).
 */
const uint8_t     pinNum        = 7;                                                           //  Определяем константу с указанием № вывода Arduino, к которому подключена гирлянда
const uint16_t    modSum        = 30;                                                          //  Определяем константу с указанием количества Trema-модулей NeoPixel в гирлянде
const uint8_t     modShift      = 2;                                                           //  Определяем константу с указанием количества Trema-модулей между шарами с Trema-модулями
const uint8_t     durationState = 6;                                                           //  Определяем константу с указанием количества секунд через которое будут меняться состояние гирлянды (режимы её работы)
#include          <iarduino_NeoPixel.h>                                                        //  Подключаем библиотеку iarduino_NeoPixel для работы со светодиодами NeoPixel
iarduino_NeoPixel led(pinNum,(modSum*4));                                                      //  Объявляем  объект led указывая (№ вывода Arduino с гирляндой, количество светодиодов в гирлянде)
uint8_t           garlandState=0;                                                              //  Определяем переменную хранящую состояние гирлянды
uint32_t          setTimeState;                                                                //  Объявляем  переменную для хранения времени последнего изменения состояния гирлянды
uint16_t          ballSum=modSum/(modShift+1);                                                 //  Определяем переменную хранящую количество шаров в гирлянде
uint8_t           colR,colG,colB;                                                              //  Определяем переменные которые будут использоваться для получения результирующего цвета
uint8_t           i=0, j=0;                                                                    //  Определяем переменные которые будут использоваться в разных участках кода по разному
void              setColorModule(uint16_t, uint8_t, uint8_t, uint8_t);                         //  Объявляем  функцию устанавливающую цвет для всех светодиодов на одном Trema-модуле (№_Trema-модуля, R, G, B)
void              setColorBall  (uint16_t, uint8_t, uint8_t, uint8_t);                         //  Объявляем  функцию устанавливающую цвет для Trema-модулей в шарах                  (№_шара,         R, G, B)
void              getColorDeg   (uint8_t);                                                     //  Объявляем  функцию возвращающую цвет в переменные colR,colG,colB по градусу        (градус от 0 до 255)
void setup(){led.begin();}                                                                     //  В функции setup выполняется только инициализация работы с адресными светодиодами
void loop(){
    switch(garlandState){                                                                      //  В зависимости от значения переменной garlandState, будет выполняться только один участок оператора switch
        case 0:  // Все шары гирлянды зажигаются одним из цветов радуги
                 if(i==0  ){i=42; }else                                                        //  i=60°  (0 ... 42  ... 255   =   0° ... 60°  ... 360°)
                 if(i==42 ){i=85; }else                                                        //  i=120° (0 ... 85  ... 255   =   0° ... 120° ... 360°)
                 if(i==85 ){i=127;}else                                                        //  i=180° (0 ... 127 ... 255   =   0° ... 180° ... 360°)
                 if(i==127){i=170;}else                                                        //  i=240° (0 ... 170 ... 255   =   0° ... 240° ... 360°)
                 if(i==170){i=212;}else                                                        //  i=300° (0 ... 212 ... 255   =   0° ... 300° ... 360°)
                 if(i==212){i=0;  }                                                            //  i=360° (0 ... 255 ... 255   =   0° ... 360° ... 360°)
                 getColorDeg(i);                                                               //  Получаем цвет в переменные colR,colG,colB по градусу i
                 setColorBall(NeoPixelAll,colR,colG,colB);                                     //  Устанавливаем цвет colR,colG,colB для всех шаров гирлянды
                 led.write(); delay(1000);                                                     //  Записываем установленные цвета и ждём 1 секунду
        break;
        case 1:  // Вся гирлянда зажигается одним из цветов радуги
                 if(i==0  ){i=42; }else                                                        //  i=60°  (0 ... 42  ... 255   =   0° ... 60°  ... 360°)
                 if(i==42 ){i=85; }else                                                        //  i=120° (0 ... 85  ... 255   =   0° ... 120° ... 360°)
                 if(i==85 ){i=127;}else                                                        //  i=180° (0 ... 127 ... 255   =   0° ... 180° ... 360°)
                 if(i==127){i=170;}else                                                        //  i=240° (0 ... 170 ... 255   =   0° ... 240° ... 360°)
                 if(i==170){i=212;}else                                                        //  i=300° (0 ... 212 ... 255   =   0° ... 300° ... 360°)
                 if(i==212){i=0;  }                                                            //  i=360° (0 ... 255 ... 255   =   0° ... 360° ... 360°)
                 getColorDeg(i);                                                               //  Получаем цвет в переменные colR,colG,colB по градусу i
                 setColorModule(NeoPixelAll,colR,colG,colB);                                   //  Устанавливаем цвет colR,colG,colB для всех Trema-модулей
                 led.write(); delay(1000);                                                     //  Записываем установленные цвета и ждём 1 секунду
        break;
        case 2:  // Случайные шары включаются случайным цветом
                 i=random(3);                                                                  //  Определяем какой из трех составляющих цветов будет отсутствовать R, G, или B
                 if(i==0){colR=0;}else{colR=random(0xFF);}                                     //  Определяем случайное значение для переменной colR
                 if(i==1){colG=0;}else{colG=random(0xFF);}                                     //  Определяем случайное значение для переменной colG
                 if(i==2){colB=0;}else{colB=random(0xFF);}                                     //  Определяем случайное значение для переменной colB
                 setColorBall(random(ballSum),colR,colG,colB);                                 //  Устанавливаем цвет colR,colG,colB для случайного шара
                 led.write(); delay(50);                                                       //  Записываем установленные цвета и ждём 50 миллисекунд
        break;
        case 3:  // Случайные модули включаются случайным цветом
                 i=random(3);                                                                  //  Определяем какой из трех составляющих цветов будет отсутствовать R, G, или B
                 if(i==0){colR=0;}else{colR=random(0xFF);}                                     //  Определяем случайное значение для переменной colR
                 if(i==1){colG=0;}else{colG=random(0xFF);}                                     //  Определяем случайное значение для переменной colG
                 if(i==2){colB=0;}else{colB=random(0xFF);}                                     //  Определяем случайное значение для переменной colB
                 setColorModule(random(modSum),colR,colG,colB);                                //  Устанавливаем цвет colR,colG,colB для случайного Trema-модуля
                 led.write(); delay(10);                                                       //  Записываем установленные цвета и ждём 10 миллисекунд
        break;
        case 4:  // Шрапнель одного из цветов радуги, которые будут меняться через каждые 20j
                 if(j>=20 ){j=0;                                                               //  Если переменная j >= 20, то сбрасываем j и меняем градус i:
                 if(i==0  ){i=42; }else                                                        //  i=60°  (0 ... 42  ... 255   =   0° ... 60°  ... 360°)
                 if(i==42 ){i=85; }else                                                        //  i=120° (0 ... 85  ... 255   =   0° ... 120° ... 360°)
                 if(i==85 ){i=127;}else                                                        //  i=180° (0 ... 127 ... 255   =   0° ... 180° ... 360°)
                 if(i==127){i=170;}else                                                        //  i=240° (0 ... 170 ... 255   =   0° ... 240° ... 360°)
                 if(i==170){i=212;}else                                                        //  i=300° (0 ... 212 ... 255   =   0° ... 300° ... 360°)
                 if(i==212){i=0;  }}                                                           //  i=360° (0 ... 255 ... 255   =   0° ... 360° ... 360°)
                 getColorDeg(i);                                                               //  Получаем цвет в переменные colR,colG,colB по градусу i
                 led.setColor(NeoPixelAll,0,0,0);                                              //  Гасим цвета для всех светодиодов
                 led.setColor(random(modSum*4),colR,colG,colB);                                //  Устанавливаем включённый цвет для первого    случайного светодиода
                 led.setColor(random(modSum*4),colR,colG,colB);                                //  Устанавливаем включённый цвет для второго    случайного светодиода
                 led.setColor(random(modSum*4),colR,colG,colB);                                //  Устанавливаем включённый цвет для третьего   случайного светодиода
                 led.setColor(random(modSum*4),colR,colG,colB);                                //  Устанавливаем включённый цвет для четвёртого случайного светодиода
                 led.setColor(random(modSum*4),colR,colG,colB);                                //  Устанавливаем включённый цвет для пятого     случайного светодиода
                 led.write(); delay(50);                                                       //  Записываем установленные цвета и ждём 50 миллисекунд
                 j++;                                                                          //  Увеличиваем переменную j. Как только она станет равна 20, то сменится цвет
        break;
        case 5:  // Шрапнель из случайных цветов
                 i=random(3);                                                                  //  Определяем какой из трех составляющих цветов будет отсутствовать R, G, или B
                 if(i==0){colR=0;}else{colR=random(0xFF);}                                     //  Определяем случайное значение для переменной colR
                 if(i==1){colG=0;}else{colG=random(0xFF);}                                     //  Определяем случайное значение для переменной colG
                 if(i==2){colB=0;}else{colB=random(0xFF);}                                     //  Определяем случайное значение для переменной colB
                 led.setColor(NeoPixelAll,0,0,0);                                              //  Гасим цвета для всех светодиодов
                 led.setColor(random(modSum*4),colR,colG,colB);                                //  Устанавливаем включённый цвет для первого    случайного светодиода
                 led.setColor(random(modSum*4),colR,colG,colB);                                //  Устанавливаем включённый цвет для второго    случайного светодиода
                 led.setColor(random(modSum*4),colR,colG,colB);                                //  Устанавливаем включённый цвет для третьего   случайного светодиода
                 led.setColor(random(modSum*4),colR,colG,colB);                                //  Устанавливаем включённый цвет для четвёртого случайного светодиода
                 led.setColor(random(modSum*4),colR,colG,colB);                                //  Устанавливаем включённый цвет для пятого     случайного светодиода
                 led.write(); delay(50);                                                       //  Записываем установленные цвета и ждём 50 миллисекунд
        break;
        case 6:  // Все шары гирлянды одновременно переливаются всеми цветами радуги
                 getColorDeg(i);                                                               //  Получаем цвет в переменные colR,colG,colB по градусу i
                 setColorBall(NeoPixelAll,colR,colG,colB);                                     //  Устанавливаем цвет colR,colG,colB для всех шаров
                 led.write(); delay(5);                                                        //  Записываем установленные цвета и ждём 5 миллисекунды
                 i++;                                                                          //  Увеличиваем градус i
        break;
        case 7:  // Вся гирлянда одновременно переливается всеми цветами радуги
                 getColorDeg(i);                                                               //  Получаем цвет в переменные colR,colG,colB по градусу i
                 setColorModule(NeoPixelAll,colR,colG,colB);                                   //  Устанавливаем цвет colR,colG,colB для всех модулей
                 led.write(); delay(5);                                                        //  Записываем установленные цвета и ждём 5 миллисекунды
                 i++;                                                                          //  Увеличиваем градус i
        break;
        case 8:  // Все шары гирлянды переливаются всеми цветами радуги
                 for(uint16_t k=0; k<ballSum; k++){                                            //  Проходим по всем шарам в гирлянде
                     i=((uint16_t)(k*256/ballSum)+j);                                          //  Определяем градус i для очередного шара на спектре цветов со смещением j
                     getColorDeg(i);                                                           //  Получаем цвет в переменные colR,colG,colB по градусу i
                     setColorBall(k,colR,colG,colB);                                           //  Устанавливаем цвет colR,colG,colB для очередного шара
                 }   led.write(); delay(2);                                                    //  Записываем установленные цвета и ждём 2 миллисекунды
                 j++;                                                                          //  Смещаем спектр цветов для всех шаров
        break;
        case 9:  // Вся гирлянда переливается всеми цветами радуги
                 for(uint16_t k=0; k<modSum; k++){                                             //  Проходим по всем модулям в гирлянде
                     i=((uint16_t)(k*256/modSum)+j);                                           //  Определяем градус i для очередного модуля на спектре цветов со смещением j
                     getColorDeg(i);                                                           //  Получаем цвет в переменные colR,colG,colB по градусу i
                     setColorModule(k,colR,colG,colB);                                         //  Устанавливаем цвет colR,colG,colB для очередного модуля
                 }   led.write(); delay(2);                                                    //  Записываем установленные цвета и ждём 2 миллисекунды
                 j++;                                                                          //  Смещаем спектр цветов для всех модулей
        break;
    }
//  Меняем состояние работы гирлянды
    if(millis()>setTimeState+(uint32_t)durationState*1000){                                    //  Если с последнего изменения состояния прошло более чем durationState сек, то..
        setColorModule(NeoPixelAll,0,0,0); led.write(); i=0; j=0;                              //  Гасим все модули и обнуляем переменные i и j
        garlandState++; if(garlandState>9){garlandState=0;}                                    //  Устанавливаем следующее состояние. Строку можно заменить на: garlandState=random(10);
        setTimeState=millis();                                                                 //  Сохраняем время смены состояния
    }
}
//  Функция устанавливающая цвет для всех светодиодов на одном Trema-модуле
void setColorModule(uint16_t n, uint8_t r, uint8_t g, uint8_t b){                              //  аргументы функции: (№_Trema-модуля, R, G, B)
    if(n!=NeoPixelAll){for(int i=0; i<4; i++){led.setColor((n*4+i),r,g,b);}}                   //  Устанавливаем цвет для каждого из 4 светодиодов Trema-модуля с номером n
    else              {                       led.setColor( n     ,r,g,b); }                   //  Устанавливаем цвет для всех светодиодов гирлянды
}
//  Функция устанавливающая цвет для Trema-модулей находящихся в шарах
void setColorBall(uint16_t n, uint8_t r, uint8_t g, uint8_t b){                                //  аргументы функции: (№_шара, R, G, B)
    if(n!=NeoPixelAll){setColorModule((n*(modShift+1)+modShift),r,g,b);}                       //  Устанавливаем цвет для Trema-модуля находящегося в шаре с номером n
    else              {for(int i=modShift; i<30; i+=(modShift+1)){setColorModule(i,r,g,b);}}   //  Устанавливаем цвет для всех Trema-модулей находящихся в шарах
}
//  Функция возвращает цвет в переменные colR,colG,colB по градусу n
void getColorDeg(uint8_t n){                                                                   //  аргументы функции: (градус n от 0 до 255)
    if(n<85) {        colB=0; colR=n*3; colG=255-colR;}else                                    //  Хорда от зелёного к красному, через жёлтый
    if(n<170){n-=85;  colG=0; colB=n*3; colR=255-colB;}else                                    //  Хорда от красного к синему  , через фиолетовый
             {n-=170; colR=0; colG=n*3; colB=255-colG;}                                        //  Хорда от синего   к зелёному, через голубой
}

Ссылки:




Обсуждение

Гарантии и возврат Используя сайт Вы соглашаетесь с условями