Одометр и часы arduino oled. Подключение к Arduino

Здравствуйте, MySku`вчане! Сегодня расскажу вам о графическом OLED дисплее на контроллере SSD1306. Похожий дисплей уже на муське, я постараюсь дополнить обзор, а также покажу, как его подключить к Digispark на базе ATtiny 85. Возможно, эта информация пригодится вам в ваших проектах.

Данный дисплей был куплен в магазине Gearbest за свои деньги.

Скрины заказа




Заказ был сделан 02.12.2015, посылка дошла на удивление быстро, перед самым новым годом я забрал её на почте. Сейчас данный лот стоит на 47 центов дороже.


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

Упаковка и внешний вид




На сам дисплей наклеена защитная пленка от царапин.


Тут видно, что отсутствует резистор с нулевым сопротивлением в качестве перемычки BS1. Когда перепаивал её в другое положение, спружинил пинцет, и потерялась такая красивая перемычка, запаял обычную проволочную.




Технические характеристики дисплея:
- Тип дисплея: OLED монохромный, в данном дисплее 2 цвета, желтый и голубой
- Драйвер дисплея: SSD1306
- Разрешение: 128 х 64 пикселей
- Размер дисплея: 0,96 дюйма
- Углы обзора: >160°
- Интерфейс подключения: 3-wire SPI, 4-wire SPI, I2C
- Напряжение питания: 3,3 В
- Потребляемый ток на пиксел: 100 мкА
- Размеры: 33 мм х 33.5 мм

Картинка с габаритами



Электрическая схема



на драйвер SSD1306.

Подключать данный дисплей будем к Digispark.

Что это такое и как его настроить на работу в Arduino IDE, можно прочитать в этом . От себя лишь сделаю ремарку. Настоятельно рекомендую использовать версию Arduino IDE 1.6.5 . Сейчас на официальном сайте доступна версия 1.6.7, но с ней у меня постоянно сыпались ошибки. Теперь все собираем на одной макетке.


Подключается Digispark к дисплею следующим образом:
- Т.к. подключать будем по шине I2C, необходимо перепаять перемычку BS1 в положение «1».
- Vcc это питание дисплея, подаем 3,3В
- GND тут понятно, это земля
- DIN (SDA) подключаем к контакту P0 на Digispark (и подтягиваем к +5В резистором 4,7 К)
- CLK (SCL) подключаем к контакту P2 на Digispark (и подтягиваем к +5В резистором 4,7 К)
- CS подключаем к земле
- D/C тут нюанс, если на этот вывод подать «низкий» уровень, т.е. землю, то адрес дисплея будет 0x3C , если подать «высокий» уровень, т.е. подключить к 3,3В, то адрес дисплея будет 0x3D . Я подключил к земле.
- RES подтягиваем к питанию т.е. 3,3В

Теперь загружаем стандартный скетч DigisparkOLED из папки примеров. Тут замечание, при необходимости нужно изменить адрес дисплея в файле DigisparkOLED.h на ваш. Вносите изменения в строку:
#define SSD1306 0x3C // Slave address.
По умолчанию там указан 0x3D.
При попытке загрузить данный пример в ATtiny 85 вываливалась ошибка о нехватке памяти мк. Закомментируйте или удалите «картинки» в скетче, т.е. строчки:
#include "img0_128x64c1.h" #include "digistump_128x64c1.h"
и подправьте скетч, у меня получилось так:


В итоге на дисплее увидим




Как видно, вывод 2 строчек текста на экран занимает 4062 байт, что составляет 67% памяти мк. Библиотека довольно прожорливая, если даже пожертвовать загрузчиком, памяти мк останется процентов 50, маловато однако.
Решено было найти или написать библиотеку «полегче». На просторах интернета была найдена библиотека TinySSD1306. Скачивал с этого . Распакуйте библиотеку в папку libraries (если вы ставили Arduino IDE по умолчанию, то данная папка будет находится по такому пути: «C:\Users\имя_пользователя\AppData\Roaming\Arduino15\packages\digistump\hardware\avr\1.6.5\libraries»). После перезапуска Arduino IDE, в папке примеров загружаете скетч ssd1306_demo.
Немного подправил данный скетч, чтобы просто вывести одну строку.

Как видно, вывод одной строки у нас занял 2 138 байт, что занимает 35% памяти мк. Это совсем другое дело:) Если убрать загрузчик и использовать «голый» мк, то остается уйма места.
Также я провел некоторые электрические тесты.
Потребляемый дисплеем ток составил 5,6 мА.


Совместно с Digispark потребляемый ток составил 28,2 мА.


Решил понизить частоту ATtiny до 1 Мгц. Потребляемый ток конструкции составил 16,5 мА.


Думаю, что уменьшить ток потребления можно еще раза в 2, если использовать «голый» мк, т.к. на плате Digispark есть еще и светодиод, потребляющий ток. А также можно понизить напряжение для ATtiny до 1,8В.
В итоге:
Дисплеем остался доволен. Высокие углы обзора, высокая контрастность, низкое энергопотребление. Для увеличения быстродействия есть возможность подключить по шине SPI.
Из минусов могу отметить отсутствие стабилизатора 3,3В на плате дисплея, хотя места там полно. В интернете читал, что данные дисплеи толерантны и к 5 Вольтам, но экспериментировать не стал, т.к. в даташит к контроллеру указано, что питание «логики» от 1,65 до 3,3В.
На этом все, постараюсь ответить на ваши вопросы, если будут таковые.

OLED — дисплей являются одним из самых привлекательным и современным дисплеем, при небольших размерах и незначительном энергопотребление OLED дисплей, обеспечивает насыщенную контрастность. Дисплеи в основном доступны на чипе SSD1306, работающим на интерфейсе I2C, для работы которого необходимо только 2 провода, что позволяет быстро подключить и начать использовать. В этом статье расскажу, как подключить OLED дисплей, диагональю 0.96 дюйма и расширением 128 х 64 пикселя.

Технические параметры

Технология дисплея: OLED
Разрешение дисплея: 128 на 64 точек
Диагональ дисплея: 0,96 дюйма
Уол обзора: 160°
Напряжение питания: 2.8 В ~ 5.5 В
Мощность: 0,08 Вт
Габариты: 27.3 мм х 27.8 мм х 3.7 мм

Общие сведения OLED дисплея

А что же такое, технология OLED? Расшифровывается как Organic Light-Emitting Diode, состоит дисплей из большого числа органических светодиодов, главное отличие от LCD дисплея, в том, что каждый светодиод светится сам и не нуждается в отдельной подсветки. Благодаря этому, дисплей обладает значительными преимуществом по сравнению с обычными LCD, такими как контрастностью, углом обзора и малая потребляемая мощность, конечно есть и недостатки, небольшой срок службы и дороговизна.

OLED модуль с расширением 128×64 (0.96 дюйма) состоит из двух частей, из самого дисплея, который в свою очередь можно разделить на две части, графический дисплей и контроллер SSD1306 от которого идет гибкий шлейф на обратную сторону платы. Вторая часть, модуля, представляет собой печатную плату (которая по сути является переходником), на которой установлена минимальная электрическая обвязка, однорядный разъем шаг 2.54 мм и четырьмя крепежными отверстиями.
OLED модули, выпускаются с различным расширением 128×64, 128×32 и 96×16 (в статье и примере используется дисплей с расширением 128×32), сам контроллер SSD1306 может работать с OLED матрицами с максимальным расширение 128×64, так-же, модули бывают белые, синие и сине-желтые (сверху, желтая полоса, шириной 15 пикселя). Каждый производитель, выпускают свою печатные плату с различной компоновкой электронных компонентов и выведенным интерфейсом, так-как контроллер SSD1306 поддерживает сразу три протокола работы:

8-bit 6800/8080-series parallel interface
3 /4 wire Serial Peripheral Interface
I2C

Для изменения протокола работы, предусмотрены три линии BS0, BC1 и BS2 с помощью которых, контроллер дисплея определяет по какому протоколу ему работать. В моем случаи, OLED дисплей разработан для работы по одному протоколу I2C, в других вариантов, возможно смена протокола работы с помощью нулевых резисторах или DIP переключателей.

Ниже приведена принципиальная схема OLED дисплея на микросхеме SSD1306, работающая по интерфейсу I2C, из нее видно, что микросхема U2 выполняет функцию стабилизатора напряжение (3.3В), конденсатор C8 необходим для сглаживания выходного напряжения. Резисторы R6 и R7 выполняют функцию подтяжки линии SCL и SAD, если к шине I2C, подключено не одно устройство, необходимо использовать подтягивающие резисторы только на одном устройстве. С помощью резистора на 0 Ом (без обозначении), можно произвести смену адреса 0x78 или 0x7A.

Назначение контактов J2:
SCL: линия тактирования (Serial CLock)
SDA: линия данных (Serial Dфta)
VCC: «+» питание
GND: «-» питание

Подключение к Arduino

Необходимые детали:
Arduino UNO R3 x 1 шт.
LCD-дисплей 1602A (2×16, 5V, Синий) x 1 шт.
Провод DuPont, 2,54 мм, 20 см, F-M (Female — Male) x 1 шт.
Кабель USB 2.0 A-B x 1 шт.

Подключение :
В примере буду использовать плату Arduino UNO R3 и OLED дисплей (расширением 128×64), как говорил ранее, используемый интерфейс I2c, для подключения необходимо всего два провода, подключаем SDA дисплея к выводу A4 (Arduino), а SCL к выводу A5 (Arduino). При использовании, других платформ Mega или Nano необходимо использовать другие порты, для удобства приведу таблицу, подключения для различных плат. Далее, необходимо подключить питание, GND к GND, а VCC к 5 В или 3.3В, схема собрана, теперь осталось загрузить скетч.


Таблица подключений

Для работы с OLED дисплеем необходима библиотека, так-как библиотек несколько, пример работы покажу через библиотеку OLED_I2C (скачать библиотеку можно в конце статьи)
Программа только отображает текст на дисплей и больше не какого функционала не несет, скачиваем скетч и загружаем ее в плату Arduino UNO R3.

/* Тестировалось на Arduino IDE 1.8.0 Дата тестирования 27.01.2017г. */ #include // Подключаем библиотеку OLED_I2C OLED myOLED(SDA, SCL, 8); // Выбор порта, UNO это SDA 8 pin, SCL - 9 pin. extern uint8_t SmallFont; // Подключаем шрифт void setup() { myOLED.begin(); // инициализация экрана myOLED.setFont(SmallFont); } void loop() { myOLED.clrScr(); // Очищаем экран myOLED.print("Hello!", CENTER, 24); // Выводим текст: в центре, строка 24 myOLED.print("www.robotchip.ru", CENTER, 40); // Выводим текст: в центре, строка 40 myOLED.update(); // delay (500); // пауза 0.5 с }

Тестировалось на Arduino IDE 1.8.0

Дата тестирования 27.01.2017г.

#include // Подключаем библиотеку OLED_I2C

OLED myOLED (SDA , SCL , 8 ) ; // Выбор порта, UNO это SDA 8 pin, SCL - 9 pin.

extern uint8_t SmallFont ; // Подключаем шрифт

void setup ()

myOLED . begin () ; // инициализация экрана

myOLED . setFont (SmallFont ) ;

void loop ()

myOLED . clrScr () ; // Очищаем экран

myOLED . print ("Hello!" , CENTER , 24 ) ; // Выводим текст: в центре, строка 24

myOLED . print ("www.robotchip.ru" , CENTER , 40 ) ; // Выводим текст: в центре, строка 40

myOLED . update () ; //

delay (500 ) ; // пауза 0.5 с

Скачать скетч

Добрый день, друзья!
Эта статья открывает цикл, посвящённый средствам визуального отображения информации.
Нами будут рассмотрены модули, в состав которых входят следующие дисплеи и управляющие контроллеры:


3. TFT дисплей на 2.8 дюйма (240×320 пикселей), контроллер ILI9341.
4. TFT дисплей на 3.5 дюйма (320×480 пикселей), контроллер ILI9481.

Весь материал разбит на пять частей, в четырёх из которых изложена информация по модулям (технические параметры, подключение и инициализация, вывод на дисплей базового графического элемента - точки), а пятая содержит единую графическую библиотеку для описанных дисплеев.

Сама идея единой библиотеки и большинство приёмов её реализации позаимствованы из библиотеки Adafruit_GFX, а также отдельных работ её авторов - Лимор Фрид (Limor Fried) и Кевина Таунсенда (Kevin Townsend).
Моя скромная заслуга заключается в переносе кода с С++ на С, написании отдельных функций и выборочном переводе даташитов с целью более детального освещения особенностей работы модулей.

OLED дисплей на 0.96 дюйма (128×64 пикселей), контроллер SSD1306

Тема сегодняшней нашей беседы – вот такой модуль:

Основные характеристики OLED-модуля

Размеры: 27мм х 27мм х 4.1 мм.
Разрешение: 128х64 пикселя.
Угол обзора: >160°.
Цветность: чёрно-белый. В реальности «белый» пиксель может светиться голубым или, как на рисунке выше, жёлтым цветом, но это, как вы понимаете, не делает дисплей цветным.
Энергопотребление: 0.08Вт при включённом дисплее.
Рабочая температура: от – 30 до 70 градусов по Цельсию.
Напряжение питания: 3В – 5В.
Протокол обмена данными: I2c или SPI.

Назначение выводов

Для модуля с протоколом I2c:
SCL, SDA – линии протокола. Подтягивающие резисторы уже встроены в модуль, поэтому соединение с микроконтроллером (МК) – напрямую.
VCC, GND – линии питания.

Для модуля с протоколом SPI:
SCK, MOSI – линии протокола. Тут каждый производитель старался, как мог, поэтому эти выводы могут иметь и другие названия – DO/DI, CLK/DIN и даже, как ни странно, SCL/SDA. Вывод MISO отсутствует по причине, о которой будет сказано ниже.
CS – выбор чипа, аналог SS. Активный уровень – низкий.
DC – выбор типа записываемого в SSD1306 слова – данные или команда.
RES – аппаратный сброс. В прилагаемой библиотеке прописана функция программного сброса, так что, если вы ограничены в выводах микроконтроллера, можно соединить этот вывод с аналогичным пином МК либо подтянуть его к питанию.
VCC, GND – линии питания.

Особенности протоколов обмена данными

Протокол SPI – стандартный, за исключением двух нюансов:
1. Чтение из модуля невозможно по причине отсутствия вывода MISO. Причина, по которой производители пошли на это, заключается, как мне кажется, в следующем. Единственная информация, которую можно извлечь из SSD1306 – включен дисплей или нет. Данные, согласитесь, не настолько бесценные, чтобы тратиться на организацию целой линии обмена.
2. В зависимости от состояния вывода DC записываемый в модуль байт будет интерпретироваться как команда (состояние «0») или данные (состояние «1»).

Функция записи команды, с учётом макроопределений, будет выглядеть так:
#define cbi(_byte, _bit) _byte &= ~(1<<_bit) #define sbi(_byte, _bit) _byte |= (1<<_bit) void ssd1306_command(uint8_t command) { cbi(SSD_PORT, DC_pin); cbi(SSD_PORT, CS_pin); SPI_byte(command); sbi(SSD_PORT, CS_pin); }

А байт данных записывается следующим образом:
void ssd1306_data(uint8_t data) { sbi(SSD_PORT, DC_pin); cbi(SSD_PORT, CS_pin); SPI_byte(data); sbi(SSD_PORT, CS_pin); }

Для выяснения особенностей протокола I2c обратимся к следующему рисунку из прилагаемого даташита SSD1306:

Как видите, запись в модуль происходит как минимум тремя байтами.
Первый байт – сдвинутый на один бит влево адрес (0х3С) с добавленным битом выбора типа операции (чтение или запись). В интернете упоминается, что адрес SSD1306 может быть и 0x3D, поэтому, если ваш модуль не запускается, возможно, стоит попробовать поменять в программе его адрес.
Следующим идёт контрольный байт, шестой бит которого (D/C) определяет тип записываемого слова: команда или данные. По сути, этот бит – программный аналог вывода DC в модулях с протоколом SPI.
Третий байт – непосредственно команда или данные.
Таким образом, функции обмена обретают следующий вид:
#define SSD1306_ADDRESS 0x3C #define DC_BIT 6 #define CONTROL_BYTE_COMMAND 0 << DC_BIT #define CONTROL_BYTE_DATA 1 << DC_BIT #define WRITE 0 void ssd1306_command(uint8_t command) { i2c_start(); i2c_write((SSD1306_ADDRESS << 1) | WRITE); i2c_write(CONTROL_BYTE_COMMAND); i2c_write(command); i2c_stop(); } void ssd1306_data(uint8_t data) { i2c_start(); i2c_write((SSD1306_ADDRESS << 1) | WRITE); i2c_write(CONTROL_BYTE_DATA); i2c_write(data); i2c_stop(); }
Функция чтения для протокола I2c в библиотеке не прописана по соображениям, приведённым выше для объяснения отсутствия вывода MISO.

Система команд

Полный перевод таблиц команд выложен в архиве. Все команды условно разделены на шесть групп:
1. Базовые команды.
2. Команды прокрутки.
3. Команды адресации.
4. Команды аппаратной настройки.
5. Команды тайминга и схемы управления.
6. Команды ёмкостного умножителя.

Команды могут быть как однобайтными так и многобайтными, причем второй и последующие байты записываются как отдельные команды:
ssd1306_command(command_byte_1); ssd1306_command(command_byte_2); ssd1306_command(command_byte_3);

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

0хAE/0хAF – выключение/включение дисплея. Как только модуль подключается к питанию, SSD1306 готов принимать и исполнять команды, в том числе выводить изображение на дисплей. Однако само изображение вы не увидите, поскольку по сбросу/подаче питания выполняется команда 0хAE, т.е. дисплей выключен. Поэтому в функции инициализации модуля необходимо, среди прочего, прописать команду 0хAF.

0х81 – двухбайтная команда установки контрастности, значение которой определяется вторым байтом в диапазоне от 1 до 256.

0х20 – установка режима адресации. Эта команда определяет порядок вывода данных на дисплей: горизонтальный, вертикальный или постраничный. Более подробно об этом - чуть позже, а пока лишь скажу, что мы будем использовать режим горизонтальной адресации.

0х21/0х22 – установка адресов столбца/страницы. В более понятном выражении эти команды позволяют задать координаты пикселя, который вы хотите активировать.

А0/А1 - с точки зрения изображения на дисплее эти команды ответственны за отражение по горизонтали.


C0/C8 – определение порядка сканирования COM-выводов дисплея. Если проще – отражение по вертикали.


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


0x8D - включение/выключение ёмкостного умножителя. При включении дисплея без использования этой команды, изображение будет едва видимо, даже, если командой 0х81 выставить максимальное значение контрастности. Дело в том, что рабочее напряжение дисплея – от 7В до 15В. Поскольку подаваемого на выводы модуля напряжения (3В – 5В) не достаточно, в его состав включён емкостной умножитель, повышающий уровень напряжения до необходимого. По сбросу/подаче питания этот узел отключен, поэтому второй обязательной командой в функции инициализации модуля должна быть, помимо 0хAF, команда включения ёмкостного умножителя.

Вывод изображения на дисплей

Собственно, как только вывод DC (протокол SPI) или бит D/C контрольного байта (протокол I2c) выставлены в 1, записываемый в модуль байт будет выводиться на дисплей. Если быть более точным, мы с помощью функции ssd1306_data() отправляем байт в ОЗУ (GDDRAM), входящего в состав SSD1306, а далее данные автоматически выводятся на дисплей.

Давайте разберёмся, как именно происходит этот процесс.
В соответствии с количеством пикселей на дисплее ОЗУ содержит 128х64 бит, разделенных на восемь страниц по 128х8 бит или 128 байт в каждой. В случае настроек по сбросу/подаче питания данные из ОЗУ выводятся на дисплей в следующем порядке:


А комбинация команд 0хА1 и 0хС8 меняет порядок вывода таким образом:


Каждому из 128 байтов в странице ОЗУ соответствует вертикальная черта шириной 1 и высотой 8 пикселей в области дисплея, ограниченной на рисунке прямоугольником с соответствующей надписью. Отсчёт адреса столбцов ведётся слева-направо, а порядок расположения битов байта – сверху-вниз. Более наглядно сказанное поясняет рисунок из даташита:


Здесь выполнены следующие действия: соответствующими командами заданы столбец 4 (SEG4) и страница 2 (PAGE2), а затем с записано число 01000001 (65 – в десятичном исчислении). Часть кода, обеспечивающая этот процесс, выглядит для режимов горизонтальной или вертикальной адресации так:
//записываем команду установки адреса столбца ssd1306_command(0х21); //начальный адрес столбца ssd1306_command(4); //конечный адрес столбца, в данном случае он совпадает с начальным ssd1306_command(4); //записываем команду установки адреса страницы ssd1306_command(0х22); //начальный адрес страницы ssd1306_command(2); //конечный адрес страницы, в данном случае он совпадает с начальным ssd1306_command(2); //записываем число 65 ssd1306_data(65);
По исполнению вы получите два светящихся пикселя в заданном месте дисплея:


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

В состав SSD1306 входят счётчики адресов столбцов и страниц, текущее значение которых и определяет адрес в ОЗУ (читай – координаты на дисплее), по которому будет записан байт данных. Каждое обращение к GDDRAM приводит к автоматическому инкременту того или иного счётчика, а заданные нами начальный и конечный адреса определяют, начиная с какого и до какого значения будет происходить счёт.

Выбирая же режим адресации, мы определяем порядок работы и взаимодействия счётчиков.
Для режима горизонтальной адресации при каждом исполнении функции ssd1306_data() увеличивается на единицу значение счётчика адреса столбца. По достижении заданного конечного значения счётчик адреса столбца сбрасывается в начальное значение, а счётчик адреса страницы увеличивается на единицу. После достижения счётчиком адреса страницы заданного конечного значения оба счётчика сбросятся в начальные значения и процесс пойдёт по второму кругу.

Для режима вертикальной адресации, наоборот, увеличивается на 1 значение счётчика адреса страницы. После его заполнения следует сброс в начальное значение, инкремент счётчика адреса столбца и так далее.

Для режима постраничной адресации предусмотрен только счётчик адреса столбца, то есть все действия происходят в пределах одной выбранной страницы. Кроме того, в этом режиме не предусмотрен конечный адрес столбца, так что рост значения счётчика продолжается до значения 127 (конец страницы), а затем, в отличие от двух других режимов, не сбрасывается в начальное значение, а обнуляется.

Для наглядности изложенного приведу части кода и полученные на дисплее результаты для всех трёх режимов адресации.
#define HORIZONTAL_ADDRESSING 0x00 // выбираем режим горизонтальной адресации ssd1306_command(0x20); ssd1306_command(HORIZONTAL_ADDRESSING); // пределы счёта для счётчика столбцов – от 64 до 127 ssd1306_command(0x21); ssd1306_command(64); ssd1306_command(127); // пределы счёта для счётчика страниц – от 3 до 4 ssd1306_command(0x22); ssd1306_command(3); ssd1306_command(4); // выводим 65 вертикальных чёрточек по 8 пикселей на дисплей for(int i = 0; i < 65; i++) { ssd1306_data(255); }

#define VERTICAL_ADDRESSING 0x01 // выбираем режим вертикальной адресации ssd1306_command(0x20); ssd1306_command(VERTICAL_ADDRESSING); // пределы счёта для счётчика столбцов – от 64 до 65 ssd1306_command(0x21); ssd1306_command(64); ssd1306_command(65); // пределы счёта для счётчика страниц – от 3 до 7 ssd1306_command(0x22); ssd1306_command(3); ssd1306_command(7); // выводим 6 вертикальных чёрточек по 8 пикселей на дисплей for(int i = 0; i < 6; i++) { ssd1306_data(255); }

#define PAGE_ADDRESSING 0x02 #define COLUMN_NUMBER 64 #define PAGE_NUMBER 3 // выбираем режим постраничной адресации ssd1306_command(0x20); ssd1306_command(PAGE_ADDRESSING); // младшая тетрада начального адреса столбца ssd1306_command(0x00 | (COLUMN_NUMBER & 0x0F)); // старшая тетрада начального адреса столбца ssd1306_command(0x10 | (COLUMN_NUMBER >> 4)); //начальный адрес страницы ssd1306_command(0xB0 | PAGE_NUMBER); // выводим 65 вертикальных чёрточек по 8 пикселей на дисплей for(int i = 0; i < 65; i++) { ssd1306_data(255); }


Перейдём к прорисовке базового элемента – точки. Как вы поняли, конструктивные особенности SSD1306 не дают нам возможность задавать отдельную строку на дисплее, а лишь страницу. Во-первых, из-за этого мы не можем объединить единой библиотекой этот модуль с другими, которые оперируют координатами пикселя - столбец/строка (или – х/у). Во-вторых, это – просто неудобно и непривычно.
Используем следующие конструкции для определения из координаты «у» номера страницы:
uint8_t page; if(y < 8) { page = 0; } else if (y >= 8) { page = (int)(y/8); }
и строки:
y&7
Тогда вывести точку в нужное место дисплея можно так:
#define BLACK 0 #define WHITE 1 //х – от 0 до 127, у – от 0 до 63 void draw_pixel(uint8_t x, uint8_t y, uint8_t color) { uint8_t page; if(y < 8) { page = 0; } else if (y >= 8) { page = (int)(y/8); } ssd1306_command(0x21); ssd1306_command(x); ssd1306_command(x); ssd1306_command(0x22); ssd1306_command(page); ssd1306_command(page); if(color == WHITE) { ssd1306_data(1 << (y&7)); } else if(color == BLACK) { ssd1306_data(0 << (y&7)); } }
На этом статью можно было бы считать завершённой, если бы не одно «но» - мы не можем поменять состояние одного пикселя, не затронув остальные семь, связанные с ним. Используя функцию draw_pixel() в приведённом виде мы будем гасить на дисплее 7 ни в чём не повинных точек.

Чтобы этого не происходило, необходимо не только каким-то образом изменить функцию, но и, до вхождения в неё, знать состояние пикселей – 0 или 1. В масштабе всего дисплея мы должны в любой момент знать текущее состояние всех 128х64 пикселей или 128х8 байт памяти. Поскольку извлечь эту информацию из SSD1306, как вы помните, невозможно, придётся создать массив соответствующей размерности.
#define SSD1306_LCDWIDTH 128 #define SSD1306_LCDHEIGHT 64 uint8_t buffer;
Создание массива порождает новый вопрос – как оптимально, с точки зрения кода, увязать порядковый номер элемента массива с координатами 8-пиксельной черты на дисплее? Создатели библиотеки Adafruit_GFX использовали простой и изящный приём, приняв во внимание следующее:
1. При режиме горизонтальной адресации сдвиг координат на дисплее происходит слева-направо и сверху-вниз, так же, как и при последовательной выборке элементов из массива.
2. Размеры 128х64 пикселя позволяют незаметно для человеческого глаза прорисовывать каждый раз весь дисплей.

В итоге прорисовку точки будут обеспечивать две функции:
//эта функция меняет состояние соответствующего бита //в элементе массива, определяемого координатами х/у void draw_pixel(int16_t x, int16_t y, uint16_t color) { switch (color) { case WHITE: buffer |= (1 << (y&7)); break; case BLACK: buffer &= ~(1 << (y&7)); break; } } //а эта последовательно выбирает байты из массива и отправляет их в ОЗУ SSD1306 void ssd1306_draw_display(void) { ssd1306_command(SSD1306_COLUMNADDR); ssd1306_command(0); ssd1306_command(SSD1306_LCDWIDTH-1); ssd1306_command(SSD1306_PAGEADDR); ssd1306_command(0); ssd1306_command(7); #if defined I2C_INTERFACE i2c_start(); i2c_write((SSD1306_ADDRESS << 1) | WRITE); i2c_write(CONTROL_BYTE_DATA); for (uint16_t i=0; i<(SSD1306_LCDWIDTH*SSD1306_LCDHEIGHT/8); i++) { i2c_write(buffer[i]); } i2c_stop(); #elif defined SPI_INTERFACE sbi(SSD_PORT, DC_pin); cbi(SSD_PORT, CS_pin); for (uint16_t i=0; i<(SSD1306_LCDWIDTH*SSD1306_LCDHEIGHT/8); i++) { SPI_byte(buffer[i]); } sbi(SSD_PORT, CS_pin); #endif }

Структура и содержание библиотеки SSD1306

Библиотека состоит из 8 файлов. Приведу их краткое содержание:
1. main.c – подключает необходимые для работы библиотеки, инициализирует модуль и выводит на дисплей изображение. Какое именно, вы узнаете, запустив программу.
2. main.h – выбор протокола обмена (SPI или I2c) и типа сброса (программный или аппаратный). Библиотека пригодна к использованию для модулей с обоими вариантами протокола и сброса, поэтому для выбора подходящих вам параметров раскомментируйте соответствующие строки в этом файле.
3. i2c.c – содержит функции программного протокола I2c. Обычно я пользуюсь аппаратным вариантом. Но, хотелось, чтобы библиотека была полезна как можно большему кругу людей, поэтому я воспользовался кодом из этой . Вы можете заменить содержимое этого файла тем кодом, которому больше доверяете и обычно используете, обеспечив лишь соответствие названий функций.
4. i2c.h – назначение выводов МК, участвующих в протоколе I2c.
5. spi.c – функции программного SPI. Так же, как и в случае с I2c, можете заменить их на свои.
6. spi.h – назначение выводом МК, к которым подключается модуль с одноимённым протоколом обмена.
7. ssd1306.с – функции, непосредственно обеспечивающие работу модуля. Кроме тех, что уже упомянуты в статье, здесь вы найдёте функции инициализации, аппаратного и программного сброса, полной очистки дисплея, выбора ориентации изображения на экране, а также, для желающих организовать бегущую строку, функции прокрутки.
8. ssd1306.h – определение параметров дисплея (цвета, размеры), макроопределения всех используемых команд контроллера. Здесь же объявлен массив buffer, который развёрнут по причине, указанной в п.1.

Файлы

Релиз 2. 14-09-2016 обновлена библиотека. В main.c подключение фалов библиотеки не через h-файлы, как было, а через с-файлы, как принято в большинстве компиляторов. Кроме того явно прописано подключение стандартной библиотеки string.h

Trema-модуль OLED-дисплей (128x64) - это графический дисплей, каждый пиксель которого является отдельным OLED (organic light-emitting diode) светодиодом.

Дисплей не нуждается в подсветке, значит черный цвет - действительно чёрный (не светится в темноте), а использование органических светодиодов позволило достичь угла обзора более 160° и значительно снизить энергопотребление. Так же стоит отметить высокую контрастность и небольшие размеры дисплея - всего 0.96 дюйма. Всё это позволяет сказать, что OLED-дисплей является одним из лучших дисплеев.

Видео

Характеристики

  • Тип дисплея: графический, OLED (organic light-emitting diode) на основе органических светодиодов.
  • Тип драйвера матрицы: SSD1306.
  • Разрешение: 128 x 64 точек.
  • Цвет пикселей (светодиодов): белый.
  • Количество цветов: белый и черный (монохромный).
  • Угол обзора: > 160°.
  • Коэффициент контрастности: 10000:1.
  • Яркость: >120 кд/м 2 .
  • Напряжение питания: 3,3 ... 5 В.
  • Энергопотребление: до 80 мВт (при свечении всего экрана);
  • Интерфейс: I2C (поддерживается Arduino, WeMos, STM32, MSP430 и множеством других микроконтроллеров, и отладочных плат).
  • Адрес на шине I2C: 0x3C или 0x3D выбирается переключателем.
  • Время отклика < 10 мкс.
  • Рабочая температура: -40 ... 85 °С.
  • Габариты: 30x30 мм.

Все модули линейки "Trema" выполнены в одном формате

Подключение

Для удобства подключения к Arduino воспользуйтесь , или .

Для работы с Trema OLED дисплеями, нами разработано сразу две библиотеки.

Поделиться: