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

Платка

Круглое число светодиодов (8 штук) + 9-й светодиод с драйвером для проверки. Кроме самих светодиодов судя по datasheet не нужно ничего, даже шунтирующих конденсаторов по 0,1 мкФ. Хотя для варианта с отдельным драйвером конденсатор советуют. Отдельно советуют, но не обязывают пощадить порт микроконтроллера, а заодно и выходной порт светодиода токоограничивающим резистором на 30 Ом. Я же ошибок себе не прощаю, потому им пренебрег. Вот что значит современные высоко-интегрированные решения, плата свободно вывелась в одном слое. По итогу можно смело подключать к контроллеру, Остается одна проблема, светодиоды питаются от 5В, и рассчитаны на пятивольтовый порт ввода-вывода, а в STM32 3.3.

Порт ввода-вывода (совместимость 5В и 3,3В)

Судя по datasheet к старым микросхемам 70х, единица начинается у них с 2,4В, а падение напряжения на Pull-Up транзисторе микроконтроллера 0,2В и не более 0,3В. Получается что +3В при +2,4 предельно допустимых, уже на грани, но в большинстве случаях может и прокатить. Прокатило и здесь.

Если по честному тогда в случае с STM32 подойдут не все порты, а только те что допускают 5В. Отличие обычных от пятивольтовых одно, на обычных стоит защитный диод, выравнивающий напряжения с напряжением питания, который и не разрешит подать 5В. Пятивольтовые помечаются пометкой FV в таблице datasheet. В итоге для работы с пятивольтовой логикой нужно сконфигурировать такой порт в режиме открытый сток (open drain), подтянув к +5В внешним резистором. Но здесь была замечена еще одна странность или пятивольтовых портов не бывает, или порт WS2812 очень прожорливый. Сформировать 0-5В получилось только с 500 омным резистором, с килоомными резисторами единица падала до 3,4В. Но опять же все эти трюки необязательны, потому как прокатывает и так.

Протокол светодиода

Код доступа к светодиодам в файле ws2812.c. В datasheet что то говорится про NRZ, я же чую что их протокол похож на 1-wire в DS18B20. С той лишь разницей что тайминги там наносекундные, в то время как на ds микросекундные. Организовать такой протокол сложнее, атмеговоды пишут код на ассемблере что бы строго отмеренным количеством NOP-ов поддерживать нужные тайминги. В случае с STM можно обойтись и обычным таймером, главное убрать из функции передачи данных в светодиод лишнее барахло вроде вызова других функций, тогда получится вписаться в строгие тайминги. У меня получилось не сразу, сразу не понял, что таймер для следующего бита нужно обнулять в конце цикла а не в начале, т.к. иначе на каждый бит уходит не одинаковое время и это сбивает отправку. Вообще оставалось еще два крайних варианта, это либо использование ШИМ с DMA, либо UART. В uartе каждый байт бы символизировал бит (с dsками такой трюк работал), а в варьируя по dma скважность ШИМ так же можно было бы подавать 0 и 1. Но опять же раз уж прокатил ручной вариант, то пускай он и работает, да и меня буфферы с intом для каждого бита не впечатляют.

Остальные особенности

Видимо из за удобства разводки светодиоды не RGB а ГРУ, вернее GRB. В то время как драйвер нормальный, RGB. Пришлось добавить отдельную функцию переворачивалку туда и обратно. В остальном очень удобно объявить union который когда надо три переменных по 8 бит с красным синим и зеленым цветом, а для функции отправки одно 32 битное число. По итогу все происходит внутри библиотеки, а вам нужно запихать массив структур с цветами светодиодов в функцию wsUpdateCascade(*led_array, size), не забыв указать при этом какой из них 11й, а какой 12й в поле type. На этом низкоуровневые мучения заканчиваются, начинается веселье.

Random

Какие же эффекты без рандома. Благо что за целочисленным рандомом далеко ходить не надо. Я скачал исходники AVR-libc и скопировал оттуда функцию rand. Там она целочисленная и 32 битная, то что нужно для STM32, но никак не для меги. Обожаю opensource за такие возможности.

Эффекты

Больше трех так и не выдумал. Эффекты лежат в файле.

  1. Радуга, в которой все светодиоды выстроены во все цвета радуги и плавно перетекают из одного цвета в следующий.

  2. Из сериала рыцарь дорог с бегущим огоньком, и еще эмуляцией залипания огонька как на лампочках накаливания. Заранее написанную функцию радуги добавил и в него.

  3. Огонь. Тупее всех остальных, просто пихаем в канал красного цвета рандомное число 0–255. А что бы огонек переливался с красного в желтый, генерируем рандом и для зеленого канала, но не даем ему быть ярче чем четверть красного. А еще ловим условием моменты когда красный больше 250, тогда включаем на всю все цвета, чтобы эмулировать искорки.

С одной стороны это обычная рутинная отладочная плата, с другой можно залипнуть возле этой полоски на пол дня, еще и в интернетах полно самостоятельных мегапроектов, ничего кроме тех же самых огоньков не предлагающих. Эффекты масштабируемые, можете зашивать их себе в ваши контроллеры со светодиодной лентой, меняя макрос Line size по вашему усмотрению.

Вывод

Чудная дрянь эти RGB светодиоды. Спокойно ужились и отдельный драйвер и светодиоды в одной цепи, не понадобилось никаких внешних элементов и ассемблерных вставок кода. Побольше бы такого дешевого китайского интегрального, простого в использовании и залипательного, и тик ток не нужон будет это ваш.

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


  1. agalakhov
    00.00.0000 00:00
    +3

    Идея с UART хорошая, SPI конкретно на STM32 работает хуже. DMA не обязателен, достаточно включения буферизации у UART. Скорость должна быть 3.75 Мбод, 8-N-1, отправляются два бита в одном байте. Формат байта: 0xx100yy, где xx - первый бит, yy - второй бит (каждый бит повторяется дважды). Алгоритм проверен на WS2812 и SK6812. Моя реализация.

    По-колхозному можно подавать на WS2812 и 3-вольтовую логику, в большинстве случаев они ее воспринимают, хотя это не гарантируется. Преобразовывать уровень в случае, если между диодами и схемой есть провод, надежнее не подтяжкой, а любым 74LVT. Если диодов очень много, то в качестве этого 74-го можно использовать демультиплексор, чтобы разбить светодиоды на несколько независимых групп, а не ставить все одной цепью.


    1. AlanDrakes
      00.00.0000 00:00
      +1

      Собрал как раз на SPI. Частота ядра - 20МГц, предделитель SPI - /4 (5МГц). 8 бит-слотов занимают 12.8мкс, 1 бит-слот - 1.6мкс (по какой-то причине светодиоды лучше всего заработали именно с этой скоростью). Данные отправляются по DMA. Используется 48 байт. 0x70 = '1', 0x40 = 0. Буфер кольцевой, 2*24 байта (бита). По прерыванию DMA уже отправленная половина буфера заполняется новыми значениями для передачи. 20 светодиодов вообще без сбоев приёма обновляются.

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


      1. agalakhov
        00.00.0000 00:00

        На SPI пакость в том, что SPI довольно значительно различается между разными STM32 и местами даже между ревизиями одного и того же чипа, про него много Errata. Поэтому код получается плохо переносим. Это не значит, что он не будет работать, но с UART просто проще и переносимее. Код для UART вообще можно написать полностью переносимым и не зависящим от архитектуры контроллера, если его параметризовать функцией "послать байт".


    1. dltex Автор
      00.00.0000 00:00

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


      1. agalakhov
        00.00.0000 00:00

        I2C работает на очень небольших дистанциях и чувствительна к помехам из-за большого сопротивления подтяжки и отсутствия согласования линии как класса. Повторитель с push-pull выходом имеет меньшее выходное сопротивление и допускает более длинные кабели, что как раз для светодиодов актуально.

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

        Демультиплексоры актуальны, если процессор рулит не только светодиодами. Израсходовать 100+ пинов гораздо проще, чем кажется, особенно если нужно вешать внешнюю память и/или дисплей. Если не уложиться в 176 пинов, придется паять BGA.


        1. dltex Автор
          00.00.0000 00:00

          Сперва покажи мне проект со 100+ матрицами на 1024 светодиода на длинных проводах подключенных к обычному контроллеру, потом уже говори что так нельзя. Пока что ваше решение разве что дороже, но не лучше.


          1. agalakhov
            00.00.0000 00:00

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


  1. Hisoka
    00.00.0000 00:00

    Жирный минус этих светиков - слишком яркие на минимальной яркости и эффектов не получишь кроме вкл/выкл, т.к. яркость "регулируется цветом". Потому, для ламп-ночников не годятся.


    1. IvanPetrof
      00.00.0000 00:00

      Можно прикрыть их чем-нить полупрозрачным - покрасить, наклеить тонировочную плёнку ( для авто продаётся разной плотности)


      1. Hisoka
        00.00.0000 00:00

        Это да, но есть аналоги с отдельным байтом под яркость.


      1. csharpreader
        00.00.0000 00:00

        Вот бы сейчас в 2023-м красить и плёнку колхозить. В 80-е накрасились и наколхозились.


        1. Dakar
          00.00.0000 00:00

          Правильно. Лучше мерзотный ШИМ вкорячить на частоте поменьше.


          1. MW_dem1305
            00.00.0000 00:00
            +1

            Всё там нормально управляется. Сделал драйвер без проблем, куча эффектов на фастлед, IR, датчик света, микрофон+FHT и PIR. Работает как надо.


        1. dltex Автор
          00.00.0000 00:00

          в те же 80е все газоразрядники прикрывались тонированным прозрачным пластиком, что бы яркие цвета стали загадочными полутонами. Кстати светодиодные индикаторы в китайских дивидишниках и тв dvbt приставках до сих пор тонированные, норм решение.


          1. Sun-ami
            00.00.0000 00:00

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


    1. aumi13
      00.00.0000 00:00
      +1

      слишком яркие на минимальной яркости и эффектов не получишь кроме вкл/выкл, т.к. яркость "регулируется цветом". Потому, для ламп-ночников не годятся.

      какая-то ересь. нет такого.


  1. aumi13
    00.00.0000 00:00
    +1

    закажи сразу круг, и будет тебе развлечение


    1. dltex Автор
      00.00.0000 00:00

      в планах матрица 8x8 или сколько там на сколько с одного пакета 100шт получится, я их дома травлю/паяю.


  1. osmanpasha
    00.00.0000 00:00
    +1

    А зачем вам копировать рандом из AVR-libc? У gcc-arm свой должен быть (скорее всего примерно такой же). Точнее у newlib-nano или что там


    1. dltex Автор
      00.00.0000 00:00

      Я сперва себе для проекта с attiny вот эту функцию написал, https://github.com/dltech/desk_lamp/blob/main/lib/random127.c . А тут уже чисто по привычке скопировал, щас заглянул в исходники libnewlib, понял что тупанул.


  1. comargo
    00.00.0000 00:00
    +1

    Я В своё время пытался сделать HAL для светодиодов. В качестве исходных кодов для переписывания нашел работу через DMA и bit-banding и библиотеку для Ардуино от Алекса Гивера.

    https://www.martinhubacek.cz/blog/stm32-ws2812b-dma-library/

    https://github.com/comargo/stm32_hal_ws281x

    https://github.com/comargo/christmas_lights