Близится Новый год, а гирлянда на ёлку не готова. В комоде уложена старая, её использовали уже пять раз и хочется чего-то нового. Предлагаю сделать свою, на популярной плате STM32 BluePIll в связке с адресными светодиодами. Это история с открытым концом. Если читателю идея покажется интересной, будет прошивка на git с реализацией интересных задумок; в противном случае, придётся купить готовую на маркетплейсе. Но мы же этого не допустим?
Предыстория
Волей случая довелось программировать приборную панель, в которой индикаторами режимов работы выступали адресные светодиоды WS2812B. На этапе прототипа нужно было регулировать цвет и яркость индикаторов для проверки оптических свойств световых фильтров. Так появилась удобная схема для экспериментов: терминал ПК – STM32 BluePIll – адресные светодиоды. Первоначальная отладка прошивки проводилась на матрице 8x8, для которой, забавы ради, были написаны простые сценарии: бегущий огонь, имитация тлеющих углей, случайный выбор цвета и яркости. И вот вместо приборной панели мы получаем макет светодиодной гирлянды.
Техническая составляющая
Протокол адресных светодиодов
Для светодиодов WS2812B сигнал сброса, логической единицы и нуля задаются временными таймаутами. Поэтому необходим «конвертер», который будет преобразовывать цифру во временной импульс. Время передачи одного бита составляет 1,25 мкс.
![Рисунок 2 - Протокол адресного светодиода WS2812B. Источник изображения [2]. Рисунок 2 - Протокол адресного светодиода WS2812B. Источник изображения [2].](https://habrastorage.org/r/w780/getpro/habr/upload_files/1fc/928/a10/1fc928a1050e63e8443dfd2145654808.png)
Для этой цели удобно использовать таймер, работающий в режиме широтной импульсной модуляции.
![Рисунок 3 - Схема работы таймера через DMA. Источник изображения [2]. Рисунок 3 - Схема работы таймера через DMA. Источник изображения [2].](https://habrastorage.org/r/w780/getpro/habr/upload_files/f31/cc6/3c0/f31cc63c00d606d29b0971177729e491.png)
При работе таймера в режиме ШИМ, единичный импульс формируется значением регистра CCR. Уровень логического нуля или единицы при значении CNT < CCR устанавливается программно. Соответственно необходимо:
1) Значение регистра ARR установить так, чтобы счет от 0 до ARR проходил за время передачи одного бита (1,25 мкс);
2) Записывать значение регистра CCR так, чтобы одно соответствовало либо значению «1» либо «0» по протоколу адресных светодиодо��.
Для примера возьмем байт 0x05 (0000 0101). Младший бит равен 1, его необходимо отправить временной последовательностью «1». Для этого в регистр CCR необходимо записать число, соответствующее времени «1». Для нуля записываем в CCR число, соответствующее времени «0». И так далее. Регистра ARR при этом отсчитывает время периода 1,25 мкс.
Таким образом, для управления гирляндой необходимо сформировать массив, в котором байт каждого цвета разобран на биты, которые в свою очередь заменены магическими (рассчитанными в зависимости от тактовой частоты) числами, соответствующими временным интервалам протокола WS2812B. Этот массив передаем в таймер через DMA.
Линеаризация яркости
Управление яркостью свечения светодиодов требует отдельного внимания. Дело в том, что глаз воспринимает изменение яркости светодиода непропорционально изменению подаваемой на него мощности. Соотношение между световым стимулом – яркостью и уровнем вызываемого ощущения упрощенно можно выразить следующей формулой:
где:
B – яркость воспринимаемого ощущения;
N – значение яркости (мощности) светодиода.
Эта формула, определяющая зависимость уровня зрительного ощущения от яркости действующего излучения представляет собой психофизический закон Вебера-Фехнера. Чтобы получить линейное изменение яркости необходимо составить массив с логарифмами N, при этом по порядку возрастания индекса массива, значения данных логарифмов должны представлять линейную функцию. График такого расчета представлен на рисунке:

Точки линии «Эталон» вычислены математически (функция y = k*x), точки линии«Яркость» подобранные под такие (целые) значения, которые возможно записать в светодиод. Сценарии свечения, наподобие «градиент яркости» или «плавное затухание» на светодиодной гирлянде требуют корректировки данных согласно приведенному выше графику. Стоит отметить, что «цвета» светодиодов WS2812B также светят неодинаково (зеленый ярче остальных) и по идее, тоже требуют индивидуальной калибровки. Но мы не станем на текущем этапе так углубляться.
Генератор случайных чисел
Реализация сценария случайного свечения требует TRNG (генератор истинных случайных чисел). Но в микроконтроллере STM32F103 такого генератора нет. В качестве источника «шума» предлагаю использовать канал АЦП (без вывода на ножку), данные на котором считаем достаточно случайными (в младшем значащем разряде). Считанные с АЦП значения прогоняются через CRC полином. Для наших целей результат считаем достаточно случайным. Вот результат проверки:

Modbus RTU
STM32F103 помимо невысокой цены радует поддержкой интерфейса USB, который будем использовать для связи с ПК. Выбор протокола Modbus RTU обосновывается наличием готовых библиотек, существенно ускоряющих процесс разработки. Для ёлочный гирлянды такое решение кажется слегка тяжеловесным, оно вместе с тем оно универсально. Регистровая модель Modbus RTU в целом несложная, её легко расширять под новый функционал. В текущий момент в устройстве тринадцать регистров.
Регистр |
Описание |
По умолчанию |
|
0 |
DEVICE_TYPE |
Тип устройства |
3 |
1 |
PRG_HW_VERSION |
Версия прошивки и платы |
1 |
2 |
MODBUS_ADDRESS |
Modbus адрес устройства |
1 |
3 |
MODBUS_SPEED |
Скорость обмена через Modbus: 0 – 1200, 1 – 2400, 2 – 4800, 3 – 9600, 4 – 19200, 5 – 38400, 6 – 57600, 7 – 115200 |
3 |
4 |
DEVICE_ERRORS |
Ошибки устройства |
|
5 -9 |
Резерв |
|
|
10 |
LEDS_COUNT |
Число подключенных светодиодов |
|
11 |
LEDS_BRIGHTNESS |
Яркость свечения светодиодов, %: 0 – минимальная, 100 – максимальная |
|
12 |
LEDS_MODE |
0 – светодиоды выключены, 1 – красный, 2 – зеленый, 3 – синий, 4 – белый, 5 – желтый, 6 – бегущий огонь (синий на жёлтом), 7 – случайный выбор цвета и яркости, 8 – имитация раскаленных углей, 9 – градиент красного цвета, 10 – круговая смена цветов, 11 – режим «Арбуз». |
|
DFU загрузчик
DFU загрузчик нужен исключительно для удобства обновления прошивки. К счастью, писать самостоятельно его не нужно, уже есть готовый. Особенностью данного загрузчика является то, что он размещается в конце Flash памяти, а значит прошивку можно компилировать без смещения адресов. Для первоначальной записи загрузчика в BluePill нужен внешний программатор. Впоследствии, можно обновлять прошивку через STM32Cube Programmer, подключаясь к плате через USB.
Терминал на Python
Последний шаг подготовительных работ – небольшой терминал, написанный на Ptyhon, для управления гирляндой. Здесь мы можем задать число светодиодов, а также их цвет (выбрать сценарий) и яркость.
Вот примеры некоторых режимов работы гирлянды:

Схема подключения адресной светодиодной матрицы или гирлянды к BluePill выглядит так:

Обязательно используйте внешний сетевой адаптер с выходным напряжением 5 В, так как светодиоды WS2812B могут потреблять значительный ток.
Творческая составляющая
Рассмотрев технические особенности проекта, можно перейти к основной цели публикации – поиску творческой составляющей. Идея гирлянды на адресных светодиодах не нова, рынок завален всевозможными вариантами: Bluetooth, бесконечные вариации миганий, генерация и��ображений, мерцание под музыку, шторка с каплями, бахрома и т.д.
Что может предложить DIY проект? Озвучу возможные идеи:
1. Обучение с телевизионного пульта;
2. Радиоканал с секретным режимом;
3. Имитация неисправности;
4. Датчик освещенности;
5. Работа от АКБ;
….
А может вовсе не нужна гирлянда, когда в распоряжении светодиодная матрица?
Как было сказано в начале публикации – это история с открытым концом. Интересно, во что можно развить проект, который начался с индикаторов приборной панели. Хорошие идеи (реальные для реализации на BluePill) будут добавлены к текущей прошивке и терминалу, актуальные версии которых можно скачать в git. Скачивайте, заливайте на BluePill, пишите идеи в комментариях.
Ресурсы
1. Прошивка и терминал для STM32 BluePill;
2. Протокол WS2812B без пустых циклов и прерываний;