DIY: Экранчик для «умного дома»

от автора

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

Фишка тут в том, что можно приобрести их б/у за копейки, и получить при этом винтажный газоразрядный экран, приятного зеленого или синего цвета.
Пусть алфавитно-цифровой — для часов этого более чем достаточно.

Поскольку сервер времени я себе уже сделал — дай-ка, думаю, и эту штуку попробую освоить, будут часы с синхронизацией по 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/