Проводка OLED — это четыре провода, и именно на этой лёгкости я однажды обжёгся. Экран висел на макетке через дальнюю рейку питания, сигнальные перемычки шли с лишним метром по периметру платы, и всё выглядело правильно: VCC к 5V, GND к GND, подписи совпадали. Сканер то видел модуль, то нет, а кадр время от времени рвался серыми полосами. Диагноз ставил осциллограф соседа по гаражу, но можно было догадаться и без него: длинные провода добавляют ёмкость, ёмкость мылит фронты — и шина на сто килогерц перестала понимать экран.
В этом уроке соберём схему подключения SSD1306 к Uno и Nano по правилам, а не по наитию: куда идут VCC, GND, SDA и SCL, почему питание — 3.3–5 В и чем модуль с регулятором отличается от голого стекла, где экрану место на макетке и какой симптом даёт перепутанные сигнальные линии. В конце — проверка сборки в симуляторе, где каждый кадр виден в панели дисплея, а подъём шины — в журнале I2C.
Один кадр этого урока стоит часа отладки: таблица распиновки с колонкой «если перепутать». Сфотографируйте её себе на телефон — пригодится у макетки, когда руки будут заняты проводами.
Четыре ошибки в этой схеме повторяются чаще остальных, и все четыре — электрические: питание на голое стекло без стабилизатора, перепутанные SDA и SCL, разорванная рейка макетки и метр перемычек по периметру. Код в этих историях всегда невиновен: экран — самое честное устройство в проекте, он либо подключён, либо нет. Поэтому урок построен от схемы к коду: сначала провода и питание, потом подтяжки и соседи по шине, и только в конце — скелет скетча с проверкой в симуляторе.
Четыре линии: распиновка и питание
Распиновка — четыре ножки в ряд: GND, VCC, SCL, SDA. Порядок на разных партиях встречается разный, поэтому читайте подписи на плате, а не память: перепутанные соседние линии — самая частая причина тёмного экрана. GND — общий провод с платой, без вариантов. VCC — плюс питания, и тут важна конструкция модуля: диапазон 3.3–5 В написан не для красоты. Большинство синих плат 0.96 дюйма несут на борту стабилизатор и резисторы под 5-вольтовую логику — им подавайте 5 В с платы. Голое стекло или модуль без стабилизатора — только 3.3 В: пять вольт на ножках перегревают контроллер, и экран умирает тихо, без дыма и заявлений.
Сигнальные линии на Uno и Nano живут на A4 и A5: SDA — A4, SCL — A5. Это не произвольный выбор — аппаратный I2C сидит именно там. Следствие: отобрать эти пины под аналоговые чтения уже нельзя, они заняты шиной. На Mega провода переезжают на 20 и 21, на ESP32 пару линий назначают в коде — там шина программная в смысле выбора пинов. Если вы привыкли, что A0–A5 — входы для потенциометров, привыкайте дважды: карта макетки тут бессильна, распределение пинов делает кремний.
Про перепутанные SDA и SCL — краткая гробовая: сканер молчит, на шине тишина, экран тёмный, код при чём. Сканер из урока про сканер I2C — первый прибор, который я достаю в такой ситуации: за минуту он отличает ошибку проводки от ошибки адреса. Подробный разбор адресов ждёт вас в следующем уроке, здесь важно другое: молчащая шина лечится таблицей выше и парой минут против схемы.
Отдельно про 3.3 В на Uno и Nano: он есть на плате, выводом 3V3, и OLED-модулю его хватает с запасом — экран ест единицы-десятки миллиампер против лимита в полсотни. Если модуль без стабилизатора, питайте его оттуда, а не от 5V через делители: здесь простота честнее «универсальности». И проверьте рейки макетки до подключения: полноразмерные платы разорваны посередине, и половина моих «мёртвых» экранов питалась от рейки без общего провода с платой — диагнозу про общую землю посвящён отдельный урок, а прозвонка занимает минуту.
| Пин модуля | Куда на Uno / Nano | Если перепутать |
|---|---|---|
| GND | GND | Общего провода нет — экран молчит, сканер пуст |
| VCC | 5V (модуль с регулятором) или 3.3V (голое стекло) | Пять вольт на стекло без стабилизатора — перегрев контроллера |
| SDA | A4 | Поменяны с SCL — шина не отвечает, сканер печатает ноль устройств |
| SCL | A5 | Тот же симптом: тишина при идеальном коде |
| (На Mega) | SDA — 20, SCL — 21 | Провода от Uno по привычке на A4/A5 — шина пуста |
Подтяжки, длина проводов и соседи по шине
На линиях SDA и SCL стоят подтягивающие резисторы к питанию — без них шина физически не работает. Хорошая новость: у большинства модулей SSD1306 они уже распаяны, 4.7–10 кОм, докупать ничего не надо. Нюанс появляется, когда на ту же шину садятся другие модули со своими подтяжками: резисторы соединяются параллельно, итоговое сопротивление падает. Два-три модуля со штатными подтяжками живут нормально; на четырёх-пяти я уже выпаиваю лишние или беру платы без них — иначе шина начинает светиться в осциллограф перекрученными фронтами.
Длина проводов — второй подводный камень, с которого начался этот урок. Каждая перемычка — это ёмкость: чем длиннее провод, тем медленнее нарастает фронт сигнала. Пара сантиметров по макетке — ничего; метр хвоста — уже лотерея на 100 кГц. Мои лимиты простые: до тридцати сантиметров — спокойно; до полуметра — только со скрученной рядом землёй; дальше — витая пара и консервативная частота. Команда Wire.setClock(100000) возвращает базовый режим, если эксперименты с 400 кГц обернулись ошибками кадров — разгон оставьте на короткие провода.
И место на макетке. Четырёхпиновый модуль идеально встаёт поперёк центральной канавки, но сигнальные ножки разводите короткими проводами к ближайшим столбцам, а не через всю плату. Цветовая дисциплина из урока про перемычки здесь не украшение: красный — только плюс, чёрный — только минус, сигнальные — свой цвет на обе линии. Через месяц при поиске обрыва глаза скажут спасибо.
Практический тест здоровья шины стоит двух минут: прогоните сканер при подключённом экране, затем добавьте к шине второй модуль и прогоните снова. Если при двух устройствах сканер стал ловить сбои — подтяжки просели слишком низко, и лишние резисторы пора снимать. Тот же тест с длинным хвостом проводов отличает живую шину от пограничной: макетка прощает пограничную, прибор в корпусе — уже нет. Я держу в ящике модуль OLED без бортовых подтяжек специально: он подключается последним в спорных сборках и показывает, тянет ли шина ещё одного жильца.
#include <Wire.h>#include <Adafruit_GFX.h>#include <Adafruit_SSD1306.h> // Модуль 0.96" 128x64 — самый ходовой вариантAdafruit_SSD1306 display64(128, 64, &Wire, -1); // Вытянутый модуль 0.91" 128x32 — своя геометрияAdafruit_SSD1306 display32(128, 32, &Wire, -1); void setup() { // Отдельный Wire.begin() не нужен: display.begin() запустит шину сам. // На Uno и Nano SDA=A4, SCL=A5 — провода идут туда напрямую. display64.begin(SSD1306_SWITCHCAPVCC, 0x3C); display64.clearDisplay(); display64.setTextSize(1); display64.setCursor(0, 0); display64.println("SDA -> A4"); display64.println("SCL -> A5"); display64.println("VCC -> 5V (s regulyatorom)"); display64.println("GND -> GND"); display64.display();} void loop() {}Шина тем и хороша: к тем же A4 и A5 цепляются часы DS3231 из урока про RTC, LCD с переходником, датчики — каждый со своим адресом, по двум проводам I2C. OLED с адресом 0x3C дружит с RTC на 0x68 без единого конфликта: адреса не пересекаются, а очерёдностью пакетов управляет библиотека.
Конфликт возникает другой — геометрический. Конструктор Adafruit_SSD1306 задаёт размеры экрана: 128 на 64 для 0.96 дюйма, 128 на 32 для вытянутого 0.91. Перепутаете — экран не сгорит, но нижняя половина кадра уйдёт за физический край, а строки съедут вниз. Я наклеиваю на обратную сторону модуля бумажку с размером и адресом: два числа, которые экономят пересборку и один бессонный вечер.
Про порядок запуска — одна строка, которую стоит запомнить: display.begin() сам вызывает Wire.begin() внутри. Отдельный вызов шины до него не ошибка, но и не нужен — двойная инициализация безвредна, зато лишняя строка сбивает того, кто будет читать ваш setup. После begin шина уже живая: рисуйте, шлите команды, сканьте адреса.
Если экранов понадобится два — второй живёт на 0x3D после перепайки адресной перемычки, и об этом подробно говорит следующий урок. А пока заметка про питание общей шины: суммарный ток нескольких модулей по-прежнему смешной для Uno, но провода к далёким устройствам должны возвращаться на землю платы, а не на ближайшую рейку. Плавающая земля модуля — источник фантомных сбоев, которые лечатся одним перемычечным проводом, если вовремя догадаться, где искать.
- Четыре провода: VCC, GND, SDA на A4, SCL на A5 у Uno и Nano; на Mega — 20 и 21
- Питание 3.3–5 В: модуль со стабилизатором ест 5 В, голое стекло — только 3.3 В
- display.begin() сам запускает Wire — отдельный Wire.begin() в setup не нужен
- Подтяжки 4.7–10 кОм уже на модуле; с каждым новым устройством на шине они соединяются параллельно
- Конструктор задаёт геометрию: 128x32 против 128x64 — нижняя половина кадра уезжает за край
- Длинные перемычки добавляют ёмкость и мылят фронты: до 30 см — спокойно, дальше — короче провода и 100 кГц
- 1. Сколько проводов подключает OLED SSD1306 по I2C?
- 2. К каким пинам идут SDA и SCL на Arduino Uno?
- 3. Почему в скетче не нужен отдельный Wire.begin() перед display.begin()?
- 4. В конструкторе указано 128x64, а модуль — 128x32. Что вы увидите?
Схема собрана, шина отвечает, кадры идут по расписанию — проводку можно забыть до следующей пересборки. Финальный штрих на живой плате: прогоните сканер, убедитесь, что модуль отвечает на своём адресе, и только потом начинайте интерфейс. С работающей электрикой любая проблема кода становится видимой, а не маскируется под дурной контакт.
Дальше — адреса: почему модуль может молчать при идеально собранной схеме, чем 0x3C отличается от 0x3D и от загадочного 0x78, и как сканер I2C экономит час диагностики. Тридцать секунд на сканирование перед первым запуском — привычка, которую я советую унести из этого раздела в каждый будущий проект.
Частые вопросы по теме урока
- Сколько проводов подключает OLED SSD1306 по I2C?
- Питание, земля и две сигнальные линии. Параллельный HD44780 требует шесть сигнальных плюс питание — I2C-вариант заметно скромнее. Четыре — VCC, GND, SDA, SCL
- К каким пинам идут SDA и SCL на Arduino Uno?
- Аппаратный I2C на Uno сидит на A4 (SDA) и A5 (SCL). После подключения эти аналоговые входы шине не отдать. A4 и A5
- Почему в скетче не нужен отдельный Wire.begin() перед display.begin()?
- begin() дисплея стартует шину внутри и заодно выделяет буфер кадра. Лишний вызов не сломает ничего, но и пользы не даёт. Библиотека вызывает его сама внутри begin
- В конструкторе указано 128x64, а модуль — 128x32. Что вы увидите?
- Библиотека рисует в буфер 128x64, а физически строк на 32 пикселя высоты — содержимое ниже уходит за край. Конструктор обязан совпадать с модулем. Нижние строки уходят за край: геометрия другая