Есть такая штука, как «дисплей покупателя» — это тот самый экран на кассе, где пишут сколько денег вы должны заплатить.
И есть такое народное развлечение — делать из этих экранов всякое разное — ну например, «часы или метеостанцию» (с)
Фишка тут в том, что можно приобрести их б/у за копейки, и получить при этом винтажный газоразрядный экран, приятного зеленого или синего цвета.
Пусть алфавитно-цифровой — для часов этого более чем достаточно.
Поскольку сервер времени я себе уже сделал — дай-ка, думаю, и эту штуку попробую освоить, будут часы с синхронизацией по NTP.
А еще можно приспособить их для полезного дела — показывать температуру воды в котле, например — чтобы не бегать смотреть на основные экраны «умного дома», и не хвататься за телефон.
Итак, под руку попался Wincor Nixdorf BA64-2: 2 строки по 20 символов, газоразрядный, аккуратный черный корпус.

По даташиту он может работать с кассой как по USB, так и по RS232, в зависимости от кабеля.
На самом дисплее всего один разьем типа RJ45, но он не сетевой, просто для удобства подключения кабелей.
У моего экземпляра был кабель для RS232, но сразу же возник вопрос: а как конкретно его подключать?
Стандартный RS232 — разьем DB25 или DB9 со штырьками, «папа», соответственно — у кабеля должен быть парный ему, «мама» — но здесь наоборот, штырьки на кабеле.
И RJ45 тоже не то, чем кажется.
Где гарантия, что распиновка разьема хоть как-то соответствует стандартам, и что дисплей не сгорит с дымом, если подключить его как положено, а не к родной кассе?
О распиновке даташит молчал, как партизан. В интернете тоже ничего не нашлось по этой модели.
Конечно, кабель можно прозвонить тестером — но кто его знает, какой провод к чему относится, раз уж тут всё не по стандарту?
Пришлось лезть внутрь — и не зря.
Разбирается он неочевидно: сначала нужно открутить всего один винт сзади, а вот потом с помощью чего-то типа пластиковых карт и стальной линейки аккуратно отжать нижнюю рамку от экрана, и приподнять «стекло».
И только когда зацепы выскочат — можно будет его снять полностью.

Дальше просто — два винта держат плату, сверху на ней стеклянный индикатор, но нам нужна нижняя сторона.

Если внимательно посмотреть — видно, что 1 пин разьема (справа, металлический корпус, сверху вниз ) идет на какой-то элемент зеленого цвета, подозрительно напоминающий предохранитель (fuze), и 4 пин — на “землю”.
Вероятно, это питание: плюс и GND. Остальные — явно сигнальные.
Вспоминаем, что дисплей может работать от USB, то есть от 5В — поэтому подаем именно 5В (хотя вроде он и 12 выдержит, для RS232).
Случилось чудо: дисплей ожил, что-то показал, и погас.
Уже хорошо, питание работает, теперь нужно подключить передачу данных.
Осциллограф показал наличие разных постоянных напряжений на разных пинах:
2 — 0,
3 — +3,
5 — 0,
6 — -5,
7 — 0,
8 — +7.
Там, где -5 и +7 — похоже на сигналы RS232, а 2 и 3 похожи на напряжения USB в состоянии покоя.
Так и оказалось: если подключиться к 2 и 3 пинам к USB — дисплей определяется в системе:
Manufacturer: Wincor Nixdorf
hid-generic 0003:0AA7:0208.002B: hiddev97,hidraw4: USB HID v1.11 Device [Wincor Nixdorf BA64-2 Customer Display] on usb-5101000.usb-1.4.3/input1
…
и тому подобное.
В устройствах появляются несколько /dev/hidrawX, с которыми теоретически уже можно работать (но непонятно как именно).
Сигналы RS232 проверить было нечем, адаптера нет, а TTL serial с таким не работает.
Но вероятно, это всё-таки они, а молчащие 5 и 7 пины — RTS/CTS.
Таким образом, распиновка разьема RJ45:
1 — + 5 VCC
2 — 0 -Data USB (white)
3 — 3 +Data USB(green)
4 — GND
5 — 0 ?
6 — -5 rs232 ?
7 — 0 ?
8 — +7 rs232 ?
Уже лучше, но надо с этим как-то работать, и желательно не через подключение проводами к компьютеру.
Смотрим на плату внимательно, и видим там такую интересную микросхему:

Это — ADM3232E, конвертор уровней TTL-RS232.
Он занимается преобразованием TTL-serial (0-3В) в RS2 32-serial (-7/+7В), причем сам питается от 3.3В, которые умножает в два раза для формирования RS232.
Но важнее тут другое: он напрямую работает с TTL-serial контроллера дисплея! А значит, не нужны ни USB, ни RS232 — можно подключиться напрямую к данным, используя всё ту же ESP8266. То есть, приделать к дисплею Wifi-интерфейс.
Тогда из проводов остается только питание, например от обычной USB-зарядки.
Для этого сначала с помощью фена аккуратно сдуваем эту микросхему.

Освободились контактные площадки: 3.3В питание, GND, RX/TX.
Строго говоря, там два комплекта RX/TX, проверить какой именно отвечает на ввод-вывод — несложно ( не очень понятно зачем второй — ну да ладно).
Рабочие выводы здесь — R2out / T2in: out идет из конвертера на контроллер, и соответственно, in из контроллера на конвертер.
Схема подключения — простейшая, поэтому все делается с помощью проводков и скотча


А, ну не забыть сначала залить прошивку: для этого подключиться к RX/TX ESP8266 через компьютер, закоротить GPIO0 на землю, подать питание и прошить средствами Ардуино.

после прошивки освободить GPIO0.
И всегда оставлять для себя возможность перепрошивки по OTA.
Простейшая тестовая прошивка — принимает по MQTT строку байт и пишет ее в порт.
Единственно что — пришлось добавить небольшую задержку записи, дисплей не успевает за ESP, приходится писать побайтно:
...bool outs = false;void outString(char * buf, int length){ if(outs) return; outs = true; for(int i=0; i< length; i++){ Serial.write(buf[i]); delay(4); } outs = false;}...void msg_callback(char* topic, byte* payload, unsigned int length){ ... if(!strncmp((char *)payload, "test ", 5) && length > 5){ outString((char*)&payload[6], length - 6); } ...}
Отправка команд из консоли по MQTT (список команд есть в даташите на дисплей):
printf "\x1B[2J\x1B[1;0HHello world!" | mqtt-simple -h mosqit -p command/ba64
Что ж, всё работает.
Теперь добавляем, наконец, часы. Синхронизация — по NTP, с тем самым сервером точного времени:
#define CLEAR_SCREEN "\x1B[2J"#define CLEAR_EOL "\x1B[0K"#define UTF8_MODE "\x1B[1u"time_t olddtm = 0;bool clock_mode = true;char * wdays[] = { "Воскресение", "Понедельник", "Вторник", "Среда", "Четверг", "Пятница", "Суббота", "Воскресение"};#include <RTClib.h>....void drawClock(){ time_t dtm = time(nullptr); dtm += (3 * 3600); if(dtm != olddtm){ DateTime now = DateTime(dtm); olddtm = dtm; char buf[21]; int year = now.year(); int month = now.month(); int day = now.day(); int wday = now.dayOfTheWeek(); uint8_t h = now.hour(); uint8_t m = now.minute(); uint8_t s = now.second(); sprintf(buf,"\x1B[1;%dH%02d.%02d.%04d %02d:%02d:%02d", 0 ,day,month,year,h,m,s); outString(buf,strlen(buf)); sprintf(buf,"\x1B[2;%dH%s\x1B[0K", 0 ,wdays[wday]); outString(buf,strlen(buf)); }}...#include <time.h>void TimeSetup(){ configTime(0, 0, "ntpserver.home"); int cnt = 4; while (!time(nullptr) && cnt > 0) { delay(1000); cnt --; }}void setup(){ Serial.begin(9600); WifiSetup(); MqttSetup(); TimeSetup(); ... pinMode(IND,OUTPUT); digitalWrite(IND,HIGH); outString(CLEAR_SCREEN,strlen(CLEAR_SCREEN)); outString(CLEAR_SCREEN,strlen(CLEAR_SCREEN)); outString(UTF8_MODE,strlen(UTF8_MODE)); olddtm = 0;}void loop() { WifiLoop(); MqttLoop(); ... drawClock(); ... delay(100);}
Но просто часы — это не особо интересно. Добавим возможность показа принятого по MQTT текста (уже почти есть) и автоматическое возвращение к показу часов через 60 секунд.
...#define UTF8_MODE "\x1B[1u"#define LINE1_0 "\x1B[1;0H"#define LINE2_0 "\x1B[2;0H"bool clock_mode = true;#define INFO_PERIOD 60000unsigned long info_timer = 0;...void msg_callback(char* topic, byte* payload, unsigned int length){ if(!strncmp((char *)payload, "reset", length)){ ESP.reset(); } if(!strncmp((char *)payload, "clock", length)){ clock_mode = true; olddtm = 0; outString(CLEAR_SCREEN,strlen(CLEAR_SCREEN)); } if(!strncmp((char *)payload, "line1 ", 5) && length > 5){ clock_mode = false; info_timer = millis(); outString(LINE1_0,strlen(LINE1_0)); outString((char*)&payload[6], length - 6); outString(CLEAR_EOL,strlen(CLEAR_EOL)); } if(!strncmp((char *)payload, "line2 ", 5) && length > 5){ clock_mode = false; info_timer = millis(); outString(LINE2_0,strlen(LINE2_0)); outString((char*)&payload[6], length - 6); outString(CLEAR_EOL,strlen(CLEAR_EOL)); } } void setup(){ ... olddtm = 0; clock_mode = true; info_timer = 0;}void loop(){ ... if(clock_mode){ drawClock(); }else{ if(( millis() - info_timer ) > INFO_PERIOD){ clock_mode = true; olddtm = 0; outString(CLEAR_SCREEN,strlen(CLEAR_SCREEN)); } } ...}
Например, как и планировалось, можно отправлять данные о температуре котла — они будут появляться на экране, потом снова часы, снова температура и т.д.
‘line1 котел 63.28/55.43\xC2\xB0C’ -> “котел 63.28/55.43°C”
‘line2 ’ -> » «
Можно конечно было бы просто подписать сам дисплей на сообщения от датчика температуры — но по принятой у меня системе рассылкой информации занимаются скрипты на сервере. Вдруг потребуется выводить что-то еще и по-другому? Дисплей получается универсальный, и их может быть несколько.
А вот дальше я подумаю, что именно туда выводить, и где еще можно это использовать…
Да, это как раз было сделано из чисто академического интереса.

ссылка на оригинал статьи https://habr.com/ru/articles/1025130/