Всем доброго времени суток!
Хочу поделиться с Вами своими мыслями, о том можно ли приспособить WS2812B в качестве экрана для самоделок.
Конечного устройства я все еще не собрал, но вот небольшой дисплей, по-моему, получился. Всем кому интересно прощу под кат.
Давно хотелось попробовать поработать с такими светодиодами, но как обычно то руки не доходили, то зеленая в пупырышках голос подавала, а тут как то все сложилось и я стал счастливым обладателем 8 плат со светодиодами WS2812B.
От продавца каждая плата приходит запечатанной в антистатический пакет, так что поездку платы пережили хорошо.
Упаковка
Платы небольшие, размером всего лишь 3х3 см.
В конечном итоге после сборки дисплея его размер получился 6х12 см.
Сзади все выглядит не так хорошо как спереди, но это пока что тестовый образец.
На каждой плате есть две группы по 4 контакта, все контакты подписаны так, что сборка не составляет какого либо труда. Для правильной передачи сигнала данных в матрице главным условием является последовательное подключения контакта OUT предыдущей платы, к контакту IN последующей платы. Контакты VCC отвечают за "+" питания, их можно подключать к источнику питания в произвольном порядке. Идеальным решением будет параллельное подключение всех плат, что позволит обеспечить наиболее равномерную яркость светодиодов во всей матрице. Контакт GND отвечает за подачу "0" или "-", все четыре контакта GND каждой платы соединены между собой и для работы платы достаточно подключить хотя бы один из них.
Как видно на фото, я использовал GND контакты для сборки всех плат в одну матрицу. Решение спорное, но для тестирования возможно. Так как изначально планировал разделить дисплей программно на четыре модуля, то и питание подавал на каждый из таких модулей отдельно. Линия данных в свою очередь подключена к каждой группе из двух плат последовательно: от нижнего модуля к верхнему и опять к нижнему. Можно было бы и не заводить данные именно так, но как сказал выше первой идеей было собрать матрицу состоящую из четырех логических индикаторов и для упрощения математики при нахождении номера требуемого светодиода в индикаторе решил собирать модули именно так.
На фото видно, что при такой сборке линии данных как раз и получается матрица из практически независимых сегментов. Для того что бы включить один и тот же светодиод в каждом сегменте достаточно знать номер светодиода для первого сегмента, количество светодиодов в сегменте (в моем случае их 32), и номер сегмента в котором нужно включить светодиод, а это уже всего лишь работа с прямоугольным массивом.
Но это я уже убежал немного вперед в программирование.
Так как дисплей получился не совсем жесткий, решил для него сделать временный корпус из пары кусочков полупрозрачного пластика (за пластик отдельное спасибо софтверной компании на букву М и ее детищу с цифрой 7 в названии).
Как оказалось, без рассеивателя диоды светят слишком жестко, поэтому в качестве рассеивателя был использован кусочек тонкого белого пластика.
Знаю что получилось несколько топорно, но о корпусе пока не думал, главным было собрать дисплей и в работе понять для чего он подойдет.
Перед тем как окончательно перейти к программированию пару слов об энергопотреблении.
Согласно datasheet напряжение питания для таких светодиодов составляет от +3,5 до +5,3 вольта. А с током потребления все как то странно, в datasheet пишут 18 мА на цвет, другими словами при работе в белом цвете на максимальной яркости светодиод должен потреблять около 54 мА, а на форумах пишут о токе около 60-70 мА минимум.
Мой дисплей на 128 светодиодов питается напряжением 4,6В и при таком напряжении для белого света он потребляет ни много ни мало 2,49 А
Получается что ток 18 мА указанный в datasheet это ток не одного цвета, а всех трех.
Заливка одним из основных цветов (зеленым) потребляет 1.23 А.
А вот разноцветная мозаика потребляет всего 0,65А
Ну а теперь немного программирования:
Для управления дисплеем использовал библиотеку NeoPixel, поэтому все ниже сказанное относится в первую очередь к ней.
Сначала пару слов о том, как собственно можно управлять светодиодами с точки зрения программиста, не забираясь в то как сигнал передается по проводу.
Каждый светодиод в дисплее имеет свой порядковый номер, нумерация начинается с нуля, номера считаются последовательно в порядке подключения светодиодов. Для включения или выключения светодиода используется функция setPixelColor которая в качестве параметров принимает номер светодиода и его цвет в кодировке rgb. После установки/изменения цвета всех требуемых светодиодов необходимо выполнить функцию Show, которая отправит команду светодиодам принять установленный цвет.
По-большому счету только этих двух функций достаточно чтобы выводить на такой дисплей практически любую информацию.
Как только начал свои эксперименты с дисплеем, сразу обнаружил его главное преимущество: светодиоды запоминают полученный цвет. При работе с семисегментными индикаторами обычно требуется либо установить много регистров для хранения состояний каждого диода, либо динамически раз 40 в секунду обновлять картинку, а тут вывел один раз и хоть в сон отправляй контроллер.
Как и писал выше изначально думал поделить весь дисплей на 4 одинаковых индикатора и простым смещением на количество светодиодов выводить символы на нужный индикатор. Немного подумав, решил, что памяти пока что хватает, так что сделал единый массив констант, в который и занес массив номеров светодиодов.
Массив индексов
Для отдельного индикатора
#define sm 32 // количество светодиодов в индикаторе
// матрица первого индикатора
byte seg[8][4]={{19,20,27,28},{18,21,26,29},{17,22,25,30},{16,23,24,31},{3,4,11,12},{2,5,10,13},{1,6,9,14},{0,7,8,15}};
//для индикатора N ID светодиода равно seg[Y][X]+(N*sm)
// матрица для все дисплея
byte seg[8][16]={{19,20,27,28,51,52,59,60,83,84,91,92,115,116,123,124}
,{18,21,26,29,50,53,58,61,82,85,90,93,114,117,122,125}
,{17,22,25,30,48,54,57,62,81,86,89,94,113,118,121,126}
,{16,23,24,31,48,55,56,63,80,87,88,95,112,119,120,128}
,{3 ,4 ,11,12,35,36,43,44,67,68,75,76,99,100,107,108}
,{2 ,5 ,10,13,34,37,42,45,66,69,74,77,98,101,106,109}
,{1 ,6 ,9 ,14,33,38,41,46,65,70,73,78,97,102,105,110}
,{0 ,7 ,8 ,15,32,39,40,47,64,71,72,79,96,103,104,111}
};
Создание такого массива индексов позволяет просто по координатам X Y обратиться к любому светодиоду, не занимаясь вычислением его координат, что упрощает анимацию символов. Но с другой стороны такой подход, увеличивает размер программы и работать так с большими дисплеями не получится.
Следующим этапом было решить как хранить шрифт и где его нарисовать. Вспомнив, что в языке Arduino есть хорошая функция bitRead, которая позволяет обращаться непосредственно к каждому биту числа по его номеру, я решил, что хранить шрифт буду в виде массива двоичных чисел, а рисовать их получилось довольно удобно в Calc.
В итоге, получился файл с вот таким содержимым
Немного пояснения
Для закрашивания ячеек использована функция условного форматирования, а для формирования готового массива байт использовал функцию СЦЕПИТЬ.
В итоге, в ячейке получается готовый массив, который просто надо скопировать в код.
Например это цифра 5
и функция, позволяющая вывести любой символ из из этого массива в любые координаты дисплея:
#define matx 16
#define maty 8
void ShowSumbol(byte id, int x, int y, byte r, byte g, byte b,byte black)
// id индекс символа в таблице символов
//x,y координаты левого нижнего угла
//r,g,b цвет
//black выключить или нет неиспользуемые пиксели 1 выключать
{
for (int xi=0; xi<segx;xi++)
{
for (int yj=0; yj<segy;yj++)
{
if (bitRead(num[id][xi],yj)==1)
{
if ((y+yj)<maty && (x+xi)<matx)
{
if (((x+xi)>=0)&&((y+yj)>=0)) strip.setPixelColor(seg[y+yj][x+xi],strip.Color(r,g,b));
}
}
if (bitRead(num[id][xi],yj)==0)
{
if (black==1) strip.setPixelColor(seg[y+yj][x+xi],strip.Color(0,0,0));
}
}
}
}
Небольшое видео работы:
Еще попробовал использовать это дисплей для программного анализатора спекта работающего на основе библиотек быстрого преобразования фурье
Небольшое видео работы:
Для работы анализатора необходимо соединить левый или правый канал с аналоговым входом Ардуино (в моем случае вход 0), а общий провод соединить с землей.
На видео видео паразитный сигнал в первую очередь он вызван тем что не поставил на вход Ардуино даже элементарного фильтра, ну и конечно с качеством телефонного генератора.
Так же из за отсутствия ограничения уровня сигнала вся ответственность жизнь порта Ардуино ложиться на пользователя и подключать такой анализатор напрямую к выходу усилителя категорически не рекомендуется.
В конце кода есть строка задержки delay(15) добавил ее что бы картинка не так быстро мигала при работе с музыкой.
Выводы:
Использование светодиодов WS2812B для создания электронных табло почти идеально:
К плюсам можно отнести:
— простоту управления;
— простоту схемотехники;
— самостоятельное удержание картинки без необходимости обновления состояния светодиодов.
А вот к минусам можно отнести:
— большую по сравнения с обычными светодиодами цену;
— довольно крупный размер кристалла, из-за чего дисплей небольшого размера имеет очень маленькое разрешение.
Планирую купить+39Добавить в избранноеОбзор понравился+59
+94
У меня эти диоды в большом табло(выше 500) дохнут постоянно. Подложка довольно толстая, нагрев максимум в пик тока около 50-55 градусов, первые несколько дней работали отлично, дальше каждую неделю по штуке дохло, дохнет один — перестают работать последующие. Смотрел в микроскоп — теряют соединение тонкие контакты. Скорее всего плохое качество техпроцесса или сборки в моей партии, до этого покупал для системы танцпола и для ambielight, там количество трупов в разы меньше.
Брал в январе на пробу метр, делал светоигрушку с управлением по bluetooth, на данный момент вырезаны уже 3 диода, один потух, один сдох и все за ним начали хаотически вспыхивать, один то работает, то нет.
Прикольно, классно было бы взять большой лист текстолита, протравить дорожки и запаять россыпь таких светодиодов самому, не встретил информации у автора, интересно, ардуино сколько штук сможет «потянуть» таких светодиодов?
Программно, на сколько помню, ограничение в 1000 диодов на всех каналах.
На моей практике около 500 диодов Arduino Nano едва заметна задержка(библиотека fastled), на ESP8266 не заметна.
Спасибо буду знать что есть такая библиотека.
Надо только проверить как у нее с кириллицей.
А даже если бы знал раньше что есть такая библиотека то скорее всего попытался бы написать сам, основной профит был пощупать как оно работает, а не вкинуть одной строкой то что написал кто-то другой.
Если бы чуть лучше знал ASM то и протокол попытался бы реализовать сам вообще без библиотеки. :)
Эээээ. В смысле? GFX библиотека — это просто класс, реализующий некие графические примитивы. Физический вывод в нужную координату осуществляется через переопределение виртуальной функции drawPixel. Если её неправильно написать — естессно ничего работать не будет. Но это не проблема библиотеки :)
Как можно шрифтом «упереться в размерность матрицы»???
Создаём шрифт 3х5 и выводим его в любую точку матрицы.
Ясное дело, что шрифт высотой 20 пикселей не влезет на матрицу размером 16 пикселей, например. Но при чём здесь библиотека?
Валяется у меня десяток таких. Даже в страшном сне не могу себе представить табло на них :)
Да и цена — 158$ за 1000 штук. То есть табло в 32х32 и шагом 6 мм (будем очень большими оптимистами) обойдётся баксов в 200. Готовая панелька 32х32 с шагом 6 мм обойдётся с доставкой в 20$.
У них куча гирлянд на ws2811 (с 8 мм RGB светодиодом). Смотрятся отлично, переходить на дорогущие APA106 нет никакого смысла.
Сам такую гирлянду на ёлку вешал на новый год :)
У меня тоже 2811 висели, там блямбы здоровенные. Не такие и дорогущие 20$ за сто штук. Цена у них примерно одинаковая, только одни уже в гирлянде, а другие россыпью. Но возможно и нет смысла переходить, но если ещё понадобятся то можно было бы рассмотреть. Но конечно не самая главная идея
Если надо размер поменьше, возьмите светики APA102-2020: www.led-color.com/upload/201604/APA102-2020%20SMD%20LED.pdf
Тот же функционал, но корпус 2ммх2мм.
Бонусом — несущая частота встроенного шим более 20кГц, что делает их намного приятнее для глаза в плане мерцания, если сравнивать с WS2812
Однозначно да. Но так как прогресс не стоит на месте надо изучать что то новое пока есть возможность.
Да и тут плюсы тоже есть, хотя цена их перекрывает.
Я не думаю что в угоду достаточности ресурсов стоит удаваться в подобную оптимизацию. НО с другой стороны красивый код изначально — верх мастерства и к нему надо стремиться )
хотя как-то на ардуино.ру я заспорил с одним парнем… по его словам оптимизация как таковая — изначально не верный подход к выбранному оборудованию и что проще перейти на более производительный камень, чем заниматься вычесыванием кода.
Как по мне код надо вычесывать по возможности, а вот такие оптимизации они хороши и нужны, то только тогда когда этого требует ситуация, в моем случае код занял не больше 15% памяти, так что до момента когда стоит задумать о такой оптимизации мне еще далеко :)
Единственно о чем еще с времен института приучили думать это о размерности переменных, типа не брать Инт там где хватит Байт и так далее ибо сменить тип переменной бывает очень грустно и больно. Хотя и боролись мы с нашим преподом по программированию на предмет это в ваше время 640 килобайт было, а мы уже скоро до гига дорастем зачем ее экономить то :)
Не только — так как у AVR не общее адресное пространство (не Фон-Неймановская архитектура), то для чтения из progmem надо использовать pgm_read_byte (или её аналоги для другого размера данных).
Мини тест без PROGMEM
Скетч использует 5 446 байт (17%) памяти устройства. Всего доступно 30 720 байт.
Глобальные переменные используют 518 байт (25%) динамической памяти, оставляя 1 530 байт для локальных переменных. Максимум: 2 048 байт. c PROGMEM
Скетч использует 5 446 байт (17%) памяти устройства. Всего доступно 30 720 байт.
Глобальные переменные используют 390 байт (19%) динамической памяти, оставляя 1 658 байт для локальных переменных. Максимум: 2 048 байт.
Выигрыш есть и он не маленький, Но это только компиляция, как оно при исполнении будет не проверял :)
:)
Это особенность светодиода.
Этот диод нормально работает на статических основных цветах и на белом цвете, а вот на быстрой заливке промежуточным цветом иногда не включается или включается но другим цветом. Я пытался выяснить почему так но так и не смог, но дело явно не в коде.
И резистор висит, и пара конденсаторов на питанию тоже.
Пробовал и без резистора и без кондеров ничего не меняется. Диод то показывает то нет иногда помогает если выключенным светикам давать цвет не 0,0,0 а скажем 5,5,5 они все равно не горят но тогда этот может проснуться, но в зависимости от интенсивности картинки может опять не пахать.
При этом как видно его такая работа совсем не мешает работать другим и что немаловажно не сбивает порядок включения других диодов (сбойный стоит по-моему номером 30) а всего их 128, то есть за себя данные он успешно транслирует, а вот сам почему то ведет себя немного неадеквато.
Скорее в коде. Попробуйте с другого диода начать цепочку. Причина может быть и в звоне (я на 100% уверен, что никаких мер к согласованию не принималось).
А, «проблемный» не в начале цепочки? Переставьте диод или кластер целиком в другую позицию для контроля.
Нет не первый. он 30 или другими словами предпоследний на втором модуле.
Пытался менять местами еще когда только собирал и делал первые тесты, результат тот же потому и решил что это аппаратный глюк конкретного пикселя.
У вас i щелкает от 1 до 16. А элементы массива data_a имеют номера от 0 до 15. Соответственно — вы пишете уже в ячейку памяти за границей массива.
Это вот только то, что просто бросается в глаза. Ну и код надо чистить и чистить, конечно.
Да с размерностью массива протупил.
В первом столбце без фильтров на входе идет постоянный шум и он просто не гаснет даже в тишине поэтому матрица была пересчитана на 17 столбцов, а потом при выводе seg[j][i-1]
Номер столбца массива и номер столбца дисплея смещались на единицу. А вот о том что стоило бы увеличить размер массива я как то не подумал :)
То что код надо чистит тут я даже спорить не буду и чистить и оптимизировать но дело в другом.
Щелкает 6 светодиод 4 столбца, и это вряд ли связано конкретно с этой ошибкой. Он щелкает даже на стандартных тестах библиотеки на градиенте.
Если при замене диода эффект для конкретной точки не исчезает — это 100% ошибка программы, без малейших сомнений. Кто-то искажает информацию до отправки.
Там вроде бы говорится о том что первый в цепочке светится зеленым, вместо установленного цвета, а у меня не первый и он не светится, а просто как то не адекватно принимает свой цвет.
" о том что первый в цепочке "
имеенно так я вчера и воспринял вашу проблему
сейчас гадаю — почему?))
(разве что интерференция «первом»-«один» на LighTning; видео никогда не смотрю)
На моей практике около 500 диодов Arduino Nano едва заметна задержка(библиотека fastled), на ESP8266 не заметна.
Зачем было изобретать велосипед?
Надо только проверить как у нее с кириллицей.
А даже если бы знал раньше что есть такая библиотека то скорее всего попытался бы написать сам, основной профит был пощупать как оно работает, а не вкинуть одной строкой то что написал кто-то другой.
Если бы чуть лучше знал ASM то и протокол попытался бы реализовать сам вообще без библиотеки. :)
learn.adafruit.com/adafruit-gfx-graphics-library?view=all
Действительно, NeoMatrix выводит текст
Но при попытке изменить шрифт упираемся в размерность матрицы.
Создаём шрифт 3х5 и выводим его в любую точку матрицы.
Ясное дело, что шрифт высотой 20 пикселей не влезет на матрицу размером 16 пикселей, например. Но при чём здесь библиотека?
Лучшая цена 2 ~ 1000 шт. IC apa106 F8 8 мм/f5 5 мм круглые RGB полном Цвет Neo Pixel arduino матовый светодиодные Чип (как WS2812B) 5 В
https://aliexpress.com/item/item/10-1000Pcs-RGB-Full-Color-IC-Built-IN-APA106-F8-8mm-F5-5mm-Neo-pixel-Arduino/32704656076.html
Надо будет попробовать, хотя цена :(
Да и цена — 158$ за 1000 штук. То есть табло в 32х32 и шагом 6 мм (будем очень большими оптимистами) обойдётся баксов в 200. Готовая панелька 32х32 с шагом 6 мм обойдётся с доставкой в 20$.
Сам такую гирлянду на ёлку вешал на новый год :)
www.led-color.com/upload/201604/APA102-2020%20SMD%20LED.pdf
Тот же функционал, но корпус 2ммх2мм.
Бонусом — несущая частота встроенного шим более 20кГц, что делает их намного приятнее для глаза в плане мерцания, если сравнивать с WS2812
Главное, не берите SKxxxx — поганенькие клоны…
Да и тут плюсы тоже есть, хотя цена их перекрывает.
koticik
а цветные варианты — не менее требовательны?
ружья должны вроде умещаться
хотя как-то на ардуино.ру я заспорил с одним парнем… по его словам оптимизация как таковая — изначально не верный подход к выбранному оборудованию и что проще перейти на более производительный камень, чем заниматься вычесыванием кода.
Единственно о чем еще с времен института приучили думать это о размерности переменных, типа не брать Инт там где хватит Байт и так далее ибо сменить тип переменной бывает очень грустно и больно. Хотя и боролись мы с нашим преподом по программированию на предмет это в ваше время 640 килобайт было, а мы уже скоро до гига дорастем зачем ее экономить то :)
без PROGMEM
Скетч использует 5 446 байт (17%) памяти устройства. Всего доступно 30 720 байт.
Глобальные переменные используют 518 байт (25%) динамической памяти, оставляя 1 530 байт для локальных переменных. Максимум: 2 048 байт.
c PROGMEM
Скетч использует 5 446 байт (17%) памяти устройства. Всего доступно 30 720 байт.
Глобальные переменные используют 390 байт (19%) динамической памяти, оставляя 1 658 байт для локальных переменных. Максимум: 2 048 байт.
Выигрыш есть и он не маленький, Но это только компиляция, как оно при исполнении будет не проверял :)
Это особенность светодиода.
Этот диод нормально работает на статических основных цветах и на белом цвете, а вот на быстрой заливке промежуточным цветом иногда не включается или включается но другим цветом. Я пытался выяснить почему так но так и не смог, но дело явно не в коде.
Пробовал и без резистора и без кондеров ничего не меняется. Диод то показывает то нет иногда помогает если выключенным светикам давать цвет не 0,0,0 а скажем 5,5,5 они все равно не горят но тогда этот может проснуться, но в зависимости от интенсивности картинки может опять не пахать.
При этом как видно его такая работа совсем не мешает работать другим и что немаловажно не сбивает порядок включения других диодов (сбойный стоит по-моему номером 30) а всего их 128, то есть за себя данные он успешно транслирует, а вот сам почему то ведет себя немного неадеквато.
А, «проблемный» не в начале цепочки? Переставьте диод или кластер целиком в другую позицию для контроля.
Пытался менять местами еще когда только собирал и делал первые тесты, результат тот же потому и решил что это аппаратный глюк конкретного пикселя.
А скетч буков выложу но только вечером.
char data_a[16];
char x=17
for (i=1; i<x; i++) {
data_a[i] =
У вас i щелкает от 1 до 16. А элементы массива data_a имеют номера от 0 до 15. Соответственно — вы пишете уже в ячейку памяти за границей массива.
Это вот только то, что просто бросается в глаза. Ну и код надо чистить и чистить, конечно.
В первом столбце без фильтров на входе идет постоянный шум и он просто не гаснет даже в тишине поэтому матрица была пересчитана на 17 столбцов, а потом при выводе seg[j][i-1]
Номер столбца массива и номер столбца дисплея смещались на единицу. А вот о том что стоило бы увеличить размер массива я как то не подумал :)
То что код надо чистит тут я даже спорить не буду и чистить и оптимизировать но дело в другом.
Щелкает 6 светодиод 4 столбца, и это вряд ли связано конкретно с этой ошибкой. Он щелкает даже на стандартных тестах библиотеки на градиенте.
но она считается давно устранённой:
fastled.io/
Для подобных поделок она даже поудобнее.
имеенно так я вчера и воспринял вашу проблему
сейчас гадаю — почему?))
(разве что интерференция «первом»-«один» на LighTning; видео никогда не смотрю)
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.