ФОРУМ КУПИТЬ

Последние статьи

ВСЕ СТАТЬИ

Использование OLED I2C дисплея с MegaD-328

06/02/2016 23:30:09

Некоторое время назад я опубликовал статью, в которой описал опыт подключения к MegaD-328 типичного ЖК дисплея. И хотя сама по себе идея вывода информации на ЖК- дисплеи в различных уголках дома интересна, реализация, описанная в той статье, не вызвала особенного энтузиазма у пользователей, и тому есть вполне объяснимые причины.

1. Сложность подключения. Готового решения я не предложил, а потому необходимо было "внедряться" в межблочный шлейф, припаивать проводники к дисплею, что-то придумывать с питанием.
2. Для подключения к ЖК-дисплею требовалось использование 6 (шести!) портов, а это многовато... и в конечном счете дороговато.
3. Дисплей нельзя было удалить от контроллера на сколь-нибудь приемлемое расстояние. Надежно он работал только с коротким шлейфом до 2-3 метров.
4. Символьный дисплей - не то, что хочется иметь в Умном Доме

Но с тех пор, как была опробована программная реализация работы с шиной I2C (датчик давления BMP180, датчик температуры и влажности HTU21D), стало возможным пойти дальше и попробовать подключить какой-нибудь дисплей, поддерживающий эту шину.

OLED SSD1306 I2C

Для тестирования я выбрал монохромный 0,96" OLED дисплей (128х64) стоимостью около $5-$8 со встроенным контроллером SSD1306 и поддержкой I2C. Эти дисплеи бывают, кстати, с белой и синей подсветкой, а также двухцветные.
В чем преимущество этого и подобных ему дисплеев:

1. Простота подключения. Не требуется ничего припаивать или модифицировать. Нужно только подключить 4 провода (питание +3,3В, земля, линии SCL и SDA)
2. Для работы с дисплеем требуется только 2 порта. Причем на одной шине может висеть несколько разных устройств.
3. I2C устройства могут располагаться на некотором расстоянии от контроллера (несколько метров или даже десятков метров).
4. Выводить на дисплей можно все, что угодно: графику, текст (любыми шрифтами). В контроллер дисплея даже встроены некоторые функции анимации (скроллинг).

Подключение OLED дисплея к MegaD-328 IN Kit

Подключение дисплея к исполнительному модулю MegaD-14-IN полностью аналогично подключению датчиков. Линии SCL и SDA можно подключать к любым портам. Необходимо произвести только два действия. Установить конфигурационные джамперы в нижнее положение. Установить в Web-интерфейсе контроллера тип портов NC. С питанием все очевидно - подключаем к +3,3В. Кстати, на плате дисплея присутствует стабилизатор, позволяющий подключать дисплей также к +5В. От +12В, он, замечу, тоже не сгорит, но это не рекомендуется.

Первое, что я сделал, написал драйвер дисплея для библиотеки I2C-PHP. Конечно, у меня все заработало, но прежде, чем показать результат, я бы хотел сказать несколько слов о реализации I2C-PHP для MegaD-328. Эта библиотека посредством отдельных HTTP-пакетов и стандартного MegaD API обеспечивает работу протокола I2C. Никакой специальной поддержки шины I2C в целом или конкретных устройств для этой технологии в прошивке нет. Преимущество такого подхода в том, что можно реализовать работу абсолютно с любыми устройствами без необходимости изменять прошивку. Написал программу на сервере и погнали! Но есть у этого подхода один минут - скорость работы. "Нативная" реализация I2C средствами микроконтроллера предполагает скорость от 100 до 400 Кбит/с. В случае программной реализации на PHP через протокол HTTP скорость существенно ниже. Ну, то есть, СУЩЕСТВЕННО ниже, понимаете? Дело в том, что, когда мы работаем с любыми датчиками, нам необходимо обменяться только парой тройкой байт данных. Это занимает 1-3 секунды и совершенно приемлемо. Но когда речь заходит о дисплее с 8192 точками, то скорость уже начинает иметь самое непосредственное значение. И все же... Как говорится: а что? а вдруг?..

OLED radmom gddram garbage

Когда дисплей впервые подключается к питанию, в его памяти (GDDRAM) содержится всякий мусор. Поэтому перед тем, как начать работу, дисплей необходимо проинициализировать и очистить. Инициализация проходит достаточно быстро, а вот очистка экрана занимает... порядка 75 секунд. Убийственно? Даа... Впрочем, нет, давайте разберемся по порядку. Может быть, не все так плохо?
Забегая вперед скажу, что уже есть версия прошивки, которая значительно ускоряет работу с дисплеем. Очистка или прорисовка всего дисплея занимает 10 секунд!

<?
define("SCL", "8");
define("SDA", "9");
define("MD", "http://192.168.0.14/sec/?");

require_once("mod_i2c_ssd1306.php");

ssd1306_init();
ssd1306_clear_display();
?>

В начале кода мы определяем URL устройства MegaD-328 и порты, к которым подключены линии SCL и SDA. Далее я для краткости буду пропускать эти строчки.
Инициализацию и очистку графической памяти по сути нужно произвести только один раз. Затем достаточно только обновлять изменяющуюся часть данных. Позже я покажу, как это сделать, а начать я решил с самого простого в данном случае - вывода графического изображения.

Для того, чтобы вывести на дисплей какую-нибудь произвольную графику, нужна программа, конвертирующая BMP в формат, который удобно скормить дисплею. Можно было бы написать что-то свое, тем более, что это не трудно, и даже интегрировать эту функцию в драйвер, но для простоты и наглядности я использовал программу LCD Assistant.

Затем я написал функцию, которая загружает массив данных из файла и отображает картинку на экране дисплея.

ssd1306_draw_pic("ab_log_logo");

Вот так, незамысловато. Параметр "ab_log_logo" здесь имя массива из файла libs/ssd1306/mod_ssd1306_pics.php, который включен в общий архив. Вы найдете его внизу статьи.
Собственно, результат... Конечно, для монохромной графики требуется специальная доработка любого изображения, иначе могут вылезти всякие артефакты, которые заметны на фотографии. Но это отдельная тема.

Ну а теперь самое интересное, отображение текста. В контроллере дисплея нет никаких встроенных таблиц со шрифтами или чего-то такого подобного - рисуй, что хочешь. Прекрасно, но как? В этом нам поможет другая программа: The Dot Factory, которая преобразует любые символы в формат, подходящий для отображения на дисплее.

В настройках программы нужно выбрать Rotate: 90 и Line wrap: At bitmap. The Dot Factory генерирует код для C, который нам не подходит, но я написал конвертор, который включен в архив с остальными исходными кодами. Не буду в данной статье углубляться в вопрос генерации данных со шрифтами. Скажу лишь, что мой архив уже содержит такие шрифты как Verdana 8 pt, Verdana 10 pt, Mistral 10 pt. А вот и PHP-код, который выводит текст на экран моего OLED-дисплея.

ssd1306_write_text("Температура: 24.62", "verdana_10", 0, 0);
ssd1306_write_text("Влажность: 47%", "verdana_10", 0, 2);
ssd1306_write_text("   ХОРОШЕГО ДНЯ!", "mistral_10", 0, 5);

Вывод информации на дисплеи Умного Дома

Функция ssd1306_write_text() принимает в качестве параметров: строку; имя массива, содержащего шрифт; номер колонки (от 0 до 128) и номер строки (от 0 до 7).

А вот теперь имеет смысл вернуться к вопросу о скорости работы с дисплеем. Вы помните об этих ужасных 75 секундах для прорисовки / очистки дисплея целиком. А если нам необходимо обновить не весь дисплей, а только данные по температуре и влажности? Сколько занимает отображение одного символа? Около 1 секунды. Значит, ключевые данные обновятся за 8-10 секунд. Что ж, вполне сносно... Кроме того, медленное изменение цифр выглядит где-то даже забавно. Как будто специальная этакая анимация. С модифициованной же прошивкой та же самая операция займет около 1 секунды.

ssd1306_write_text("22.82 ", "verdana_10", 84, 0);

Здесь мы указываем, что новые данные (новое значение температуры) должны отображаться, начиная с 84 колонки.

Расстояние от контроллера до дисплея.

Закономерный вопрос. На каком расстоянии от контроллера можно расположить дисплей, чтобы он стабильно работал. Я провел эксперимент, подключив дисплей обычной витой парой (UTP 5 AWG 24), используя только четыре провода. Длина кабеля 18 метров (больше одним куском в доме на этот момент не оказалось). Дисплей прекрасно работал. Никаких намеков на сбои или ошибки. Думаю, на тех расстояниях, которые есть в домашних условиях, дисплеи и другие I2C устройства будут работать нормально.

Итак. К устройствам MegaD-328 с исполнительным модулем MegaD-14-IN можно подключать OLED/LCD-дисплеи, работающие по шине I2C. Низкая стоимость такого решения и простота реализации позволяют использовать эти дисплеи в различных ситуациях. Дисплеи можно размещать в щитках для отображения текущего потребления или напряжения по фазам. Экранчики можно встраивать в корпуса для температурных датчиков, о которых я писал ранее. OLED дисплеи почти не нагреваются, а значит не будут влиять на измеряемую температуру. Будучи размещенным на корпусе датчика, дисплей может отображать информацию о текущей температуре, влажности, качестве воздуха (например, содержании CO2) и другие данные. Дисплеи можно вешать на кухне или в спальне, они могут работать как часы или отображать прогноз погоды. Управляемые сервером, дисплеи также способны менять яркость свечения в зависимости от времени суток.

PHP библиотека для работы с OLED дисплеем на контроллере SSD1306 пока умеет не очень много и содержит лишь самые простейшие функции, но если у пользователей будет интерес к данной теме, я с удовольствием продолжу разработку. Что касается медлительности в части обмена информацией с дисплеем, то и здесь есть потенциальная возможность все-таки переложить часть работы на сторону контроллера, что позволит многократно увеличить скорость отображения информации.

Я уже опробовал тестовый вариант прошивки, когда контроллеру передаются по сети Ethernet не отдельные биты, а байт целиком. Это ускоряет работу с дисплеем почти в 8 раз. Прорисовка всего дисплея занимает 10 секунд. Но, думаю, и это еще не предел.

Кстати, дисплей с белыми пикселами мне понравился больше...

Исходники I2C-PHP для MegaD-328 и дисплея OLED SSD1306

 

Автор: Andrey_B
Любое использование материалов сайта возможно только с разрешения автора и с обязательным указанием источника.



Добавить комментарий:

(необязательно, не отображается на сайте)


Сортировка комментариев: Последние сверху | Первые сверху

2016-02-25 15:43:37 | Tarasella
Андрей, на сколько я понял, Вы запускали все это дело на версии прошивки 3.43beta1?


2016-02-25 17:08:12 | Andrey_B
Да, лучше использовать версию прошивки не ниже 3.43beta1


2016-06-02 02:40:58 | Александр
Отличная идея! Размер дисплея удобный, скажем для быстройинформации около выключателя. На больших дисплейя пробовали?


2016-06-02 04:09:35 | Александр
Интерес конечно же есть! Представьте, на корпус датчика повесить сразу отображать температуру, Или же у выключателя отображать теущую яркость диммера. Ну и самое интересное - это использование с голосовыми порталами(микрофоны для передачи команд) - сразу же в реальном времени можно видеть реакцию сервера.
Я две руки За! Пожалуйста развивайте софт!


2016-06-02 04:21:53 | Александр
Забыл сказать. У меня на сервере крутится скрипт. Написан на Bash.
Скрипт собирает значениях и настройках устройств за три разных промежутка времени. Вычисляет среднее значение и перезаписывает. Таким образом мой Дом подстраивается под меня.

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


Bash - консольный язык программирования nix-серверов


2016-06-02 04:25:17 | Александр
Андрей,

Вы с отображением символа градуса вопрос не решили?


2016-06-02 04:41:24 | Александр
Вы не смотрели - там стоят Pull-up резисторы? Обычно для I2C шины достаточно что б на одном устройстве хотя бы стояли. Если так, то могу сказать, опираясь на опыт использования I2C на RPI - подобные устройства можно свободно использовать на расстояниях до 50м даже с обычным Al+Cu CAT5E кабелем. Вложил бы фотку - да нельзя прикрепить здесь в коментарии свою схему расположения I2C устройств.
Сама I2C шина живучая и быстрая. Но больше мороки, чем с 1-Wire, например.


2016-06-02 18:06:37 | Andrey_B
На больших дисплеях не пробовал. Но, думаю, принципиально мало что измениться.


2017-01-03 20:50:56 | Алексей Ефремов
Андрей! У вас в статье не раскрыто полностью как обновлять только изменяющиеся данные. Например, есть скрипт, который работает по cron, в нем проводим инициализацию, очистку дисплея, первичный вывод информации. Вот как проверить, что дисплей уже инициализирован и ему уже передали первичные данные, а теперь можно только обновлять меняющиеся данные? В МК было бы просто - при первом включении инициализируем, очищаем, выводим данные устанавливаем флаг - флаг есть. значит только обновляем данные. А как это сделать в linux (debian)?


2017-01-04 00:54:15 | Andrey_B
Алексей, ПК может все. Например, он может сохранять у себя информацию об инициализации дисплея (в БД или в файле). Скажем, в виде флага. А когда устройство стартует/ресетится, то передача на сервер st=1 является сигналом сбросить этот флаг и проинициализировать дисплей заново. Это лишь один из вариантов.
Конечно, дисплей может проинициализировать и сам контроллер, но для этого (если мы говорим о MegaD-2561) необходимо предусмотреть настройку порта, чтобы контроллер знал, что к нему подключен дисплей.


2017-12-07 21:24:22 | Pmet
Надеюсь критика здесь не удаляется. Не очень понимаю, а зачем вообще делать реализацию I2С на сервере, когда софтовая реализация I2C в авр на любых портах способна работать на 40кГ даже при 1Мгц кварце? Например, если мы захотим подключить девайс SMbus (тот же I2C только минимальная частота 10кГц), то вашей реализации оно работать не будет. 10-100 Гц это не 10-100 кГц. Согласитесь, когда запись кадра в экран занимает 75 секунд вместо 75 мс, это сильно ограничивает применение такого экрана. И это всего лишь 128х64 точки, экранчик размером 2 см х 1 см. Всего 2 квадратных см! Ради вывода трех цифр проще было взять семисегментные индикаторы (https:/ab-log.ru/smart-house/ethernet/megad-2561-ssd1306). Для них ваша реализация вполне подошла бы. А вот для OLED дисплеев ваша реализация просто противопоказана. Они не предназначены для вывода статических изображений. Выгорают за пол года. Вывод информации на такой дисплей в виде бегущей строки просто обязателен, чтобы продлить срок эксплуатации такого экрана. Но в вашей реализации это мало вероятно. Тут сразу всплывает еще такой вопрос. А сравнима ли нагрузка на сервер и нагрузка на МК от реализации софтового I2C? Представьте, что нужно по всему дому десяток таких датчиков с экранами развесить и устроить бегущую строку на них. Думаю серверу будет не весело по 75 секунд общаться с каждым экранчиком, чтобы вывести 3 цифры. Пусть даже если использовать ваш Web-I2C, гораздо более правильным решением было бы запихнуть в коробку с экраном простенький МК, который который общался по I2C с сервером, но получал бы только значение температуры, а вот изображение на дисплей выводил бы не сервер, а этот МК.


2017-12-08 17:26:39 | Andrey_B
Pmet, контроллеры MegaD-328 сняты с производства. Вместо них сейчас производятся MegaD-2561, которые работают с I2C-устройствами напрямую без дополнительного участия сервера.


2019-11-20 14:02:48 | Олег
Здравствуйте, Андрей! Будет ли работоспособна такая конфигурация:
8 дисплеев SSD1306 подключены непосредственно к колодке портов MegaD-2561.
SDA каждый на отдельный порт, SCL все 8 на один порт. 3.3в все на одну линию питания Меги. 8 дисплеев будут показывать 8 DS18B20 (1W) без сервера крупными цифрами. Есть ли подтяжка в дисплеях, или надо делать свою?


2019-11-20 19:44:57 | Andrey_B
Олег, чисто теоретически можно, если дисплеи будут висеть на одной шине SCL или если длина линий будет небольшая. Подтяжка в дисплеях должна быть. Можно пробовать подключать напрямую.


2019-11-20 21:19:13 | Олег
И как можно одной кнопкой включить все 8 дисплеев на 20 секунд и выключить?


2019-11-21 10:26:42 | Andrey_B
Олег, вероятно, такой длинный сценарий не поместится в Act. Но можно подумать по поводу использования команды "a:0" или Program. Это когда часть сценария в Act, а часть в Program.


2020-11-08 19:04:11 | Илья
Здравствуйте! Вопрос по дисплею. Как сбросить у него память запросом? Проблема в следующем. Сервер с некоторой периодичностью (секунд 10) отправляет запросы на дисплей. После 7-8 запросов, на дисплее отображается пустота. Если в настройках порта нажать save. То я так понимаю память очищается и снова всё работает. На одном порту висит дисплей и bme280. Порт настроен как на дисплей.


2020-11-08 20:55:40 | Andrey_B
Илья, если через пару запросов дисплей "виснет", значит происходит сбой в передаче данных по шине I2C. Здесь главным образом стоит искать проблему в самой шине. Может быть, слишком длинная линия. Может быть, BME280 и SSD1306 подключены не шиной, а звездой. Может быть подключены шиной, но слишком длинные ответвления. Может быть, какие-то проблемы с помехами или питанием или качеством контактов. Вариантов много. И у каждого свое решение.
После перезагрузки контроллера он заново инициализирует дисплей. Специальной команды (GET-запроса) для переинициализации нет. А если бы и была - это так себе лечение... Симптоматическое. Нужно найти причину, тогда и команда такая не потребуется.


2020-11-13 18:40:53 | Илья
BME280 и SSD1306 подключены точно шиной. От контроллера один провод, длина около 5 метров. Дальше 2 ответвления по 3 см. На датчик и дисплей. И датчик и дисплей находятся в D-Sen box. Помехи или качество контактов - может быть. Буду выяснять. Но самое интересное. Что row1 col 0 и row 6 col 0 не зависают. Только вместо центрального значения пустота. А row1 и row2 меняются как и должны...


2021-05-24 01:17:06 | Сергей
А информацию с датчиков bme280 без сервера на данный дисплей вывести нельзя ? Что-то не появился пункт Disp.


2021-05-24 10:52:36 | Andrey_B
Сергей, автономно (без команд от сервера) нельзя.


2021-08-22 09:59:02 | Сергей
Добрый день. На форуме часто встречаю сообщения про общий scl, отсюда вопрос. Можно ли для освобождения портов к примеру 3 или 5 экранчиков посадить на общий scl и разные sda ?


2021-08-23 17:55:23 | Andrey_B
Сергей, общий SCL использовать можно, если устройства подключаются шиной. Если же от каждого устройства приходит свой кабель (звездой), то емкость линии не позволит надежно использовать общий SCL.


2021-10-14 19:04:13 | Сергей
На улице под навесом выживет ?


2021-10-14 22:50:13 | Andrey_B
Сергей, я лично не использовал подобные дисплеи в условиях отрицательных температур и в жару. Но можно попробовать. Деталь то недорогая.