SSD1306 распознается сканером I2C, но не может его отобразить

Суть моей проблемы в названии. У меня есть дешевый дисплей ebay SSD1306 128x64, который я подключил к своей Arduino и проверил проводку не менее 50 раз, и адрес правильный, на дисплее установлена перемычка на 0x78, и Arduino (Nano с ATmega168) видит его на сканер i2c как 0x3C, что ожидается.

Теперь я установил библиотеки Adafruit SSD1306 и GFX, а также библиотеку OLED i2c, которую я где-то нашел (не могу ее найти, извините. В среде IDE она называется OLED_I2C), и запустил оба примера кода (укороченные Adafruit, чтобы они соответствовали 168) и Я не могу заставить его показать что-нибудь. Я пробовал много вещей, в том числе безуспешно пытался использовать код 128x32, даже не пропустив ни одной строки. Я думаю, что дисплей работает, так как он отображается в сканере, кто-нибудь знает, что может быть не так? Заранее спасибо

Мой сокращенный код Adafruit:

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

#define SCREEN_WIDTH 128 // Ширина OLED-дисплея в пикселях
#define SCREEN_HEIGHT 64 // Высота OLED-дисплея в пикселях

// Объявление для дисплея SSD1306, подключенного к I2C (контакты SDA, SCL)
#define OLED_RESET     4 // Номер вывода сброса (или -1, если используется общий вывод сброса Arduino)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);


void setup() {
  Serial.begin(9600);

  // SSD1306_SWITCHCAPVCC = генерировать внутреннее напряжение дисплея от 3,3 В
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3D)) { // Адрес 0x3D для 128x64
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Не продолжать, цикл навсегда
  }

  // Показать содержимое буфера начального отображения на экране --
  // библиотека инициализирует это с помощью экрана-заставки Adafruit.
  display.display();
  delay(2000); // Пауза на 2 секунды

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

  // Рисуем один пиксель белым цветом
  display.drawPixel(10, 10, SSD1306_WHITE);

  // Показать буфер отображения на экране. Вы ДОЛЖНЫ вызывать display() после
  // команды рисования, чтобы сделать их видимыми на экране!
  display.display();
  delay(2000);
  // display.display() НЕ требуется после каждой отдельной команды рисования,
  // если это то, что вы хотите... скорее, вы можете собрать кучу
  // операции рисования, а затем сразу обновить весь экран, вызвав
  // дисплей.дисплей(). Эти примеры демонстрируют оба подхода...

  testdrawline();      // Рисуем много линий

  testdrawrect();      // Рисуем прямоугольники (контуры)
}

void loop() {
}

void testdrawline() {
  int16_t i;

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

  for(i=0; i<display.width(); i+=4) {
    display.drawLine(0, 0, i, display.height()-1, SSD1306_WHITE);
    display.display(); // Обновляем экран с каждой вновь нарисованной линией
    delay(1);
  }
  for(i=0; i<display.height(); i+=4) {
    display.drawLine(0, 0, display.width()-1, i, SSD1306_WHITE);
    display.display();
    delay(1);
  }
  delay(250);

  display.clearDisplay();

  for(i=0; i<display.width(); i+=4) {
    display.drawLine(0, display.height()-1, i, 0, SSD1306_WHITE);
    display.display();
    delay(1);
  }
  for(i=display.height()-1; i>=0; i-=4) {
    display.drawLine(0, display.height()-1, display.width()-1, i, SSD1306_WHITE);
    display.display();
    delay(1);
  }
  delay(250);

  display.clearDisplay();

  for(i=display.width()-1; i>=0; i-=4) {
    display.drawLine(display.width()-1, display.height()-1, i, 0, SSD1306_WHITE);
    display.display();
    delay(1);
  }
  for(i=display.height()-1; i>=0; i-=4) {
    display.drawLine(display.width()-1, display.height()-1, 0, i, SSD1306_WHITE);
    display.display();
    delay(1);
  }
  delay(250);

  display.clearDisplay();

  for(i=0; i<display.height(); i+=4) {
    display.drawLine(display.width()-1, 0, 0, i, SSD1306_WHITE);
    display.display();
    delay(1);
  }
  for(i=0; i<display.width(); i+=4) {
    display.drawLine(display.width()-1, 0, i, display.height()-1, SSD1306_WHITE);
    display.display();
    delay(1);
  }

  delay(2000); // Пауза на 2 секунды
}

void testdrawrect(void) {
  display.clearDisplay();

  for(int16_t i=0; i<display.height()/2; i+=2) {
    display.drawRect(i, i, display.width()-2*i, display.height()-2*i, SSD1306_WHITE);
    display.display(); // Обновляем экран с каждым вновь нарисованным прямоугольником
    delay(1);
  }

  delay(2000);
}

, 👍-2

Обсуждение

Сканер (?) находит дисплей по адресу 3C, но вы настраиваете библиотеку на адрес 3D. Также код Adafruit не указан для 168. Это _могло_ быть проблемой. Я также не ожидал найти устройство по адресу 0x3C, если перемычка установлена на 0x78. Что я пропустил? А где вы используете загадочную библиотеку OLED I2C? Я не видел включения. Вы упомянули «оба примера», но показали только один. Возможно, я недостаточно знаю, чтобы понять ваш вопрос (или, по крайней мере, факты), но я в полном замешательстве. ;-), @Peter Paul Kiefer

Да, я показал только один adafruit, потому что я чувствовал, что этого достаточно, чтобы показать, где была моя ошибка. Я не использовал эту библиотеку в своем коде adafruit, я попытался использовать ее пример отдельно. Судя по онлайн-учебникам, если дисплей находится на 0x78, он отображается на 0x3C. Можете ли вы показать мне, где я установил его на 0x3D? очень признателен, @Xilog

@Xilog Да, это, вероятно, проблема с адресацией, дисплей Oled, который вы используете, SSD1306 имеет интерфейс IIC, а интерфейсы IIC имеют около 127 адресов, насколько я знаю, два возможных адреса для такого дисплея: 0x3C и 0x3D, но так как он показал в сканере I2c, что он находится на 0x3C, вы должны объявить, что в 19-й строке кода, который вы предоставляете, вместо 0x3D измените его на 0x3C., @Shams M.Monem

Мы знаем адрес 3C, так почему вы хотите изменить его на 3D? Вы просто можете получить к нему доступ по уже настроенному адресу, например, предложенному @ShamsEl-Deen. Еще одна мысль: вы уверены, что 0x3C — это ваш дисплей OLEAD? Возможно, у вас есть другое устройство I2C с адресом 0x3C, подключенное к шине I2C «сканера», и ваш OLED по адресу 0x78 по какой-то причине невидим., @Peter Paul Kiefer

Спасибо, я нашел это в строке 19 и изменил, но это ничего не исправило. Я уверен, что на дисплее 0x3C. Когда я отключаю его, сканер говорит, что устройства не найдены., @Xilog


4 ответа


Лучший ответ:

2

Некоторое время после того, как я задал этот вопрос, я попытался провести исследование. Оказывается, изменение OLED_RESET на -1 исправило это.

Фото

,

2

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

  • Изменение адреса в коде

Дисплей OLED, который вы используете, использует так называемый протокол I2c или IIC, который является аббревиатурой «Inter Intergrated Circuit», вот его страница в Википедии, чтобы прочитать о это.

Коммуникация IIC имеет 7-битное адресное пространство, что означает наличие 127 различных адресов, например 0x3C, 0x3D, 0x38 и т. д....

Ваш дисплей может иметь адрес 0x3C или 0x3D, поэтому вы можете попробовать изменить эти значения, пока что-нибудь не появится.

  • Отключение любого другого устройства IIC

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

  • Правильное напряжение?

Возможно, вы знаете, что в некоторых дисплеях используется напряжение 3,3 В, а в некоторых — 5 В, но, как показал сканер IIC, я не думаю, что это проблема в вашем случае, но вы должны это учитывать.

  • Попробуйте использовать другие скетчи

Ну, я думаю, что 99% проблем кроется в вашем коде (иногда это случается со мной), поэтому я предлагаю использовать другие примеры библиотек или совсем другие библиотеки, или, если вы хотите принять вызов, откройте таблицу данных для ssd1306 и создайте собственную библиотеку и коды.

Надеюсь, эти советы помогут вам или любому другому зрителю.

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

,

это не ответ и не решение., @hcheung

Большое спасибо! Попробую ваши советы. Очень признателен, @Xilog


1

Я скопировал ваш код и загрузил его на свой дисплей. Это ничего не показывает. Вот код, который я успешно запустил.

#include <Adafruit_SSD1306.h>
Adafruit_SSD1306 display = Adafruit_SSD1306(128, 64, &Wire);

void setup() {

  // SSD1306_SWITCHCAPVCC = генерировать внутреннее напряжение дисплея от 3,3 В
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // Адрес 0x3C для 128x32

  display.display();
  delay(2000);

  display.clearDisplay();      //эта строка для очистки предыдущего логотипа
  display.setTextColor(WHITE); //без этого нет отображения
  display.print("Hello World!");//здесь ваш ТЕКСТ
  display.display();            //чтобы показать или обновить ваш ТЕКСТ
}

void loop() {

 }

Удачи, Аунг Мио Оо

,

Спасибо, но я исправил это с чем-то другим. Проверьте мой ответ, если вам нужны подробности, @Xilog


2

На самом деле путаница с адресом I2C возникает из-за того, обрабатывается ли он как байтовый или 7-битный (MSB).

Например, на плате OLED указан адрес I2C = 0x78, что равно 0b_0111_1000 (запись адреса I2C).

В библиотеке Adafruit Arduino SSD1306 используется 7-битный адрес I2C, который 0x78 становится 011_1100 (принимая 7-битный старший бит) = 0x3C

,