Месяц с небольшим назад я рассказывал о таком девайсе как МС6205. Тема подобных экранов меня заинтересовала, и вот ко мне в руки попал другой экземпляр, однострочный и с более простым управлением. Тем не менее, несмотря на схожий вид, внутри он устроен совершенно иначе — если в МС6205 был матричный индикатор, то тут используется панель с самосканированием. Как же оно работает и как это запустить? Давайте разбираться.
Итак, в сегодняшней статье поговорим о семействе советских текстовых индикаторов ПИУ. Узнаем, как они устроены и как работают. Попутно поговорим о текстовых газоразрядных дисплеях с самосканированием. Традиционно будет много интересного.
❯ Суть такова
Началась эта история ещё в 2022 году, когда я услышал про существование такого устройства как ПИУ-2 и немедленно захотел себе такой экземпляр. Девайс был куплен без промедления, интереса ради. Далее последовали выпившие немало моей крови попытки его подключения, которыми я наконец и решил поделиться.
ПИУ-1 и ПИУ-2 — две модели индикаторных приборов, использовавшихся в неком оборудовании (мне так и не удалось выяснить, где именно, но, по слухам, стояли такие где-то на ЖД). Оба этих девайса имеют схожую конструкцию и отличаются лишь кодовой таблицей. Так что практически всё, что будет сказано тут, применимо и к ПИУ-1.
❯ Обзор оборудования
Так уж вышло, что в моих руках побывали два ПИУ — ранней и поздней версии.
Общий вид первого экземпляра. Здесь только индикаторный модуль. Также по бокам должны были располагаться два крепёжных ушка, но у моего прибора они замяты.
На обратной стороне разъём, клемма заземления, крепёжные винты (один из которых под пломбой) и заводская табличка. Как и практически все интересные и необычные советские приборы индикации, выпускался девайс на ровненском «Газотроне».
Снимем кожух. Внутри металлическая рама, к которой прикручены плата, панель и разъём.
С обратной стороны ничего интересного.
Плата. На ней вся электроника — чипы логики, память, ПЗУшка с таблицей символов и импульсный преобразователь для питания панели.
Разъём, связывающий панель с внешним миром. Почему-то очень сложно было найти какую-то информацию на этот счёт, так что оставлю тут для потомков: ответная его часть называется 2РМ30КПН32Г5В1В.
Панель представляет собой законченный модуль, соединённый с платой разъёмом МРН. Состоит он из стеклянного индикатора, рамки и платы, к которой он подключается.
Интересно то, как подключается непосредственно стеклянная колба к плате — тоненькими проволочками-волосинками, которые легко сминаются и рвутся. Для защиты от жизненных ударов щели заклеены полоской липкой ленты.
А вот более старая панель. Внешне отличия заметны не особо…
С обратной стороны отличие лишь в годе выпуска — 1983. Также видно, что изолятор в разъёме на этот раз карболитовый.
Вскрываем. Внутри это совершенно иное устройство, построенное уже на двух платах. Эти платы вставляются в слоты, позволяющие при необходимости вытащить какую-либо из них без паяльника.
Первая плата — низковольтная. На ней расположена управляющая логика и ПЗУшки.
Вторая — высоковольтная. Здесь преобразователь, выдающий все необходимые для питания панели напряжения, а также транзисторные сборки, призванные управлять анодами и катодами индикатора. Интересное схемотехническое решение в виде дорожки-спиральки — явно какая-то катушка низкой индуктивности.
Шасси со снятыми платами.
Оба модуля втыкаются в расположенную на боковой стенке кросс-плату. От неё же расходятся жгуты проводов к разъёму и индикатору. К слову, о разъёме. Вместо ОНЦ здесь стоит другой разъём — 2РМ30Б32Ш5В1В. Впрочем, ответная часть к нему та же самая.
Те самые слоты.
Разъём МРН, через который подключается индикатор.
Индикатор отдельно. От рассмотренного ранее он не отличается ничем.
❯ Как работает ПИУ
Вообще, по своей структуре ПИУ во многом схож с МС6205 — здесь тоже есть преобразователь питания, генератор импульсов, знакогенератор, блок интерфейса и подобная логика. Но вот индикаторы тут стоят совершенно иные. Это так называемые газоразрядные индикаторы с самосканированием.
Вообще, если вы никогда не интересовались подобным железом, то вид матричного индикатора, способного работать всего по двенадцати проводам, уже способен заинтересовать. А уж упоминание того, что прибор этот не содержит ни единого полупроводника, и вовсе поставит в ступор обывателя.
Наиболее доходчиво о работе таких ГРИ рассказывал товарищ radiolok. Я сам узнал об этих индикаторах, посмотрев этот ролик, после чего немедленно захотел себе какой-то законченный девайс на базе такой панели. Именно им и стал ПИУ.
Принцип работы таких панелей очень схож с декатронами, а также (немного) с газоразрядным индикатором ИН-33. Помимо обычных анодов и катодов девайс имеет вспомогательные аноды (аноды сканирования). Если последовательно подавать импульсы между группой анодов сканирования и одной из групп катодов, то можно получить разряд, последовательно проходящий все столбцы индикатора. Если в момент, когда разряд сканирования горит в некотором положении (которое можно однозначно отсчитать благодаря наличию отдельно выведенного катода сброса, с которого начинается прохождение разряда по столбцам), подать импульс на анод сканирования, то в выбранной строке этого столбца загорится точка. Таким образом, для работы индикатора необходима схема сканирования, которая постоянно будет проходить по всей панели, и схема индикации, которая, зная, где сейчас находится разряд (благодаря работе от того же тактового генератора) может включать и выключать аноды индикации.
❯ В чём разница между ПИУ-1 и ПИУ-2
Изначально я думал, что эти две модели — разные ревизии одного и того же прибора. Но всё оказалось куда интереснее. Первая и вторая версия отличаются кодовой таблицей.
У ПИУ-1 она такая.
А у ПИУ-2 — вот такая.
По просторам гуляют две документации: одна называется «ПИУ-1: паспорт, техническое описание и руководство по эксплуатации», другая — «Приборы индикаторные универсальные ПИУ-1, ПИУ-2: паспорт, техническое описание и руководство по эксплуатации». При этом они описывают по сути два совершенно разных по схемотехнике устройства. Первая рассказывает про более старую версию, имеющую внутри два слотовых модуля и кросс-плату, вторая — про поздний вариант, собранный на одной плате. Помимо этого в первой инструкции детально описаны некоторые аспекты работы устройства в синхронном и асинхронном режимах (в документации к ПИУ-2 эти моменты скромно опущены). Чтобы вам не пришлось искать эти архивы среди кучи битых, ссылку на них я дам чуть позже.
❯ Первый запуск
Итак, самое время приступить к экспериментам.
Берём ответную часть разъёма и припаиваем провода. Распиновка есть в документации.
Но, увы, при попытке что-то вывести меня ждала неудача — на экране отображался один и тот же символ. Последующие проверки показали, что в индикаторе, судя по всему, вылетела ПЗушка, так как адресный счётчик работал исправно. Я понятия не имею, где взять такую же, чем её прошить и какой прошивкой, так что разбирательства с этим индикатором я забросил, а через полгода его лежания у меня и вовсе продал.
Также именно упомянутый экземпляр успел засветиться в ролике всё того же radiolok, где на 2:37 показаны внутренности моего ПИУ. Этими фотографиями я поделился в чатике давным-давно, и вот они наконец пригодились.
❯ Подключение
Так уж вышло, что детального описания работы ПИУ практически нигде нет. Есть, конечно, документация (причём сразу в двух версиях), но на этом всё. Поэтому сейчас я расскажу о том, как же вообще работает эта штука с точки зрения программиста микроконтроллеров.
Начнём, конечно же, с разъёма. Предыдущая ответная часть ушла вместе с неисправной панелью, пришлось намутить другой. Как оказалось, за минувший год такие разъёмы в местном магазине радиодеталей кончились, пришлось купить у сборщика металла. На этот раз он уже был частью какого-то жгута (если вдруг это условное обозначение вам о чём-то говорит, напишите в комментариях).
Разбираем разъём и выпаиваем остатки проводов. Их, разумеется, не выкидываем — ещё пригодятся.
Теперь можно перейти к распиновке самого блока. Она здесь оказалась вот такая:
- X8
- Первая строка
- X7
- Вторая строка
- X6
- Третья строка
- X5
- Четвёртая строка
- X4
- Пятая строка
- X3
- Шестая строка
- X2
- Седьмая строка
- X1
- Ничего
- Гашение
- Синхросигнал
- Запись/индикация
- Импульсы сброса
- Строб
- Ничего
- Сброс
- 5 В
- Управление яркостью
- -12,6 В
- Ничего
- Ничего
- Ничего
- Земля
- Ничего
- Масса
Для питания требуется два напряжения — +5 и -12,6 В. Взять их можно, разумеется, в компьютерном БП. Как показала практика, от -12 В он девайс тоже отлично стартует.
Если просто подать питание, девайс тоже должен запуститься — послышится тихое пищание преобразователя, а экран очень тускло засветится оранжевым — именно так выглядит процесс сканирования. Для примера фото я сделал в темноте при большой выдержке и почти полностью открытой диафрагме, в реальности увидеть это свечение получится только если приглядываться.
❯ Синхронный и асинхронный режим
Индикатор может работать в двух режимах — синхронном и асинхронном.
В асинхронном режиме ПИУ находится в одном из двух состояний. Когда на контакте 19 разъёма присутствует высокий уровень, управляющая схема ожидает поступления на вход данных. Когда напряжение снимается, прибор переходит в режим индикации.
В синхронном режиме контакт 19 всегда заземлён, а отображаемая информация обновляется сразу при поступлении новых данных. Именно этот режим мы и задействуем.
❯ Пишем первую программу
Памятуя о жёстких глюках неясной природы при подключении МС6205 напрямую к выводам МК, я решил и тут использовать сдвиговый регистр. Подключение, таким образом, очень простое — строб и сброс к выводам МК, X1...X8 — к Q0...Q7 регистра. В качестве управляющего девайса была взята всё та же тестовая ардуино.
Саму микросхему удалось уместить внутри разъёма.
Теперь о программе. Для начала необходимо сбросить экран (после чего он погаснет), после чего последовательно загрузить в регистр каждый символ, не забывая после этого дёргать строб. У ПИУ нет шины адреса как у МС6205, он работает по сути как обычный дисплей 1602: выставляем на шине код, после чего даём высокий уровень на строб. Для программиста единственное отличие лишь в том, что у HD44780 строб по спаду сигнала, а также есть поддержка управляющих команд, тогда как единственная команда, которую знает ПИУ, — это считать код символа с восьмибитной шины и протолкнуть его в буфер. Программа для этого получилась вот такая:
#define CLOCK 5 //SH_CP
#define DATA 6 //DS
#define LATCH 7 //ST_CP
#define STROBE 4
#define RESET 3
void setup() {
pinMode(CLOCK, OUTPUT);
pinMode(DATA, OUTPUT);
pinMode(LATCH, OUTPUT);
pinMode(STROBE, OUTPUT);
pinMode(RESET, OUTPUT);
digitalWrite(LATCH, HIGH);
digitalWrite(STROBE, LOW);
digitalWrite(RESET, LOW);
delay(300);
digitalWrite(RESET, HIGH);
Serial.begin(115200);
Serial.println("test");
showString("priwet, habr");
}
void sendData(uint8_t toLCD) {
digitalWrite(LATCH, LOW);
shiftOut(DATA, CLOCK, MSBFIRST, toLCD);
digitalWrite(LATCH, HIGH);
delay(10);
digitalWrite(STROBE, HIGH);
delay(1);
digitalWrite(STROBE, LOW);
}
void showString(String data) {
for (int i = 0; i < data.length(); i++) {
sendData(data[i]);
}
}
void loop() {
}
Прибор работает в кодировке КОИ-7, что тоже надо учитывать.
Остаётся только залить её, и, если ПИУ живой, на экране должно будет появиться примерно следующее:
Наконец-то оно работает!
❯ Немного про ГТИ и внешний знакогенератор
У индикатора имеется возможность управления полностью извне. Оно позволяет использовать ПИУ при отсутствии возможности подключить его по штатному интерфейсу, а также если встроенный знакогенератор сдох.
Для этого индикатор обладает выводами управления строками, ГТИ и импульсов сброса.
Контакты 2, 4, 6, 8, 10, 12, 14 служат для непосредственного включения или выключения пикселей в столбце. ГТИ — генератор тактовых импульсов, от которого работает схема сканирования. В момент смены уровня этого сигнала с высокого на низкий происходит считывание данных с выводов управления строками. Контакт импульсов сброса нужен для определения начала панели — на нём появляется низкий уровень в тот момент, когда сканирующий разряд проходит «нулевой» катод.
И при попытке запустить индикатор в таком режиме можно наглядно увидеть, насколько же всё-таки слабо работает Arduino! «Медленные» digitalWrite не справляются с таким переключением, отчего изображение размазывается.
const uint8_t System5x7C[156][5] = {
{0x00, 0x00, 0x00, 0x00, 0x00},// (space)
{0x00, 0x00, 0x5F, 0x00, 0x00},// !
{0x00, 0x07, 0x00, 0x07, 0x00},// "
{0x14, 0x7F, 0x14, 0x7F, 0x14},// #
{0x24, 0x2A, 0x7F, 0x2A, 0x12},// $
{0x23, 0x13, 0x08, 0x64, 0x62},// %
{0x36, 0x49, 0x55, 0x22, 0x50},// &
{0x00, 0x05, 0x03, 0x00, 0x00},// '
{0x00, 0x1C, 0x22, 0x41, 0x00},// (
{0x00, 0x41, 0x22, 0x1C, 0x00},// )
{0x08, 0x2A, 0x1C, 0x2A, 0x08},// *
{0x08, 0x08, 0x3E, 0x08, 0x08},// +
{0x00, 0x50, 0x30, 0x00, 0x00},// ,
{0x08, 0x08, 0x08, 0x08, 0x08},// -
{0x00, 0x60, 0x60, 0x00, 0x00},// .
{0x20, 0x10, 0x08, 0x04, 0x02},// /
{0x3E, 0x51, 0x49, 0x45, 0x3E},// 0
{0x00, 0x42, 0x7F, 0x40, 0x00},// 1
{0x42, 0x61, 0x51, 0x49, 0x46},// 2
{0x21, 0x41, 0x45, 0x4B, 0x31},// 3
{0x18, 0x14, 0x12, 0x7F, 0x10},// 4
{0x27, 0x45, 0x45, 0x45, 0x39},// 5
{0x3C, 0x4A, 0x49, 0x49, 0x30},// 6
{0x01, 0x71, 0x09, 0x05, 0x03},// 7
{0x36, 0x49, 0x49, 0x49, 0x36},// 8
{0x06, 0x49, 0x49, 0x29, 0x1E},// 9
{0x00, 0x36, 0x36, 0x00, 0x00},// :
{0x00, 0x56, 0x36, 0x00, 0x00},// ;
{0x00, 0x08, 0x14, 0x22, 0x41},// <
{0x14, 0x14, 0x14, 0x14, 0x14},// =
{0x41, 0x22, 0x14, 0x08, 0x00},// >
{0x02, 0x01, 0x51, 0x09, 0x06},// ?
{0x32, 0x49, 0x79, 0x41, 0x3E},// @
{0x7E, 0x11, 0x11, 0x11, 0x7E},// A
{0x7F, 0x49, 0x49, 0x49, 0x36},// B
{0x3E, 0x41, 0x41, 0x41, 0x22},// C
{0x7F, 0x41, 0x41, 0x22, 0x1C},// D
{0x7F, 0x49, 0x49, 0x49, 0x41},// E
{0x7F, 0x09, 0x09, 0x01, 0x01},// F
{0x3E, 0x41, 0x41, 0x51, 0x32},// G
{0x7F, 0x08, 0x08, 0x08, 0x7F},// H
{0x00, 0x41, 0x7F, 0x41, 0x00},// I
{0x20, 0x40, 0x41, 0x3F, 0x01},// J
{0x7F, 0x08, 0x14, 0x22, 0x41},// K
{0x7F, 0x40, 0x40, 0x40, 0x40},// L
{0x7F, 0x02, 0x04, 0x02, 0x7F},// M
{0x7F, 0x04, 0x08, 0x10, 0x7F},// N
{0x3E, 0x41, 0x41, 0x41, 0x3E},// O
{0x7F, 0x09, 0x09, 0x09, 0x06},// P
{0x3E, 0x41, 0x51, 0x21, 0x5E},// Q
{0x7F, 0x09, 0x19, 0x29, 0x46},// R
{0x46, 0x49, 0x49, 0x49, 0x31},// S
{0x01, 0x01, 0x7F, 0x01, 0x01},// T
{0x3F, 0x40, 0x40, 0x40, 0x3F},// U
{0x1F, 0x20, 0x40, 0x20, 0x1F},// V
{0x7F, 0x20, 0x18, 0x20, 0x7F},// W
{0x63, 0x14, 0x08, 0x14, 0x63},// X
{0x03, 0x04, 0x78, 0x04, 0x03},// Y
{0x61, 0x51, 0x49, 0x45, 0x43},// Z
{0x00, 0x00, 0x7F, 0x41, 0x41},// [
{0x02, 0x04, 0x08, 0x10, 0x20},// ""
{0x41, 0x41, 0x7F, 0x00, 0x00},// ]
{0x04, 0x02, 0x01, 0x02, 0x04},// ^
{0x40, 0x40, 0x40, 0x40, 0x40},// _
{0x00, 0x01, 0x02, 0x04, 0x00},// `
{0x20, 0x54, 0x54, 0x54, 0x78},// a
{0x7F, 0x48, 0x44, 0x44, 0x38},// b
{0x38, 0x44, 0x44, 0x44, 0x20},// c
{0x38, 0x44, 0x44, 0x48, 0x7F},// d
{0x38, 0x54, 0x54, 0x54, 0x18},// e
{0x08, 0x7E, 0x09, 0x01, 0x02},// f
{0x08, 0x14, 0x54, 0x54, 0x3C},// g
{0x7F, 0x08, 0x04, 0x04, 0x78},// h
{0x00, 0x44, 0x7D, 0x40, 0x00},// i
{0x20, 0x40, 0x44, 0x3D, 0x00},// j
{0x00, 0x7F, 0x10, 0x28, 0x44},// k
{0x00, 0x41, 0x7F, 0x40, 0x00},// l
{0x7C, 0x04, 0x18, 0x04, 0x78},// m
{0x7C, 0x08, 0x04, 0x04, 0x78},// n
{0x38, 0x44, 0x44, 0x44, 0x38},// o
{0x7C, 0x14, 0x14, 0x14, 0x08},// p
{0x08, 0x14, 0x14, 0x18, 0x7C},// q
{0x7C, 0x08, 0x04, 0x04, 0x08},// r
{0x48, 0x54, 0x54, 0x54, 0x20},// s
{0x04, 0x3F, 0x44, 0x40, 0x20},// t
{0x3C, 0x40, 0x40, 0x20, 0x7C},// u
{0x1C, 0x20, 0x40, 0x20, 0x1C},// v
{0x3C, 0x40, 0x30, 0x40, 0x3C},// w
{0x44, 0x28, 0x10, 0x28, 0x44},// x
{0x0C, 0x50, 0x50, 0x50, 0x3C},// y
{0x44, 0x64, 0x54, 0x4C, 0x44},// z
{0x00, 0x08, 0x36, 0x41, 0x00},// {
{0x00, 0x00, 0x7F, 0x00, 0x00},// |
{0x00, 0x41, 0x36, 0x08, 0x00},// }
{0x08, 0x08, 0x2A, 0x1C, 0x08},// ->
{0x08, 0x1C, 0x2A, 0x08, 0x08}, // <-
{0x7E, 0x11, 0x11, 0x11, 0x7E},// A
{0x7F, 0x49, 0x49, 0x49, 0x30},// Б
{0x7F, 0x49, 0x49, 0x49, 0x36},// B
{0x7F, 0x01, 0x01, 0x01, 0x01},// Г
{0x60, 0x3F, 0x21, 0x3F, 0x60},// Д
{0x7F, 0x49, 0x49, 0x49, 0x41},// E
{0x63, 0x14, 0x7F, 0x14, 0x63},// Ж
{0x49, 0x49, 0x49, 0x49, 0x36},// З
{0x7F, 0x10, 0x08, 0x04, 0x7F},// И
{0x7F, 0x10, 0x09, 0x04, 0x7F},// Й
{0x7F, 0x08, 0x14, 0x22, 0x41},// К
{0x40, 0x3F, 0x01, 0x01, 0x7F},// Л
{0x7F, 0x02, 0x04, 0x02, 0x7F},// М
{0x7F, 0x08, 0x08, 0x08, 0x7F},// H
{0x3E, 0x41, 0x41, 0x41, 0x3E},// O
{0x7F, 0x01, 0x01, 0x01, 0x7F},// П
{0x7F, 0x09, 0x09, 0x09, 0x06},// P
{0x3E, 0x41, 0x41, 0x41, 0x22},// C
{0x01, 0x01, 0x7F, 0x01, 0x01},// T
{0x63, 0x14, 0x08, 0x04, 0x03},// У
{0x3E, 0x41, 0x7F, 0x41, 0x3E},// Ф
{0x63, 0x14, 0x08, 0x14, 0x63},// X
{0x3F, 0x20, 0x20, 0x3F, 0x60},// Ц
{0x07, 0x08, 0x08, 0x08, 0x7F},// Ч
{0x7F, 0x40, 0x7F, 0x40, 0x7F},// Ш
{0x3F, 0x20, 0x3F, 0x20, 0x7F},// Щ
{0x01, 0x7F, 0x48, 0x48, 0x30},// Ъ
{0x3C, 0x41, 0x42, 0x20, 0x7C},// ѝ
{0x7F, 0x08, 0x3E, 0x41, 0x3E},// Ю
{0x46, 0x29, 0x19, 0x09, 0x7F},// Я
{0x20, 0x54, 0x54, 0x54, 0x78},// а
{0x7E, 0x49, 0x45, 0x45, 0x39},// б
{0x7C, 0x54, 0x54, 0x58, 0x20},// в
{0x7C, 0x04, 0x04, 0x04, 0x04},// г
{0x08, 0x14, 0x54, 0x54, 0x3C},// д
{0x38, 0x54, 0x54, 0x54, 0x18},// е
{0x44, 0x28, 0x7C, 0x28, 0x44},// ж
{0x54, 0x54, 0x54, 0x54, 0x28},// з
{0x3C, 0x40, 0x40, 0x20, 0x7C},// и
{0x3C, 0x41, 0x42, 0x21, 0x7C},// й
{0x00, 0x7C, 0x10, 0x28, 0x44},// к
{0x40, 0x3C, 0x04, 0x04, 0x7C},// л
{0x7C, 0x08, 0x10, 0x08, 0x7C},// м
{0x00, 0x7C, 0x10, 0x10, 0x7C},// н
{0x38, 0x44, 0x44, 0x44, 0x38},// о
{0x00, 0x7C, 0x04, 0x04, 0x7C},// п
{0x7C, 0x14, 0x14, 0x14, 0x08},// р
{0x38, 0x44, 0x44, 0x44, 0x20},// с
{0x04, 0x04, 0x7C, 0x04, 0x04},// т
{0x0C, 0x50, 0x50, 0x50, 0x3C},// у
{0x38, 0x44, 0x7C, 0x44, 0x38},// ф
{0x44, 0x28, 0x10, 0x28, 0x44},// х
{0x3C, 0x20, 0x20, 0x3C, 0x60},// ц
{0x00, 0x0C, 0x10, 0x10, 0x7C},// ч
{0x7C, 0x40, 0x7C, 0x40, 0x7C},// ш
{0x3C, 0x20, 0x3C, 0x20, 0x7C},// щ
{0x04, 0x7C, 0x50, 0x50, 0x30},// ъ
{0x00, 0x7C, 0x50, 0x50, 0x30},// ь
{0x7C, 0x10, 0x38, 0x44, 0x38},// ю
{0x48, 0x34, 0x14, 0x14, 0x7C} // я
};
#define PANEL_RESET 2
#define PANEL_CLK 3
#define PANEL_D0 47
#define PANEL_D1 45
#define PANEL_D2 43
#define PANEL_D3 41
#define PANEL_D4 39
#define PANEL_D5 37
#define PANEL_D6 35
volatile uint8_t n = 0;
volatile uint8_t lines[111];
void changeN() {
n++;
panelWrite(lines[n]);
}
void panelInit() {
n = 0;
panelWrite(0x00);
}
void panelWrite(uint8_t toPanel) {
digitalWrite(PANEL_D0, (toPanel >> 0) & 1);
digitalWrite(PANEL_D1, (toPanel >> 1) & 1);
digitalWrite(PANEL_D2, (toPanel >> 2) & 1);
digitalWrite(PANEL_D3, (toPanel >> 3) & 1);
digitalWrite(PANEL_D4, (toPanel >> 4) & 1);
digitalWrite(PANEL_D5, (toPanel >> 5) & 1);
digitalWrite(PANEL_D6, (toPanel >> 6) & 1);
}
void setup() {
// put your setup code here, to run once:
pinMode(31, OUTPUT);
pinMode(47, OUTPUT);
pinMode(35, OUTPUT);
pinMode(37, OUTPUT);
pinMode(39, OUTPUT);
pinMode(41, OUTPUT);
pinMode(43, OUTPUT);
pinMode(45, OUTPUT);
for (int i = 0; i < 111; i++) lines[i] = 0x00;
Serial.begin(115200);
String s = "";
while(!Serial.available());;
s = Serial.readStringUntil('r');
Serial.println(s);
int index = 3;
for(int i = 0; i < s.length(); i++) {
for(int t = 0; t < 5; t++) {
lines[index] = System5x7C[s[i] - 0x20][t];
index++;
}
index += 3;
}
for(int i = 0; i < 111; i++) Serial.println(lines[i],HEX);
attachInterrupt(digitalPinToInterrupt(3), changeN, FALLING);
attachInterrupt(digitalPinToInterrupt(2), panelInit, FALLING);
}
void loop() {
// put your main code here, to run repeatedly:
}
{0x00, 0x00, 0x00, 0x00, 0x00},// (space)
{0x00, 0x00, 0x5F, 0x00, 0x00},//!
{0x00, 0x07, 0x00, 0x07, 0x00},// "
{0x14, 0x7F, 0x14, 0x7F, 0x14},// #
{0x24, 0x2A, 0x7F, 0x2A, 0x12},// $
{0x23, 0x13, 0x08, 0x64, 0x62},// %
{0x36, 0x49, 0x55, 0x22, 0x50},// &
{0x00, 0x05, 0x03, 0x00, 0x00},// '
{0x00, 0x1C, 0x22, 0x41, 0x00},// (
{0x00, 0x41, 0x22, 0x1C, 0x00},// )
{0x08, 0x2A, 0x1C, 0x2A, 0x08},// *
{0x08, 0x08, 0x3E, 0x08, 0x08},// +
{0x00, 0x50, 0x30, 0x00, 0x00},//,
{0x08, 0x08, 0x08, 0x08, 0x08},// — {0x00, 0x60, 0x60, 0x00, 0x00},//.
{0x20, 0x10, 0x08, 0x04, 0x02},// /
{0x3E, 0x51, 0x49, 0x45, 0x3E},// 0
{0x00, 0x42, 0x7F, 0x40, 0x00},// 1
{0x42, 0x61, 0x51, 0x49, 0x46},// 2
{0x21, 0x41, 0x45, 0x4B, 0x31},// 3
{0x18, 0x14, 0x12, 0x7F, 0x10},// 4
{0x27, 0x45, 0x45, 0x45, 0x39},// 5
{0x3C, 0x4A, 0x49, 0x49, 0x30},// 6
{0x01, 0x71, 0x09, 0x05, 0x03},// 7
{0x36, 0x49, 0x49, 0x49, 0x36},// 8
{0x06, 0x49, 0x49, 0x29, 0x1E},// 9
{0x00, 0x36, 0x36, 0x00, 0x00},//:
{0x00, 0x56, 0x36, 0x00, 0x00},//;
{0x00, 0x08, 0x14, 0x22, 0x41},// <
{0x14, 0x14, 0x14, 0x14, 0x14},// =
{0x41, 0x22, 0x14, 0x08, 0x00},// >
{0x02, 0x01, 0x51, 0x09, 0x06},//?
{0x32, 0x49, 0x79, 0x41, 0x3E},// @
{0x7E, 0x11, 0x11, 0x11, 0x7E},// A
{0x7F, 0x49, 0x49, 0x49, 0x36},// B
{0x3E, 0x41, 0x41, 0x41, 0x22},// C
{0x7F, 0x41, 0x41, 0x22, 0x1C},// D
{0x7F, 0x49, 0x49, 0x49, 0x41},// E
{0x7F, 0x09, 0x09, 0x01, 0x01},// F
{0x3E, 0x41, 0x41, 0x51, 0x32},// G
{0x7F, 0x08, 0x08, 0x08, 0x7F},// H
{0x00, 0x41, 0x7F, 0x41, 0x00},// I
{0x20, 0x40, 0x41, 0x3F, 0x01},// J
{0x7F, 0x08, 0x14, 0x22, 0x41},// K
{0x7F, 0x40, 0x40, 0x40, 0x40},// L
{0x7F, 0x02, 0x04, 0x02, 0x7F},// M
{0x7F, 0x04, 0x08, 0x10, 0x7F},// N
{0x3E, 0x41, 0x41, 0x41, 0x3E},// O
{0x7F, 0x09, 0x09, 0x09, 0x06},// P
{0x3E, 0x41, 0x51, 0x21, 0x5E},// Q
{0x7F, 0x09, 0x19, 0x29, 0x46},// R
{0x46, 0x49, 0x49, 0x49, 0x31},// S
{0x01, 0x01, 0x7F, 0x01, 0x01},// T
{0x3F, 0x40, 0x40, 0x40, 0x3F},// U
{0x1F, 0x20, 0x40, 0x20, 0x1F},// V
{0x7F, 0x20, 0x18, 0x20, 0x7F},// W
{0x63, 0x14, 0x08, 0x14, 0x63},// X
{0x03, 0x04, 0x78, 0x04, 0x03},// Y
{0x61, 0x51, 0x49, 0x45, 0x43},// Z
{0x00, 0x00, 0x7F, 0x41, 0x41},// [
{0x02, 0x04, 0x08, 0x10, 0x20},// ""
{0x41, 0x41, 0x7F, 0x00, 0x00},// ]
{0x04, 0x02, 0x01, 0x02, 0x04},// ^
{0x40, 0x40, 0x40, 0x40, 0x40},// _
{0x00, 0x01, 0x02, 0x04, 0x00},// `
{0x20, 0x54, 0x54, 0x54, 0x78},// a
{0x7F, 0x48, 0x44, 0x44, 0x38},// b
{0x38, 0x44, 0x44, 0x44, 0x20},// c
{0x38, 0x44, 0x44, 0x48, 0x7F},// d
{0x38, 0x54, 0x54, 0x54, 0x18},// e
{0x08, 0x7E, 0x09, 0x01, 0x02},// f
{0x08, 0x14, 0x54, 0x54, 0x3C},// g
{0x7F, 0x08, 0x04, 0x04, 0x78},// h
{0x00, 0x44, 0x7D, 0x40, 0x00},// i
{0x20, 0x40, 0x44, 0x3D, 0x00},// j
{0x00, 0x7F, 0x10, 0x28, 0x44},// k
{0x00, 0x41, 0x7F, 0x40, 0x00},// l
{0x7C, 0x04, 0x18, 0x04, 0x78},// m
{0x7C, 0x08, 0x04, 0x04, 0x78},// n
{0x38, 0x44, 0x44, 0x44, 0x38},// o
{0x7C, 0x14, 0x14, 0x14, 0x08},// p
{0x08, 0x14, 0x14, 0x18, 0x7C},// q
{0x7C, 0x08, 0x04, 0x04, 0x08},// r
{0x48, 0x54, 0x54, 0x54, 0x20},// s
{0x04, 0x3F, 0x44, 0x40, 0x20},// t
{0x3C, 0x40, 0x40, 0x20, 0x7C},// u
{0x1C, 0x20, 0x40, 0x20, 0x1C},// v
{0x3C, 0x40, 0x30, 0x40, 0x3C},// w
{0x44, 0x28, 0x10, 0x28, 0x44},// x
{0x0C, 0x50, 0x50, 0x50, 0x3C},// y
{0x44, 0x64, 0x54, 0x4C, 0x44},// z
{0x00, 0x08, 0x36, 0x41, 0x00},// {
{0x00, 0x00, 0x7F, 0x00, 0x00},// |
{0x00, 0x41, 0x36, 0x08, 0x00},// }
{0x08, 0x08, 0x2A, 0x1C, 0x08},// ->
{0x08, 0x1C, 0x2A, 0x08, 0x08}, // < — {0x7E, 0x11, 0x11, 0x11, 0x7E},// A
{0x7F, 0x49, 0x49, 0x49, 0x30},// Б
{0x7F, 0x49, 0x49, 0x49, 0x36},// B
{0x7F, 0x01, 0x01, 0x01, 0x01},// Г
{0x60, 0x3F, 0x21, 0x3F, 0x60},// Д
{0x7F, 0x49, 0x49, 0x49, 0x41},// E
{0x63, 0x14, 0x7F, 0x14, 0x63},// Ж
{0x49, 0x49, 0x49, 0x49, 0x36},// З
{0x7F, 0x10, 0x08, 0x04, 0x7F},// И
{0x7F, 0x10, 0x09, 0x04, 0x7F},// Й
{0x7F, 0x08, 0x14, 0x22, 0x41},// К
{0x40, 0x3F, 0x01, 0x01, 0x7F},// Л
{0x7F, 0x02, 0x04, 0x02, 0x7F},// М
{0x7F, 0x08, 0x08, 0x08, 0x7F},// H
{0x3E, 0x41, 0x41, 0x41, 0x3E},// O
{0x7F, 0x01, 0x01, 0x01, 0x7F},// П
{0x7F, 0x09, 0x09, 0x09, 0x06},// P
{0x3E, 0x41, 0x41, 0x41, 0x22},// C
{0x01, 0x01, 0x7F, 0x01, 0x01},// T
{0x63, 0x14, 0x08, 0x04, 0x03},// У
{0x3E, 0x41, 0x7F, 0x41, 0x3E},// Ф
{0x63, 0x14, 0x08, 0x14, 0x63},// X
{0x3F, 0x20, 0x20, 0x3F, 0x60},// Ц
{0x07, 0x08, 0x08, 0x08, 0x7F},// Ч
{0x7F, 0x40, 0x7F, 0x40, 0x7F},// Ш
{0x3F, 0x20, 0x3F, 0x20, 0x7F},// Щ
{0x01, 0x7F, 0x48, 0x48, 0x30},// Ъ
{0x3C, 0x41, 0x42, 0x20, 0x7C},// ѝ
{0x7F, 0x08, 0x3E, 0x41, 0x3E},// Ю
{0x46, 0x29, 0x19, 0x09, 0x7F},// Я
{0x20, 0x54, 0x54, 0x54, 0x78},// а
{0x7E, 0x49, 0x45, 0x45, 0x39},// б
{0x7C, 0x54, 0x54, 0x58, 0x20},// в
{0x7C, 0x04, 0x04, 0x04, 0x04},// г
{0x08, 0x14, 0x54, 0x54, 0x3C},// д
{0x38, 0x54, 0x54, 0x54, 0x18},// е
{0x44, 0x28, 0x7C, 0x28, 0x44},// ж
{0x54, 0x54, 0x54, 0x54, 0x28},// з
{0x3C, 0x40, 0x40, 0x20, 0x7C},// и
{0x3C, 0x41, 0x42, 0x21, 0x7C},// й
{0x00, 0x7C, 0x10, 0x28, 0x44},// к
{0x40, 0x3C, 0x04, 0x04, 0x7C},// л
{0x7C, 0x08, 0x10, 0x08, 0x7C},// м
{0x00, 0x7C, 0x10, 0x10, 0x7C},// н
{0x38, 0x44, 0x44, 0x44, 0x38},// о
{0x00, 0x7C, 0x04, 0x04, 0x7C},// п
{0x7C, 0x14, 0x14, 0x14, 0x08},// р
{0x38, 0x44, 0x44, 0x44, 0x20},// с
{0x04, 0x04, 0x7C, 0x04, 0x04},// т
{0x0C, 0x50, 0x50, 0x50, 0x3C},// у
{0x38, 0x44, 0x7C, 0x44, 0x38},// ф
{0x44, 0x28, 0x10, 0x28, 0x44},// х
{0x3C, 0x20, 0x20, 0x3C, 0x60},// ц
{0x00, 0x0C, 0x10, 0x10, 0x7C},// ч
{0x7C, 0x40, 0x7C, 0x40, 0x7C},// ш
{0x3C, 0x20, 0x3C, 0x20, 0x7C},// щ
{0x04, 0x7C, 0x50, 0x50, 0x30},// ъ
{0x00, 0x7C, 0x50, 0x50, 0x30},// ь
{0x7C, 0x10, 0x38, 0x44, 0x38},// ю
{0x48, 0x34, 0x14, 0x14, 0x7C} // я
};
#define PANEL_RESET 2
#define PANEL_CLK 3
#define PANEL_D0 47
#define PANEL_D1 45
#define PANEL_D2 43
#define PANEL_D3 41
#define PANEL_D4 39
#define PANEL_D5 37
#define PANEL_D6 35
volatile uint8_t n = 0;
volatile uint8_t lines[111];
void changeN() {
n++;
PORTC = lines[n];
}
void panelInit() {
n = 0;
PORTC = 0x00;
}
void setup() {
// put your setup code here, to run once:
DDRC = 0xFF;
for (int i = 0; i < 111; i++) lines[i] = 0x00;
Serial.begin(115200);
String s = "";
while(!Serial.available());;
s = Serial.readStringUntil('r');
Serial.println(s);
int index = 3;
for(int i = 0; i < s.length(); i++) {
for(int t = 0; t < 5; t++) {
lines[index] = System5x7C[s[i] — 0x20][t];
index++;
}
index += 3;
}
for(int i = 0; i < 111; i++) Serial.println(lines[i],HEX);
attachInterrupt(digitalPinToInterrupt(3), changeN, FALLING);
attachInterrupt(digitalPinToInterrupt(2), panelInit, FALLING);
}
void loop() {
// put your main code here, to run repeatedly:
}
Смена «медленных» pinMode и digitalWrite на «быструю» работу с портами резко меняет ситуацию к лучшему.
❯ Управление яркостью
25 контакт разъёма — ещё один генератор импульсов, служащий для управления яркостью панели. Если подать высокий уровень на контакт 17, то индикатор погаснет. Но, само собой, если подавать на него сигнал случайной частоты и фазы, то индикатор будет мерцать. Чтобы этого не происходило, существует контакт управления яркостью: импульсы на контакт гашения подаются синхронно с таковыми на 25 выводе, а их длительность позволяет регулировать время горения столбца панели.
❯ Неожиданные глюки
В процессе опытов столкнулся с проблемой, что после прогрева девайсу плохеет — при выводе появляются фантомные символы, сброс не приводит к полному гашению экрана. Предположительно, всему виной электролиты, которые следует поменять все и полностью.
❯ Библиотека для Arduino
Я прекрасно понимаю, что большинство из заинтерсовавшихся, скорее всего, будут использовать ПИУ для сборки часов или другого подобного устройства. Специально для них я привёл все тестовые проги в нормальный вид и написал библиотеку для работы с этим прибором при помощи Arduino. Также в репозитории лежат обе версии документации, упомянутые ранее.
❯ Вот как-то так
При кажущейся простоте ПИУ оказался прибором, не менее интересным, что и МС6205.
По сравнению с цифровыми ГРИ или ВЛИ, проектов на подобных девайсах немного, но они всё же есть. На просторах удалось найти вот такой вот шикарнейший девайс. Индикатор очень круто выглядит и разбавляет уже приевшиеся проекты типа привычных «ИН-12 с синей подсветкой».
Такие дела.
Автор: Лев