Автор: Юрий Всеволодович Ревич

Arduino и матричные индикаторы

Платформа Arduino предлагает широкие возможности для конструирования всяческих измерителей, но вопрос всегда упирается в вывод показаний так, чтобы это было эстетично и удобно. ЖК-дисплеи очень хорошо подходят для автономных малопотребляющих приборов, но для настенных или настольных конструкций, по моему мнению, не годятся решительно из-за своей малой яркости и контраста. Куда лучше подходят для этой цели светодиодные или другие самосветящиеся устройства. Семисегментные светодиодные индикаторы всем хороши в качестве дисплеев часов или измерителей каких-то величин, но, во-первых, уже навязли в зубах, во-вторых, недостаточно гибкие. Практически они ограничены узкой областью отображения цифр, в крайнем случае еще нескольких сопутствующих знаков. Вообще, ассортимент достаточно эстетично выглядящих светодиодных конструкций на рынке куда уже всех остальных разновидностей. Не размахиваться же на графический OLED-экран, когда нужно отобразить всего несколько символов, правда?

Image1
Рис.1 Разряд матричного индикатора 5×7

Поразрядные матричные индикаторы
Здесь я предлагаю обратить свой взор в сторону матричных индикаторов 5×7 точек (Рис.1). Они выпускаются самых разных размеров и нескольких цветов, могут отображать любые символы, хоть китайские иероглифы. Сложность состоит в надлежащей организации управления большим количеством светодиодов: только один разряд содержит их 35 штук, значит приемлемые для практических нужд линейки из четырех таких разрядов буду содержать 5х7х4 = 140 точек. Разумеется, индивидуальное управление каждой точкой здесь невозможно и не предполагается: выводы таких индикаторов объединены по столбцам и строкам (Рис.1).
Чтобы засветить все нужные точки независимо друг от друга, приходится городить довольно сложные алгоритмы управления. Экономичный с точки зрения числа управляющих выводов метод «мультиплексирования Чарли» (Charlieplexing) еще может оказаться относительно приемлемым для одного такого разряда, и то при этом будут заняты минимум семь выводов контроллера и при этом придется еще дополнительно ставить пять транзисторов с парой резисторов на каждый. А самое главное, что в «методе Чарли» экономия числа управляющих выводов достигается за счет еще большего снижения коэффициента заполнения (то есть относительного времени в процентах, когда каждый светодиод оказывается включен), чем для обычного мультиплексирования. Для одного разряда по «методу Чарли» коэффициент заполнения будет около 15%. При этом при обычном мультиплексировании (то есть, например, по столбцам, которых меньше, чем строк) коэффициент заполнения вырастет до 20%, но зато увеличится число управляющих выводов — на один разряд их придется 12. А на линейку из четырех таких индикаторов прямое мультиплексирование потребует уже 27 выводов, при этом коэффициент заполнения снизится еще в четыре раза, до 5% от максимальной светимости.
Учитывая, что у матриц и без того не слишком большая яркость (например, 18-миллиметровая зеленая ТА07-11GWA имеет силу света 8 мКд при токе 10 мА — вдвое хуже, чем самые тусклые дискретные светодиоды), такое падение яркости нельзя назвать хоть сколько-нибудь приемлемым. Приходится искать альтернативные решения, позволяющие увеличить максимальный ток через каждую точку матрицы хотя бы до 15-20 мА и одновременно получить максимально возможный коэффициент заполнения.
Решение в виде схемы управления одновременно парой разрядов на коммутаторах-мультиплексорах малой степени интеграции с буферными элементами в каждой строке и столбце позволяет выжать максимум возможного из подобных схем подключения линейки 5х7х4: 24 управляющих вывода, ток через каждый светодиод до максимально допустимого (25 мА для матрицы ТА07-11). Однако коэффициент заполнения все равно оказывается равен 10%, что слишком мало для нормального свечения, а схема получается настолько навороченной, что возникают сомнения в целесообразности использования таких матриц вообще. К тому же решение без дополнительных усилий не тиражируется на число разрядов, отличное от четырех. По всем этим причинам я не буду останавливаться на нем подробно.
Видимо, эти обстоятельства и обусловили малую применимость точечных матриц в качестве простых индикаторов и в любительских, и в профессиональных применениях. Однако, есть готовое решение, причем очень удобное как раз для простых приборов: это драйверы матричного дисплея конфигурации 5х7 точек х4 разряда под названием MAX6952 и MAX6953 (русское описание здесь и здесь), где эти проблемы решены. MAX6952/6953 может обеспечить ток (устанавливаемый и программно и схемотехнически) через точку матрицы вплоть до 48 мА, обладает встроенной таблицей шрифтов из 104 символов, дополняемых 24 пользовательскими, и управляется через скоростной SPI-интерфейс (MAX6952) или I2C (MAX6953). Их недостаток — достаточно высокая стоимость (около 20 долларов) и редкость в отечественной розничной продаже, отчего приходится заказывать в компаниях, имеющих склады за рубежом, что медленно и дорого. Зато никаких проблем с управлением матричными табло вы больше иметь не будете.
Сразу отмечу, что решение с этими драйверами можно масштабировать практически неограниченно, получая линейки из четырех, восьми, двенадцати и т.д. разрядов. Причем без каких-то усложений, кроме увеличения числа микросхем и роста общего потребления. Для SPI-варианта при этом увеличится лишь число управляющих выводов «выбор кристалла» соответственно числу микросхем, а для I2C-версии в схеме управления не изменится вообще ничего — MAX6953 позволяет устанавливать коммутацией соответствующих выводов до 16 вариантов внутреннего I2C-адреса.

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

sxema_matrix_6953
Рис.2 Схема подключения 4-х матричных индикаторов 5х7 точек с драйвером MAX6953

Схема подключения линейки матричных индикаторов типа ТА07-11, рассчитанных на работу в качестве дисплея электронных часов, к драйверу MAX6953 показана на рис. 2. Всего она имеет пять внешних соединений: питание +5 В и «земля», два вывода управляющего I2C-интерфейса (SDA и SCL), а также объединенные катоды светодиодов разделительной точки, обозначенные на схеме, как Blink_Dots. Этот вывод подключается к любому из свободных портов Arduino, и управляется отдельно.
Разбор схемы начнем с вопроса о подборе величин резистора R3 и конденсатора С1, от которых зависит как максимально возможный ток через светодиоды матрицы, так и внутренняя тактовая частота драйвера. От тактовой частоты зависит частота мигания дисплея при включении режима BLINK через драйвер. Мы такой режим не используем, потому частота (fOSC) нас волнует во вторую очередь (документация рекомендует выбирать ее от 1 до 8 МГц), а вот ток через сегменты (ISEG) очень важен. Согласно документации на MAX6953, эти величины определяются формулами (обозначения далее — в соответствии со схемой рис. 2):
ISEG = 2144/R3 mA
fOSC = 6003/(R3 ✕ (C1 + C0)) MHz
Здесь R3 подставляется в килоомах, C1 — в пикофарадах, С0 – паразитная емкость монтажа (типовое значение около 2 пФ).
По умолчанию документация рекомендует для R1 и C3 нестандартные значения 53,6 кОм и 26 пФ, что дает частоту fOSC в 4 МГц, и максимальный ток ISEG равный 40 мА. Разобраться в том, что в документации понимается под «сегментом», непросто, потому я поясню, к чему относится эта величина тока: в каждый момент времени включены два из четырех разрядов, и для расчета общего среднего тока потребления величину ISEG надо умножать не на 20 (5х4 — общее число столбцов), а на 10. Это равносильно коэффициенту заполнения 50%, т.е. реальный средний ток через столбец матрицы будет вдвое меньше ISEG, следовательно, под сегментом тут понимаются два столбца в разрядах, горящих одновременно. То есть при таком токе вся конструкция будет потреблять около 415 мА, считая собственное потребление драйвера. Однако, при напряжении питания 5 В выделяющаяся мощность может превысить возможности микросхемы, потому документация рекомендует ставить дополнительный резистор по питанию. Мы в эти тонкости вникать не хотим, потому просто увеличим номинал R3 до 100 кОм, тем самым снизив пиковый ток через светодиоды матрицы до 20 мА. Но имейте в виду, что у вас есть некоторый запас по яркости, и если вы, например, поставите матрицу побольше размерами, то можете увеличить яркость, просто уменьшив номинал R3 (только внимательно изучите документацию перед этим).
Второе соображение относится к источнику питания. При питании Arduino от USB-порта, его номинальных возможностей (500 мА максимум) может не хватить, особенно, если к Arduino подключены еще какие-то устройства. При питании от адаптера 7-9 В встроенный в Arduino Uno или Micro стабилизатор NCP1117 имеет достаточно высокую нагрузочную способность (до 1 А), однако надо учитывать, что он не установлен на радиатор, и при большом токе и высоком напряжении адаптера может перегреваться. По всем этим причинам питать нашу схему от платы Arduino необходимо с оглядкой. А на период отладки настоятельно рекомендую включать ее от отдельного источника 5 В — если вы что-то не так соедините, какие-то выводы MAX6953 окажутся висящими в воздухе или перемкнуты между собой (что случается при любительском монтаже микросхем в корпусах с мелким шагом), то ток потребления может резко возрасти и лучше пожертвовать одной микросхемой MAX6953, чем еще и платой Arduino. По той же причине для любительских целей я рекомендую приобретать MAX6953 в DIP-корпусе с шагом 2,54, хотя они встречаются в продаже еще реже, чем в корпусе SSOP с шагом 0,8 мм, и занимают гораздо больше места.
В остальном схема столь тонких расчетов не требует. Токоограничивающие резисторы для светодиодов разделительного двоеточия выбраны опытным путем, чтобы подогнать яркость под точки матрицы. Тип трехмиллиметровых светодиодов L132 выбран по длине волны (т.е. их цвету свечения) соответствующему индикатору ТА07-11 и минимальной яркости среди других типов. Контакты MAX6953 21 (SDA) и 22 (SCL) подключаются к штатным выводам интерфейса I2C Arduino A4 и A5, соответственно, а катоды светодиодов (вывод Blink_Dots) — к выводу A0 (цифровой вывод 14).

Программа
Рассмотрим построение программы управления драйвером MAX6953 от Arduino. Схема рис. 2 предполагает I2C-адрес устройства по умолчанию (0x50). О том, какие выводы надо переключить для изменения адреса, если это необходимо, читайте документацию. Запуск драйвера предполагает довольно громоздкую процедуру инициализации всех нужных регистров, которую следует размещать в секции setup. Предварительно в программе следует подключить библиотеку wire.h и установить необходимые переменные:

#include
#define deviceaddress 0x50 //адрес по умолчанию MAX6953
int ledPin = 14; //A0 – мигалка разделительной точки
//определяем переменные для разрядов дисплея:
int dig3 = 0x23; //номера регистров взяты из документации
int dig2 = 0x22;
int dig1 = 0x21;
int dig0 = 0x20;

void setup()
{
//====инициализация матрицы=====
Wire.begin(); // подключаем i2c bus
Wire.beginTransmission(deviceaddress); // запись в устройство
Wire.write(0x04); // регистр конфигурации
//MAX6953 Table 6 – номер таблицы в описании
Wire.write(0x01); // выключаем режим shutdown;
Wire.endTransmission();
//MAX6953 Table 23 – следующий шаг:
Wire.beginTransmission(deviceaddress);
Wire.write(0x01); // Интенсивность разрядов 0 и 2
Wire.write(0xFF); //все сегменты на максимум = 20 мА
Wire.endTransmission();
//MAX6953 Table 24 – следующий шаг:
Wire.beginTransmission(deviceaddress);
Wire.write(0x02); // Интенсивность разрядов 1 и 3
Wire.write(0xFF); // все сегменты на максимум = 20 мА
Wire.endTransmission();
//Включаем test mode для проверки: все светодиоды горят
//MAX6953 Table 22
Wire.beginTransmission(deviceaddress);
Wire.write(0x07);
Wire.write(0x01);
Wire.endTransmission();
delay(1000); //секундная задержка
//выключаем test mode
//MAX6953 Table 22
Wire.beginTransmission(deviceaddress);
Wire.write(0x07);
Wire.write(0x00);
Wire.endTransmission();
//=====конец инициализации =======
pinMode(ledPin, OUTPUT); //управление разделительным двоеточием
}

Далее отдельно вставляем текст функции для вывода символа в определенный разряд. Автор этих строк ненавидит перечеркнутый ноль на дисплеях — анахронизм времен АЦПУ и алфавитно-цифровых терминалов, потому функция заодно заменяет цифру «0» на букву «O». Если вас это не волнует, удалите всю функцию IF..ELSE, оставив от нее только строку Wire.write(value)):

//запись символа value в разряд disp
void writeChar(byte value,byte disp)
{
Wire.beginTransmission(0x50);
Wire.write(disp);
if (value == ‘0’) Wire.write(‘O’); //ноль заменяем на букву O!!
else Wire.write(value);
Wire.endTransmission();
}

И, наконец, собственно проба вывода символов в функции Loop:

void loop()
{
//матрица:
writeChar(‘0′,dig3);
writeChar(‘2′,dig2);
writeChar(‘0′,dig1);
writeChar(‘3′,dig0);
delay(500);
digitalWrite(ledPin, LOW);
writeChar(‘6′,dig3);
writeChar(‘0′,dig2);
writeChar(‘8′,dig1);
writeChar(‘0′,dig0);
delay(500);
digitalWrite(ledPin, HIGH);
}

Эта программа выводит на дисплей попеременно строку цифр «30:20» и «08:06» с одновременным подмигиванием двоеточием. Вы можете поэкспериментировать, подставляя в функции writeChar разные другие символы. Придется, однако, ограничиться только английским алфавитом и рядом специальных знаков (см. таблицу 15 в документации). Среди этих знаков есть символы доллара, евро и иены, что позволяет на основе MAX6953 делать, например, табло валютных обменников.

Часы полностью
Остановимся поподробнее на реализации электронных часов, для чего мы и вводили мигающее двоеточие. Для этого надо лишь подключить любой модуль часов, например, на основе микросхемы DS1307. Я рекомендую распространенный модуль RTC, продающийся, например, в «Амперке» Он самый малогабаритный из всех, однако рассчитан на редко встречающуюся в рознице батарейку типоразмера 1225. Несколько более громоздкий модуль, рассчитанный на стандартную CR2032 (к тому же большей емкости), продается в «Чипе-Дипе» Он основан на версии тех же часов под названием M41T56 от STMicroelectronics. Библиотека DS1307.h (ее можно скачать на этой странице), которую мы будем использовать далее, полностью совместима с M41T56 и опыт показал, что модуль работает даже стабильнее оригинального.

matrix_display
Внешний вид платы часов c матричными индикаторами.

Обратите внимание, что, в отличие от семисегментных, в индикаторах отсутствует разделительное поле справа и слева, они рассчитаны на возможность составлять непрерывные матрицы большего размера. Это, однако, приводит к тому, что символы шрифта 5х7 сливаются, потому индикаторы установлены с некоторым промежутком. Видимый на фото концевик, прикрученный к плате справа, не имеет отношения к нашей теме — он пробовался в усложненном варианте программы для вывода других параметров на тот же дисплей. Контакты I2C-интерфейса модуля RTC подключаются к тем же выводам Arduino A4 и A5, параллельно драйверу дисплея.
Полную программу для такого варианта часов можно скачать с сайта автора по этой ссылке. Обратите внимание, что там пришлось дополнительно вводить функцию decToBcd для распаковки значений часов и минут, чтобы иметь возможность вывести цифры поразрядно — это очень важный нюанс, который придется учитывать во всех случаях вывода многоразрядных чисел на такой дисплей.
Второй нюанс заключается в том, что как минимум при первом запуске часы необходимо установить на текущее время. Это можно сделать из той же программы, если сначала раскомментировать соответствующие строки в секции setup, ввести в них значения времени, загрузить программу, потом закомментировать их снова и заново загрузить уже окончательный вариант. О том, как можно оформить процедуру установки часов через последовательный порт, читайте в 3-м издании моей книги «Занимательная электроника».
Если будут вопросы, пишите автору по адресу revich@lib.ru.


Оставить комментарий

Ваш email не будет опубликован. Обязательные поля отмечены *


Вы можете использовать это HTMLтеги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>