Pull to refresh
2682.01
RUVDS.com
VDS/VPS-хостинг. Скидка 15% по коду HABR15

Подключаем алфавитно-цифровой экран к VGA

Reading time 5 min
Views 15K

Нет, это не шутка. В действительности к VGA, DVI, HDMI можно подключать различные устройства, и даже питать их. И это очень удобный способ работы с различными устройствами и нестандартное использование обычного интерфейса.

Ларчик просто открывается, всё дело в том, что в интерфейсе VGA (а также в других видеоинтерфейсах) присутствует ещё одна шина данных I²C, которая доступна для использования и её легко можно применить в своих самоделках.

▍ В поисках шины I²C


На самом деле, задумка очень простая. В одной из задач мне понадобилось найти в компьютере шину I²C для подключения весьма специфического устройства.

В обычном компьютере обычно присутствует несколько подобных шин. В этом легко можно убедиться, просто введя:

ls -la /dev/i2c*
crw-rw---- 1 root i2c 89, 0 сен 24 12:35 /dev/i2c-0
crw-rw---- 1 root i2c 89, 1 сен 24 12:35 /dev/i2c-1
crw-rw---- 1 root i2c 89, 2 сен 24 12:35 /dev/i2c-2
crw-rw---- 1 root i2c 89, 3 сен 24 12:35 /dev/i2c-3
crw-rw---- 1 root i2c 89, 4 сен 24 12:35 /dev/i2c-4
crw-rw---- 1 root i2c 89, 5 сен 24 12:35 /dev/i2c-5
crw-rw---- 1 root i2c 89, 6 сен 24 12:35 /dev/i2c-6

Целых шесть шин I²C! Но где обитают эти шины, и как к ним получить физический доступ?

Самый «простой» способ — это получить непосредственно с разъёма PCI/PCI-e. Но для этого нужно делать какую-то плату-расширитель.

На материнской плате, которую я использую сейчас и о которой писал в статье «Серверные мощности в домашнем ПК» есть специальный разъём PMBUS, для подключения блока питания.



Это вполне официальный способ подключения к шине I²C и служит для управления серверным блоком питания, режимами его резервирования и получение данных энергопотребления.


Распиновка разъёма PMBUS

Эмпирическим путём было установлено, что на разъёме PCI/PCI-e и на контактах PMBUS, это одна и та же шина I²C (даже электрически связана между собой). В системе она видна как файл-устройство /dev/i2c-0. Но, вместе с тем на ней висит достаточно большое количество устройств. В чём можно легко убедиться:

i2cdetect -y 0
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- 08 -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- UU -- UU -- UU -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- 2e UU 
30: 30 -- 32 -- 34 -- -- -- -- -- -- -- -- -- 3e -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: 50 -- 52 -- 54 -- -- -- -- -- -- -- -- -- -- -- 
60: -- 61 -- -- -- -- -- -- -- 69 -- -- -- -- 6e -- 
70: -- -- -- -- -- -- -- --           

Так уж получилось, что устройство пересекалось по адресам с устройствами на материнской плате, а по определённым причинам адреса устройства поменять я не мог. Попытки «подвинуть» по адресам микросхемы на материнской плате тоже не увенчались успехом.

Поэтому пришлось искать другой вариант. И тут я вспомнил, что в интерфейсе VGA тоже присутствует шина i2c, при этом разъём на материнской плате у меня свободен.


Свободный разъём на материнской плате

Монитор для компьютера к нему подключить уже не получится, а вот всякие I²C-железки, вполне.

▍ Подключаем дисплей 20x4 по I²C к VGA


Благодаря the_matrix, у меня появился в хозяйстве этот дисплейчик, с шиной I²C на своём борту, и я решил на нём потестировать, а заодно и продемонстрировать подключение своих устройств по шине I²C к ПК.

Начну с того, где же найти шину в разъёме VGA. Эта шина есть и в других интерфейсах, таких как HDMI, DVI. Нужна она для того, чтобы получить параметры монитора. Это именно та шина, по которой драйвер понимает, какие параметры допустимы именно для вашего монитора.

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


Где обитает I²C в разъёме VGA

Нужно просто взять 4 провода, и подключить к соответствующим местам на дисплее. Питание к питанию, шину к соответствующим контактам, которые подписаны.


Подключение

Самое главное, после подключения не забыть покрутить резистор контраста и убедиться, что видны тестовые линии.


Регулировка контраста

Если вы всё сделали правильно, то дисплей можно будет увидеть на шине I²C следующей командой:

i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- 27 -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --           

Если вы видите не пустые поля, а некоторый адрес, значит вы всё сделали правильно. В моём случае дисплей живёт по адресу 0x27 (справедливости ради — это 0x4E, но не будем путать людей).

Если устройство видно, значит, всё готово к варварским экспериментам. Если нет, то проверяйте подключение.

▍ Программирование


Как обычно, всё хорошее придумано за нас. И писать библиотеку мне совершенно не хотелось, тем более что я уже достаточно пописал для этих дисплеев, особенно после статьи «Создание собственных драйверов под Linux».

Нашёл хорошую годную статью Raspberry Pi with I2C 2004 LCD и просто взял готовый проект с гитхаба https://github.com/CaptainStouf/raspberry_lcd4x20_I2C.

Клонирую его, перехожу в папку проекта и достаточно теперь выводить сообщения прямо из питона:

git clone https://github.com/ArcadiaLabs/raspberry_lcd4x20_I2C.git
cd raspberry_lcd4x20_I2C/
python3

Запускаю python и подключаю модуль:

import lcddriver

После этого нужно инициализировать класс и очистить дисплей:

lcd = lcddriver.lcd()
lcd.lcd_clear()

Ну и можно вывести что-то прикольное. Например, машинку, из моего поста про драйвера:

avto  = ["            ___     ",
         "     .--.  [STP]    ",
         ".----'--,'--.|      ",
         "'-()-----()-'|      "]

for i in range(4):
    lcd.lcd_display_string(avto[i],i+1)




Хотел реализовать в динамике, как было там. Но что-то нахрапом не удалось и стало лениво.

Давайте котика попробуем вывести:

cat = [" |\\__/,|   (`\\",
        " |_ _  |.--.) )",
        " ( T   )     /", 
        "(((^_(((/(((_/"]
for i in range(4):
     cd.lcd_display_string(cat[i],i+1)


Но котик получился не очень.


Котик

А причина достаточно простая, в кодировке дисплея отсутствует обратная косая черта «\». Можно даже убедится в этом, посмотрев в документацию.



Вместо неё подставляется вот такая вот кракозябра.

▍ Заключение




На поиск альтернативных способов подключения к шине I²C меня подвигли рабочие задачи, когда не удалось подключить устройство к шине PMBUS из-за конфликта адресов. На голой материнской плате в системе было видно всего два устройства. Одно из которых было PMBUS+PCI/PCI-E, а другое было VGA.

Несмотря на некоторую странность подключения своего устройства к разъёму VGA, способ оказался простым и надёжным, активно используется в наших проектах.

На самом деле, я далеко не первый, кто пишет о подобных способах подключения по видеоинтерфейсу устройств к шине I²C. Не так давно наткнулся на перевод статьи «Прямое подключение крохотного OLED-дисплея по HDMI», где человек так заморочился, что даже сделал отдельный драйвер для дисплея.

▍ Полезные ссылки


  1. Raspberry Pi with I2C 2004 LCD.
  2. Документация на дисплей.
  3. Создание собственных драйверов под Linux.
  4. Прямое подключение крохотного OLED-дисплея по HDMI.
Telegram-канал и уютный чат
Tags:
Hubs:
+125
Comments 46
Comments Comments 46

Articles

Information

Website
ruvds.com
Registered
Founded
Employees
11–30 employees
Location
Россия
Representative
ruvds