Управление светодиодными индикаторами с помощью регистров сдвига с токовым выходом +34



Речь в этой статье пойдет о цифровых или цифробуквенных дисплеях для индикации различных показаний, которые часто так и называют индикаторами. Здесь мы остановимся только на одной их разновидности — светодиодных (LED) семисегментных индикаторах и нюансах обращения с ними. На мой взгляд, одна из самых древних разновидностей дисплеев незаслуженно отставлена на периферию разработок, хотя по многим параметрам (контрасту, читаемости, минимальной неиспользуемой площади окна, надежности и долговечности, наконец) LED-семисегментники дают фору любым другим разновидностям, включая ближайших конкурентов в виде OLED.

Их самый главный очевидный недостаток — ограниченное количество доступных символов. Если не изощряться, то фактически это только цифры и небольшое количество значков, вроде минуса, градуса или буквы Е. В некоторой части этот недостаток преодолим, если принять в рассмотрение 14- и 16-сегментные разновидности. Кроме того, его можно обойти практически полностью, если вспомнить про матричные LED-индикаторы. Но матричные индикаторы и управление ими — предмет отдельного разговора, здесь мы поведем речь только о семисегментных. В существенной части небольших проектов и любительского и профессионального уровня — часах, метеодатчиках, различных измерителях — и требуется отображать только цифры и значок минус, так что их возможностей вполне хватает.

Странно, но про семисегментные LED-индикаторы толковой литературы не так и много. Имеющаяся в основном делится на три части — либо это древние громоздкие схемы динамической индикации на базе счетчиков и дешифраторов, либо учебные примеры применения Arduino с одним-единственным разрядом, либо применение готовых модулей (о недостатках и ограничениях последних см. далее). Мы же постараемся рассмотреть, как построить на более-менее современной базе универсальный узел управления любыми такими индикаторами, не ограничивая себя готовыми решениями.

Недостатки готовых 7-сегментных модулей

Сначала давайте разделаемся с готовыми модулями. Встречаются модули, построенные либо просто на сдвиговом регистре типа 74HC595 (что не слишком удобный вариант), либо на специальных микросхемах-драйверах TM1637 (интерфейс I2C) или MAX7219/MAX7221 (интерфейс SPI). Удобство применения таких драйверов в том, что они сами организуют динамическую индикацию, вам об этом заботиться не надо. Потому такие модули популярны в сочетании с Arduino — схема подключения предельно проста, а об остальном позаботятся готовые библиотеки. Драйверы MAX7219/MAX7221 ко всему еще имеют кучу удобных опций, что разнообразит составление программы управления, не особо ее усложняя. Почему-то львиная часть таких модулей выпускается в конфигурации «для часов» (с дополнительным двоеточием посередке), но несложно приобрести и обычные с десятичными точками и даже восьмиразрядные.

Однако недостаток готовых модулей на этой основе заключается в весьма ограниченном ассортименте конфигураций самих индикаторов. Это связано в основном с нежеланием производителей затовариваться различными версиями одного и того же устройства, которые, возможно, никогда не будут востребованы — например, сочетание шести типоразмеров индикаторов различной высоты знака (в пределах 0,3 – 0,8 дюйма) с шестью цветами свечения (красный, зеленый, желтый, янтарный, синий, белый) дает 36 разновидностей на выбор, что, конечно, не потянет ни один реальный продавец. Даже на Ali найдете хорошо, если три-четыре основных цвета и пару разновидностей по высоте, в вариантах выбора «побольше» и «поменьше». В отечественных интернет-магазинах выбор еще больше ограничен.

И еще малый выбор связан с тем, что драйверы рассчитаны на 5-вольтовое питание, тогда как крупные индикаторы (высота знака 1 дюйм и более) требуют управления более высоким напряжением. Причем просто дополнить перечисленные выше удобные микросхемы-драйверы преобразователями уровня непросто — если попробовать это сделать (для чего потребуется «нарастить» управление и разрядами и сегментами), то схема получается чересчур громоздкой, и само применение этих драйверов вырождается, проще применить другие решения. Если я не ошибаюсь, готовые модули с цифрами большого размера вообще никто не решается производить.

Хочешь сделать хорошо — сделай сам

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

Схема предлагаемого решения не содержит загромождающих ее токозадающих резисторов (которые еще надо довольно тщательно подбирать под напряжение питания), и максимально экономична в отношении остальных компонентов. Причем общее питание схемы может быть любым вплоть до 16-17 вольт без изменений в схеме, даже нестабилизированным. Нижняя граница зависит от применяемого контроллера и индикаторов и мы о ее выборе еще поговорим. Заметим сразу, что решение легко масштабируется для теоретически любого количества разрядов (в зависимости от выбранного варианта — об этом также см. далее), и нет принципиальных проблем в его доработке для матричных индикаторов.

Но давайте обо всем по порядку.

Светодиодный драйвер MBI5167

В основе всех вариантов решений, предлагаемых далее, лежит очень удобная микросхема — драйвер линейки из 8 светодиодов MBI5167. Довольно толковый пересказ сведений из даташита можете найти здесь. Приобретение MBI5167 — не проблема, но по указанной ссылке можно найти и заменяющие его аналоги. Выпускается микросхема в двух вариантах планарного корпуса (с шагом 1,27 и 0,64 мм), потому для проб на обычной макетной плате придется приобретать переходник на шаг 2,54.

MBI5167 представляет собой объединение в одном устройстве сразу трех функций: обычного 8-разрядного сдвигового регистра, регистра-защелки его параллельных выходов и линейки раздельных токовых драйверов, к которым подключаются светодиоды. При этом выходы защелки являются управляющими сигналами для токовых драйверов: если в соответствующей позиции стоит единица – драйвер включен (светодиод горит), если ноль — выключен (светодиод гаснет). Напряжение питания светодиода, подключенного к токовому выходу, может быть любым (вплоть до 17 вольт), лишь бы оно превышало прямое падение напряжения на этом светодиоде.

Блок-схема токового драйвера MBI5167
Блок-схема токового драйвера MBI5167

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

Разводка выводов MBI5167
Разводка выводов MBI5167

Разводка выводов MBI5167 представлена на рисунке слева. До подключения необходимо сначала решить, какой именно ток вы хотите задать через выходы. Для задания тока служит вывод, обозначенный как R-EXT (вывод 15 микросхемы). Между этим выводом и «землей» подключается резистор Rext (показан на рисунке). Ток через каждый из выводов OUT определяется по формуле: Iout (мА) = 18,6/Rext (кОм). То есть для тока 5 мА нужен резистор 3,74 кОм, 10 мА — 1,87 кОм, для тока 20 мА — 976 Ом (приведены ближайшие к расчетным значения из 1-процентного ряда). Конечно, с такой точностью выдерживать номиналы не имеет смысла (погрешность самих источников тока равна ±3%), так что вполне подойдут 5-процентные резисторы 3,6, 1,8 и 1 кОм.

При составлении схемы придется проверять тепловыделение микросхемы, ведь лишнее напряжение сверх падения на светодиоде сегмента будет падать на источнике тока, а это заставит микросхему MBI5167 нагреваться. Сразу скажем, что для усредненных значений тока в пределах 10 мА и напряжении питания светодиода вплоть до 15 вольт это безопасно. В самом деле, примем грубо, что падение на светодиоде равно 2 вольта. Тогда при питании светодиода, равном 15 вольт, на каждом источнике тока будет падать 13 вольт, при токе 10 мА это приведет к выделению 130 мВт тепла. На семь сегментов это почти ровно ватт, а даташит уверяет, что предельная величина тепловыделения для MBI5167 составляет около 1,5 ватт. Но, как видите, это почти предельные величины, баз запаса, их превышение нежелательно. И если захочется увеличить яркость, то придется уже изобретать более низковольтный источник.

Схема и программа для тестирования MBI5167

Подключение одного разряда к микросхеме MBI5167
Подключение одного разряда к микросхеме MBI5167

Подключение регистра к семисегментному индикатору показано на рисунке выше. Нумерация выводов индикаторов здесь и на схемах далее, естественно, опущена, так как она бывает очень разнообразной — справляйтесь в даташите. Питание микросхемы (выв. Vcc) должно совпадать с питанием управляющего микроконтроллера. Его можно сделать из общего повышенного питания с помощью маломощного стабилизатора, например, типа LP2950-5.0 или LP-2950-3.3. На схеме питание анода индикатора подключено к отдельному питанию Uи, как мы говорили, оно может быть и нестабилизированным.

Для питания индикаторов с одним светодиодом на сегмент (до 0,8 дюйма включительно) при применении MBI5167 достаточно нестабилизированного питания 3-5 вольт, с двумя (1-1,5 дюйма) — 7-9 вольт. Возможностей MBI5167 с запасом хватит до пяти-шести светодиодов на сегмент (трехдюймовые индикаторы и более, прямое падение — до 12 вольт, нестабилизированное питание — около 15 вольт). Ну, наверное, для уличных табло надо индикаторы еще крупнее, но там и решения применяются явно иные.

Конечно, для индикаторов малых размеров (до 0,8 дюйма) можно и не городить отдельное питание, просто подключив Uи к тем же 5 вольтам, но тогда, наоборот, это питание должно быть хорошо стабилизировано, чтобы броски при переключении сегментов не повлияли на работу контроллера (качества встроенного стабилизатора Arduino может не хватать!). И не забудьте проверить в соответствии с выбранным током через сегмент, выдержит ли 100-миллиамперный стабилизатор подключения 7-8 сегментов, или придется ставить что-то помощнее.

Коды для семисегментного индикатора представлены на рисунке выше. Отметим, что на схеме сегмент a индикатора подключен к младшему биту выходов регистра (OUT0). Потому при обычном порядке написания кода слева направо от a к g (как в таблице), его придется проталкивать через регистр младшим битом вперед. Десятичная точка при этом оказывается в самом младшем бите кода (бите 0), но в старшем выводе регистра (OUT7). То есть коды всех цифр будут содержать нули в младшем разряде, а для засветки точки надо при выводе просто приплюсовать к нужному коду единицу.

Arduino-программа для вывода одной цифры в один разряд носит название Shift_out_7seg_1dig. Вы найдете ее в архиве по ссылке в конце статьи. У Arduino задействованы выводы 10 (данные – dataPin), 11 (перезапись – latchPin) и 12 (такты – clockPin). Вывод данных осуществляется с помощью штатной функции shiftOut().

А теперь перейдем к многоразрядным индикаторам, что гораздо интереснее.

Статическая индикация

Вы будете удивлены, но для построения простейшей статической индикации, причем на индикаторах любого размера, больше ничего не требуется. Каждый семисегментный разряд подключается катодами сегментов к отдельной микросхеме MBI5167. Их удобно соединить в одну длинную линейку, подключив вход SDI следующего разряда к выходу SDO предыдущего. Тогда для управления всей линейкой достаточно трех выводов контроллера: для подачи последовательных данных на вход SDI первого разряда, для подачи тактовых импульсов (входы CLK всех микросхем объединяются) и для подачи импульса перезаписи на входы LE (которые тоже объединяются между собой). Так как микросхема довольно шустрая (подача тактов на вход CLK – до 25 МГц, что на пару порядков превышает частоту, например, шины I2C), то даже с учетом замедленной скорости работы Arduino-функции shiftOut(), никаких задержек при обновлении данных вы не заметите. Скорость вывода с помощью функции shiftOut() (о чем нет никаких официальных сведений!) примерно соответствует реальной скорости переключения вывода с применением digitalWrite() (см. разборки по этому поводу в моей книге, а также в книге Монка). Тактовая частота по выводу CLK получается около 75 кГц, значит передача целого байта займет где-то 120 мкс, с учетом импульса перезаписи по выводу LE.

Статическая индикация на 4 разряда
Статическая индикация на 4 разряда

Сказанное иллюстрируется схемой выше, где показано подключение четырех разрядов. Если подобная схема делается с конкретной целью индикации значения температуры в пределах 99,9 градусов по абсолютной величине, то ее можно упростить, если сократить основную часть до трех разрядов, а значок градуса (сегменты a-b-f-g) засветить в четвертом разряде постоянно с помощью подобранных резисторов. Для знака минус в любом случае не имеет смысла ставить целый индикатор (так как знак плюс все равно получить на семигментниках невозможно) — его можно сформировать отдельно с помощью плоского светодиода с подобранной под цвет индикатора длиной волны (не забудьте закрасить у такого светодиода боковые грани черным маркером). То же самое относится к двоеточию в часах, которое для мигания просто запитывается от отдельного вывода контроллера (не забывайте про подбор цвета!).

Схема будет потреблять достаточно большой ток. Обычно можно считать, что необходимый и достаточный ток через один сегмент составляет 5 мА, тогда через четыре разряда по семь сегментов каждый в экстремальном случае (все восьмерки) потечет суммарный ток 5´7´4 = 140 мА. При 10 мА на сегмент он составит уже 280 мА, не считая десятичных точек. Что не такая уж и маленькая величина для маломощных устройств и она может создать проблемы с тепловыделением внутри корпуса. И при сохранении подобранной яркости исправить это с переходом на динамическую индикацию не получится (о динамической индикации см. далее).

Главный недостаток этой схемы — большое число межсоединений, что усложняет и удорожает плату. При традиционных статических схемах с управлением хоть от счетчиков с дешифраторами, хоть непосредственно от выводов контролера, этот недостаток был решающим: в самом деле, для управления 7-ю сегментами в 4-х разрядах по отдельности нужно 28 свободных выводов контроллера. Замена на динамическую индикацию резко уменьшает число управляющих линий — для 4-х разрядов их потребуется уже всего 11 (7 – для сегментов и 4 для разрядов), поэтому там динамический вариант безусловно выигрывал. Способ с регистром сдвига делает ситуацию с управляющими линиями обратной — как мы увидим, для динамической индикации выводов потребуется больше, хотя в сумме и не слишком много. Но в статическом варианте никуда не деваются индивидуальные соединения регистров MBI5167 с катодами каждого из индикаторов, что все равно оставляет плату достаточно громоздкой. А, главное, сдвоенные-строенные-счетвереные индикаторы (которые могут быть и дешевле и компактней отдельных одноразрядных, и, кроме того, резко упрощают разводку платы) здесь применить не получится, они рассчитаны на динамический вариант.

Напоминаю, что ссылка на архив с тестовыми программами для Arduino — в конце статьи. Нужная демо-программа статической индикации носит название Shift_out_7seg_4dig_static, подключение соответствует схеме выше. Вопрос источника данных и их обработки здесь игнорируется, программа просто отображает последовательные цифры — сначала 1234, в следующем цикле 5678.

Динамическая индикация и ее особенности

Динамическая индикация прежде всего позволяет снизить аппаратурные затраты: вместо сдвигового регистра (или дешифратора с защелкой в традиционных схемах без контроллера), устанавливаемого на каждый разряд отдельно, здесь нужен один регистр на все разряды. Уменьшается и число соединений на плате — так как все одноименные сегменты разных разрядов объединяются, то можно просто взять сдвоенные, строенные или счетверенные варианты, где соединения сегментов уже выполнены внутри единого корпуса. Мы не будем здесь касаться вышеупомянутого случая применения готовых драйверов типа MAX7219/MAX7221 или TM1637 — они, конечно, позволяют снизить число необходимых выводов контроллера до минимума (так как организуют динамическую индикацию сами по себе), но, как мы говорили, удобно их применение только в пределах 5-вольтового питания индикаторов.

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

Подключение ключа на биполярных транзисторах для управления анодами
Подключение ключа на биполярных транзисторах для управления анодами

Во-вторых, для управления разрядами понадобятся ключи, в общем случае (при повышенном напряжении питания индикаторов) — снабженные еще и преобразователями уровня. В простейшем случае ключами (для индикаторов с общим анодом, напоминаю) могут служить pnp-транзисторы, подключенные эмиттером к питанию. Преобразователями уровня могут служить любые маломощные npn-транзисторы, коллекторная цепь которых управляет включением pnp-ключа, а базовая управляется контроллером. Соответствующая схема показана на рисунке.

Транзисторы в этой схеме могут быть любые, только надо учесть, что pnp-ключ управляет суммарным током всех сегментов, а здесь он для достижения той же яркости может в разы превышать оптимальные для статического варианта 5-10 мА на сегмент (см. далее раздел «О яркости индикаторов»). Иными словами, для четырех разрядов pnp-транзистор VT2 должен выбираться с допустимым током не менее 0,5-0,6 А. Указанный на схеме BC327 этому условию удовлетворяет, но если у вас завалялись отечественные, то придется ставить уже что-то из средней мощности — КТ814/816 или еще лучше, КТ973. При маленьких индикаторах и питании 5 В, равным питанию контроллера, преобразователь уровня на npn-транзисторе VT1 можно исключить для упрощения схемы, но не забудьте, что логику управления разрядами при этом необходимо инвертировать: включенному разряду будет соответствовать логический ноль на выходе контроллера.

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

Замечу, что у меня вот уже более 20 лет успешно работают настольные часы с индикаторами в дюйм высотой, где ключи управления и разрядами и сегментами сделаны на советских биполярных транзисторах (которые мне тогда не стоили ничего вообще — как устаревшие, они были списаны при какой-то очередной инвентаризации). Ничего с ними не происходит, так что схемы вполне рабочие. Но помню, как я мучился, впаивая в плату миллион выводных резисторов МЛТ, которые вместе с транзисторами заняли полплаты. Конечно, при наличии драйверов-дешифраторов с токовым выходом сейчас о ключах управления сегментами заботиться не нужно, да и SMD-компоненты заняли бы втрое меньшую площадь, но зачем все это, если есть более современные решения?

MOSFET’ы в качестве ключей куда удобнее, тем более в низкочастотных схемах, где мы вполне можем абстрагироваться от динамических потерь. Кроме того, специально для управления этими самыми MOSFET’ами есть необъятный ассортимент штатных преобразователей уровня, роль которых играют MOSFET-драйверы. А если мы еще правильно выберем сам полевик (по минимуму порогового напряжения VGS), то можем забыть про любые потери, независимо от напряжения питания.

Динамическая индикация на четыре разряда
Динамическая индикация на четыре разряда

Соответствующая схема для четырех разрядов приведена на рисунке. В качестве преобразователей уровня здесь использованы сдвоенные драйверы TC4426A с инвертирующим выходом, удобные для p-канальных транзисторов. Указанные на схеме транзисторы IRFD9014 выпускаются в корпусе типа «усеченный DIP» (DIP-4), который одинаково хорошо годится как для макетирования, так для установки на плату, где он занимает не слишком много места. Разумеется, можно выбрать из миллиона других вариантов, в том числе и более дешевых, только при низких напряжениях питания не забывайте про пороговое напряжение — VGS должно быть не больше 2-3 вольт. Как и в случае биполярных ключей, при одинаковом питании контроллера и индикаторов драйверы TC4426A можно исключить (не забыв при этом инвертировать логику управления разрядами), но я бы не советовал это делать: схема будет работать надежнее, если делать все строго по инструкции. Драйверы не нагружают выходы контроллера, а как альтернатива биполярным преобразователям уровня они просто займут меньше места на плате.

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

В программе обход разрядов происходит по прерываниям совпадения 8-разрядного Таймера 2.  Таймер устанавливается на коэффициент предделителя частоты, равный 1024 (что дает 15625 Гц на входе), с загрузкой в регистр совпадения числа 64 получается частота возникновения прерываний, равная ~244 Гц. Каждый разряд 4-разрядного числа горит в течении 1 периода этой частоты, соответственно, частота обновления каждого разряда и всего дисплея получается ~61 Гц. Этого достаточно, чтобы не воспринимать глазом мерцание индикаторов. Существенно увеличивать частоту переключения тут незачем — нам еще когда-то надо получать данные и преобразовывать их в отдельные цифры, а также, возможно, производить всякие другие действия. Динамическая индикация, осуществляемая с помощью отдельных микросхем-драйверов, примерно на порядок быстрее (у MAX7219/MAX7221 частота сканирования разрядов ~800 Гц), но они заняты только этим и ни на что больше не отвлекаются.

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

О возможных перебоях динамической индикации

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

Например, скорость штатного TWI (библиотека Wire) по умолчанию устанавливается на уровне 100 Кбит/с, что дает скорость обмена примерно в 1 байт за 100 микросекунд (учитывая всякие «старты» и «аски»), а в реальности еще меньше, так как какое-то время занимает посылка адресов устройств и регистров. Мы можем считать, что, например, чтение полного содержимого регистров часов типа DS1307, состоящего из 7 байт (Секунды: Минуты: Часы: День: День недели: Месяц: Год) займет около 1 миллисекунды. Это сравнимо с периодом нашей частоты переключения разрядов (244 Гц — около ~4 мс), потому нужно довольно внимательно отнестись к правильной организации обмена данными, не сбивающего индикацию. Единичный сбой из-за отложенного прерывания вы не заметите, но если период обновления разрядов дисплея начнет сбиваться регулярно, то изменение или мерцание яркости индикаторов будет заметно на глаз. Причем увеличить скорость обмена (библиотека Wire это позволяет), не всегда возможно: например, каноническая микросхема часов DS1307, как указано в ее описании, «operates in the regular mode (100kHz) only». 

Еще хуже дела обстоят с интерфейсом UART. Фиксированные скорости работы из предопределенного ряда значений не всегда позволяют организовать обмен без сбоев на достаточно высокой скорости — слишком велика оказывается ошибка установления битрейта даже при 16-мегагерцовой частоте контроллера. Именно поэтому предпочитаемая «по умолчанию» скорость в различных проектах обычно устанавливается равной 9600 — это компромиссная величина, работающая с достаточной надежностью.  Но 9600 бит/с — это вдесятеро меньше, чем у TWI, передача или прием каждого байта занимает около 1 миллисекунды. Увеличить ее, конечно, можно, но без тонких расчетов и оговорок лучше все равно ограничиться величиной 38400, что капитально проблему не решает. То есть при получении данных через UART приходится организацию обмена продумывать очень тщательно.

Вот со скоростью SPI не возникает никаких проблем, обычно все устройства легко поддерживают битрейт 1 МГц и выше. Но уж больно этот интерфейс редок среди обычных источников данных: он все-таки по природе предназначен для обмена в масштабах платы. Потому так или иначе приходится процедуры получения данных тщательно рассчитывать по времени.

О яркости индикаторов

Максимальный допустимый средний ток одного сегмента индикаторов обычных размеров (0,5-1,5 дюйма) примерно соответствует максимальному току сигнальных светодиодов, т.е. составляет около 30 мА. Обычное значение тока непрерывного свечения сегмента, при котором любой индикатор будет хорошо виден — 5-10 мА (для красных поменьше, для желтых и зеленых — побольше). Причем для увеличения видимого контраста цифры не стоит тупо увеличивать ток через нее — напомним, что у драйверов есть свои ограничения на выделяемую мощность, да и у каждого типа индикаторов, кроме предельно допустимого среднего тока, есть еще и предельная рассеиваемая мощность на сегмент, и чем дальше мы от нее отстоим, тем схема окажется долговечнее.

Потому лучший способ улучшения видимости цифры — поместить индикатор под фильтр из дымчатого оргстекла, причем на некотором расстоянии вглубь. Фильтр сделает фон светящегося сегмента даже при обычной молочно-матовой лицевой поверхности корпуса визуально абсолютно черным, и общий контраст увеличится, несмотря на то, что сам фильтр задержит часть излучаемого света. Особенно это важно при разглядывании дисплея издалека, например, в настольных часах или настенной метеостанции. Заметим, что нейтрально-серый дымчатый фильтр наиболее  универсален, но если у вас индикаторы одного цвета, то можно подобрать фильтр соответствующего оттенка: скажем, желтые индикаторы лучше смотрятся через коричневое оргстекло (а вот зеленые при этом могут потерять в насыщенности цвета). Можно вместо дымчатого или цветного прозрачного оргстекла, которое достать бывает непросто, воспользоваться пленками-фильтрами, применяемыми в фотографии и театральном деле.

Еще следует учитывать такой нюанс: десятичная точка у индикаторов увеличенного размера обычно отличается от остальных сегментов уменьшенным прямым падением напряжения (например, у индикаторов высотой 1 дюйм сегмент состоит из двух последовательно включенных светодиодов, а десятичная точка — из одного). Потому, если вы хотите десятичную точку засветить отдельно от цифр через резистор, чтобы она не выделалась на фоне цифр или не светила слишком тускло, величину этого резистора придется подгонять индивидуально — скорее всего, рассчитать его точную величину не получится.

При подключении десятичной точки к драйверу с токовым выходом это обстоятельство перестает иметь значение, но зато вылезает досадная ошибка, которую допускают, кажется, абсолютно все производители семисегментников. Круглая точка визуально кажется меньше остальных сегментов (имеющих форму вытянутого параллелограмма или прямоугольника) и при совпадающей яркости теряется на их фоне — издалека и не поймешь, где именно стоит разделитель. Потому совсем не вредно все-таки засветить ее отдельно и подобрать яркость так, чтобы десятичная точка немного выделалась. Эта проблема совершенно отсутствует в разновидностях с запятой вместо точки, или в тех редких случаях, когда точка не круглая, а прямоугольная. Заметим в скобках, что в некоторых ЖК-дисплеях эта проблема стоит еще острее и хоть как-то сгладить ее не получается вообще. Ну не догадываются компании-разработчики дисплеев о необходимости привлекать художников-шрифтовиков (и если бы это было единственное их упущение в части дизайна!).

При динамической индикации на все это накладывается коэффициент заполнения. В нашем случае он равен обратной величине от количества индикаторов (в драйверах типа TM1637 и MAX7219/MAX7221 это не так!). Зависимость видимой яркости от коэффициента заполнения в общем случае нелинейная, но мы можем считать, что в практически значимых пределах она обратно пропорциональна количеству индикаторов. Потому при двух индикаторах подобранный в статическом режиме ток через сегмент следует увеличить вдвое, при четырех — вчетверо. Легко подсчитать, что уже при 4-х индикаторах небольшого размера, если первоначально подобранная величина тока равна 10 мА, мы вроде бы выходим за пределы максимально допустимого тока 30 мА. Но все станет на свои места, если вспомнить, что это максимально допустимый средний ток, а усредненная величина в зависимости от коэффициента заполнения не меняется. Но и пиковый ток, разумеется, ограничен, потому при большом количестве индикаторов для них будет лучше, если вы разделите индикаторы на группы не более 4-5 штук в каждой.

Управление яркостью

У драйверов есть специальные команды управления яркостью, регулирующие относительную длительность включенного состояния разряда. У TM1637 8 градаций яркости, у MAX7219/MAX7221 по 16. В реальности такое количество ступеней совершенно излишнее — обычно имеют значение три величины (низкая-средняя-высокая), но вот сами эти величины для разных типов дисплеев могут отличаться, и еще зависеть от плотности фильтров, устанавливаемых, как мы говорили, для увеличения контраста.

На практике в нашем случае наличие начальной программной регулировки необязательно: проще заранее подобрать значение тока под конкретные условия с помощью токозадающего резистора Rext. Единственный вариант, когда такая регулировка понадобится —  необходимость регулировать яркость в зависимости от внешнего освещения. В некоторых случаях это совершенно обязательная функция (дисплеи на торпеде автомобиля, на судовых пультах управления — во избежание засветки поля зрения и отражения в лобовых стеклах в ночных условиях), да и просто нередко хочется приглушить яркость настольных часов ночью.

В случае статической индикации чисто программной регулировки не добиться,  придется переключать токозадающие резисторы Rext во всех разрядах одновременно. Это не очень сложно сделать с помощью КМОП-коммутаторов (например, 74HC4066, старинных 590КН2 или маломощных электронных реле), только довольно сильно загромождает схему.

Тут динамическая индикация выигрывает — вот там никаких проблем с программной регулировкой не существует. Для ее осуществления достаточно в каждом периоде ввести задержку на включение разряда в пределах длительности периода. Расписывать подробно не стоит — практические случаи могут быть самые разные, от ручной установки кнопкой «больше-меньше» до автоматической плавной или ступенчатой регулировки в зависимости от освещенности, измеряемой фотодиодом. Замечу, что в случае ручной регулировки неплохо ввести запоминание установленной яркости в EEPROM, чтобы не приходилось давить на кнопку после каждого перебоя в питании.

А вот и обещанная ссылка на архив с программами. Ассемблерные демо-варианты выкладывать я не стал, кому потребуется управление на низком уровне (оно гораздо гибче и удобнее) — обращайтесь.




Комментарии (37):

  1. Z2K
    /#23755957 / +1

    "выбор еще больше ограничен."

    - а если так - "выбор еще меньше"

  2. Serge78rus
    /#23755999 / +1

    Огромное спасибо автору за приятные ностальгические воспоминания о конце 80-х — начале 90-х, когда приходилось решать подобные проблемы. Да и вообще подача материала и стиль изложения заслуживает уважения.
    Но… Вы меня простите, но вынужден выступить с резкой критикой исходника обработчика прерывания таймера в примере программы для динамической индикации. Использование в обработчике прерывания функции digitalWrite(), да еще и многократное — это самое настоящее преступление. То же касается и shiftOut(), которая внутри использует digitalWrite(). Посмотрите на исходник digitalWrite() чтобы раз и навсегда понять, что ей не место в обработчике прерывания, особенно для AVR с его примитивной подсистемой прерываний.

    • Sdima1357
      /#23756121 / -1

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

      • Serge78rus
        /#23756157

        Вы действительно считаете неоднозначным вопрос об использовании в обработчике прерывания одной операции записи в регистр порта или функции, выполняющиейся за несколько десятков тактов? Гляньте, просто ради интереса, исходник digitalWrite().

        • Sdima1357
          /#23756169

          Эта функция - совместимая оболочка в ардуине для записи бита в порт. Ее имплементации очень различны для разных архитектур. Посмотрите для интереса на avr, stm8, stm32( тут тоже разные для m0,m4, m7) esp xtensa, esp risc-v и т.д.

          • Serge78rus
            /#23756185 / +2

            В данном случае говорить о переносимости кода бессмысленно. Как код самого обработчика прерывания таймера, так и его инициализация все равно не переносимы, а написаны конкретно для AVR.

            • Sdima1357
              /#23756207 / +1

              Бессмысленная оптимизация . Программа справляется с поставленной задачей? Если да - то больше ничего делать не надо. Если нет то можно и пооптимизировать. В данном случае выигрыш будет копеечный. И я думаю что автор статьи тоже умеет писать в порт напрямую на AVR -ке. Просто не посчитал нужным и я бы не стал придираться

              • Serge78rus
                /#23756249 / +1

                Автор, безусловно, умеет работать напрямую с регистрами, об этом говорит хотя бы операция инициализации таймера. Да и другие статьи автора. И именно поэтому у меня этот кусок кода и вызвал резкий диссонанс. Если бы статью написал типичный «ардуинщик», то претензий бы не было (я бы и читать ее не стал дальше первого абзаца).
                Кстати, насчет «справляется с поставленной задачей» — у меня нет уверенности, что при такой реализации полностью отсутствует паразитная подсветка погашенных сегментов. Я бы сделал так: сначала снимается напряжение с анодов индикаторов, затем выполняются все манипуляции с сегментами, и только потом подается питание на анод активного разряда.

                • Sdima1357
                  /#23756257

                  Это демо версия :)

                  • Serge78rus
                    /#23756265 / +1

                    Согласен, но уж больно понравилась сама статья, чтобы обратить внимание даже на мелочи. К сожалению, это сейчас случается не часто.

                • YRevich
                  /#23756599

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

                  Удивился странной претензии. Вы времена выполнения операций считать умеете? Во-первых, выполнение сдвига через ShiftOut(), специально мной промеренное, занимает 120 мкс, там написано. Что примерно 3% от времени горения разряда. Во-вторых, разряд зажигается ПОСЛЕ сдвига и переписывания в защелку. Разница в задержках порядка времени выполнения одной-двух digitaWrite(), т.е. где-то 13-25 мкс, максимум 0,6% от времени горения. Это скажется хоть как-то на яркостях? Зачем напрямую писать в порты, когда все это нас устраивает выше крыши? Я вообще всегда по возможности привык применять штатные средства, если к этому нет прямых противопоказаний.

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

                  • Serge78rus
                    /#23756703 / +2

                    Вы времена выполнения операций считать умеете?
                    Умею, и считаю, когда пишу критические по времени выполнения участки кода, к которым относятся обработчики прерываний.
                    Во-первых, выполнение сдвига через ShiftOut(), специально мной промеренное, занимает 120 мкс, там написано. Что примерно 3% от времени горения разряда.
                    Да бог с ним, с временем горения. Этот интервал входит в общее время обработки прерывания, когда процессор не реагирует на другие прерывания. Это же AVR.
                    Во-вторых, разряд зажигается ПОСЛЕ сдвига и переписывания в защелку.
                    Но и предыдущий разряд гасится ПОСЛЕ сдвига, а надо бы его погасить ДО, во избежание паразитных засветок.
                    Разница в задержках порядка времени выполнения одной-двух digitaWrite(), т.е. где-то 13-25 мкс, максимум 0,6% от времени горения. Это скажется хоть как-то на яркостях?
                    На яркости нет, собственный разброс яркости разных сегментов индикатора намного больше. А вот на потере данных с какого-нибудь быстрого интерфейса из-за несвоевременной обработки его прерываний — вполне.
                    Я вообще всегда по возможности привык применять штатные средства, если к этому нет прямых противопоказаний.
                    Смотря что считать «штатными средствами». Если это стандартная библиотека или библиотека от производителя — то да. Библиотеку Ардуино я бы к ним относить не стал. А противопоказания в данном случае — затягивание времени обработки прерывания.
                    Напрямую в порты я пишу в ассемблерных версиях тех же программ. Там все просчитать, включая и не показанный здесь обмен данными, можно намного точнее и, конечно, никакие digitaWrite() там не уместны.
                    Прямая запись в регистр на Ассемблере и на C не особо отличается, если конечно адресоваться напрямую к порту, а не как это принято в Ардуино к некоей лишней сущности в виде «номера пина». Что касается digitaWrite(), то на мой взгляд она нигде не уместна, ну а уж в обработчике прерывания — безусловно.

                    • YRevich
                      /#23756893

                      Замучали, честно.

                      Этот интервал входит в общее время обработки прерывания, когда процессор не реагирует на другие прерывания.

                      И что из того, если мы тут больше ничего не делаем, а время это занимает доли процента от промежутка между прерываниями? Чему мы можем навредить? Я вообще-то между прерываниями еще собираюсь данные получать по уарту. Уарт в сотню раз дольше, чем все эти переключения, как они могут на него повлиять, если он даже и отложится на пару десятков микросекунд? Народ вообще переоценивает влияние этой фичи AVR, обычно то, что процессор затормаживается, приносит одни только удобства. Тут просто надо все внимательно считать, и никаких проблем не будет, хоть с ардуиной, хоть напрямую.

                      "Потеря данных с какого-нибудь быстрого интерфейса" при применении прерываний - этот миф пошел от уважаемого DiHalt, с которым я уже спорил по этому поводу и он со мной согласился. Не существует "какого-нибудь интерфейса" в виде сферического коня в вакууме, есть конкретные задачи с конкретными устройствами, про которые все известно. Если у вас "потеря данных", значит вы что-то не просчитали или AVR вообще не подходит под задачу.

                      Но и предыдущий разряд гасится ПОСЛЕ сдвига, а надо бы его погасить ДО, во избежание паразитных засветок.

                      Откуда паразитные засветки, если все хранится в защелке? И до этого горел предыдущий разряд с предыдущим содержимым защелки?

                      Ну а это уже чисто ваши личные принципы:

                      если конечно адресоваться напрямую к порту, а не как это принято в Ардуино к некоей лишней сущности в виде «номера пина». Что касается digitaWrite(), то на мой взгляд она нигде не уместна, ну а уж в обработчике прерывания — безусловно.

                      Я тоже в чем-то перфекционист, но все-таки по делу, а принципы оставляю фанатикам. Есть конкретная задача, под нее и принимаем конкретные решения.

                      • Serge78rus
                        /#23757795

                        Замучали, честно.
                        Будьте великодушны, простите меня.
                        И что из того, если мы тут больше ничего не делаем ...
                        Это так, пока это демонстрационная программа. В реальной программе придется параллельно решать и другие задачи. Вы же в статье пишете:
                        Далее я предлагаю универсальное решение для любых типоразмеров индикаторов.
                        Я это трактую, как претензии на некое универсальное решение, которое в дальнейшем будет использоваться в реальных задачах. Хотя, возможно, я неправильно понял и Вы предлагаете только аппаратное решение, а код пишете только для демонстрации его работоспособности. В таком случае примите мои извинения за ненужную дискуссию, на которую все мы потратили время. Но боюсь, что кто-то еще, но имеющий меньший опыт и потому менее критический подход, может воспринять информацию в статье как прямое руководство к действию (а аппаратное решение Вы действительно подали и разжевали прекрасно и это имеет полное право быть руководством к действию).
                        «Потеря данных с какого-нибудь быстрого интерфейса» при применении прерываний — этот миф...
                        Это не миф, а вполне реальная проблема. И чем дольше мы находимся в обработчиках прерываний, тем больше шансов с ней столкнуться. Да и помимо обслуживания интерфейсов есть другие критичные ко времени задачи, хотя бы тот же «ногодрыг».
                        Откуда паразитные засветки, если все хранится в защелке? И до этого горел предыдущий разряд с предыдущим содержимым защелки?
                        Засветка будет как раз если наоборот до этого предыдущий разряд не горел, а следующий горит. Давайте для понимания все предельно упростим: будем рассматривать только два разряда и всего один сегмент в ситуации, когда в первом разряде он не горит, а во втором горит. При переключении от первого ко второму разряду у Вас, при запитаном аноде первого разряда, сначала подается состояние для второго разряда на катод (включенное), и только потом происходит коммутация анодов. Да, это достаточно короткий импульс, чтобы перепутать погашенное и включенное состояние сегмента, но все же достаточный, чтобы погашенный сегмент слегка подсвечивался. И главное, чтобы этого избежать не нужно никакого усложнения программы, достаточно всего лишь соблюсти временную последовательность:
                        1. отключение анода первого разряда
                        2. изменения состояния сигналов сегментов (катодов) от состояния для первого разряда на состояние для второго разряда
                        3. включение анода второго разряда

                        Ну а это уже чисто ваши личные принципы:

                        Я тоже в чем-то перфекционист, но все-таки по делу, а принципы оставляю фанатикам. Есть конкретная задача, под нее и принимаем конкретные решения.
                        Здесь предлагаю остаться каждому со своим мнением и уважением чужого, иначе похоже дискуссия может затянуться до бесконечности.

                      • YRevich
                        /#23758653

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

                        Но вот в чем я попрежнему останусть на своих позициях, это в вопросе работы по прерываниям. Я имел дело с AVR с момента их появления, около 1997 года. И мы задолго до появления всяких навороченных студий старались писать код так, чтобы он выполнялся именно в прерываниях. Основной цикл по возможности оставляли пустым или выполняли в нем какие-то второстпенные действия, которые можно отложить. Тот самый diHalt назвал это в разговоре со мной бесплатной многозадачностью. На мой вкус, уж извините, выполнение основной задачи в главном цикле - моветон, надо все делать в прерываниях (и считать времена удобнее, и вклиниться ничего не может). Благо именно AVR отлично приспособлены к такому порядку работы. Про Arduino тут речи нет, это просто удобное средство для быстрой проверки принципов работы, как в данном случае с семисегментниками. Хотя простые проекты можно выполнять и на Arduino, удобно, быстро и дешево.

                        Но чего я не пытался делать на AVR - работать с большим потоком данных, идущих подряд (звук, например). Вот в таких задачах да, можно что-то потерять, как вы говорите. Но к этому AVR совершенно не приспособлены, они банально медленные, и попытки, скажем, воспроизведения звука через ШИМ дают крайне убогий результат. А в большинстве задач автоматики, управления или обработки данных с датчиков совершенно неважно, отложится прием пакета данных по UART на десяток микросекунд или нет. И если все-таки надо дрыгнуть ногой в точно определенный момент (вот как вы там описывали про поорядок переключения разрядов - на семисегментнике это не скажется, но может сказаться, например, при каком-то синхронном обмене), то всегда можно организовать временной поток так, чтобы первостепенные задачи выполнялись вовремя. В конце концов, там можно организовать и вложенные прерывания, никто не запрещает. Ну а если все-таки нельзя, то AVR попросту не годятся, повторяю, сейчас есть уже много чего более быстрого и производительного.

                        Тут кто-то еще упоминал про переносимость кода - при мне лучше об этом не вспоминать, завою и начну кусаться. Мы не заметили, как программисты со своим специфическим мышлением постепенно заняли территорию электронщиков (отсюда такое большое количество несуразностей в том же Arduino). И програмный код вместо инструмента выполнения инженерной задачи постепенно превратился в самоцель.

                      • Serge78rus
                        /#23759031

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

  3. gleb_l
    /#23756255

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

    • YRevich
      /#23756619

      Не выйдет. Догадываетесь, почему? Потому что у красных-желтых LED при токах в десятки мА падение до 2 с лишним вольт, у синих - до 3. А у обычных диодов максимум 0,9-1 вольт, даже у мощных выпрямительных - до полутора. Это все никак не скажется при питании 12-15 вольт (да и сама разница между точкой и сегментом тоже будет незаметна), а вот при питании 6-7 В будет причиной разнобоя в яркостях.

      • AndrBell
        /#23800969

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

        На мой взгляд можно обойтись без резистора (у нас динамическое питание). Нужно отдельное время засветки для точки и для остальных сегментов. Поясню подробнее:

        Записать в порт сначала только точку (если ее нужно засвечивать) (или не точку в противоположность , если она наоборот слишком яркая, т.е остальные нужные сегменты) для включения "дополнительного" света на "регулируемое" время, а потом полностью все нужные (до конца времени засветки индикатора).

  4. Delsian
    /#23757069 / +2

    А можно не заниматься изобретанием велосипедов, а просто поставить копеечную PCA9745

    • Ivanii
      /#23757281

      И использовать аппаратный SPI в МК, может останавливать цена 200 р/шт и отсутствие в России, но она вполне доставаема.

  5. svitoglad
    /#23757295 / +1

    В ТМ1637 интерфейс не І2С а похожий на него безадресный интерфейс.

    • Tomasina
      /#23758141

      Ага, налетел однажды на эту особенность.

  6. sim2q
    /#23757871

    MBI5167

    Так какой китайский аналог то смотреть?
    А то все эти преимущества всё равно разбиваются ценой 595 с резисторами

  7. Tomasina
    /#23758153

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

    Поэтому пока остаюсь на полубестолковой 1637, и все руки не доходят до переделки на OneWire.

  8. iShrimp
    /#23760475

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

    Светодиоды больше всего боятся импульсов тока, поэтому расчёт лучше вести от максимального пикового значения.

    • YRevich
      /#23761959 / +1

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

  9. YRevich
    /#23761953

    Почему-то коменнт продублировался, см. ответ iShrimp

  10. moviq
    /#23764967

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

    0 1 2 3 4 5 6 7 8 9 A b C d E F. Ну и да, ещё минус, градус

    • jok40
      /#23798411

      А если всё таки поизощряться, то ещё больше: 0 1 2 3 4 5 6 7 8 9 A b C d E F G h I J L n o P q r S t u Y

  11. b_t
    /#23770823

    Спасибо за статью! Есть идеи как управлять установкой тока нескольких драйверов в статическом режиме при помощи одного потенциометра?

    • YRevich
      /#23771449

      А как вы это себе представляете? Там входы Rext между собой нельзя соединять, т.е. переменники должны быть раздельными. Объединять можно только линии управления, но и это не так просто. Можно, например, взять цифровые потенциометры и управлять ими через один интерфейс. Теоретически еще, наверное, можно что-то замутить с токовыми зеркалами, но не думаю, что получится хорошо и с полпинка. Если придумаете еще что-то, пишите.

      • b_t
        /#23775505

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

        • Sdima1357
          /#23775537

          А чем Вас не устраивает динамическая регулировка ( PWM ) ?

          • b_t
            /#23775575

            У меня "аллергия" на "видимый" ШИМ (освещение и диспеи, но не двигатели и нагревали). Для щитовых показометров, на которые нужно сомтреть 30 секунд в месяц это не критично, но у меня тут завалялся проект настольных часов, которые почти все время в области видимости. Вот в таких часах или ШИМ на несколько кГц или статика, причем статика лучше, как минимум психологически. Обычно семисегментные индикаторы я делаю на max7219, он не плох, но не идеален - для крупных семисегментников без доп. обвяза не подходит, частота в пару-тройку раз ниже, чем мне бы хотелось. Вот и заинтересовался таким подходом, но нужна регулировка яркости, как минимум дневной и ночной режимы.

            • Sdima1357
              /#23776597

              Можно регулировать общее, относительно высокое напряжение с большим постоянным резистором (источник тока).

              Можно использовать TFT LCD с добавочным светофильтром

              Распять из дискретных ледов