| Ваш IP: 100.26.179.251 | Online(30) - гости: 8, боты: 22 | Загрузка сервера: 0.34 ::::::::::::

Адресная светодиодная лента (Arduino)

Адресная светодиодная лента представляет собой ленту на которой размещены адресные светодиоды, каждый светодиод состоит из RGB светодиода и контроллера. Адресная лента имеет как правило имеет три входных контакта: +5V, GND и DIN. Каждый отдельный светодиод ленты (пиксель) имеет выход DOUT, для передачи управляющего сигнала к следующему светодиоду.

Наиболее популярные адресные ленты работают на чипах WS2812b и WS2811. Чип WS2812b размещен внутри RGB светодиода, питание 5 В, а в адресных лентах использующих чип WS2811 установлен отдельно от светодиода, напряжение питания 12 В, так же чип WS2811 управляет сразу тремя RGB светодиодами, которые представляют собой один пиксель.

Те же адресные ленты имеют разное кол-во светодиодов на 1 метр и соответственно разную мощность потребления и цену.

Если просто подать питание на адресную ленту, то она работать не будет, чтобы она заработала необходимо подать управляющий цифровой сигнал на вход DIN. Управляющий цифровой сигнал состоит 24 бит, по 8 бит на каждый цвет, причем в начале каждого байта первый бит старший.

При этом один бит передается за 1,25 мкс, все 24 бита передаются за 30 мкс. Длительность импульса при передачи логического нуля равна 0,4 мкс ±0,125 мкс, а скважность 0,85 мкс ±0,125 мкс, длительность импульса для логической единицы равна 0,85 мкс ±0,125 мкс, а скважность 0,4 мкс ±0,125 мкс.

После передачи всех 24 бит в первый RGB светодиод следует пауза не более 50 мкс, далее снова передаются 24 бита, но первый светодиод не реагирует на них, он просто передается эту информацию следующему светодиоду и так далее по цепочке до последнего светодиода. После окончания передачи следует пауза больше 50 мкс, после чего лента переходит в исходное состояние и готова принимать цифровой сигнал начиная с первого светодиода.

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

Первоначально был написан следующий скетч для Arduino Nano:

// D8 >> DIN
#define L_BIT    PORTB &= ~(1<<0)
#define H_BIT    PORTB |=  (1<<0)    
 
byte times;
int i=0;
 
void setup(){
   DDRB |= (1<<0); // выход D8
}
 
void loop(){ 
    led(100, 0, 0);
    led(0, 100, 0);
    led(0, 0, 100);
    led(100, 0, 0);
    res();
    delay(500);
  }
 
void bit_0(){H_BIT;asm("nop");asm("nop");   L_BIT;asm("nop");asm("nop");asm("nop");   asm("nop");}
void bit_1(){H_BIT;asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");   L_BIT;}
void bit_w(bool x){if(x) bit_1(); else bit_0();}
void res(){delayMicroseconds(100);}
 
void led(long rrr, int ggg, byte bbb){
  unsigned long data = ((rrr << 16) & 0xFF0000) + ((ggg << 8) & 0xFF00) + bbb;
  cli();
bit_w(data  & 0b100000000000000000000000);
bit_w(data  & 0b010000000000000000000000);
bit_w(data  & 0b001000000000000000000000);
bit_w(data  & 0b000100000000000000000000);
bit_w(data  & 0b000010000000000000000000);
bit_w(data  & 0b000001000000000000000000);
bit_w(data  & 0b000000100000000000000000);
bit_w(data  & 0b000000010000000000000000);
 
bit_w(data  & 0b000000000000000010000000);
bit_w(data  & 0b000000000000000001000000);
bit_w(data  & 0b000000000000000000100000);
bit_w(data  & 0b000000000000000000010000);
bit_w(data  & 0b000000000000000000001000);
bit_w(data  & 0b000000000000000000000100);
bit_w(data  & 0b000000000000000000000010);
bit_w(data  & 0b000000000000000000000001);  
 
bit_w(data  & 0b000000001000000000000000);    
bit_w(data  & 0b000000000100000000000000);    
bit_w(data  & 0b000000000010000000000000);    
bit_w(data  & 0b000000000001000000000000);    
bit_w(data  & 0b000000000000100000000000);    
bit_w(data  & 0b000000000000010000000000);    
bit_w(data  & 0b000000000000001000000000);    
bit_w(data  & 0b000000000000000100000000);    
   sei(); 
delayMicroseconds(10);
  }

Скетч использует 972 байт (3%) памяти устройства. Всего доступно 32256 байт.
Глобальные переменные используют 9 байт (0%) динамической памяти, оставляя 2039 байт для локальных переменных. Максимум: 2048 байт.

После загрузки скетча адресная лента заработала, скетч занимает всего 972 байта и 9 байт динамической памяти.

WS2811

Выход D8 Arduino через резистор 300 Ом подключен ко входу адресной ленты.

За создание нуля или единицы для отправки на вход DIN отвечают две функции:

void bit_0(){H_BIT;asm("nop");asm("nop");   L_BIT;asm("nop");asm("nop");asm("nop");   asm("nop");}
void bit_1(){H_BIT;asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");   L_BIT;}

Эти функции задают правильные временные импульсы:

Бит нуля (развертка 1 мкс.дел)

Бит единицы (развертка 1 мкс.дел)

Для отправки бита нуля или единицы отвечает функция bit_w():

void bit_w(bool x){if(x) bit_1(); else bit_0();}

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

Далее следует функция led(), в которую заносятся три байта яркости для каждого цвета RGB (0…255), осуществляется преобразование 3-х байт в один 24-х битный байт и отправка 24 раза бита со сдвигом бита. В итоге адресная лента получает 24 битный байт, после каждого байта следует пауза в 10 мкс.

void led(long rrr, int ggg, byte bbb){
  unsigned long data = ((rrr << 16) & 0xFF0000) + ((ggg << 8) & 0xFF00) + bbb;
  cli();
bit_w(data  & 0b100000000000000000000000);
bit_w(data  & 0b010000000000000000000000);
bit_w(data  & 0b001000000000000000000000);
bit_w(data  & 0b000100000000000000000000);
bit_w(data  & 0b000010000000000000000000);
bit_w(data  & 0b000001000000000000000000);
bit_w(data  & 0b000000100000000000000000);
bit_w(data  & 0b000000010000000000000000);

bit_w(data  & 0b000000000000000010000000);
bit_w(data  & 0b000000000000000001000000);
bit_w(data  & 0b000000000000000000100000);
bit_w(data  & 0b000000000000000000010000);
bit_w(data  & 0b000000000000000000001000);
bit_w(data  & 0b000000000000000000000100);
bit_w(data  & 0b000000000000000000000010);
bit_w(data  & 0b000000000000000000000001);  
    
bit_w(data  & 0b000000001000000000000000);    
bit_w(data  & 0b000000000100000000000000);    
bit_w(data  & 0b000000000010000000000000);    
bit_w(data  & 0b000000000001000000000000);    
bit_w(data  & 0b000000000000100000000000);    
bit_w(data  & 0b000000000000010000000000);    
bit_w(data  & 0b000000000000001000000000);    
bit_w(data  & 0b000000000000000100000000);    
   sei(); 
delayMicroseconds(10);
  }

Функция res(), просто содержит паузу в 100 мкс для перезапуска ленты:

void res(){delayMicroseconds(100);}

Функция отправки данных в один пиксель ленты:

    led(10, 0, 0);

Отправка функции led() в этом скетче требуется для каждого пикселя адресной ленты, что не совсем удобно, но зато скетч занимает очень мало места и при использовании функции led() динамическая память не заполняется, а используется только память для программ (флеш память). Для простых проектов, особенно для контроллеров с малым объемом памяти можно использовать этот скетч.

Немного доработав скетч, функция led() стала иметь адрес пикселя, что заметно упростило создание различных световых эффектов. Например если указать:

led(23, 255, 255, 255);

то загорится только светодиод под номером 23 (считать с нуля).

Ниже показан скетч, повторяющий предыдущий, но с адресами для пикселей:

#define L_BIT    PORTB &= ~(1<<0)
#define H_BIT    PORTB |=  (1<<0)    
#define LED_MAX  4
 
unsigned long dat[LED_MAX];
byte aa,bb,cc;
 
void setup(){
   DDRB |= (1<<0);
}
 
void loop(){
  data_led(0,  10,0,0);
  data_led(1,  0,10,0);
  data_led(2,  0,0,10);
  data_led(3,  10,0,0);
   led_rgb();
   res();
}
 
void bit_0(){H_BIT;asm("nop");asm("nop");   L_BIT;asm("nop");asm("nop");asm("nop");   asm("nop");}
void bit_1(){H_BIT;asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");   L_BIT;}
void bit_w(bool x){if(x) bit_1(); else bit_0();}
void res(){delayMicroseconds(100);}
 
void data_led(int num, unsigned long rrr, int ggg, byte bbb){
  dat[num] = ((rrr << 16) & 0xFF0000) + ((ggg << 8) & 0xFF00) + bbb;
  }
 
void led_rgb(){
  for(unsigned char num_i=0;num_i<LED_MAX;num_i++){unsigned long data=dat[num_i];
  cli();
bit_w(data & 0x80);
bit_w(data & 0x40);
bit_w(data & 0x20);
bit_w(data & 0x10);
bit_w(data & 0x08);
bit_w(data & 0x04);
bit_w(data & 0x02);
bit_w(data & 0x01);
bit_w(data & 0x800000);
bit_w(data & 0x400000);
bit_w(data & 0x200000);
bit_w(data & 0x100000);
bit_w(data & 0x080000);
bit_w(data & 0x040000);
bit_w(data & 0x020000);
bit_w(data & 0x010000);  
bit_w(data & 0x8000);    
bit_w(data & 0x4000);    
bit_w(data & 0x2000);    
bit_w(data & 0x1000);    
bit_w(data & 0x0800);    
bit_w(data & 0x0400);    
bit_w(data & 0x0200);    
bit_w(data & 0x0100); 
   sei(); 
delayMicroseconds(10);
}}

Скетч использует 962 байт (2%) памяти устройства. Всего доступно 32256 байт.
Глобальные переменные используют 25 байт (1%) динамической памяти, оставляя 2023 байт для локальных переменных. Максимум: 2048 байт.

В этом скетче функция led(), не отправляет команду адресной ленте, а создает массив из данных функции led(). Отправка данных осуществляется функцией led_rgb(). При этом чем больше светодиодов используется тем больше расходуется динамическая память.

Следующий скетч демонстрирует простой световой эффект:

#define L_BIT    PORTB &= ~(1<<0)
#define H_BIT    PORTB |=  (1<<0)    
#define LED_MAX  4
 
unsigned long dat[LED_MAX];
byte aa,bb,cc;
 
void setup(){
   DDRB |= (1<<0);
}
 
void loop(){
/////////////////
  for(int i1=LED_MAX;i1>=0;i1--){
  for(int i=0;i<100;i++){
   switch(i1){
    case 0:  aa=i;bb=0;cc=0;break;
    case 1:  aa=0;bb=i;cc=0;break;
    case 2:  aa=0;bb=0;cc=i;break;
    case 3:  aa=i;bb=i;cc=i;break;
    }
  data_led(i1,  aa,bb,cc);
  led_rgb();res();
  delay(2);
  }}
 
  for(int i1=0;i1<LED_MAX;i1++){
  for(int i=100;i>=0;i--){
   switch(i1){
    case 0:  aa=i;bb=0;cc=0;break;
    case 1:  aa=0;bb=i;cc=0;break;
    case 2:  aa=0;bb=0;cc=i;break;
    case 3:  aa=i;bb=i;cc=i;break;
    }
  data_led(i1,  aa,bb,cc);
  led_rgb();res();
  delay(2);
  }}
 delay(50);
///////////////////
 
  for(int i1=0;i1<LED_MAX;i1++){
  for(int i=0;i<100;i++){
   switch(i1){
    case 0:  aa=i;bb=0;cc=0;break;
    case 1:  aa=0;bb=i;cc=0;break;
    case 2:  aa=0;bb=0;cc=i;break;
    case 3:  aa=i;bb=i;cc=i;break;
    }
  data_led(i1,  aa,bb,cc);
  led_rgb();res();
  delay(2);
  }}
 
  for(int i1=LED_MAX;i1>=0;i1--){
  for(int i=100;i>=0;i--){
   switch(i1){
    case 0:  aa=i;bb=0;cc=0;break;
    case 1:  aa=0;bb=i;cc=0;break;
    case 2:  aa=0;bb=0;cc=i;break;
    case 3:  aa=i;bb=i;cc=i;break;
    }
  data_led(i1,  aa,bb,cc);
  led_rgb();res();
  delay(2);
  }}
 delay(50);
 ////////////////////////
 
}
 
void bit_0(){H_BIT;asm("nop");asm("nop");   L_BIT;asm("nop");asm("nop");asm("nop");   asm("nop");}
void bit_1(){H_BIT;asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");   L_BIT;}
void bit_w(bool x){if(x) bit_1(); else bit_0();}
void res(){delayMicroseconds(100);}
 
void data_led(int num, unsigned long rrr, int ggg, byte bbb){
  dat[num] = ((rrr << 16) & 0xFF0000) + ((ggg << 8) & 0xFF00) + bbb;
  }
 
void led_rgb(){
  for(unsigned char num_i=0;num_i<LED_MAX;num_i++){unsigned long data=dat[num_i];
  cli();
bit_w(data & 0x80);
bit_w(data & 0x40);
bit_w(data & 0x20);
bit_w(data & 0x10);
bit_w(data & 0x08);
bit_w(data & 0x04);
bit_w(data & 0x02);
bit_w(data & 0x01);
bit_w(data & 0x800000);
bit_w(data & 0x400000);
bit_w(data & 0x200000);
bit_w(data & 0x100000);
bit_w(data & 0x080000);
bit_w(data & 0x040000);
bit_w(data & 0x020000);
bit_w(data & 0x010000);  
bit_w(data & 0x8000);    
bit_w(data & 0x4000);    
bit_w(data & 0x2000);    
bit_w(data & 0x1000);    
bit_w(data & 0x0800);    
bit_w(data & 0x0400);    
bit_w(data & 0x0200);    
bit_w(data & 0x0100); 
   sei(); 
delayMicroseconds(10);
}}

Скетч использует 1858 байт (5%) памяти устройства. Всего доступно 32256 байт.
Глобальные переменные используют 28 байт (1%) динамической памяти, оставляя 2020 байт для локальных переменных. Максимум: 2048 байт.

 

Добавить комментарий

Войти с помощью: 

Случайные статьи

  • Узел настройки УКВ-ЧМ приемника

    Узел настройки УКВ_ЧМ приемника представляет собой синтезатор напряжения для электронной настройки УКВ_ЧМ приемника и как дополнительное уст-во — электронную линейную шкалу напряжения для контроля напряжения подаваемого на варикапы приемника. Напряжение настройки приемника устанавливается при помощи полевого транзистора VT1, в его затворной цепи включен С1, при нажатии S1 или S2 С1 …Подробнее...
  • Стерео усилитель класса D 2*25Вт на базе TDA7490

    Стерео усилитель класса D 2*25Вт на базе TDA7490

    Микросхема TDA7490 имеет защиту от перенапряжения, тепловую и защиту от КЗ, так же микросхема имеет встроенные функции MUTE и STAND-BY. Усилитель на TDA7490 имеет следующие технические характеристики: Напряжение питания от +/-10В до +/-25В (номинальное напряжение +/-21В) Ток покоя от 70 до 120мА в зависимости от  напряжения питания Выходная мощность 25Вт …Подробнее...
  • Усилитель мощности звуковой частоты класса D на ИМС MAX9709

    Усилитель мощности звуковой частоты класса D на ИМС MAX9709

    Усилитель мощности звуковой частоты класса D на ИМС MAX9709 обеспечивает выходную мощность до 25Вт на канал (стерео) при нагрузке 8 Ом и 50Вт в режиме моно при нагрузке 4 Ом. ИМС MAX9709 обеспечивает высокую производительность (КПД 87%), при этом используется небольшой радиатор охлаждения. Напряжение питания усилителя от 10 до 22В. MAX9709  имеет …Подробнее...
  • Простой испытатель тиристоров

    Простой испытатель тиристоров

    Из подручных радиоэлементов можно собрать простой испытатель тиристоров, который состоит из трансформатора со вторичной обмоткой на 6,3В (0,5А), диода, конденсатора, лампы и трех переключателей. Выбор постоянного или переменного тока осуществляется переключателем SA2. Электроды тиристора подключаются при помощи зажимов, индикатор служит лампа накаливания 6,3Вх0,28А. Для проверки тиристора постоянным током переведите переключатель …Подробнее...
  • УМЗЧ на 50Вт на полевых MOSFET транзисторах

    УМЗЧ на 50Вт на полевых MOSFET транзисторах

    На рисунке показана схема 50 Вт усилителя с выходными полевыми MOSFET транзисторами. Первый каскад усилителя представляет собой дифференциальный усилитель на транзисторах VT1 VT2. Второй каскад усилителя состоит из транзисторов VT3 VT4. Оконечный каскад усилителя состоит из МОП-транзисторов IRF530 и IRF9530. Выход усилителя через катушку L1 соединен с нагрузкой 8 Ом. Цепь состоящий …Подробнее...