| Ваш IP: 3.91.92.194 | Online(51) - гости: 28, боты: 23 | Загрузка сервера: 3.93 ::::::::::::

Индикатор уровня сигнала на адресной светодиодной ленте WS2812B (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 мкс, после чего лента переходит в исходное состояние и готова принимать цифровой сигнал начиная с первого светодиода.

На базе адресной светодиодной ленты WS2812B можно собрать простой индикатор уровня аудио сигнала. Индикатор уровня собран на адресной ленте плотностью 96 пикселей на 1 метр.

На индикатор уровня подается стерео сигнал на аналоговые входы А0 и А1, центр ленты является разделителем правого и левого канала, поэтому ленту можно разделить на две части, отдельно для правого и левого канала. Так же в индикации уровня присутствует пиковый индикатор.

Кнопка MODE служит для переключения режима расцветки свечения светодиодов.

Особенностью индикатора уровня аудио сигнала является, то что Вы можете использовать разную длину адресной ленты с четным количеством светодиодов. Для настройки индикатора в скетче необходимо указать четное количество пикселей Вашей ленты, яркость, усиление сигнала и плавность работы пикового индикатора.

#define LED_MAX  60
#define GAIN 1  // усиление 1...20
#define STEP 5  // плавность полос 1...20
#define BRIG 2  // яркость 2...255

При установке яркости более 10 единиц, необходимо использовать отдельный от Arduino источник питания 5 В, так ток потребления адресной ленты может превысить 2 А. 

// Atmega328, Atmega8 16MHz
 
#include <avr/io.h>
#include <util/delay.h>
 
#define L_BIT    PORTB &= ~(1<<PB0)
#define H_BIT    PORTB |=  (1<<PB0)    
#define LED_MAX  60
#define GAIN 1  // усиление 1...20
#define STEP 5  // плавность полос 1...20
#define BRIG 2  // яркость 2...255
 
  byte rr[LED_MAX],gg[LED_MAX],bb[LED_MAX];
  int ur,ul,urr,ull,urrr,ulll;
  int x,i,u_maxr,u_maxl;
  int u_l0[20],u_r0[20];
  int ull_sum,urr_sum;
  byte r,g,b;
  int u_r,uur,u_l,uul;
  int mode;
  unsigned long times, times0;
  bool w;
 
 
int main(void){
  cli();
  DDRB |= (1<<PB0); // INPUT WS2812B (D8 - ARDUINO)
  DDRD &= ~(1<<PD2);// BUTTON (D2 - ARDUINO)
  PORTD |=(1<<PD2); // INPUT_PULLUP
  ADCSRA = 0b10000100; 
  TCCR0A = 0;TCCR0B = 0;TCNT0 = 0;
  OCR0A = 249;
  TCCR0A |= (1 << WGM01);
  TCCR0B |= (1 << CS01) | (1 << CS00);
  TIMSK0 |= (1 << OCIE0A);
  sei();
  mode = EEPROM_read(0);
 
 
 while(1){
  if(((PIND >> PD2) & 1) == 0){mode++;if(mode>4){mode=0;}_delay_ms(300);w=1;times0=times;}
////////// ANALOG READ
 ADMUX = 0b01000001; // input A1 
  do{ADCSRA |= (1 << ADSC);}while ((ADCSRA & (1 << ADIF)) == 0);urr = (ADCL|ADCH << 8)*GAIN;if(urr>LED_MAX/2){urr=LED_MAX/2;}
 ADMUX = 0b01000000; // input A0
  do{ADCSRA |= (1 << ADSC);}while ((ADCSRA & (1 << ADIF)) == 0);ull = (ADCL|ADCH << 8)*GAIN;if(ull>LED_MAX/2){ull=LED_MAX/2;}
  uur = urr;if(uur<u_r){u_r=u_r-1;_delay_ms(STEP);}else{u_r = uur;} 
  uul = ull;if(uul<u_l){u_l=u_l-1;_delay_ms(STEP);}else{u_l = uul;} 
////////// RGB ////////////////////////////////////////////////
 
  for(int i1=u_l;i1<LED_MAX/2;i1++){data_led(LED_MAX/2-i1-1,  0,0,0);}led_rgb();res();
  for(int i1=u_r;i1<LED_MAX/2;i1++){data_led(i1+LED_MAX/2,  0,0,0);}led_rgb();res();
 
  if(mode==0){
  for(int i1=1;i1<u_l-1;i1++){if(i1<LED_MAX/2/3){r=0;g=1*BRIG;b=0;}
  else if(i1>=LED_MAX/2/3&&i1<LED_MAX/2/2){r=0;g=0;b=1*BRIG;}
  else {r=1*BRIG/2;g=1*BRIG/2;b=1*BRIG/2;}   data_led(LED_MAX/2-i1-1,  r,g,b);}led_rgb();res();
  data_led(LED_MAX/2-1,  1*BRIG,1*BRIG,0);led_rgb();res();
 
  for(int i1=1;i1<u_r-1;i1++){if(i1<LED_MAX/2/3){r=0;g=1*BRIG;b=0;} 
  else if(i1>=LED_MAX/2/3&&i1<LED_MAX/2/2){r=0;g=0;b=1*BRIG;}
  else {r=1*BRIG/2;g=1*BRIG/2;b=1*BRIG/2;}  data_led(i1+LED_MAX/2,  r,g,b);}led_rgb();res();
  data_led(LED_MAX/2,  1*BRIG,1*BRIG,0);led_rgb();res();
  }
  if(mode==1){
  for(int i1=1;i1<u_l-1;i1++){if(i1<LED_MAX/2){r=1*BRIG;g=1*BRIG;b=1*BRIG;}
  data_led(LED_MAX/2-i1-1,  r,g,b);}led_rgb();res();
  data_led(LED_MAX/2-1,  1*BRIG,1*BRIG,0);led_rgb();res();
 
  for(int i1=1;i1<u_r-1;i1++){if(i1<LED_MAX/2){r=1*BRIG;g=1*BRIG;b=1*BRIG;} 
  data_led(i1+LED_MAX/2,  r,g,b);}led_rgb();res();
  data_led(LED_MAX/2,  1*BRIG,1*BRIG,0);led_rgb();res();
  } 
  if(mode==2){
  for(int i1=1;i1<u_l-1;i1++){if(i1<LED_MAX/2){r=0;g=1*BRIG;b=1*BRIG;}
  data_led(LED_MAX/2-i1-1,  r,g,b);}led_rgb();res();
  data_led(LED_MAX/2-1,  1*BRIG,1*BRIG,0);led_rgb();res();
 
  for(int i1=1;i1<u_r-1;i1++){if(i1<LED_MAX/2){r=0;g=1*BRIG;b=1*BRIG;} 
  data_led(i1+LED_MAX/2,  r,g,b);}led_rgb();res();
  data_led(LED_MAX/2,  1*BRIG,1*BRIG,0);led_rgb();res();
  } 
  if(mode==3){
  for(int i1=1;i1<u_l-1;i1++){if(i1<LED_MAX/2){r=0;g=0;b=1*BRIG;}
  data_led(LED_MAX/2-i1-1,  r,g,b);}led_rgb();res();
  data_led(LED_MAX/2-1,  1*BRIG,1*BRIG,0);led_rgb();res();
 
  for(int i1=1;i1<u_r-1;i1++){if(i1<LED_MAX/2){r=0;g=0;b=1*BRIG;} 
  data_led(i1+LED_MAX/2,  r,g,b);}led_rgb();res();
  data_led(LED_MAX/2,  1*BRIG,1*BRIG,0);led_rgb();res();
  } 
  if(mode==4){
  for(int i1=1;i1<u_l-1;i1++){if(i1<LED_MAX/2){r=0;g=1*BRIG;b=0;}
  data_led(LED_MAX/2-i1-1,  r,g,b);}led_rgb();res();
  data_led(LED_MAX/2-1,  1*BRIG,1*BRIG,0);led_rgb();res();
 
  for(int i1=1;i1<u_r-1;i1++){if(i1<LED_MAX/2){r=0;g=1*BRIG;b=0;} 
  data_led(i1+LED_MAX/2,  r,g,b);}led_rgb();res();
  data_led(LED_MAX/2,  1*BRIG,1*BRIG,0);led_rgb();res();
  } 
 
 i++;if(i<19){u_l0[i]=ull-2;u_r0[i]=urr-2;}else{i=0;}
 if(i==18){u_maxr=0;u_maxl=0;
   for(x=1;x<=15;x++){
    u_maxl=maxim(u_maxl,u_l0[x]);
    u_maxr=maxim(u_maxr,u_r0[x]);}}
 if(u_maxl<=ull){u_maxl=ull+1;} 
 if(u_maxr<=urr){u_maxr=urr+1;}
 if(u_maxl<ulll){ulll=ulll-1;_delay_ms(STEP);}else{ulll = u_maxl;}
 if(u_maxr<urrr){urrr=urrr-1;_delay_ms(STEP);}else{urrr = u_maxr;}
 if(ulll>LED_MAX/2){ulll=LED_MAX/2;}
 if(urrr>LED_MAX/2){urrr=LED_MAX/2;}
    data_led(LED_MAX/2-ulll,  1*BRIG,0,0);led_rgb();res();
    data_led(urrr-1+LED_MAX/2,  1*BRIG,0,0);led_rgb();res();
    _delay_ms(2);  
////// EEPROM ///////////////////
 if(times-times0>10000&&w==1){if(EEPROM_read(0)!=mode){EEPROM_write(0,mode);}w=0;} 
}} // end loop
 
ISR(TIMER0_COMPA_vect) {times++;}// millis = 1 ms
 
int maxim(int basa, int srav){if(srav>basa){basa = srav;}return basa;}
 
unsigned char EEPROM_read(unsigned int uiAddress){
  while(EECR & (1<<EEPE));  // проверка готовности EEPROM 
    EEARH = ((uiAddress & 0xF0) << 2); // регистр адреса H
    EEARL = uiAddress & 0x0F; // регистр адреса L
    EECR |= (1<<EERE);// чтение EEPROM
    return EEDR; // вывод значения
}
 
void EEPROM_write(unsigned int uiAddress, unsigned char ucData){
  while(EECR & (1<<EEPE)); // проверка готовности EEPROM 
    EEARH = ((uiAddress & 0xF0) << 2); // регистр адреса H
    EEARL = uiAddress & 0x0F; // регистр адреса L
    EEDR = ucData; // регистр данных 
    EECR |= (1<<EEMPE);// Разрешение записи в EEPROM
    EECR |= (1<<EEPE); // Запись в EEPROM
} 
 
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(){_delay_us(100);}
 
void data_led(int num, byte rrr, byte ggg, byte bbb){
  bb[num]=bbb;rr[num]=rrr;gg[num]=ggg;
  }
 
void led_rgb(){
  for(int num_i=0;num_i<LED_MAX;num_i++){ 
  cli();
bit_w((bb[num_i] & 0x80)>>7);
bit_w((bb[num_i] & 0x40)>>6);
bit_w((bb[num_i] & 0x20)>>5);
bit_w((bb[num_i] & 0x10)>>4);
bit_w((bb[num_i] & 0x08)>>3);
bit_w((bb[num_i] & 0x04)>>2);
bit_w((bb[num_i] & 0x02)>>1);
bit_w((bb[num_i] & 0x01)>>0);
 
bit_w((rr[num_i] & 0x80)>>7);
bit_w((rr[num_i] & 0x40)>>6);
bit_w((rr[num_i] & 0x20)>>5);
bit_w((rr[num_i] & 0x10)>>4);
bit_w((rr[num_i] & 0x08)>>3);
bit_w((rr[num_i] & 0x04)>>2);
bit_w((rr[num_i] & 0x02)>>1);
bit_w((rr[num_i] & 0x01)>>0);
 
bit_w((gg[num_i] & 0x80)>>7);
bit_w((gg[num_i] & 0x40)>>6);
bit_w((gg[num_i] & 0x20)>>5);
bit_w((gg[num_i] & 0x10)>>4);
bit_w((gg[num_i] & 0x08)>>3);
bit_w((gg[num_i] & 0x04)>>2);
bit_w((gg[num_i] & 0x02)>>1);
bit_w((gg[num_i] & 0x01)>>0);
   sei(); 
}}

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

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

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

  • Параллельное и последовательное соединение резисторов, конденсаторов и катушек индуктивности

    Параллельное и последовательное соединение резисторов, конденсаторов и катушек индуктивности

    Резисторы Последовательное соединение резисторов   Последовательное соединение резисторов это такое соединение когда резисторы подключаются последовательно друг за другом. При этом через все резисторы будет протекать одинаковый ток. Для расчета общего сопротивления всех последовательно соединенных резисторов используется формула: Rобщ = R1 + R2 + R3 + … + Rn. Параллельное соединение …Подробнее...
  • Расчёт стабилизатора напряжения (источника опорного напряжения)

    Расчёт стабилизатора напряжения (источника опорного напряжения)

    Для расчёта стабилизатора, как правило, используются только два  параметра — Uст (напряжение стабилизации) , Iст (ток стабилизации), при условии что ток нагрузки равен или меньше тока стабилизации. Для простого расчета стабилизатора на примере будем использовать следующие параметры: Входное напряжение 10 В Выходное напряжение 6,8 В Ток нагрузки 10 мА Из …Подробнее...
  • Простой стрелочный частотомер

    Частотомер имеет диапазон измеряемых частот от 0-100Гц до 100кГц. Схема весьма проста и не содержит дорогостоящих элементов. Чувствительность частотомера 100мВ. В качестве индикатора используется миллиамперметр 0-100мкА, частотомер имеет 4-е диапазона 100Гц, 1Кгц, 10кГц, 100кГц.  В частотомере использованы две микросхемы — ОУ  CA3130 и таймер LM555. Оу имеет высокое входное сопротивление, тем …Подробнее...
  • Простой УКВ-приемник

    УКВ-приемник работает в диапазоне 64-108МГц. Схема приемника основана на 2-х микросхемах: К174ХА34 и ВА5386, дополнительно в схеме присутствуют 17 конденсаторов и всего 2-а резистора. Колебательный контур один, гетеродинный. На А1 выполнен супергетеродинный УКВ-ЧМ без УНЧ. Сигнал от антенны поступает через С1 на вход ПЧ микросхемы А1(вывод12). Настройка на станцию производится …Подробнее...
  • Регулятор громкости и  тембра на PT2319 (Arduino)

    Регулятор громкости и тембра на PT2319 (Arduino)

    ИМС PT2319 представляет собой аудиопроцессор специально разработанный для регулирования параметров аудиосигнала с минимальными искажениями. Аудиопроцессор включает в себя регулятор громкости, тембра, коммутатор входов и предусилители входа и выхода. Более подробно об аудиопроцессоре можно узнать из статьи Аудиопроцессор PT2319 (Arduino). Регулятор громкости и тембра построен на базе Arduino Nano. Основные параметры …Подробнее...