Реализация протокола ws2812b на ATmega

    Светодиоды 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 протоколом. Получилось весело.

    Поделиться публикацией
    Никаких подозрительных скриптов, только релевантные баннеры. Не релевантные? Пиши на: adv@tmtm.ru с темой «Полундра»

    Зачем оно вам?
    Реклама
    Комментарии 11
    • +5
      Автору спасибо за статью!
      По теме тюнинга фар, хочу предостеречь использовать красный цвет в фарах. Бывает выезжаешь в сумерках на обгон и видишь красные габариты в далеке, предполагая что кто-то далеко уже кого-то обгоняет. Потом О-очень удивляешься, почему габариты так _быстро_ приближаются :)
      Не нужно вводить в заблуждение других водителей.
      • +5
        Поделка исключительно для развлечения зевак на автостоянках. Езжу только с белым цветом. Любой другой цвет (кроме желтого само собой) запрещен.
      • +3
        О, здорово. Сам только недавно доделал проект на WS2812B: imgur.com/a/0I84E
        Вот как-то так это сейчас выглядит: youtu.be/fmolAxGdiCE
        • 0
          кстати такой проект вполне полиции можно продавать — им не надо будет маячки ставить ручные
          • +4
            Я бы предложил использовать SPI для вывода данных.
            Настроить частоту на 2.5МГц, для передачи 0 запихивать в MOSI 0b100, для передачи 1 — 0b110.
            Памяти в меге хватит на то, что бы сформировать сразу весь массив данных. Таким образом получите очень точные тайминги.

            Мы таким образом (тоже через SPI) умудрялись формировать Ч/Б сигнал для VGA. Правда, не на меге, а на Atmel AT91SAM7x
            • 0
              Интересно, спасибо за совет. Но в данном случае мне точные тайминги не нужны.
            • 0
              Спасибо за статью, пришлась как нельзя кстати. Подскажите только такой момент, если микросхема запитана от 12 вольт, управляющий сигнал может быть 5 вольт?
              • 0
                Про какую «микросхему» речь? У светодиодов питание 5В, от 12В они помрут, соответственно и сигнал им нужен 5В.
                • 0
                  У меня светодиодная лента на микросхеме ws2812b. Питание ленты 12 В, могу ли я управлять 5 В, при таком питании?
                  • 0
                    Покажите мне эту ленту. Не видел таких на 12В, пока сказать не могу.
              • 0
                -

                Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.