Использование OLED дисплея совместно с Arduino

Надоело использовать символьные ЖК-дисплей в своих проектах Arduino? Что ж! Они действительно уходят в прошлое. Используйте в своих проектах современные OLED (органические светодиоды) дисплеи! Они легкие, тонкие, теоретически гибкие и дают более яркое и четкое изображение.

Модуль OLED диспля на основе драйвера SSD1306

В основе модуля лежит мощный однокристальный CMOS контроллер SSD1306. Он может общаться с микроконтроллером несколькими способами, включая I2C и SPI .

Протокол SPI, как правило, быстрее, чем I2C, но требует большего количества контактов ввода/вывода микроконтроллера. В то время как I2C требует только два контакта и может использоваться совместно с другими периферийными устройствами I2C. Это компромисс между экономией выводов и скоростью.

Благодаря универсальности контроллера SSD1306, модуль поставляется в разных размерах и цветах: например, 128×64, 128 × 32, с белыми OLED, синими OLED и двухцветными OLED. Хорошей новостью является то, что все эти дисплеи взаимозаменяемы.

Требование к источнику питания

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

Отсутствие подсветки значительно снижает ток потребления. В среднем дисплей потребляет около 20 мА , хотя это зависит от того, какая часть дисплея задействована.

Рабочее напряжение контроллера SSD1306 составляет от 1,65 до 3,3 В, в то время как для OLED-панели требуется напряжение питания от 7 до 15 В. Все эти различные требования к питанию решаются путем использования схемы Charge Pump. Это позволяет легко подключить модуль к Arduino или любому 5-вольтовому логическому микроконтроллеру без использования преобразователя логического уровня.

Организация памяти SSD1306

Независимо от размера OLED модуля драйвер SSD1306 имеет встроенную память объемом 1 КБ (GDDRAM). Эта область памяти разбита на 8 страниц (от 0 до 7). Каждая страница содержит 128 столбцов / сегментов (блок от 0 до 127). И каждый столбец может хранить 8 бит данных (от 0 до 7):

8 страниц x 128 сегментов x 8 бит данных = 8192 бит = 1024 байт = 1 Кб памяти

 

Организация памяти SSD1306

Каждый бит представляет собой определенный OLED пиксель на экране, который может быть включен или выключен программно.

Экран 128 × 64 OLED отображает все содержимое ОЗУ, тогда как экран 128 × 32 OLED отображает только 4 страницы (половину содержимого) ОЗУ.

Распиновка модуля дисплея OLED

Прежде чем перейти к написанию кода и рассмотрению примеров, давайте сначала посмотрим на распиновку OLED модуля:

Распиновка модуля дисплея OLED

  • GND — вывод должен быть подключен к земле Arduino
  • VCC — вывод  питания для дисплея, к которому мы подключаем 5-вольтный контакт на Arduino
  • SCL — вывод синхронизации для интерфейса I2C
  • SDA — вывод данных для интерфейса I2C

Подключение модуля OLED к Arduino Uno

Прежде чем мы перейдем к загрузке кода и отправке данных на дисплей, давайте подключим дисплей к Arduino.

Схема подключения довольно проста. Начните с подключения контакта VCC к выходу 5V на Arduino и GND к земле. Теперь остались выводы, которые используются для связи по I2C. Обратите внимание, что каждая плата Arduino имеет разные контакты I2C.

На платах Arduino с маркировкой R3 SDA (линия передачи данных) и SCL (линия синхронизации) находятся на разъемах рядом с выводом AREF. Они также известны как A5 (SCL) и A4 (SDA).

Если у вас MEGA, контакты будут другие! Используйте цифровые 21 (SCL) и 20 (SDA).

линии I2C для различных Arduino

На следующей схеме показано как все должно быть подключено:

Подключение модуля OLED к Arduino Uno

Установка библиотеки для модуля OLED

Контроллер SSD1306 OLED дисплея имеет гибкие, но сложные драйверы. Для использования контроллера SSD1306 необходимы огромные знания по адресации памяти. К счастью,  была написана библиотека Adafruit SSD1306, которая позволяет довольно простыми и понятными командами управлять OLED дисплеем.

Чтобы установить библиотеку, перейдите в раздел Sketch > Include Library > Manage Libraries…. Подождите, пока менеджер библиотеки загрузит индекс библиотек и обновит список установленных библиотек.

 библиотека Adafruit SSD1306

Отфильтруйте результаты поиска, введя adafruit ssd1306. Там должна быть пара записей. Ищите Adafruit SSD1306 от Adafruit. Нажмите на эту запись, а затем выберите Установить.

Библиотека Adafruit SSD1306 представляет собой аппаратную библиотеку, которая выполняет функции более низкого уровня. Она должна быть сопряжена с библиотекой Adafruit GFX для отображения графических примитивов, таких как точки, линии, круги, прямоугольники и т. д. Также установите и эту библиотеку.

 библиотека Adafruit GFX

Известная проблема с контроллером SSD1306

Хотя SSD1306 имеет встроенный GDDRAM для экрана, мы не можем прочитать его содержимое (согласно Adafruit). Следовательно, невозможно управлять экранным буфером для выполнения математических операций.

В качестве альтернативы библиотека выделяет 1 КБ (128 × 64) / 8 бит) памяти ATmega328P в качестве буфера. Таким образом, появляется возможность манипулировать экранным буфером и затем выполнять массовую передачу из памяти ATmega328P во внутреннюю память контроллера SSD1306.

Модификация библиотеки Adafruit SSD1306

Библиотека Adafruit SSD1306 не настроена для 128 × 64 OLED-дисплеев (используемый в данной статье). Размер экрана необходимо изменить в заголовочном файле Adafruit_SSD1306.h.

Если этого не сделать, то при компиляции мы получим сообщение об ошибке #error (“Height incorrect, please fix Adafruit_SSD1306.h!”):

сообщение об ошибке

Чтобы изменить заголовочный файл Adafruit_SSD1306.h, откройте Документы > Arduino. Теперь перейдите в библиотеку Adafruit_SSD1306:

Модификация библиотеки Adafruit SSD1306

Откройте файл Adafruit_SSD1306.h в текстовом редакторе (например, notepad++). Прокрутите файл вниз, чтобы найти раздел с дисплеями SSD1306 или сразу перейдите к строке №73. Закомментируйте #define SSD1306_128_32 и раскомментируйте #define SSD1306_128_64, чтобы код в этом разделе выглядел следующим образом:

редактирование библиотеки

Вот и все. Теперь сохраните файл и перезапустите вашу Arduino IDE.

Скетч для отображения текста на OLED

Теперь самое интересное!

Следующий тестовый скетч напечатает «Hello World!» сообщение на дисплее. Он также включает:

  • Отображение перевернутого текста
  • Отображение номеров
  • Отображение чисел  (Hex, Dec)
  • Отображение ASCII символов
  • Прокрутка текста по горизонтали и вертикали
  • Прокрутка части дисплея

Это даст вам полное представление о том, как использовать OLED-дисплей, и может послужить основой для реализации своих проектов.

При компиляции кода в среде IDE появиться  предупреждение о нехватке памяти. Это связано с тем, что библиотека выделяет 1 КБ памяти ATmega328P в качестве буфера отображения. Вы можете игнорировать это.

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <SPI.h>
Adafruit_SSD1306 display(-1);
void setup()   
{                
  // инициализируем I2C addr 0x3C
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  

  // Очистить буфер.
  display.clearDisplay();

  // Показать текст
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,28);
  display.println("Hello world!");
  display.display();
  delay(2000);
  display.clearDisplay();

  // Показать инвертированный текст
  display.setTextColor(BLACK, WHITE);
  display.setCursor(0,28);
  display.println("Hello world!");
  display.display();
  delay(2000);
  display.clearDisplay();

  // Изменение размера шрифта
  display.setTextColor(WHITE);
  display.setCursor(0,24);
  display.setTextSize(2);
  display.println("Hello!");
  display.display();
  delay(2000);
  display.clearDisplay();

  // Показать числа
  display.setTextSize(1);
  display.setCursor(0,28);
  display.println(123456789);
  display.display();
  delay(2000);
  display.clearDisplay();

  // Указание базиса для чисел
  display.setCursor(0,28);
  display.print("0x"); display.print(0xFF, HEX); 
  display.print("(HEX) = ");
  display.print(0xFF, DEC);
  display.println("(DEC)"); 
  display.display();
  delay(2000);
  display.clearDisplay();

  // Отображение символов ASCII
  display.setCursor(0,24);
  display.setTextSize(2);
  display.write(3);
  display.display();
  delay(2000);
  display.clearDisplay();

  // Прокрутка всего экрана
  display.setCursor(0,0);
  display.setTextSize(1);
  display.println("Full");
  display.println("screen");
  display.println("scrolling!");
  display.display();
  display.startscrollright(0x00, 0x07);
  delay(2000);
  display.stopscroll();
  delay(1000);
  display.startscrollleft(0x00, 0x07);
  delay(2000);
  display.stopscroll();
  delay(1000);    
  display.startscrolldiagright(0x00, 0x07);
  delay(2000);
  display.startscrolldiagleft(0x00, 0x07);
  delay(2000);
  display.stopscroll();
  display.clearDisplay();

  // Прокрутка части экрана
  display.setCursor(0,0);
  display.setTextSize(1);
  display.println("Scroll");
  display.println("some part");
  display.println("of the screen.");
  display.display();
  display.startscrollright(0x00, 0x00);
}
void loop() {}

Скетч начинается с подключения четырех библиотек, а именно. SPI.h, Wire.h, Adafruit_GFX.h и Adafruit_SSD1306.h. Хотя библиотека SPI.h не требуется для I2C OLED-дисплеев, нам нужно добавить ее для компиляции нашей программы:

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <SPI.h>

Далее нам нужно создать объект Adafruit_SSD1306.h. Конструктор Adafruit_SSD1306 принимает номер контакта Arduino, к которому подключен вывод сброса дисплея. Поскольку используемый нами OLED-дисплей не имеет вывода RESET, мы отправим в конструктор -1 , чтобы ни один из выводов Arduino не использовался в качестве сброса для дисплея.

Adafruit_SSD1306 display(-1);

В функции setup() нам нужно инициализировать объект OLED с помощью функции begin(). Функция принимает два параметра. Первый параметр SSD1306_SWITCHCAPVCC включает схему charge pump, а второй параметр устанавливает адрес I2C OLED дисплея. I2C адрес такого OLED модуля обычно равен 0x3C.

Далее мы очищаем буфер перед печатью нашего первого сообщения:

// инициализируем I2C addr 0x3C
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  
// Очистить буфер.
display.clearDisplay();

Отображение простого текста (Hello World)

display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,28);
display.println("Hello world!");
display.display();
delay(2000);

Для отображения текста на экране нам нужно установить размер шрифта. Это может быть сделано путем вызова setTextSize() и передачи размера шрифта (начиная с 1) в качестве параметра.

Далее нам нужно установить цвет шрифта, вызвав функцию setTextColor(). Передайте параметр WHITE для темного фона и BLACK для яркого фона. Теперь перед печатью сообщения нам нужно установить позицию курсора, вызвав функцию setCursor (X, Y).

Пиксели на экране адресуются по горизонтальным (X) и вертикальным (Y) координатам. Система координат размещает начало координат (0,0) в верхнем левом углу, причем положительный X увеличивается вправо, а положительный Y увеличивается вниз.

Мы можем использовать функцию print() или println() для печати сообщения на экране так же, как мы печатаем данные на последовательном мониторе. Помните, println () переместит курсор на новую строку.

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

Для этого требуется команда display(), чтобы дать указание библиотеке выполнить массовую передачу из экранного буфера ATmega328P во внутреннюю память контроллера SSD1306. Как только память будет перенесена, на OLED-дисплее появятся пиксели, соответствующие экранному буферу.

Инверсия сообщения

display.clearDisplay();
display.setTextColor(BLACK, WHITE);
display.setCursor(0,28);
display.println("Hello world!");
display.display();
delay(2000);

Для выполнения инверсии мы снова вызываем функцию setTextColor(FontColor,BackgroundColor). Если вы обратили внимание, то вы заметите, что до этого мы передали только один параметр этой функции, но теперь мы передаем два параметра.

Изменение размера шрифта

display.clearDisplay();
display.setTextColor(WHITE);
display.setCursor(0,24);
display.setTextSize(2);
display.println("Hello!");
display.display();
delay(2000);

Ранее мы вызывали функцию setTextSize() для установки размера шрифта и передавали 1 в качестве параметра. Вы можете использовать эту функцию для масштабирования шрифта, передавая любое неотрицательное целое число.

Символы отображаются в соотношении 7:10. Это означает, что при передаче размера шрифта 1 текст будет отображаться с разрешением 7 × 10 пикселей на символ, при передаче 2 будет отображаться текст с разрешением 14 × 20 пикселей на символ и т. д.

Отображение чисел

display.clearDisplay();
display.setTextSize(1);
display.setCursor(0,28);
display.println(123456789);
display.display();
delay(2000)

Числа могут быть отображены на OLED дисплее путем вызова функций print() или println().

Указание базиса чисел

Указание базиса чисел

display.clearDisplay();
display.setCursor(0,28);
display.print("0x"); display.print(0xFF, HEX); 
display.print("(HEX) = ");
display.print(0xFF, DEC);
display.println("(DEC)"); 
display.display();
delay(2000);

Функции print() и println() имеет второй необязательный параметр , который определяет базу (формат).  Допустимые значения:

  • BIN (двоичное или базовое 2),
  • OCT (восьмеричное или базовое 8),
  • DEC (десятичное или базовое 10),
  • HEX (шестнадцатеричное или базовое 16).

Для чисел с плавающей запятой этот параметр указывает количество десятичных знаков. Например:

  • print(78, BIN) — дает «1001110»
  • print(78, OCT) — дает «116»
  • print(78, DEC) — дает «78»
  • print(78, HEX) — дает «4E»
  • println(1.23456, 0) — дает «1»
  • println(1.23456, 2) — дает «1.23»
  • println(1.23456, 4) — дает «1.2346»

Отображение ASCII символов

display.clearDisplay();
display.setCursor(0,24);
display.setTextSize(2);
display.write(3);
display.display();
delay(2000);

Функции print() и println() отправляют данные на дисплей в виде удобочитаемого текста ASCII, а функция write() отправляет двоичные данные. Таким образом, вы можете использовать эту функцию для отображения символов ASCII. В нашем примере отправка числа 3 будет отображать символ сердца.

Полноэкранная прокрутка

display.clearDisplay();
display.setCursor(0,0);
display.setTextSize(1);
display.println("Full");
display.println("screen");
display.println("scrolling!");
display.display();
display.startscrollright(0x00, 0x07);
delay(2000);
display.stopscroll();
delay(1000);
display.startscrollleft(0x00, 0x07);
delay(2000);
display.stopscroll();
delay(1000);    
display.startscrolldiagright(0x00, 0x07);
delay(2000);
display.startscrolldiagleft(0x00, 0x07);
delay(2000);
display.stopscroll();

Вы можете прокручивать дисплей по горизонтали, вызывая функции startscrollright() и startscrollleft(), и по диагонали, вызывая startscrolldiagright() и startscrolldiagleft(). Все эти функции принимают два параметра, а именно: начальная страница и конечная страница.

Поскольку на дисплее отображается восемь страниц от 0 до 7, вы можете прокручивать весь экран, прокручивая все страницы, то есть передавая параметры 0x00 и 0x07. Чтобы остановить отображение прокрутки вы можете использовать функцию stopscroll().

Прокрутка определенной части

display.setCursor(0,0);
display.setTextSize(1);
display.println("Scroll");
display.println("some part");
display.println("of the screen.");
display.display();
display.startscrollright(0x00, 0x00);

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

Поскольку на дисплее отображается восемь страниц от 0 до 7, мы можете прокрутить некоторую часть экрана, передавая конкретные номера страниц в качестве параметров.

В нашем примере мы передали оба параметра как 0x00. Это позволит прокрутить только первую страницу (первые 8 строк) дисплея.

Код Arduino — базовые фигуры

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

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <SPI.h>
Adafruit_SSD1306 display(-1);
void setup()    
{                
  // инициализируем I2C addr 0x3C
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  

  // Очистить буфер.
  display.clearDisplay();

  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  display.println("Rectangle");
  display.drawRect(0, 15, 60, 40, WHITE);
  display.display();
  delay(2000);
  display.clearDisplay();

  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  display.println("Filled Rectangle");
  display.fillRect(0, 15, 60, 40, WHITE);
  display.display();
  delay(2000);
  display.clearDisplay();

  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  display.println("Round Rectangle");
  display.drawRoundRect(0, 15, 60, 40, 8, WHITE);
  display.display();
  delay(2000);
  display.clearDisplay();

  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  display.println("Filled Round Rectangl");
  display.fillRoundRect(0, 15, 60, 40, 8, WHITE);
  display.display();
  delay(2000);
  display.clearDisplay();

  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  display.println("Circle");
  display.drawCircle(20, 35, 20, WHITE);
  display.display();
  delay(2000);
  display.clearDisplay();

  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  display.println("Filled Circle");
  display.fillCircle(20, 35, 20, WHITE);
  display.display();
  delay(2000);
  display.clearDisplay();

  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  display.println("Triangle");
  display.drawTriangle(30, 15, 0, 60, 60, 60, WHITE);
  display.display();
  delay(2000);
  display.clearDisplay();

  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  display.println("Filled Triangle");
  display.fillTriangle(30, 15, 0, 60, 60, 60, WHITE);
  display.display();
  delay(2000);
  display.clearDisplay();
}

void loop() {}

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

Рисование прямоугольника

display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.println("Rectangle");
display.drawRect(0, 15, 60, 40, WHITE);
display.display();
delay(2000);

display.clearDisplay();  
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.println("Filled Rectangle");
display.fillRect(0, 15, 60, 40, WHITE);
display.display();
delay(2000);

Вы можете нарисовать на дисплее прямоугольник  с помощью функции drawRect(). Функция принимает пять параметров, а именно: координаты X и Y, ширина, высота и цвет. На самом деле эта функция рисует не закрашенный прямоугольник с границей в 1 пиксель. Вы можете нарисовать закрашенный прямоугольник, используя функцию fillRect().

Рисование скругленный прямоугольник

display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.println("Round Rectangle");
display.drawRoundRect(0, 15, 60, 40, 8, WHITE);
display.display();
delay(2000);

display.clearDisplay();  
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.println("Filled Round Rectangl");
display.fillRoundRect(0, 15, 60, 40, 8, WHITE);
display.display();
delay(2000);

Вы можете нарисовать на дисплее скругленный прямоугольник  с помощью функции drawRoundRect(). Эта функция принимает те же параметры, что и функция drawRect(), за исключением одного дополнительного параметра — радиуса скругления угла. На самом деле эта функция рисует не закрашенный скругленный прямоугольник с границей в 1 пиксель. Вы можете нарисовать закрашенный круглый прямоугольник, используя функцию fillRoundRect().

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

display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.println("Circle");
display.drawCircle(20, 35, 20, WHITE);
display.display();
delay(2000);

display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.println("Filled Circle");
display.fillCircle(20, 35, 20, WHITE);
display.display();
delay(2000);

Вы можете нарисовать круг на дисплее с помощью функции drawCircle(). Функция принимает четыре параметра, а именно: координата центра X и Y, радиус и цвет. Эта функция рисует не закрашенный круг с границей в 1 пиксель. Вы можете нарисовать закрашенный круг, используя функцию fillCircle().

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

display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.println("Triangle");
display.drawTriangle(30, 15, 0, 60, 60, 60, WHITE);
display.display();
delay(2000);

display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.println("Filled Triangle");
display.fillTriangle(30, 15, 0, 60, 60, 60, WHITE);
display.display();
delay(2000);

Вы можете нарисовать треугольник на дисплее с помощью функции drawTriangle(). Функция принимает семь параметров, а именно:  X и Y координаты (x0, y0, x1, y1, x2, y2) вершин треугольника и цвета. (x0, y0) представляет верхнюю вершину, (x1, y1) представляет левую вершину и (x2, y2) представляет правую вершину.

Эта функция рисует не закрашенный треугольник с границей в 1 пиксель. Вы можете нарисовать закрашенный треугольник, используя функцию fillTriangle().

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

Ваш электронный адрес не будет опубликован.


*