Кому-нибудь интересна микросхема TLC5940?

Есть такой замечательный светодиодный драйвер, но как справедливо заметил наш коллега,

Да, она управляет только 16-ю светодиодами (например, MAX7219 тянет 64), зато если надо что-то нестандартное, например, управлять вот таким семисегментником, то MAX7219 сразу же идёт лесом, а эта работает. То же самое, если хочется управлять яркостью каждого светодиода в отдельности (а не всеми сразу), MAX опять же сдувается, а TLC - пожалуйста. Ну, и много у неё вкусняшек, которых нет у других популярных драйверов.

Есть у неё одна беда. Поиск по гитхабу даёт «много библиотек», но, на поверку, это копии (иногда чуть модифицированные). В действительности же, есть только одна библиотека от Alex Leone. И у этой библиотеки есть большая беда – она занимает 2 (прописью: ДВА) таймера на 328P. Т.е. она оставляет разработчика вовсе без таймеров. Нулевой занят под millis, первый и второй – под эту библиотеку.

Когда-то я публиковал здесь решение, как использовать микросхему вовсе без таймеров. При этом пришлось пожертвовать 12-битным регулированием яркости каждого светодиода. Но шестибитное регулирование (через механизм «dot correction») осталось, а для большинства игр с яркостью 64 градации вполне хватит, зачем там 4096? Так что нормальное было решение для многих задач.

Я часто использую эту микросхему и вот мне таки понадобился её полный функционал (со всеми регулированиями). Почесав репу, я таки нашёл решение, как можно управлять TLC5940 используя один таймер, а не два (без какой-либо потери функционала). Правда, для этого нужен дополнительный пин.

Это кому-то интересно? Или эта микросхема не так популярна и ну её на фиг?

Популярна, не популярна. Какая разница?
Если есть что сказать - то нужно говорить. К тому же и показать имеется что?

даже слишком популярна, настолько, что большая часть предложений на Али и ебее - подделки

Это да и я даже знаю в чём проявляется неоригинальность в некоторых партиях. К сожалению, достаточно нужные вещи работают не очень корректно.

Дык, если это никому не пригодится, то зачем тратить час-другой времени и бить пальцы об клавиатуру?

я согласен, но на нашем форуме, можно потратить намного больше времени на обсуждения “надо-ненадо”, просто гуру таких обсуждений, еще не подтянулись.)

1 лайк

Ну, в общем я кратко скажу суть/идею решения, кому надо - будет иметь в виду, а кому обязательно готовый код на тарелочке - всё равно этой микросхемой не воспользуется, не так она проста.

Как я уже писал, общая схема работы этого драйвера такая:

  1. В память микросхемы посредством SPI закачивается 16 (по одному на ШИМ-канал) 12-тиразрядных числа;
  2. Защёлкивается «защёлка» (импульсом на пине XLAT)
  3. Подаётся сигнал «начало нового периода» (импульс на пине BLANK)
  4. При первом после этого восходящем фронте тактирующего сигнала (пин GSCLK), все каналы, для которых закачан не 0 включаются в HIGH и из их чисел вычитается 1;
  5. При каждом последующем восходящем фронте тактирующего сигнала, все каналы для которых число стало нулём, переводятся в LOW, а из чисел всех остальных каналов вычитается 1;
  6. И так 4096 раз. После этого всё затухает, если не придёт новый сигнал «начало нового периода». Если же он придёт, то, веселье продолжается с п.4

Итак, таймеры в библиотеке нужны для того, чтобы (А) обеспечить тактирующий сигнал на пине GSCLK и (Б) сигнал начала периода – короткие иглы на пине BLANK с частотой в 4096 раз меньшей, чем частота тактирующего сигнала. Собственно, частота игл на пине BLANK и есть частота ШИМ на светодиодах.

Хочу обойтись одним таймером. Решение такое.

Тактирующий сигнал:
В ATmega328P программируем фьюз CKOUT. На пине PB0 (он же пин 8 в Ардуино) появляется тактирующий сигнал контроллера. Если это Ардуино Uno/Nano, то частота этого сигнала – 16МГц. Этот пин (PB0) соединяем с пином GSCLK драйвера. Задача (А) решена – TLС-шка нормально тактируется.

Сигнал начала периода:
просто настраиваем таймер, чтобы он выдавал короткий пик один раз в 4096 тактов котроллера. Например, вот так (сигнал будет на 9-ом пине ардуино):

static constexpr uint8_t prescalerMask = bitMask(CS10); // делитель - 1

inline void TLCTimerStart(void) { TCCR1B |= prescalerMask; } //запустим таймер
inline void TLCTimerStop(void) { TCCR1B &= ~ bitMask(CS10, CS11, CS12); } // остановим таймер

inline void TLCTimerInit(void) {
   TLCTimerStop();
   TCCR1A = bitMask(COM1A1, WGM11);
   TCCR1B = bitMask(WGM12, WGM13);
   ICR1 = 4096;
   TCNT1 = 0;
   OCR1A = 0;
   OCR1B = 0;
   TIMSK1 = 0;
}

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

Единственное о чём осталось позаботиться, это чтобы сигнал на пине BLANK не прилетел в тот момент, когда мы защёлкиваем данных (когда на XLAT сидит HIGH). Чтобы не допустить такого, я на момент защёлкивания просто выключаю таймер функцией TLCTimerStop, а потом снова включаю функцией TLCTimerStart.

Собственно, всё. Решение работающее, проверено в железе, все функции драйвера работают, ни от чего не пришлось отказываться.

Важное дополнение:

Тщательное тестирование показало, что при таком использовании, микросхема работает нестабильно. Нет-нет, да вылазят всякие артефакты. Скрупулёзная проверка кода ничего не дала. Зато повторное, более внимательное, прочтение даташита дало результат.

Дело в том, что GSCLK у нас тактируется от контроллера его тактовой частотой, т.е. имеем восходящий фронт на каждом такте контроллера. Таким образом, любой другой сигнал у нас может подаваться только одновременно с тактовым сигналом на GSCLK и никак иначе. В то же время, даташит требует разносить по времени некоторые сигналы с GSCLK на 10-30 наносекунд:

Обойти это мы не можем никак. То, что GSCLK срабатывает не каждом такте, здесь принципиально.

Таким образом, вынужден констатировать, что идея провалилась. А жаль :frowning:

1 лайк

Хитроумная штука, непонятно только

  1. как это выглядит снаружи, для быдло-потребителя и
  2. Что это дает и зачем может юзаться, в общем п.1

А Вы стартовое сообщение точно читали?

и далее

Мало?

Прочитал, потому и спросил: непонятно, что и как это даёт снаружи. Видимо остальным это понятно, я удаляюсь.

Мне тоже непонятно. Что такое “снаружи”? То, что она работает с высокими напряжениями и умеет управлять каждым каналом по отдельности - это “внутри”? А что такое “снаружи”?

ну я имею в виду - нах это нужно? Чтобы что? Ну изменяем мы яркость 16 или сколько там, сведодиодов - нахрнена? Как это использовать?
Не сочтите за личный наезд, что вроде очевидно ))

Странный вопрос.

Чтобы, например:

  • показывать что-то на семисегментном дисплее (днём поярче, ночью потемнее);
  • анимировать куб или любую другую дизайн-штучку;
  • обслуживать сразу все светодиоды на панели управления чем-нибудь, опять же с разной яркостью, в зависимости от освещения);
  • просто нужно 16 (или больше с каскадированием) независимых каналов ШИМ;
  • в конце концов управлять четырёхногими RGB (или трёхногими RG) светодиодами.

Да, до хрена для чего. Сами придумайте - везде, где нужно несколько светодиодов, везде можно и применить.

Но вообще, тут действует общее правило: если Вы не знаете зачем нужна какая-то штука, скорее всего Вам она не нужна - нет таких задач или решаете их по-другому. Когда вещь реальна нужна, то знаешь об этом – типа только услышал про фичи и сразу: “О, так она мои проблемы решит, дайте две!

Вот это в точку! потому и спросил, может это мне нужно, а я не знаю.
Пока не нашел для себя зачем это мне. //Многие вещи так и находил.

У семисегментного индикатора большого размера в каждом сегменте бывает и 3 и 4 светодиода, включенных последовательно. Плюс нечто для ограничения тока, итого это источник на 12 вольт минимум. Кроме того, ток через сегмент тоже приличный. Все решается отдельным ключом на каждый сегмент. И не забыть, что у точки один, скорее всего светодиод, и для нее нужен свой режим, в отличие от остальных семи сегментов. Транзисторы могут инвертировать сигнал, плюс индикатор с общим анодом или катодом, все эти частные обстоятельства придется учесть при программировании - зажигаем нулем или единицей. А в остальном для таких дубовых индикаторов слишком умных контроллеров, полагаю, и не нужно. По моему мнению.

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

Покажу на своем примере -

Имеем клавиатуру
Клавиатура 16 клавиш, сейчас около 330 руб, раньше были дешевле

И простенький процессор
Микросхема MH-Tiny ATTINY88, сейчас 183 рубля

Замечу, клавиатура дороже процессора. У процессора ног много, мозгов мало, но нам хватит. Пишем простейшую программу, по SoftSerial ( у этого проца даже железного Serial нет ) отправляем наружу нажатые клавиши в символьном виде. Получаем готовый модуль, для универсального применения. Итого этот проц бесконечно молотит в опросе кнопок, но мы получаем в Serial нажатые знаки. На такой идее можно и отладочный источник импульсов сделать, если на другие ноги выдавать отдельные импульсы, один или несколько, для специфических отладочных целей.

А применительно к этой микросхеме, я бы про занятые таймеры не переживал, а просто приставил к этой микросхеме отдельный процессор типа 328P в любом конструктиве, принимал данные для управления по Serial, (115200 , думаю хватит для реализации визуальных эффектов ) и пользовался стандартной библиотекой.

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

А совсем не простенькая и намного более производительная, более функциональная и уже с обвязкой RP2040 172 р с доставкой. https://aliexpress.ru/item/1005004954596272.html

1 лайк

Даже менее - порядка 90руб за голый чип

Или, если кому мало ног, то вот оно же, но многоногое, за 178 с доставкой ))
https://aliexpress.ru/item/1005005471348846.html

Да и тиньки в основном дешевле
https://aliexpress.ru/item/1005001572687462.html