Одинаковый вывод на дисплеях с разными I2C-адресами (библиотека AdaFruit, ESP32)

У меня есть два дисплея, подключенных к ESP32 через I2C, и я использую библиотеку AdaFruit. Вся обработка вывода дисплея упакована в собственную библиотеку. Во время тестирования у меня был настроен только один дисплей, и все выглядело нормально. Теперь, в моей фактической настройке с двумя дисплеями, я получаю вывод только первого дисплея на обоих экранах. Дисплеи работают на одной I2C-шине, заданы разные адреса. Я также запустил сканер адресов/портов, который подтвердил разные адреса (0x3C и 0x3D).

Раньше я использовал в такой настройке отдельные дисплеи с библиотекой AdaFruit, но только на Arduino Uno и без перемещения кода в собственные библиотеки. Поэтому я не могу сказать, что-то портит ESP32 или наличие нескольких файлов, или я что-то упускаю.

Вот части кода в cpp-файле, который я использовал для инициализации дисплеев, и некоторых функций, которые я вызываю:

#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Wire.h>
#include <gfxfont.h>
#include <SPI.h>
#include "DisplayOut.h"
#include "Game.h"


    /* -------------esp32 Pin setup --------------------- */
    const byte displayData = 21;    // I2C SDA
    const byte displayClock = 23;   // I2C СКЛ
    /* --------------------------------------------------- */

// Определить OLED
#define OLED_RESET displayData  
Adafruit_SSD1306 display1(OLED_RESET);
Adafruit_SSD1306 display2(OLED_RESET);



/* some variables */


void DisplayOutClass::init()
{
    // Инициализируем каждый дисплей с помощью i2c-адреса

    display1.begin(SSD1306_SWITCHCAPVCC, 0x3C);
    display2.begin(SSD1306_SWITCHCAPVCC, 0x3D);
    display1.setTextWrap(false);
    display2.setTextWrap(false);
}



void DisplayOutClass::scorePlayer1(int score1)
{
    display1.clearDisplay();

    if (gameMode == 2)
    {
        display1.clearDisplay();
        display1.setCursor(0, 0);
        display1.setTextSize(2);
        display1.setTextColor(WHITE);
        display1.print(playerName[player1]);
    }

    display1.setTextSize(4);
    display1.setTextColor(WHITE);
    display1.setCursor(getCenteredPosX(3, String(score1)), 24);
    display1.print(score1);
}

void DisplayOutClass::scorePlayer2(int score2)
{
    display2.clearDisplay();

    if (gameMode == 2)
    {
        display2.clearDisplay();
        display2.setCursor(0, 0);
        display2.setTextSize(2);
        display2.setTextColor(WHITE);
        display2.print(playerName[player2]);
    }

    display2.setTextSize(4);
    display2.setTextColor(WHITE);
    display2.setCursor(getCenteredPosX(3, String(score2)), 24);
    display2.print(score2);
}



/* some more Functions */


DisplayOutClass DisplayOut;

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

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

, 👍0

Обсуждение

Ваши контакты сброса установлены на номер адреса i2c, и вы используете один и тот же контакт сброса для обоих дисплеев? Вы читали, что вы можете сделать вывод сброса -1, чтобы не использовать его или поделиться им с сбросом Arduino., @Jot

Я согласен с @Jot, контакты сброса должны быть разделены: вы используете один и тот же контакт (то же определение OLED_RESET), что приводит к сбросу первого дисплея после инициализации..., @caligari

Каждый дисплей имеет только четыре контакта: VCC, GND, SCL, SDA. Таким образом, контакта сброса нет. Установка OLED_RESET на -1 не сработала, как и установка OLED_RESET на неиспользуемые контакты., @cfu479

Добавление false к методам начала display1.begin(SSD1306_SWITCHCAPVCC, 0x3C, false) и display2.begin(SSD1306_SWITCHCAPVCC, 0x3D, false) для отключения сброса также не принесло никакого прогресса., @cfu479

Кстати, мне пришлось использовать вторую строку i2c, чтобы esp32 работал нормально. сработало хорошо и положило конец моему разочарованию, но если есть лучший способ, мне тоже любопытно., @dandavis


1 ответ


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

0

Попробуйте новые конструкторы (старые устарели):

Wire.begin(21, 23); // SDA, SCL

Adafruit_SSD1306 display1(SSD1306_LCDWIDTH, SSD1306_LCDHEIGHT);
Adafruit_SSD1306 display2(SSD1306_LCDWIDTH, SSD1306_LCDHEIGHT);

display1.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display2.begin(SSD1306_SWITCHCAPVCC, 0x3D);


,

Использование этого с «#define SSD1306_LCDWIDTH 128» и «#define SSD1306_LCDHEIGHT 64» просто дает мне ошибки и не компилируется, хотя я перезаписал библиотеку библиотекой из ссылки, чтобы быть уверенным, что у меня правильная версия., @cfu479

Нашел проблему, все еще неправильно использовал конструктор. В чем заключался трюк: #define OLED_RESET -1 #define SCREEN_WIDTH 128 // Ширина OLED-дисплея в пикселях #define SCREEN_HEIGHT 64 // Высота OLED-дисплея в пикселях Adafruit_SSD1306 display1 (SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); Adafruit_SSD1306 display2(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);, @cfu479