Играем в Тетрис на электромеханическом экране

в 11:46, , рубрики: diy или сделай сам, блинкерный экран тетрис, Разработка под Arduino, реверс-инжиниринг, схемотехника

Играем в Тетрис на электромеханическом экране - 1

Однажды, просматривая объявления на Avito, я наткнулся на очень любопытную вещь — блинкерное табло или flip-dot display по-английски. Такие табло используются для отображения информации в аэропортах, вокзалах, стадионах или маршрутоуказателях на общественном транспорте.
Я подумал, что с дисплеем такого типа можно сделать много всего интересного.

Где был установлен мой экран, можно только догадываться по остатку надписи (“АГАЗИН”). Возможно, это был информационный стенд на вокзале или остановке ОТ — пишите ваши идеи в комментариях.

Экран представлял собой матрицу ячеек размером 7 строк на 30 столбцов. Каждая ячейка содержала круглую, вращающуюся двухцветную пластину и светодиод зеленого свечения. На плате имелось некоторое количество логических элементов серии 74HCххx и других микросхем, которых, как выяснилось позже, было почти достаточно для управления экраном через нехитрый последовательный интерфейс.

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

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

Но сначала надо было поставить себе конкретную цель, для чего можно применить этот экран в быту. Первой идеей были часы с отображением расширенной информации о погоде на улице и дома, времени, даты, коротких мотивирующих посланий ;) и т. д. Потом я подумал, что, если повернуть экран на 90о, он здорово напоминает стакан для Тетриса, поэтому было решено сделать Тетрис, а дальше будет видно.

Как же работают электромеханические экраны

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

Играем в Тетрис на электромеханическом экране - 2
Устройство ячейки, источник: Eldi datasheet
Играем в Тетрис на электромеханическом экране - 3
Как происходит поворот диска, источник: Flip-Disc Display

Для удобства управления катушки через два диода объединены в матрицу строк и столбцов. Для переключения любой точки экрана нужно активировать источник тока (current source) на строке и сток тока (current sink) на ряду, на пересечении которых находится катушка электромагнита или, наоборот, для переключения в другую сторону. По сути, это аналогично управлению двигателями постоянного тока через Н-мост, только в импульсном режиме.

Играем в Тетрис на электромеханическом экране - 4

С тем, как управлять флажками в теории, мы разобрались. Пора переходить к практический реализации.

Реверс-инжиниринг экрана

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

Играем в Тетрис на электромеханическом экране - 5

Схема модуля состоит из матрицы светодиодов, катоды которых подключены к LED драйверам Toshiba TB62705. С точки зрения логики управления это обычные 8-битные сдвиговые регистры, соединенные в цепочку. Аноды светодиодов в каждой строке соединены и подключены к стокам MOSFET транзисторов. Истоки подключены к выходу DC-DC преобразователя, а затворы всех 7 транзисторов соединены с выходами дешифратора 3:8 74HC238.

Таким образом, для управления светодиодами нужно выбрать строку экрана, подав ее номер на вход дешифратора, потом загрузить 32 бита данных через SERIAL и CLOCK входы первого LED-драйвера. Затем подать лог. “1” на вход LATCH, и соответствующие светодиоды загорятся на время удержания LATCH в “1”.

Чтобы поморгать светодиодами, я использовал лежащую под рукой arduino-совместимую плату Teensy 3.5. Пример кода управления светодиодами можно найти на GitHub

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

Играем в Тетрис на электромеханическом экране - 6

Силовая часть управления колонками состоит из пары микросхем источника/стока тока (current source/sink), выходы которых соединены через защитные диоды с первым выводом каждой катушки в колонке. В качестве источника тока использована микросхема Toshiba TBD62783, а в качестве стока — любимая многими ULN2803 от TI. Вторые выводы катушек объединены в строки и подключены к разъему на плате экрана. По всей видимости, это было сделано для того, чтобы вынести управление строками в отдельный модуль, так как несколько экранов могут объединяться в один длинный экран. Однако немного непонятно, почему для управления светодиодами разработчики разместили все необходимые компоненты на каждой плате экрана.

Логика состоит из восьми 3:8 дешифраторов 74HC238, управляющие входы которых соединены параллельно. Выходы четных дешифраторов подключены к управляющим входам источников тока, а нечетных — к входам стоков. Разрешающие входы 74HC238 подключены к еще одному 3:8 дешифратору, что позволяет полностью исключить ситуацию, когда одновременно активны микросхемы источника и стока тока. Вход разрешения общего дешифратора подключен к микросхеме компаратора и активируется только при совпадении значений на его входе. Эта часть схемы, скорее всего, также отвечает за объединение нескольких модулей в один большой экран.

Таким образом, для выбора конкретной колонки нужно подать ее номер (0-7) в группе на шину COL_A0-A2, а затем активировать выходы конкретной 74HC238 путем подачи ее номера на входы COL_EN_A0-A2 общего дешифратора. Причем вход A0 можно использовать как признак источник/сток, а оставшиеся 2 бита — как номер группы (0-3).
Входы управляющей логики и питания выведены на два 50-контактных IDC разъема. Распайка одного из них показана на схеме.
Играем в Тетрис на электромеханическом экране - 7
После анализа схемы я понял, что поморгать флажками без помощи Kicad и паяльника, не получится и приступил к созданию модуля выбора строк и сопряжения.

Модуль адаптера и управление строками

Играем в Тетрис на электромеханическом экране - 8

Для упрощения конструкции я решил повторить реализацию выбора колонки и поместил на схему TBD62783 и ULN2803 в паре с дешифраторами 74HC238 для выбора нужной строки, а также одну микросхему логики 74HC00 (4хNAND) для четкого разделения режимов SET, RESET и входа PULSE, непосредственно активирующего подачу напряжения на выбранный электромагнит. Для экономии выводов микроконтроллера было решено подключить сигналы выбора строк и столбцов к выходам одного сдвигового регистра.
В итоге для управления флажком нужно:

  1. послать и зафиксировать его координаты в последовательном коде через SERIAL/CLOCK/LATCH
  2. выбрать желаемое состояние SET/RESET
  3. на короткое время активировать PULSE

Расшифровка байта координат:
Играем в Тетрис на электромеханическом экране - 9

Первая версия схемы без сдвигового регистра была собрана на беспаечной макетной плате. После проверки и небольшого волнения, что все сгорит, я включил питание и подал вручную импульс PULSE быстрым нажатием на кнопку. Ток, протекающий через катушку электромагнита, был на всякий случай ограничен на лабораторном источнике питания. Флажок переключился успешно, и при изменении уровня SET/RESET, переключился обратно. “Это успех”, ‒ подумал я и начал переносить схему на обычную макетную плату, используя любимый МГТФ-0.07 и одножильный kynar-wire для шин питания/земли.

Для подключения к экрану через 50-контактный разъем на плате нужно было задействовать 22 контакта + питание, поэтому возиться с отдельными проводками не хотелось. Напрашивалось использование плоского шлейфа, как для IDE или, скорее, старых SCSI устройств.
Немного гугления навело меня на специальный инструмент для обжима IDC коннекторов, который было решено незамедлительно купить: Кримпер ProsKit 6PK-214 для IDC коннекторов. Потренировавшись на небольших коннекторах, я с первого раза сделал себе 20-сантиметровый шлейф с IDC-50F разъемами на концах.

Пишем управляющую программу

Как я упоминал выше, в качестве управляющего контроллера использовался TEENSY 3.5, средой разработки для которого является Arduino IDE, поэтому программа была написана на arduino диалекте C.

Основная функция изменения состояния точки экрана

void update_dot(bool state, byte row, byte col) {
  byte cmd=0;

  // set 7-5 cmd bits to row 2-0 bits 
  cmd=(row&B111)<<5;
  
  // set 4-0 cmd bits to col 4-0 bits 
  cmd=cmd|(col&B11111);

  // write to Register
  digitalWriteFast(DOT_LATCH,LOW);
  for (byte i=0;i<8;i++) {
    byte onebit=bitRead(cmd,7-i);
    digitalWriteFast(DOT_CLOCK,LOW);
    digitalWriteFast(DOT_SERIAL_DATA,onebit);
    digitalWriteFast(DOT_CLOCK,HIGH);
  }
  digitalWriteFast(DOT_LATCH,HIGH);
  delayMicroseconds(10);
  digitalWriteFast(DOT_LATCH,LOW);

  // set set/reset pin
  if (state) {
    digitalWriteFast(DOT_SET_RESET,HIGH);  
  }
  else {
    digitalWriteFast(DOT_SET_RESET,LOW);
  }

  // pulse
  digitalWriteFast(DOT_PULSE,HIGH);
  delay(1);
  digitalWriteFast(DOT_PULSE,LOW);
}

Я провел несколько экспериментов, чтобы определить оптимальное напряжение источника питания и время подачи импульса. Получилось, что 12В и 1мс достаточно для стабильной фиксации флажка в одном из положений.

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

Фото починенной ячейки

Играем в Тетрис на электромеханическом экране - 10

Вот что получилось после первых экспериментов с заливками и выводом текста:

Играем в Тетрис на электромеханическом экране - 11

Тетрис

Написать реализацию Тетриса на C оказалось проще, чем я думал. Спасибо Javier López и его руководству Tetris tutorial in C++ for beginners. Я переписал основные функции так, как я их понял, и адаптировал код к особенностям моего экрана (отсутствие границ и низкое разрешение). Не буду утомлять подробностями работы, в руководстве все подробно описано.

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

Поиграв минут 10, я понял, что мне скучно, потому что скорость падения фигур не меняется и счет никак не отображается. Отсутствует элемент соревнования.
Выводить счет флажками было некрасиво из-за нехватки места на экране, так что было решено задействовать светодиоды для создания альтернативной плоскости вывода информации. Я нашел в интернете битовое представление шрифта 3x5 для цифр от 0 до 9 и написал функцию отображения счета по количеству убранных линий. Для пущей красоты решил добавить моргание заполненной строки при ее исчезновении.

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

Еще я сделал так, что скорость падения фигурок тетрамино увеличивается по мере очищения линий. В первой версии фигурки смещались на одну строку вниз каждые 200 мсек. Если отнимать от этого числа 40 мсек каждые 10 удаленных линий, то темп игры сильно ускоряется, и появляется интерес. Мой рекорд 38 линий!

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

Код проекта, схемы экрана и модуля сопряжения выложены на GitHub.

Если у вас есть идей, что еще можно сделать с таким экраном, пишите, пожалуйста, в комментарии.

Полезные ссылки:
1. Hackaday: Flip-Dot Display & DIY Controller
2. Tetris tutorial in C++ platform independent focused in game logic for beginners
3. Репозиторий проекта на GitHub

Автор: Константин Федоров

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js