Еще один способ подключения WS2812B к микроконтроллеру
Довольно популярной сегодня является тема подключения светодиодных линеек WS2812B к различным микроконтроллерам, а также тема их программирования.
Не буду подробно останавливаться на протоколе. Достаточно сказать, что кодирование бит 0 и 1 осуществляется импульсами разной длительности. Вывод этих импульсов как раз и представляет собой головную боль при программировании MCU (использование готовых библиотек для Arduino в расчёт не беру, так как цель статьи показать именно детали процесса).
Мой выбор микроконтроллера пал на TI Stellaris LM4F120 по двум причинам:
- Был в наличии (недорогая плата LaunchPad от TI);
- Мой проект достаточно требователен к ресурсам, а MCU ARM® Cortex™-M4F c возможностями прямого доступа к памяти (DMA) как раз подходящее решение.
Существует разные варианты организации вывода данных по протоколу WS2812B на микроконтроллерах ARM:
- Вывод через SPI многобитными посылками на каждый бит (1000, 1110);
- Вывод через PWM.
В обоих случаях используется прямой доступ к памяти, что разгружает процессор. При этом недостатком обоих решений является лишний расход оперативной памяти под буфер.
Я решил пойти по пути использования SPI DMA, но так, чтобы не было необходимости «раздувать» каждый бит до нескольких. Меня интересовала возможность вывода данных через SPI «как есть». Т.е. 24 бита на светодиод, на скорости 800 kHz. Для этого потребовалось сделать небольшой преобразователь SPI -> WS2812B. Это, может, покажется лишним «городить огород», если можно напрямую всё подключить. Но мне всё равно требовалось делать плату, на которой кроме протокольного преобразователя находился еще разъем карты памяти SD, а также импульсный преобразователь 12В -> 5В / 5А (линейка из 144 светодиодов достаточно прожорлива, что, к тому же, накладывает ограничение на длину и сечение проводов её питающих). А еще решается проблема преобразования логического уровня 3,3В в 5В.
Привожу принципиальную схему (используется всего 2 корпуса 74HCT).
Номиналы резисторов R1 и R2 примерные, подбираются эмпирически с помощью осциллографа (нужно вывести тестовую последовательность с микроконтроллера, померить осциллографом длительности и подогнать номиналы по мере необходимости). Реальная схема чуть-чуть другая, так как у меня не было в запасе 74HCT132 и 74HCT74, а были 74HC74, 74HCT14 и 74HCT00, поэтому корпусов получилось 3.
Схема протестирована в полевых условиях на линейке из 144 светодиодов и на длине провода между выходом схемы и входом светодиодов порядка метра. Каких либо сбоев и помех не наблюдалось.
Кстати, по поводу проводов. Как я упомянул выше, светодиодные линейки на WS2812B кушают порядочный ток на максимальном включении. Соответственно, нужно подбирать сечение провода питания, достаточное, чтобы падение напряжения на нем было не критическим. Я взял кусок трех-проводного провода питания (обычного, который для 220В) сечением 1мм2. Даже такого сечения оказалось недостаточно для провода длиной 1М. На 50% мощности всех одновременно включенных светодиодов напряжение «просело» до 4х Вольт. Еще один феномен, про который не надо забывать это то, что когда питающее напряжение проседает, линия данных остается с уровнем в 0В и 5В. Таким образом, по отношению к питанию первого светодиода уровень оказывается ниже GND и выше VCC с риском вывести из строя входную ножку. Поэтому дополнительно я поставил по диоду Шоттки на землю и питание перед самым входом данных первого светодиода.
В следующей статье я расскажу, что именно за устройство у меня получилось.