RSS блога
Подписка
DIY контроллер LED панели на CPLD
- Цена: $5
- Перейти в магазин
Некоторое время назад участвовал в обсуждении DIY проекта матричных светодиодных часов
И что меня удивило — в качестве устройства отображения использовались древние одноцветные светодиодные матрицы 8х8 с шагом 5 миллиметров. Причём под них разводились сложные печатные платы, делалась софтовая динамическая индикация. И это в то время, когда уже давно доступны по цене в районе 10-20$ готовые полноцветные панели 64х32 с шагом 3 мм. А общий ассортимент подобных панелей очень большой и имеет шаг пикселя от 2 до 10 мм и практически любой размер.
В то же время использовать такие панели в DIY конструкциях достаточно непросто — готовые контроллеры стоят довольно больших денег и не имеют нормального API. Сделать же достаточно быстрое сканирование панели на обычно используемых в DIY микроконтроллерах достаточно сложно. Причём временные интервалы должны выдерживаться с высокой точностью — иначе начинается заметная неравномерность яркости.
Есть неплохие решения на Adafruit, но они все достаточно дорогие и сложные.
После некоторого раздумья возникла мысль — а почему бы не сделать предельно недорогую плату, которая будет мостом между обычной копеечной платой типа ардуино и LED панелью? После какой-то пары месяцев возни родилось что-то работающее :)
Основная сложность заключается в том, что на LED панелях градации цвета формируются только через PWM, причём последовательный. Таким образом для того, чтобы сформировать 64 уровня яркости — за время индикации одного кадра надо 64 раза выдать картинку. То есть 64х50=3200 Гц частота выдачи полной «однобитной» картинки. Следовательно — для выдачи экрана 64х64 надо выдавать данные пикселей со скоростью 3200х64х64=13 Мпикселей/секунду.
Совершенно очевидным было то, что без CPLD или FPGA здесь не обойтись — выдавать 26 МБ/сек на недорогих микроконтроллерах физически невозможно.
В качестве памяти мне на форуме IXBT порекомендовали очень интересную FIFO память Averlogic AL422B, которая имеет примерно 400кбайт памяти и может работать на частотах до 50МГц.
Учитывая, что моим основным требованием была максимальная дешевизна компонентов, чтобы готовая платка была доступна самодельщикам — была выбрана Altera EPM3064 — CPLD c 64мя макроячейками. В то же время столь малое количество макроячеек не позволяет сделать динамически конфигурируемую плату — конфигурацию необходимо компилировать непосредственно в CPLD.
Получившаяся схема лежит здесь
Детали:
CPLD EPM3064ATC44-10 — цена на Ali примерно 13-15$ за десяток
FIFO RAM AL422B — цена на Ali примерно 15$ за десяток
Кварцевый генератор на 50МГц. На плате предусмотрена установка в корпусах DIP14/DIP8/7050. Цена на Ali примерно 6-7$ за десяток
Стабилизатор на 3.3В в корпусе SOT223 — chipdip — 40р за штуку
Разъем IDC-10MS — chipdip — 3 р/штуку
Разъем IDC-16MS — chipdip — 8 р/штуку
Разъём IDC-14MS — chipdip — 7 р/штуку
Конденсаторы 1мкФ 0805 — 8 штук примерно по 1 р/штуку
Конденсатор 0,1мкФ 0805 — примерно по 1 р/штуку
Резистор 10к 0805 — копейки :)
Итого по деталям получается 1,5+1,5+0,7=3,7$ и 40+3+8+7+8*1+1=67 р. Всё вместе в пределах 5$ — копейки.
Исходный рисунок платы лежит здесь
Подготовленные gerber файлы для заказа
При пайке платы не забыть запаять перемычки на питание на обратной стороне платы.
Для RGB888 частота регенерации = 50МГц/3/256/кол-во пикселей, то есть, например, для панели 32х32 — 64Гц.
Для RGB565 частота регенерации = 50МГц/2/64/кол-во пикселей, то есть для панели 32х32 — 381Гц.
Глаз более-менее терпит частоту от 50Гц, поэтому для RGB888 максимальный размер сборки примерно 32х32 или 64х16. Для RGB565 — 128х64 или 256х32 (частота регенерации 48Гц).
Контроллер цепляется к правой нижней панели.
Бывают панели, которые имеют по два входных и два выходных разъёма. Такие панели по сути являются просто механической сборкой двух панелей по вертикали. Коммутируются как две независимые панели.
После сборки надо посчитать общую длину цепочки в пикселях — для этого смотрим — сколько всего панелей получилось в цепочке и умножаем это число на ширину панели в пикселях. Это число потом надо будет вбить в значение PIXEL_COUNT при конфигурации FPGA.
С сайта Altera после регистрации необходимо скачать и установить Quartus II 13.0sp1. Качать надо ИМЕННО ЭТУ версию — более новые версии уже не поддерживают серию MAX3000. Ломать её не надо — достаточно Web edition (free) версии. При скачивании не забудьте поставить галочки на поддержке MAX3000 и Programmer.
Еще понадобится Altera USB Blaster — обычная цена на ali порядка 3$
Открываем проект al422b_2rgb_8s.qpf
Слева открываем закладку файл и открываем файл led_al422_main.v — это основной файл проекта. В нём надо настроить параметры:
Используемое цветовое пространство. TRUECOLOR — 3 байта на пиксель, формат RGB888. HIGHCOLOR — 2 байта на пиксель, формат RGB565.
Должна быть раскомментирована только одна нужная строка:
Сколько RGB входов на панели — на панелях со входом HUB75 может быть 1 или 2 входа RGB. Выяснить — сколько именно входов можно таким способом — берём количество пикселей на панели по вертикали. Делим её на число линий сканирования (указано в обозначении панели как 8S, например). Делим на количество входных разъёмов (1 или 2). Например — у меня панель 32х32, сканирование 8S и два входных разъёма — 32/8/2=2 — значит два входа RGB.
Должна быть раскомментирована только одна нужная строка:
Сколько линий сканирования на панели — так как поддерживается стандарт HUB75E, то может быть до 32х. Количество линий сканирования обычно есть в названии панели в виде 8S/16S/32S соответственно.
Должна быть раскомментирована только одна нужная строка:
Общее число пикселей по горизонтали в цепочке. Считаются пиксели во всей цепочке панелей — см. раздел выше «Коммутация LED панелей»
Фазы выходных сигналов. Наиболее типичная конфигурация такая — OE активен по низкому уровню (коммент снят), CLK работает по фронту (коммент стоит), LAT активен по высокому уровню (коммент стоит). Возможно всякие странные варианты. Выяснять какой именно у вас только экспериментальным способом или снятием схемы и поиском даташитов на используемые микросхемы).
Пред и пост задержки сигнала OE относительно LAT. Предназначены для подавления расплывания пикселей по вертикали в момент коммутации рядов (коммутаторы обычно сильно тормозные). Обычные значения 2/2 — меньше лучше не делать. Увеличение значений приводят к уменьшению общей яркости, поэтому можно использовать для снижения максимальной яркости. Ограничение — в сумме должны быть меньше, чем PIXEL_COUNT.
Всё, нажимаем ctrl-L — проект компилируется. Если нигде не напортачили — будет несколько warnings, но не должно быть никаких ошибок. Дальше цепляем спаянную плату к USB Blaster, подаём питание на плату. В Quartus идём в tools — programmer. Выбираем в Hardware setup USB-blaster, нажимаем Start. Всё, CPLD запрограммирована.
а) Надо много памяти. Даже небольшая панель 32х32 в режиме RGB565 требует 2кБайта памяти под экранный буфер. Обычные ардуино на базе Atmega328 содержат всего 2кбайта оперативки. Можно, конечно, использовать плату Mega на базе Atmega2560, которая содержит аж 8 кБайт оперативки, но даже этого мало для панелей нормального размера — панель 128х64 в режиме RGB565 требует 16кБайт памяти.
б) В процессе работы с AL422B вылез не документированный нигде глюк — при записи данных со скоростью меньше 2МБ/сек счётчик адресов работает некорректно и пишет данные «не туда». Возможно это глюк имеющейся у меня партии. Возможно нет. Но этот глюк приходится обходить. Учитывая, что AVR8 работает на 16МГц, то получить с неё данные на нужных скоростях почти нереально.
Предлагаемое решение — уйти на дешёвые платки на базе 32-х битного контроллера STM32F103C8T6. Такая платка стоит на Ali примерно 2.5$ поштучно или около 1.7$ при покупке десятком, то есть дешевле даже Arduino Nano. При этом мы получаем полноценный 32-х битный микроконтроллер, работающий на 72 МГЦ и имеющий 20 кБ оперативной памяти и 64 кБ флеша (сравните с 2кБ/8кБ Atmega328, которая стоит на Nano).
При этом такие платы вполне успешно программируются в среде Arduino. Про это есть неплохая статья на гиктаймс, поэтому я не буду её дублировать. В общем — делайте всё, как описано в статье.
В среде ардуино выбирайте плату Generic STM32F103C, variant STM32F103C8. Рекомендую выбирать режим оптимизации Fastest (-O3). Впрочем, сейчас данные всё равно идут через DMA, поэтому можно использовать любой вариант.
Коммутация происходит по следующей схеме:
Жёстко прибиты в библиотеке:
A0..A7 -> DI0..DI7 AL422B
B0 -> WCLK AL422B
B1 -> WRST AL422B
Назначается в скетче на контроллер:
B10 -> WE AL422B
Общий провод:
G -> GND
Ну и не забудьте подать питание 5В/GND от панели на соответствующие пины контроллера.
Распиновку разъема на контроллере брать со схемы
Библиотека LED-PANEL активно использует библиотеку Adafruit GFX, поэтому она должна быть инсталлирована.
Я настоятельно рекомендую не ставить библиотеку LED_PANEL в каталог libraries, а оставить её в папке со скетчем. Дело в том, что там много железно привязанных параметров и если вы захотите перенести работу на более «жирный» микроконтроллер, то придётся много чего менять в самом коде.
Инициализация идёт примерно в таком виде:
то есть создаём экземпляр класса LED_PANEL, для которого указываем параметры:
width — общая ширина панели в пикселях (всего)
height — общая высота панели в пикселях (всего)
bpp — байт на пиксель, соответственно 2 для RGB565 или 3 для RGB888. Должно соответствовать режиму, прошитому в контроллер.
scan_lines — количество линий сканирования — 8/16/32. Должно соответствовать режиму, прошитому в контроллер.
RGB_inputs — количество RGB входов в разъеме HUB75 — 1/2. Должно соответствовать режиму, прошитому в контроллер.
we_out_pin — пин, к которому подцеплен вывод WE
Обращаю внимание, что при инициализации задаётся только пин WE. Все остальные пины прописаны жёстко в коде, так как они привязаны к используемым каналам таймера и DMA и их изменение повлечёт существенные изменения в коде.
Запуск и очистка экрана в разделе setup:
begin инициализирует нужные пины на выход, подключает таймер и DMA
clear очищает буфер
Для рисования можно использовать все стандартные процедуры библиотеки Adafruit GFX — от простейшего drawPixel до вывода текста.
Для выдачи нарисованного в буфер используется процедуры:
В общем-то — всё.
Некоторые замечания по софту:
а) гамма-коррекция вводится только при использовании режима панели RGB888 при пересчёте цвета из RGB565 (который использует библиотека) функцией ExpandColor. Во всех прочих случаях используется линейная трансфер-функция, то есть яркость прямо пропорциональна значению.
б) софт позволяет подключать несколько LED-контроллеров к одной микроконтроллерной плате. Для этого надо отдать на контроллеры параллельно шину данных, линии RST и CLK. Нужный контроллер выбирается через линию WE. В софте нужно создать отдельный экземпляр класса LED_PANEL для каждого контроллера, при этом у каждого экземпляра при инициализации должны быть указаны разные линии WE (последний параметр).
Ну и теперь —
— сделать класс META_LED_PANEL, который позволит объединять несколько LED_PANEL в один виртуальный экран — это даст возможность создавать большие экраны
— в перспективе уйти на более мощную серию CPLD, например MAXII. Это бы существенно расширило возможности при сохранении невысокой стоимости (EPM1270, который в 20 раз мощнее, стоит 4-5$ штука). Но этим я буду заниматься когда-нибудь потом. Если захочу :) Так как подобные разработки отнимают уж слишком много времени.
И что меня удивило — в качестве устройства отображения использовались древние одноцветные светодиодные матрицы 8х8 с шагом 5 миллиметров. Причём под них разводились сложные печатные платы, делалась софтовая динамическая индикация. И это в то время, когда уже давно доступны по цене в районе 10-20$ готовые полноцветные панели 64х32 с шагом 3 мм. А общий ассортимент подобных панелей очень большой и имеет шаг пикселя от 2 до 10 мм и практически любой размер.
В то же время использовать такие панели в DIY конструкциях достаточно непросто — готовые контроллеры стоят довольно больших денег и не имеют нормального API. Сделать же достаточно быстрое сканирование панели на обычно используемых в DIY микроконтроллерах достаточно сложно. Причём временные интервалы должны выдерживаться с высокой точностью — иначе начинается заметная неравномерность яркости.
Есть неплохие решения на Adafruit, но они все достаточно дорогие и сложные.
После некоторого раздумья возникла мысль — а почему бы не сделать предельно недорогую плату, которая будет мостом между обычной копеечной платой типа ардуино и LED панелью? После какой-то пары месяцев возни родилось что-то работающее :)
Задача и проблемы
Хотелось бы иметь возможность управлять сборной панелью общим размером хотя бы 64х64, имея при этом возможность работы хотя бы в Highcolor (RGB565) с сохранением приемлемой частоты обновления экрана (не менее 50Гц).Основная сложность заключается в том, что на LED панелях градации цвета формируются только через PWM, причём последовательный. Таким образом для того, чтобы сформировать 64 уровня яркости — за время индикации одного кадра надо 64 раза выдать картинку. То есть 64х50=3200 Гц частота выдачи полной «однобитной» картинки. Следовательно — для выдачи экрана 64х64 надо выдавать данные пикселей со скоростью 3200х64х64=13 Мпикселей/секунду.
Реализация
Все файлы на GITHUBСовершенно очевидным было то, что без CPLD или FPGA здесь не обойтись — выдавать 26 МБ/сек на недорогих микроконтроллерах физически невозможно.
В качестве памяти мне на форуме IXBT порекомендовали очень интересную FIFO память Averlogic AL422B, которая имеет примерно 400кбайт памяти и может работать на частотах до 50МГц.
Учитывая, что моим основным требованием была максимальная дешевизна компонентов, чтобы готовая платка была доступна самодельщикам — была выбрана Altera EPM3064 — CPLD c 64мя макроячейками. В то же время столь малое количество макроячеек не позволяет сделать динамически конфигурируемую плату — конфигурацию необходимо компилировать непосредственно в CPLD.
Получившаяся схема лежит здесь
Детали:
CPLD EPM3064ATC44-10 — цена на Ali примерно 13-15$ за десяток
FIFO RAM AL422B — цена на Ali примерно 15$ за десяток
Кварцевый генератор на 50МГц. На плате предусмотрена установка в корпусах DIP14/DIP8/7050. Цена на Ali примерно 6-7$ за десяток
Стабилизатор на 3.3В в корпусе SOT223 — chipdip — 40р за штуку
Разъем IDC-10MS — chipdip — 3 р/штуку
Разъем IDC-16MS — chipdip — 8 р/штуку
Разъём IDC-14MS — chipdip — 7 р/штуку
Конденсаторы 1мкФ 0805 — 8 штук примерно по 1 р/штуку
Конденсатор 0,1мкФ 0805 — примерно по 1 р/штуку
Резистор 10к 0805 — копейки :)
Итого по деталям получается 1,5+1,5+0,7=3,7$ и 40+3+8+7+8*1+1=67 р. Всё вместе в пределах 5$ — копейки.
Исходный рисунок платы лежит здесь
Подготовленные gerber файлы для заказа
При пайке платы не забыть запаять перемычки на питание на обратной стороне платы.
Расчёт частоты обновления и ограничения по размерам
Прежде всего необходимо понимать ограничения по размерам сборной панели. Общий размер ограничен частотой кадров (мерцания панели).Для RGB888 частота регенерации = 50МГц/3/256/кол-во пикселей, то есть, например, для панели 32х32 — 64Гц.
Для RGB565 частота регенерации = 50МГц/2/64/кол-во пикселей, то есть для панели 32х32 — 381Гц.
Глаз более-менее терпит частоту от 50Гц, поэтому для RGB888 максимальный размер сборки примерно 32х32 или 64х16. Для RGB565 — 128х64 или 256х32 (частота регенерации 48Гц).
Коммутация LED панелей
Все панели соединяются последовательно. Схема соединения: сперва справа-налево, потом снизу-вверх. То есть сперва соединяем горизонтали последовательно, потом выход нижнего ряда ко входу второго снизу ряда и т.д. до верхнего ряда.Контроллер цепляется к правой нижней панели.
Бывают панели, которые имеют по два входных и два выходных разъёма. Такие панели по сути являются просто механической сборкой двух панелей по вертикали. Коммутируются как две независимые панели.
После сборки надо посчитать общую длину цепочки в пикселях — для этого смотрим — сколько всего панелей получилось в цепочке и умножаем это число на ширину панели в пикселях. Это число потом надо будет вбить в значение PIXEL_COUNT при конфигурации FPGA.
Прошивка FPGA
Все необходимые файлы лежат на github. Скачивать нужно прямо папкой.С сайта Altera после регистрации необходимо скачать и установить Quartus II 13.0sp1. Качать надо ИМЕННО ЭТУ версию — более новые версии уже не поддерживают серию MAX3000. Ломать её не надо — достаточно Web edition (free) версии. При скачивании не забудьте поставить галочки на поддержке MAX3000 и Programmer.
Еще понадобится Altera USB Blaster — обычная цена на ali порядка 3$
Открываем проект al422b_2rgb_8s.qpf
Слева открываем закладку файл и открываем файл led_al422_main.v — это основной файл проекта. В нём надо настроить параметры:
Используемое цветовое пространство. TRUECOLOR — 3 байта на пиксель, формат RGB888. HIGHCOLOR — 2 байта на пиксель, формат RGB565.
Должна быть раскомментирована только одна нужная строка:
//`define TRUECOLOR 1
`define HIGHCOLOR 1
Сколько RGB входов на панели — на панелях со входом HUB75 может быть 1 или 2 входа RGB. Выяснить — сколько именно входов можно таким способом — берём количество пикселей на панели по вертикали. Делим её на число линий сканирования (указано в обозначении панели как 8S, например). Делим на количество входных разъёмов (1 или 2). Например — у меня панель 32х32, сканирование 8S и два входных разъёма — 32/8/2=2 — значит два входа RGB.
Должна быть раскомментирована только одна нужная строка:
//`define RGB_out1 1
`define RGB_out2 1
Сколько линий сканирования на панели — так как поддерживается стандарт HUB75E, то может быть до 32х. Количество линий сканирования обычно есть в названии панели в виде 8S/16S/32S соответственно.
Должна быть раскомментирована только одна нужная строка:
`define SCAN_x8 1
//`define SCAN_x16 1
//`define SCAN_x32 1
Общее число пикселей по горизонтали в цепочке. Считаются пиксели во всей цепочке панелей — см. раздел выше «Коммутация LED панелей»
`define PIXEL_COUNT 64
Фазы выходных сигналов. Наиболее типичная конфигурация такая — OE активен по низкому уровню (коммент снят), CLK работает по фронту (коммент стоит), LAT активен по высокому уровню (коммент стоит). Возможно всякие странные варианты. Выяснять какой именно у вас только экспериментальным способом или снятием схемы и поиском даташитов на используемые микросхемы).
`define LED_OE_ACTIVE_LOW 1
//`define LED_CLK_ON_FALL 1
//`define LED_LAT_ACTIVE_LOW 1
Пред и пост задержки сигнала OE относительно LAT. Предназначены для подавления расплывания пикселей по вертикали в момент коммутации рядов (коммутаторы обычно сильно тормозные). Обычные значения 2/2 — меньше лучше не делать. Увеличение значений приводят к уменьшению общей яркости, поэтому можно использовать для снижения максимальной яркости. Ограничение — в сумме должны быть меньше, чем PIXEL_COUNT.
`define OE_PREDELAY 2
`define OE_POSTDELAY 2
Всё, нажимаем ctrl-L — проект компилируется. Если нигде не напортачили — будет несколько warnings, но не должно быть никаких ошибок. Дальше цепляем спаянную плату к USB Blaster, подаём питание на плату. В Quartus идём в tools — programmer. Выбираем в Hardware setup USB-blaster, нажимаем Start. Всё, CPLD запрограммирована.
Микроконтроллерная часть
Выдача данных на контроллер, в общем-то, предельно проста — сбрасываем адрес записи и потом последовательно выдаём байты данных, стробируя их сигналом WCLK. И вроде бы даже банальной ардуинки хватит для работы. Но есть две проблемы:а) Надо много памяти. Даже небольшая панель 32х32 в режиме RGB565 требует 2кБайта памяти под экранный буфер. Обычные ардуино на базе Atmega328 содержат всего 2кбайта оперативки. Можно, конечно, использовать плату Mega на базе Atmega2560, которая содержит аж 8 кБайт оперативки, но даже этого мало для панелей нормального размера — панель 128х64 в режиме RGB565 требует 16кБайт памяти.
б) В процессе работы с AL422B вылез не документированный нигде глюк — при записи данных со скоростью меньше 2МБ/сек счётчик адресов работает некорректно и пишет данные «не туда». Возможно это глюк имеющейся у меня партии. Возможно нет. Но этот глюк приходится обходить. Учитывая, что AVR8 работает на 16МГц, то получить с неё данные на нужных скоростях почти нереально.
Предлагаемое решение — уйти на дешёвые платки на базе 32-х битного контроллера STM32F103C8T6. Такая платка стоит на Ali примерно 2.5$ поштучно или около 1.7$ при покупке десятком, то есть дешевле даже Arduino Nano. При этом мы получаем полноценный 32-х битный микроконтроллер, работающий на 72 МГЦ и имеющий 20 кБ оперативной памяти и 64 кБ флеша (сравните с 2кБ/8кБ Atmega328, которая стоит на Nano).
При этом такие платы вполне успешно программируются в среде Arduino. Про это есть неплохая статья на гиктаймс, поэтому я не буду её дублировать. В общем — делайте всё, как описано в статье.
В среде ардуино выбирайте плату Generic STM32F103C, variant STM32F103C8. Рекомендую выбирать режим оптимизации Fastest (-O3). Впрочем, сейчас данные всё равно идут через DMA, поэтому можно использовать любой вариант.
Коммутация происходит по следующей схеме:
Жёстко прибиты в библиотеке:
A0..A7 -> DI0..DI7 AL422B
B0 -> WCLK AL422B
B1 -> WRST AL422B
Назначается в скетче на контроллер:
B10 -> WE AL422B
Общий провод:
G -> GND
Ну и не забудьте подать питание 5В/GND от панели на соответствующие пины контроллера.
Распиновку разъема на контроллере брать со схемы
Программная часть
Так как ставилась задача сделать всё максимально просто и доступно, то весь софт сделан под среду Arduino и оформлен в виде библиотеки LED_PANELБиблиотека LED-PANEL активно использует библиотеку Adafruit GFX, поэтому она должна быть инсталлирована.
Я настоятельно рекомендую не ставить библиотеку LED_PANEL в каталог libraries, а оставить её в папке со скетчем. Дело в том, что там много железно привязанных параметров и если вы захотите перенести работу на более «жирный» микроконтроллер, то придётся много чего менять в самом коде.
Инициализация идёт примерно в таком виде:
#include "LED_PANEL.h"
#define width 32
#define height 32
#define bpp 2
#define scan_lines 8
#define RGB_inputs 2
#define we_out_pin PB10
LED_PANEL led_panel = LED_PANEL(width, height, bpp, scan_lines, RGB_inputs, we_out_pin);
то есть создаём экземпляр класса LED_PANEL, для которого указываем параметры:
width — общая ширина панели в пикселях (всего)
height — общая высота панели в пикселях (всего)
bpp — байт на пиксель, соответственно 2 для RGB565 или 3 для RGB888. Должно соответствовать режиму, прошитому в контроллер.
scan_lines — количество линий сканирования — 8/16/32. Должно соответствовать режиму, прошитому в контроллер.
RGB_inputs — количество RGB входов в разъеме HUB75 — 1/2. Должно соответствовать режиму, прошитому в контроллер.
we_out_pin — пин, к которому подцеплен вывод WE
Обращаю внимание, что при инициализации задаётся только пин WE. Все остальные пины прописаны жёстко в коде, так как они привязаны к используемым каналам таймера и DMA и их изменение повлечёт существенные изменения в коде.
Запуск и очистка экрана в разделе setup:
led_panel.begin();
led_panel.clear();
begin инициализирует нужные пины на выход, подключает таймер и DMA
clear очищает буфер
Для рисования можно использовать все стандартные процедуры библиотеки Adafruit GFX — от простейшего drawPixel до вывода текста.
Для выдачи нарисованного в буфер используется процедуры:
led_panel.show();
В таком виде show инициирует передачу данных на контроллер по DMA и немедленно возвращает управление. Узнать — закончилась ли передача можно с помощью функции led_panel.OutIsFree() — если она говорит true, то значит передача закончилась. Есть особенность — если вызвать show, когда передача еще не завершилась — она будет просто проигнорирована.led_panel.show(false);
аналог show(), но если вызвать show(false), а передача еще не завершилась, то процедура подождёт завершения передачи, потом начнёт новую передачу и вернёт управлениеled_panel.show(true);
аналог show(false), но если вызвать show(true), то после начала новой передачи процедура не вернёт управления до завершения передачиВ общем-то — всё.
Некоторые замечания по софту:
а) гамма-коррекция вводится только при использовании режима панели RGB888 при пересчёте цвета из RGB565 (который использует библиотека) функцией ExpandColor. Во всех прочих случаях используется линейная трансфер-функция, то есть яркость прямо пропорциональна значению.
б) софт позволяет подключать несколько LED-контроллеров к одной микроконтроллерной плате. Для этого надо отдать на контроллеры параллельно шину данных, линии RST и CLK. Нужный контроллер выбирается через линию WE. В софте нужно создать отдельный экземпляр класса LED_PANEL для каждого контроллера, при этом у каждого экземпляра при инициализации должны быть указаны разные линии WE (последний параметр).
Ну и теперь —
TO DO
— разобраться с «наводкой» цветов на соседние ряды. Похоже на плохую разводку самой панели (ключи мусорят), но надо проверить.— сделать класс META_LED_PANEL, который позволит объединять несколько LED_PANEL в один виртуальный экран — это даст возможность создавать большие экраны
— в перспективе уйти на более мощную серию CPLD, например MAXII. Это бы существенно расширило возможности при сохранении невысокой стоимости (EPM1270, который в 20 раз мощнее, стоит 4-5$ штука). Но этим я буду заниматься когда-нибудь потом. Если захочу :) Так как подобные разработки отнимают уж слишком много времени.
Самые обсуждаемые обзоры
+79 |
4216
150
|
+60 |
4384
74
|
В свое время запускал подобную панель 64х32 на Orange Pi Zero.
RGB565 завелось нормально. Правда не без танцев с бубном.
Использовался SPI и буферные элементы для для согласования уровней, так как панелька была 5-ти вольтовая.
Но всё равно на грани работаете, особенно на таких скоростях. Возможно и проблемы с засветами отдельных пикселей уйдут, если уровни согласовать.
Там, правда, предполагается использование их переходника, но, вроде, это не обязательно.
У адафрута есть библиотеки для ардуины для таких панелей, правда к UNO больше чем 32*32 не подключить и места почти не остаётся.
Не буду комментировать тамошних комментаторов.
Кстати, сделал новую демку с воспроизведением видео с SD карточки :)
Кто узнает — из какого традиционного для испытания LED панелей ролика кадрик? :)
Комментаторы — они везде комментаторы, но в целом Вашу статью вытащили из песочницы -это уже отлично, и приняли благосклонно, судя по плюсам и по Вашему рейтингу :)
Кадрик узнаваем даже в таком виде :))
Поэтому DMA там не сильно помогает, так как для использования DMA надо сделать bitbanding данных в памяти, причём очень неэффективным способом.
В данном же случае микроконтроллер отдаёт «сырые» данные и всю дальнейшую обработку делает CPLD. Никакой микроконтроллер это не успеет. Попробуйте найти хоть один проект, в котором «голый» микроконтроллер поддерживает вывод на панель в честном RGB888.
На каждом входе цвета стоит цепочка регистров типа HC595 (но специальные 16-ти канальные версии для светодиодов). Регистров столько, чтобы хватало на ширину панели. Входы клока, параллельной загрузки и разрешения выхода общие для всех регистров. Входы ABCDE — это выбор ряда — идут на обычный дешифратор.
Принцип работы:
— выставляем данные на RGB входы, щелкаем клоком. Повторяем, пока не загрузим всю строку.
— выключаем выходы (чтобы помех не было)
— выдаём на дешифратор номер загруженного ряда
— щелкаем параллельной загрузкой — данные строки переносятся в выходные регистры
— включаем выходы
— повторяем для следующего ряда
То есть классическая динамическая индикация. Понятно, что при таком методе за один такой цикл мы можем каждый конкретный светодиод только включить/выключить.
Для того, чтобы получить градации яркости, такой цикл приходится повторять N-1 раз, где N — число градаций яркости. А учитывая, что при этом это всё еще и мерцает — всё это надо делать очень-очень быстро.
Есть обходной вариант, про который написал Petrovich39 — BAM. При этом время свечения в каждом цикле варьируется в зависимости от веса отображаемого бита. Скажу честно — когда я начинал работу я про этот метод ничего не нашёл. Вполне может быть, что он окажется даже эффективнее, чем я думаю. Надо пробовать.
А отличие от WS2812 именно в том, что панель надо «теребить» всё время и очень быстро. Разработанная мной платой как раз и превращает LED-панель в некий эквивалент WS2812 — выбросил данные и забыл про неё до следующего обновления.
Что делает Ваша плата — я понял из обзора, просто не совсем понимал зачем это нужно, считал, что такие панели умнее, чем (оказывается) есть на самом деле :)
А применять этот метод в ПЛИС смысла, наверное, нет, т.к. она и с нормальным ШИМ справляется легко :)
А с ПЛИС… С обычным ШИМ не совсем легко — для RGB888 максимальный размер всего 32x32, причём без гамма-коррекции.
К сожалению, без легкой переделки мою платку не заставить формировать BAM — там надо RE управлять, а она сейчас жёстко на земле висит — надо проводок на свободный пин бросать.
В общем — надо сильно подумать, потом поэкспериментировать на STM, потом попробовать сделать V2 с БД и Ш (базой данных и шимом, а не то, что вы подумали) :)
Или взять Циклон, у него своей памяти хватит на матрицу 128х128 :)
В том то всё и дело, что потенциально BAM режим эти ограничения обходит с лёгкостью вообще. То есть там вычислительная сложность алгоритма в разы меньше.
А почему я в самом начале упомянул AVR — потому что 99.9% всех поделок создаются на AVR-ардуинах :)
— загрузили биты строки в панель
— выдали OE на время, пропорциональное весу бита
— тем временем грузим следующую строку
— если время OE больше, чем время загрузки следующей строки, то ждём завершения OE
ну и по циклу
В таком случае — если для классического PWM для получения 256 градаций нам на кадр нужно 256 раз считать из памяти значение каждого пикселя, то для BAM это нужно сделать всего 8 раз (!!!). Причём в отличии от PWM ресурсоёмкость растёт пропорционально разрядности бита, а не степенная функция. То есть легко можно обеспечить и 16-ти битный пропорциональный цвет, например.
Тут, правда, вылезает компромисс. Если пытаемся получить предельно высокую частоту обновления, то надо время младшей «1» делать как можно короче (в пределе 1 такт). Но при этом мы заметно теряем в яркости. В то же время для бытовых целей 100% светимость панели вообще не нужна — она сияет как лампочка. В общем — тут надо будет подбирать значение такое, чтобы получить нормальную частоту обновления с приемлемой потерей яркости
Но у ВАМ-а другие проблемы есть. Если надо активно менять яркость светодиодов то возникают пренеприятные артефакты. Может даже «снег» пойти если много светодиодов.
Артефакты меня мало волнуют на данном этапе.
> По времни это будет занимать те же 256 минимальных временных интервалов
С чего вдруг? Для BAM нужно заполнить регистр каждой строки всего 8 раз, для PWM — 256 раз. Есть разница?
> И требования к быстродействию алгоритма сравнения останутся те же.
Вы вообще читаете — что вам отвечаю? BAM значительно проще — там вообще не надо делать 8-ми битное сравнение — надо просто выбрать 1 бит данных.
На самом деле я это всё уже реализовал и выигрыш по скорости огромный — сейчас при реализации на BAM я легко делаю на панели 32x32 в режиме RGB888 частоту кадров более 500 к/с. Для классического PWM получалось около 60 к/с. Есть разница?
Статья на гитхабе пока висит в премодерации, но весь код уже здесь:
https://github.com/Anprivate/al422-bam
Да, есть такой вариант. Может попробую после нового года реализовать — посмотрю — что получится.
И про «засвечивание» — это скорее всего проблема недостаточных задержек при переключении строк/latch/oe.
И микроконтроллер с DMA и портом для внешней памяти (EXMC у stm и клонов) вполне справляется с такой задачей.
Часы? Для них давно используются сдвиговые регистры и монохромные матрицы.
Мелкие цветные рекламные панно? Матрица из WS2812b, ардуинка и бесконечное количество графики на SD-карте.
Например — часы. Одна панелька P3 64х32 имеет габариты 192х96, что практически идеально для часов. Или можно взять P2.5 — там вообще 160х80. При этом возможности отображения практически не ограничены — можно делать плавное изменение яркости и цвета любой части часов от времени суток например. Максимальная яркость очень большая (панель 32х32 в максимуме ест почти 25 ватт и сияет как лампочка), поэтому можно использовать как временную подсветку ночью, например. То есть простор для фантазии огромный.
Рекламные табло? Пожалуй нет — проще брать готовые контроллеры. Хотя если альтернатива WS2812B, то, пожалуй — да. WS2812 обходятся дорого и имеют огромный шаг (меньше 10 мм сделать малореально). А готовые панели стоят в разы дешевле, чем стоят WS2812.
А в основном — делал для себя :) Дело в том, что мне время от времени приходится делать всевозможные таймеры и индикаторы на подобных панелях (стоят в студиях для отображения текущего времени и обратного отсчёта до рекламы, например). Делать это на STM32 мне надоело — возможностей мало, да и есть некоторые проблемы. Вот и решил сделать отдельный контроллер.
geektimes.ru/post/289389/
Кстати есть ещё APA102-2020 ;)
А вот в таких проектах — led панели просто напрашиваются.
APA102 стоят порядка 100$ за 1000шт россыпью. На ленте еще дороже. Готовая панель из них размером 16х16 с шагом 10 (!!!) стоит 70$
А нормальная LED панель P3 64x32, то есть с 2048 светодиодами стоит 20$. Цены различаются на порядок. Ну и визуально панель с наклеенными ленточками выглядит колхозом. Готовая LED панель выглядит на порядок лучше.
Ни как не придумаю что бы на них сделать;) Мне ленты не нужны обычно.
Зато шаг можно сделать 2.1мм;)
Просто я думаю что у хорошего инженера (в России) должна быть ЗП не меньше 200 т.р.
А у дизайнера fpga ещё больше.
И на самом деле это не много если сравнивать с депутатами…
Должно быть много чего. Например, я не вижу причин почему зарплата врача должна быть меньше зарплаты инженера или депутата, и что меняет это мое мнение? :)
Зная свой уровень и уровень зарплат(не только в твоём городе) можно договориться с работодателем. Ну обычно.
Насчёт врачей инфы не имею.
Мне пришлось изучать FPGA по работе, когда появилась нужда в оцифровке и очень узкополосной фильтрации сигнала. По DSP у нас спеца уже не было, уволился, да и по нашим прикидкам даже он не справился бы (подразумевали какой-то из Шарков), решили делать на FPGA и поручили это мне :) Пришлось осваивать начиная от схемотехники и самодельного прошивальщика до тонкостей оптимизации размещения результатов синтеза в кристалле :) Но от конечных результатов я сам был в легком ах… ах, какие результаты получили :) По завершению всех работ результаты превзошли по параметрам изначально планировавшиеся раз в пять :)
В ПЛИСке молотили два канала цифрового фильтра, каждый из трех ступеней, которые получали с АЦП выборки на частоте 625 кГц и накапливали в выходных буферах до 2048 результирующих значений. Во всех трех ступенях каждого фильтра участвовало до 5000 коэффициентов :) Количество коэффициентов и их значения могли меняться в зависимости от требовавшейся полосы фильтра — они загружались в ПЛИСку микроконтроллером перед измерением.
Ну и кучка второстепенных управляющих и регулирующих функций :)
Да даже на бытовом уровне некоторые проекты выиграли бы от применения FPGA. Банально — платы для 3D-принтеров или хоббийных ЧПУ-станков, где FPGA могла бы полностью взять на себя проблемы формирования траекторий и шагов для двигателей, что очень сильно может повысить скорость и точность :)
Микроконтроллеру и без того работы выше крыши. Даже на STM32 многие из стандартных команд и опций G-кода остаются недоступными из-за нехватки его ресурсов и на обработку G-кода и на формирование в реальном времени сигналов STEP/DIR для нескольких моторов. Вот FPGA как раз и могла бы взять на себя всю рутину генерации сигналов с учетом заданных скоростей/ускорений, оставив микроконтроллеру только математику и вопросы стратегии и интерфейса.
А еще на станки часто ставят оптические линейки для контроля движения оси с разрешением эдак 1-5 микрон и управление моторами согласуют с обратной связью от этих линеек.
Но только все равно в быту применений мало.
Платы я заказал, уже получил, правда пока к сожалению, нет времени спаять и заняться контроллером. Но займусь обязательно.
Немного промазал с панелями, купил 64х32, Р2.5 scan 16, 8 штук, чтобы набрать 128х128. Панели купил по ссылке из обзора на kirich.blog, заоодно, не зная, получится ли самому сделать контроллер, купил заодно и контроллер HD-D30. Панели 64х64 или 64х128 получаются чуть ли не вдвое дешевле, правда скан у них 32.
Задача у меня немного специфичная, надо при необходимости, выводить на панель цифры, тексты, может еще простенькую графику, а в промежутках крутить рекламу, подвижную и нет, а заодно и то что может китайский контроллер — температуру, влажность, часы. Посмотрел на HD-D30 — самому сделать что-то с теми же возможностями при цене около 50USD (4 GB памяти и свой настроечный софт) просто не реально. API на него не достать, но у него есть вход для IK порта, можно выбрать любую из сотен загруженных в него программ. А для подключения своего контроллера использовать доп. коммутатор на HUB75E, и выводить китайца по мере необходимости…
Вот такая немного странная идея…
Если понадобится, могу ли попросить о помощи? С FPGA никогда не возился, только очень давно с советскими ПЛМ (были и такие :)), и пытаться еще и их освоить- слишком сложно для меня
В личку тоже писал, но почему-то не отвечаете, :(