Светодиоды ws2812b весьма интересная штука. О реализации протокола их работы я и хочу сейчас поведать. Как и в прошлой статье, код написан в среде IAR под микроконтроллер ATmega32 c 16МГц кварцем. Хочу сразу уточнить, что кварца менее 16МГц скорее всего не хватит, данный протокол рассчитан на весьма жесткие тайминги. Ноль выставляется временным интервалом 0.4 мкс, единица 0.8 мкс.





Первым делом напишем функции выставления 0 и 1 в линию. Количество nop’ов в функциях подобрано экспериментальным путем через логический анализатор. Скриншоты прилагаются немного ниже.

#define ClearOutBit    PORTC &= ~(1<<1)  //0 на выход
#define SetOutBit      PORTC |= 1<<1     //1 на выход

void Set0( void ) //Выставляем в правую линию ноль ~0.4 мкс
{
SetOutBit;
asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");
ClearOutBit; 
//После этого временной интервал немного увеличен, в связи с выполнением циклов, но диоды сигнал ловят исправно
}

void Set1( void ) //Выставляем в правую линию единицу ~0.85 мкс
{
SetOutBit;
asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");
ClearOutBit; 
//После этого временной интервал немного увеличен, в связи с выполнением циклов, но диоды сигнал ловят исправно
}

Далее у нас есть массив значений. Я создал 32 битный массив из 30 значений (да, понимаю, что это излишество, но мне показалось это решение допустимо). Для каждого светодиода нам необходимо загрузить 24 бита, причем первым выгружается в линию значение для зеленого цвета, далее красного и потом синего.



На выставление в линию значений для всех 30 светодиодов у контроллера уходит не более 4 мс, что достаточно быстро. Конечно, если увеличить тактовую частоту, можно выиграть немного времени между битами. В идеале, если все временные интервалы будут соответствовать, для 30 светодиодов загрузка будет длиться менее 1 мс.

unsigned long int mas[30]; //32 битный массив из 30 значений

void setMas( void ) //выставление всего массива в линию
{
unsigned long int a;
unsigned int j,i;

for (j=0; j<30; j++) { //количество светодиодов 30
			 a = 0x1000000; //первым выставляется G (Hi->Low), потом R и B
			 for (i=0;i<24;i++){ //три байта G,R,B
					a=a>>1;	
					if ((mas[j]&a)==0x00000000) {
							Set0();	//ноль 			
							}  else {
							Set1(); //единица
							} 
			}
		}
}

По факту получается, что выдерживаются только временные интервалы “high voltage time” 0.4 и 0.8 мкс, а вот “low voltage time” программой не контролируются – они получаются за счет работы микроконтроллера между выставлением значений в линию. Ему ведь надо время, чтобы проверить условие и прокрутить цикл. Но тем не менее, светодиоды ловят посылку исправно. И конечно это время не должно превышать 50 мкс, иначе светодиод воспримет это как Reset и загрузит полученное “неполное” значение себе на индикацию.




В конце статьи видео работы этих 30 светодиодов с круговым сдвигом исходного массива по таймеру и управлением через ИК пульт с NEC протоколом. Получилось весело.

Комментарии (11)


  1. madguru
    30.04.2015 13:44
    +5

    Автору спасибо за статью!
    По теме тюнинга фар, хочу предостеречь использовать красный цвет в фарах. Бывает выезжаешь в сумерках на обгон и видишь красные габариты в далеке, предполагая что кто-то далеко уже кого-то обгоняет. Потом О-очень удивляешься, почему габариты так _быстро_ приближаются :)
    Не нужно вводить в заблуждение других водителей.


    1. oWart Автор
      30.04.2015 13:46
      +5

      Поделка исключительно для развлечения зевак на автостоянках. Езжу только с белым цветом. Любой другой цвет (кроме желтого само собой) запрещен.


  1. e_asphyx
    30.04.2015 14:04
    +3

    О, здорово. Сам только недавно доделал проект на WS2812B: imgur.com/a/0I84E
    Вот как-то так это сейчас выглядит: youtu.be/fmolAxGdiCE


  1. BalinTomsk
    30.04.2015 19:00

    кстати такой проект вполне полиции можно продавать — им не надо будет маячки ставить ручные


  1. lorc
    30.04.2015 19:01
    +4

    Я бы предложил использовать SPI для вывода данных.
    Настроить частоту на 2.5МГц, для передачи 0 запихивать в MOSI 0b100, для передачи 1 — 0b110.
    Памяти в меге хватит на то, что бы сформировать сразу весь массив данных. Таким образом получите очень точные тайминги.

    Мы таким образом (тоже через SPI) умудрялись формировать Ч/Б сигнал для VGA. Правда, не на меге, а на Atmel AT91SAM7x


    1. oWart Автор
      30.04.2015 22:05

      Интересно, спасибо за совет. Но в данном случае мне точные тайминги не нужны.


  1. yanvasilij
    06.05.2015 22:45

    Спасибо за статью, пришлась как нельзя кстати. Подскажите только такой момент, если микросхема запитана от 12 вольт, управляющий сигнал может быть 5 вольт?


    1. oWart Автор
      07.05.2015 08:39

      Про какую «микросхему» речь? У светодиодов питание 5В, от 12В они помрут, соответственно и сигнал им нужен 5В.


      1. yanvasilij
        07.05.2015 08:43

        У меня светодиодная лента на микросхеме ws2812b. Питание ленты 12 В, могу ли я управлять 5 В, при таком питании?


        1. oWart Автор
          07.05.2015 08:49

          Покажите мне эту ленту. Не видел таких на 12В, пока сказать не могу.


  1. yanvasilij
    07.05.2015 08:43

    -