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);
}
@Xilog, 👍-2
Обсуждение4 ответа
Лучший ответ:
Некоторое время после того, как я задал этот вопрос, я попытался провести исследование. Оказывается, изменение OLED_RESET на -1 исправило это.
У меня есть некоторый опыт работы с экраном, который вы используете, и я надеюсь, что эти советы помогут решить вашу проблему.
- Изменение адреса в коде
Дисплей OLED, который вы используете, использует так называемый протокол I2c или IIC, который является аббревиатурой «Inter Intergrated Circuit», вот его страница в Википедии, чтобы прочитать о это.
Коммуникация IIC имеет 7-битное адресное пространство, что означает наличие 127 различных адресов, например 0x3C, 0x3D, 0x38 и т. д....
Ваш дисплей может иметь адрес 0x3C или 0x3D, поэтому вы можете попробовать изменить эти значения, пока что-нибудь не появится.
- Отключение любого другого устройства IIC
Хотя вы можете подключить многие устройства IIC, но, как было сказано в комментариях, лучше отключить все, кроме него, для устранения неполадок.
- Правильное напряжение?
Возможно, вы знаете, что в некоторых дисплеях используется напряжение 3,3 В, а в некоторых — 5 В, но, как показал сканер IIC, я не думаю, что это проблема в вашем случае, но вы должны это учитывать.
- Попробуйте использовать другие скетчи
Ну, я думаю, что 99% проблем кроется в вашем коде (иногда это случается со мной), поэтому я предлагаю использовать другие примеры библиотек или совсем другие библиотеки, или, если вы хотите принять вызов, откройте таблицу данных для ssd1306 и создайте собственную библиотеку и коды.
Надеюсь, эти советы помогут вам или любому другому зрителю.
Кстати, я учусь, поэтому буду признателен любому, кто редактирует ответ, чтобы сделать его лучше или понятнее.
это не ответ и не решение., @hcheung
Большое спасибо! Попробую ваши советы. Очень признателен, @Xilog
Я скопировал ваш код и загрузил его на свой дисплей. Это ничего не показывает. Вот код, который я успешно запустил.
#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
На самом деле путаница с адресом I2C возникает из-за того, обрабатывается ли он как байтовый или 7-битный (MSB).
Например, на плате OLED указан адрес I2C = 0x78, что равно 0b_0111_1000 (запись адреса I2C).
В библиотеке Adafruit Arduino SSD1306 используется 7-битный адрес I2C, который 0x78 становится 011_1100 (принимая 7-битный старший бит) = 0x3C
- Не удалось выделить SSD1306 при добавлении константы
- сканер i2c застрял на сканировании моего 0,96 дюймового OLED экрана с помощью Arduino Nano
- Arduino Nano и oled-экран 0.96 i2c не работают
- Как отображать переменные на 0,96-дюймовом OLED-дисплее с библиотекой u8glib?
- Путаница между SPI и I2C для SSD1306 OLED
- Как перевести Arduino Nano в спящий режим с низким энергопотреблением (<0,05 мА)
- Запуск 7-контактного OLED-дисплея с 4 контактами (I2C)
- MAX30100 не работает
Сканер (?) находит дисплей по адресу 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