OLED-дисплей Arduino – подключение SSD1306 по I2C и пример кода

Четырёхконтактный OLED-модуль с выводами GND, VCC, SCL, SDA, подключённый проводами к Arduino Nano на беспаечной макетной плате

Миниатюрный OLED-дисплей позволяет выводить измерения датчиков, состояние устройства и простое меню без отдельного монитора. В любительских проектах часто используют модуль 0,96 дюйма с разрешением 128×64 и контроллером SSD1306, подключённый по интерфейсу I2C. Основная сложность в том, что похожие снаружи модули отличаются питанием, числом контактов и даже контроллером. Разберём, как определить тип платы, проверить адрес на шине и запустить текстовый вывод без механического копирования схемы для другой модификации.

Какие OLED-модули подходят для Arduino

Обозначение OLED описывает технологию дисплея, но не интерфейс управления. На рынке встречаются SSD1306, SH1106 и другие контроллеры, а платы используют I2C или SPI. Типичный четырёхконтактный модуль имеет выводы GND, VCC, SCL и SDA; шестиконтактные и семиконтактные варианты часто рассчитаны на SPI, но число контактов не гарантирует протокол. Разрешение 128×64 также нужно подтвердить: существуют 128×32 и другие модели. Для правильного подключения следует прочитать маркировку микросхемы или документацию модуля. Код для SSD1306 может не подойти дисплею SH1106 без смены библиотеки и параметров буфера.

Распиновка I2C: GND, VCC, SDA и SCL

GND – общий провод, VCC – питание модуля, SDA – линия данных, SCL – линия тактового сигнала. На классической Arduino Uno с ATmega328P аппаратная шина I2C использует A4 для SDA и A5 для SCL; на Arduino Nano на том же контроллере обычно применяются те же линии. На других платах выводы отличаются, их следует брать из распиновки конкретной ревизии. Питание – отдельный важный пункт: модуль с собственным стабилизатором может допускать 5 В, а дисплейная плата без согласования уровней может требовать 3,3 В. Вывод 3,3 В не является универсальной рекомендацией для любого модуля без документации.

Подключение OLED SSD1306 по I2C к Arduino Uno и NanoЧетырёхконтактный модуль OLED 128 на 64 с контроллером SSD1306. Вывод GND соединяют с GND платы Arduino, VCC – с выводом 5V или 3V3 в зависимости от документации модуля, SCL – с A5, SDA – с A4; для Uno R3 и Nano назначение одинаковое. Примечания: порядок выводов на модулях бывает другим; контроллер SSD1306 рассчитан на логическое питание 1,65–3,3 вольта, а модули на 5 вольт имеют собственный стабилизатор; у Uno R3 линии SDA и SCL дополнительно выведены рядом с выводом AREF.OLED SSD1306 (I2C, 4 вывода) и Arduino Uno / Nano128 × 64SSD1306GNDGNDGNDVCC5V / 3V3*5V / 3V3*SCLA5 (SCL)A5SDAA4 (SDA)A4Uno R3NanoПорядок выводов на модулях бывает и другим (VCC, GND, SCL, SDA): читайтенадписи на своей плате, а не повторяйте цвета проводов с чужого фото.* Питание – по документации модуляКонтроллер SSD1306 рассчитан на логику 1,65–3,3 В; модули на 5 В имеютсвой стабилизатор. У Uno R3 линии SDA/SCL выведены также у вывода AREF.
OLED SSD1306 по I2C: GND – GND, VCC – 5V или 3V3 по документации модуля, SCL – A5, SDA – A4.
Вывод модуляНазна­че­ниеArduino Uno R3Arduino Nano
GNDобщий проводGNDGND
VCCпи­та­ние модуля5V или 3V3 – по до­ку­мента­ции модуля5V или 3V3 – по до­ку­мента­ции модуля
SCLтакто­вая линия I2CA5 (дубли­ро­ва­на вы­во­дом SCL у AREF)A5
SDAлиния данных I2CA4 (дубли­ро­ва­на вы­во­дом SDA у AREF)A4
Сам контроллер SSD1306 по даташиту Solomon Systech питается логическим напряжением 1,65–3,3 В; модули, допускающие 5 В, содержат собственный стабилизатор.

Почему у OLED может быть адрес 0x3C или 0x3D

I2C позволяет нескольким устройствам использовать общую пару проводов, если их адреса не конфликтуют. На многих платах SSD1306 встречается адрес 0x3C, иногда 0x3D; его определяет конфигурация самого модуля. По даташиту Solomon Systech семибитный адрес контроллера – 0111100 или 0111101, младший бит задаёт вывод SA0 (в режиме I2C это вывод D/C#): 0x3C при низком уровне, 0x3D при высоком. Адрес не нужно угадывать: тестовый скетч I2C Scanner перебирает доступные адреса и выводит найденные устройства в последовательный порт. Если сканер ничего не обнаружил, проверьте питание, землю, соответствие SDA/SCL, разъёмы и отсутствие коротких замыканий. Не меняйте произвольно несколько параметров сразу: последовательная диагностика позволяет понять, какой шаг устранил проблему.

Библиотеки для SSD1306 и требования к памяти

Удобный вариант – библиотека Adafruit SSD1306 вместе с Adafruit GFX. Первую используют для обмена с экраном, вторую – для рисования текста и геометрических примитивов. Для полноэкранного монохромного буфера 128×64 требуется 1024 байта памяти, что заметно для контроллеров с небольшим объёмом RAM. Если скетч содержит множество строк, массивов и других библиотек, могут появиться сбои. Альтернативой бывает U8g2 с режимом постраничного вывода, но интерфейсы библиотек различаются. При переносе примера между ними необходимо менять код осознанно, а не только имя заголовочного файла.

128 × 64 пикселя / 8 бит = 1024 байта

У ATmega328P, на котором построены Uno и Nano, 2 КБ оперативной памяти, поэтому буфер дисплея сразу занимает половину. Библиотека Adafruit выделяет его при вызове begin(); если памяти не хватило, функция вернёт false.

Минимальный пример вывода текста

Для модуля SSD1306 128×64 с адресом 0x3C, подключённого к штатной I2C-шине Arduino Uno, можно использовать объект Adafruit_SSD1306 display(128,64,&Wire,-1). В setup() вызывают display.begin(SSD1306_SWITCHCAPVCC,0x3C), затем очищают буфер clearDisplay(), устанавливают цвет и размер текста, задают позицию setCursor() и вызывают print(). Команда display.display() отправляет подготовленный кадр на экран. Полный пример приведён ниже; библиотеки Adafruit SSD1306 и Adafruit GFX устанавливают через менеджер библиотек Arduino IDE. Если инициализация возвращает false, программа должна сообщить об этом в Serial и не продолжать вывод в неинициализированный дисплей.

Пример скетча для Arduino Uno и Nano

Ниже приведён минимальный код, рассчитанный на установленную библиотеку Adafruit SSD1306 и зависимость Adafruit GFX:

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

Adafruit_SSD1306 display(128, 64, &Wire, -1);

void setup() {
  Serial.begin(9600);
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println("OLED init failed");
    while (true) {}
  }
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 0);
  display.println("Skrutka.ru");
  display.display();
}

void loop() {}

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

Как выводить показания датчика без мерцания

В реальном проекте значение температуры или напряжения меняется во времени. Обновлять экран каждую миллисекунду необязательно: частые перерисовки расходуют процессорное время и могут создавать визуально неприятное мерцание. Практический вариант – выполнять обновление с заданным интервалом через millis(), очищать буфер, выводить подписи и числовые значения, затем отправлять готовый кадр. Текстовую часть следует располагать на фиксированных координатах, учитывая размеры выбранного шрифта. Для стабильности полезно отделить чтение датчика, расчёты и отрисовку в разные функции; тогда ошибки измерения не будут маскироваться кодом дисплея.

Типичные проблемы: белый экран, пустой экран, мусор

Если на экране ничего нет, сначала измерьте питание и убедитесь, что модуль именно I2C SSD1306. Затем запустите сканер адресов и попробуйте минимальный пример без датчиков и меню. Если сканер видит устройство, но изображение неправильное, вероятны несоответствие разрешения, контроллера или библиотеки. Если дисплей периодически пропадает, проверьте контакты, длину проводов, качество питания и использование подтягивающих резисторов на I2C. Слишком длинные соединения на макетной плате могут ухудшать фронты сигналов. Переход на другой адрес не исправляет плохой контакт или неверную разводку.

OLED и Arduino Nano: особенности питания

Компактный Nano нередко используют в автономных устройствах. При выборе дисплея важно учитывать суммарное потребление платы, датчиков, преобразователей и самого экрана. OLED обычно экономичнее подсвечиваемого LCD при небольшом количестве светящихся пикселей, но потребление зависит от яркости и характера изображения. Для батарейного устройства могут потребоваться сон контроллера и команды отключения дисплея. Не стоит питать неизвестный модуль от вывода с недостаточной нагрузочной способностью. Если Nano совместимая плата имеет иной логический уровень, требуется учитывать это в связке с конкретным дисплеем.

I2C или SPI – что выбирать

I2C требует меньше сигнальных проводов и удобен, когда на шине уже есть другие датчики. SPI занимает больше выводов, но в определённых условиях обеспечивает более быстрый обмен. Выбор зависит от требований к частоте обновления и доступных выводов контроллера. Иногда интерфейс выбирается перемычками на самой плате: такие переключения нельзя выполнять по чужому фото без схемы своего модуля. Для начинающего проекта с выводом нескольких чисел обычно достаточно I2C. Для сложной графики важны особенности контроллера, скорость шины, объём RAM и реализация библиотеки.

Диагностика I2C-сканером по шагам

Прежде чем устанавливать графическую библиотеку, полезно запустить простейший скетч поиска адресов I2C. Если найден один адрес, его записывают и используют при инициализации дисплея. При нескольких устройствах на шине следует убедиться, что адрес относится именно к экрану: на шине могут находиться часы реального времени, датчик температуры и память. Нулевое количество найденных адресов обычно указывает на проблему питания или связи, а не на размер шрифта в графической библиотеке. При работе с другой платой Arduino важно использовать её аппаратные выводы SDA/SCL. Два устройства с одинаковым фиксированным адресом могут конфликтовать, и в этом случае выбирают альтернативную адресацию либо специализированный мультиплексор.

Минимальный сканер перебирает адреса от 1 до 126 и печатает в монитор порта (9600 бод) те, на которые устройство ответило подтверждением:

#include <Wire.h>

void setup() {
  Wire.begin();
  Serial.begin(9600);
  Serial.println("I2C scan");
  for (byte addr = 1; addr < 127; addr++) {
    Wire.beginTransmission(addr);
    if (Wire.endTransmission() == 0) {
      Serial.print("Found: 0x");
      if (addr < 16) Serial.print('0');
      Serial.println(addr, HEX);
    }
  }
  Serial.println("Done");
}

void loop() {}

Как поместить на экран несколько строк

При использовании стандартного встроенного шрифта размером 1 символы имеют небольшую матрицу, благодаря чему на экран 128×64 помещается несколько строк короткого текста. У встроенного шрифта Adafruit GFX символ 5 × 7 пикселей занимает ячейку 6 × 8 с интервалом, поэтому при setTextSize(1) в строке помещается 21 символ, а строк восемь; при setTextSize(2) ячейка становится 12 × 16 – это 10 символов и 4 строки. Шрифты с увеличенным размером занимают больше пикселей, поэтому расчёт позиции нельзя делать только по количеству букв. Для меню полезно заранее разметить экран на области: заголовок, значение, единицы измерения и строку состояния. Числа с меняющимся количеством цифр лучше выводить после очистки прямоугольной области либо всего буфера, чтобы старые символы не оставались на экране. При переходе на кириллические шрифты следует выбрать библиотеку и набор символов с поддержкой русского текста: стандартный GFX-шрифт не гарантирует корректное отображение кириллицы.

Как подключить несколько устройств к одной I2C-шине

Основное преимущество I2C – общие линии данных и тактирования при наличии отдельных адресов. Например, на одной короткой шине можно разместить OLED и датчик температуры. Однако общая линия означает, что уровни напряжения и подтягивающие резисторы должны быть совместимы со всеми участниками. Нельзя бездумно объединять модуль 5 В и микроконтроллер 3,3 В, если на шине присутствуют подтяжки к более высокому напряжению. При большом числе устройств возрастает суммарная ёмкость проводников и входов. В макетном прототипе это может вызывать периодические зависания дисплея. Для диагностики полезно сначала оставить только экран, а затем последовательно подключать остальные модули.

OLED и другие устройства на общей шине I2CДве линии шины – SDA и SCL – подтянуты резисторами к питанию. К ним параллельно подключены Arduino как ведущее устройство (выводы A4 и A5), OLED на контроллере SSD1306 с адресом 0x3C, часы реального времени DS3231 с адресом 0x68 и датчик BME280 с адресом 0x76 или 0x77. Подпись: у каждого устройства свой адрес, его находят скетчем I2C Scanner; подтяжки и уровни напряжения должны подходить всем устройствам, длинные провода ухудшают фронты.Несколько устройств на одной шине I2CVCCSDASCLподтяжкиArduinoведущееA4 / A5OLEDSSD1306адрес 0x3CRTCDS3231адрес 0x68ДатчикBME2800x76 или 0x77У каждого устройства свой адресАдрес находят скетчем I2C Scanner. Подтяжки и уровни (5 или 3,3 В) должныподходить всем участникам; длинные провода ухудшают фронты сигналов.
Общая шина I2C: OLED 0x3C, часы DS3231 0x68 и датчик BME280 0x76/0x77 на одних линиях SDA и SCL.

Выбор SSD1306 или SH1106 для нового проекта

По внешнему виду и разрешению модуль SH1106 иногда выглядит как SSD1306, но организация памяти и команды контроллера могут отличаться. При неверной библиотеке изображение сдвигается, обрезается или отсутствует. Перед покупкой стоит проверить точный чип, интерфейс, напряжение питания, доступные примеры и поддержку выбранной платы Arduino. Для недорогих измерителей достаточно SSD1306 с I2C, если не требуется высокая частота обновления. Для графически насыщенных проектов лучше заранее оценить RAM микроконтроллера, размер прошивки и тип библиотеки. Это предотвращает ситуацию, когда экран работает отдельно, но после подключения датчиков скетч начинает перезагружаться из-за нехватки памяти.

Как сделать показания удобными для чтения

Размер дисплея 0,96 дюйма предполагает компактный интерфейс. На первой строке можно разместить название измеряемого параметра, на следующих – значение и единицу измерения, а внизу – индикатор связи. Важно различать пропущенное измерение и реальный ноль: если датчик не отвечает, лучше показать понятную надпись об ошибке, чем прежнее число без отметки. Для измерителя батареи полезен крупный шрифт напряжения, а подробная диагностика может выводиться по запросу. Если на экране отображаются русские слова, следует заранее подобрать шрифт с кириллицей. В учебном примере проще начинать с латинских символов и проверенного стандартного шрифта, чтобы отделить проблемы кодировки от неисправностей дисплея.

Частые вопросы

К каким контактам Arduino Uno подключают SDA и SCL?

Для классической Uno с ATmega328P используют A4 (SDA) и A5 (SCL). Для других плат сверяются с официальной распиновкой.

Как узнать I2C-адрес экрана?

Запустить I2C Scanner. Часто встречаются 0x3C и 0x3D, но адрес определяется фактическим модулем.

Почему библиотека Adafruit SSD1306 не показывает картинку?

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

Можно ли подключить OLED к 5 В?

Только если плата дисплея рассчитана на 5 В или имеет нужное согласование. Проверяют паспорт конкретного модуля.

Зачем нужна Adafruit GFX?

Она предоставляет средства рисования текста, линий и фигур; библиотека SSD1306 передаёт данные конкретному дисплею.

Материалы по теме