ThingPulse / esp8266-oled-ssd1306

Driver for the SSD1306 and SH1106 based 128x64, 128x32, 64x48 pixel OLED display running on ESP8266/ESP32
https://thingpulse.com
Other
2.03k stars 643 forks source link

Bus is in Slave Mode with Arduino core for the ESP32 release v2.0.1 #360

Open whogarden opened 3 years ago

whogarden commented 3 years ago

Describe the bug Nothing is displayed on an oled sh1106 with ESP32 dev board SSD1306SimpleDemo.ino (it's your example code)

To Reproduce I use ESP32 dev board An SH1106 Wire sda to gpio21, scl to gpio22 Flash SSD1306SimpleDemo.ino with Arduino core for the ESP32 release v2.0.1 an nothing is displayed on the oled screen. If I go back to Arduino core for the ESP32 release v2.0.0, it's working

Sample code Provide a MCVE below.

/**
   The MIT License (MIT)

   Copyright (c) 2018 by ThingPulse, Daniel Eichhorn
   Copyright (c) 2018 by Fabrice Weinberg

   Permission is hereby granted, free of charge, to any person obtaining a copy
   of this software and associated documentation files (the "Software"), to deal
   in the Software without restriction, including without limitation the rights
   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   copies of the Software, and to permit persons to whom the Software is
   furnished to do so, subject to the following conditions:

   The above copyright notice and this permission notice shall be included in all
   copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
   SOFTWARE.

   ThingPulse invests considerable time and money to develop these open source libraries.
   Please support us by buying our products (and not the clones) from
   https://thingpulse.com

*/

// Include the correct display library

// For a connection via I2C using the Arduino Wire include:
//#include <Wire.h>               // Only needed for Arduino 1.6.5 and earlier
//#include "SSD1306Wire.h"        // legacy: #include "SSD1306.h"
#include "SH1106Wire.h"   // legacy: #include "SH1106.h"

// For a connection via I2C using brzo_i2c (must be installed) include:
// #include <brzo_i2c.h>        // Only needed for Arduino 1.6.5 and earlier
// #include "SSD1306Brzo.h"
// OR #include "SH1106Brzo.h"

// For a connection via SPI include:
// #include <SPI.h>             // Only needed for Arduino 1.6.5 and earlier
// #include "SSD1306Spi.h"
// OR #include "SH1106SPi.h"

// Optionally include custom images
#include "images.h"

// Initialize the OLED display using Arduino Wire:
//SSD1306Wire display(0x3c, SDA, SCL);   // ADDRESS, SDA, SCL  -  SDA and SCL usually populate automatically based on your board's pins_arduino.h e.g. https://github.com/esp8266/Arduino/blob/master/variants/nodemcu/pins_arduino.h
// SSD1306Wire display(0x3c, D3, D5);  // ADDRESS, SDA, SCL  -  If not, they can be specified manually.
// SSD1306Wire display(0x3c, SDA, SCL, GEOMETRY_128_32);  // ADDRESS, SDA, SCL, OLEDDISPLAY_GEOMETRY  -  Extra param required for 128x32 displays.
 SH1106Wire display(0x3c, 21, 22);     // ADDRESS, SDA, SCL

// Initialize the OLED display using brzo_i2c:
// SSD1306Brzo display(0x3c, D3, D5);  // ADDRESS, SDA, SCL
// or
// SH1106Brzo display(0x3c, D3, D5);   // ADDRESS, SDA, SCL

// Initialize the OLED display using SPI:
// D5 -> CLK
// D7 -> MOSI (DOUT)
// D0 -> RES
// D2 -> DC
// D8 -> CS
// SSD1306Spi display(D0, D2, D8);  // RES, DC, CS
// or
// SH1106Spi display(D0, D2);       // RES, DC

#define DEMO_DURATION 3000
typedef void (*Demo)(void);

int demoMode = 0;
int counter = 1;

void setup() {
  Serial.begin(115200);
  Serial.println();
  Serial.println();

  // Initialising the UI will init the display too.
  display.init();

  display.flipScreenVertically();
  display.setFont(ArialMT_Plain_10);

}

void drawFontFaceDemo() {
  // Font Demo1
  // create more fonts at http://oleddisplay.squix.ch/
  display.setTextAlignment(TEXT_ALIGN_LEFT);
  display.setFont(ArialMT_Plain_10);
  display.drawString(0, 0, "Hello world");
  display.setFont(ArialMT_Plain_16);
  display.drawString(0, 10, "Hello world");
  display.setFont(ArialMT_Plain_24);
  display.drawString(0, 26, "Hello world");
}

void drawTextFlowDemo() {
  display.setFont(ArialMT_Plain_10);
  display.setTextAlignment(TEXT_ALIGN_LEFT);
  display.drawStringMaxWidth(0, 0, 128,
                             "The pain itself\n pain is important, it has been resolved over the years." );
}

void drawTextAlignmentDemo() {
  // Text alignment demo
  display.setFont(ArialMT_Plain_10);

  // The coordinates define the left starting point of the text
  display.setTextAlignment(TEXT_ALIGN_LEFT);
  display.drawString(0, 10, "Left aligned (0,10)");

  // The coordinates define the center of the text
  display.setTextAlignment(TEXT_ALIGN_CENTER);
  display.drawString(64, 22, "Center aligned (64,22)");

  // The coordinates define the right end of the text
  display.setTextAlignment(TEXT_ALIGN_RIGHT);
  display.drawString(128, 33, "Right aligned (128,33)");
}

void drawRectDemo() {
  // Draw a pixel at given position
  for (int i = 0; i < 10; i++) {
    display.setPixel(i, i);
    display.setPixel(10 - i, i);
  }
  display.drawRect(12, 12, 20, 20);

  // Fill the rectangle
  display.fillRect(14, 14, 17, 17);

  // Draw a line horizontally
  display.drawHorizontalLine(0, 40, 20);

  // Draw a line horizontally
  display.drawVerticalLine(40, 0, 20);
}

void drawCircleDemo() {
  for (int i = 1; i < 8; i++) {
    display.setColor(WHITE);
    display.drawCircle(32, 32, i * 3);
    if (i % 2 == 0) {
      display.setColor(BLACK);
    }
    display.fillCircle(96, 32, 32 - i * 3);
  }
}

void drawProgressBarDemo() {
  int progress = (counter / 5) % 100;
  // draw the progress bar
  display.drawProgressBar(0, 32, 120, 10, progress);

  // draw the percentage as String
  display.setTextAlignment(TEXT_ALIGN_CENTER);
  display.drawString(64, 15, String(progress) + "%");
}

void drawImageDemo() {
  // see http://blog.squix.org/2015/05/esp8266-nodemcu-how-to-create-xbm.html
  // on how to create xbm files
  display.drawXbm(34, 14, WiFi_Logo_width, WiFi_Logo_height, WiFi_Logo_bits);
}

Demo demos[] = {drawFontFaceDemo, drawTextFlowDemo, drawTextAlignmentDemo, drawRectDemo, drawCircleDemo, drawProgressBarDemo, drawImageDemo};
int demoLength = (sizeof(demos) / sizeof(Demo));
long timeSinceLastModeSwitch = 0;

void loop() {
  // clear the display
  display.clear();
  // draw the current demo method
  demos[demoMode]();

  display.setFont(ArialMT_Plain_10);
  display.setTextAlignment(TEXT_ALIGN_RIGHT);
  display.drawString(128, 54, String(millis()));
  // write the buffer to the display
  display.display();

  if (millis() - timeSinceLastModeSwitch > DEMO_DURATION) {
    demoMode = (demoMode + 1)  % demoLength;
    timeSinceLastModeSwitch = millis();
  }
  counter++;
  delay(10);
}

Expected behavior Debug level "Debug" [ 10][I][esp32-hal-i2c-slave.c:234] i2cSlaveInit(): Initialising I2C Slave: sda=22 scl=22 freq=100000, addr=0x15 [ 11][D][esp32-hal-i2c-slave.c:494] i2c_slave_set_frequency(): Fifo thresholds: rx_fifo_full = 28, tx_fifo_empty = 4 [ 28][E][Wire.cpp:283] setClock(): Bus is in Slave Mode [ 33][E][Wire.cpp:308] beginTransmission(): Bus is in Slave Mode [ 39][E][Wire.cpp:331] endTransmission(): Bus is in Slave Mode [ 45][E][Wire.cpp:308] beginTransmission(): Bus is in Slave Mode [ 51][E][Wire.cpp:331] endTransmission(): Bus is in Slave Mode [ 57][E][Wire.cpp:308] beginTransmission(): Bus is in Slave Mode [ 63][E][Wire.cpp:331] endTransmission(): Bus is in Slave Mode [ 68][E][Wire.cpp:308] beginTransmission(): Bus is in Slave Mode [ 74][E][Wire.cpp:331] endTransmission(): Bus is in Slave Mode [ 80][E][Wire.cpp:308] beginTransmission(): Bus is in Slave Mode

Additional context Compile wire used : Wire version 2.0.0 dans le dossier: C:\Users\me\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.1\libraries\Wire

speedlao commented 2 years ago

Hi whogarden, I'm having the same issue now, has yours resolved yet?

whogarden commented 2 years ago

Hi speedlao, I can't remember how it was solved. I just try it now and it's working with : ESP32 arduino core 2.0.2 ESP8266 and ESP32 OLED driver for SSD1306 displays version=4.2.1 Wire version 2.0.0( coming with the esp32 arduino core 2.0.2)

speedlao commented 2 years ago

Hi speedlao, I can't remember how it was solved. I just try it now and it's working with : ESP32 arduino core 2.0.2 ESP8266 and ESP32 OLED driver for SSD1306 displays version=4.2.1 Wire version 2.0.0( coming with the esp32 arduino core 2.0.2)

Thanks for the reply. my problem solved just now. In my case is using u8g2 lib for SSD1306 OLED. The problem is when constructing u8g2 instance with hardwre I2C pin configuration, it won't work. A pre-called Wire.setPins saved my day.

So, have a nice day, cheers!

Logos7 commented 2 years ago

I have the same problem on Heltec LoRa32 v2.

[ 28][E][Wire.cpp:283] setClock(): Bus is in Slave Mode [ 33][E][Wire.cpp:308] beginTransmission(): Bus is in Slave Mode [ 39][E][Wire.cpp:331] endTransmission(): Bus is in Slave Mode [ 45][E][Wire.cpp:308] beginTransmission(): Bus is in Slave Mode [ 51][E][Wire.cpp:331] endTransmission(): Bus is in Slave Mode [ 57][E][Wire.cpp:308] beginTransmission(): Bus is in Slave Mode [ 63][E][Wire.cpp:331] endTransmission(): Bus is in Slave Mode [ 68][E][Wire.cpp:308] beginTransmission(): Bus is in Slave Mode

whogarden commented 2 years ago

Hi Logos7 Did you solved the pb? If not can you post your code And the first 2 lines before [ 28][E][Wire.cpp:283] setClock(): Bus is in Slave Mode

Logos7 commented 2 years ago

I used u8g2 lib for SSD1306 OLED.

I used the following type:

U8X8_SSD1306_128X64_NONAME_SW_I2C u8x8(SCL_OLED, SDA_OLED, RST_OLED);

Logos7 commented 2 years ago

setClock() looked like:

bool TwoWire::setClock(uint32_t frequency)
{
    esp_err_t err = ESP_OK;
#if !CONFIG_DISABLE_HAL_LOCKS
    //acquire lock
    if(lock == NULL || xSemaphoreTake(lock, portMAX_DELAY) != pdTRUE){
        log_e("could not acquire lock");
        return false;
    }
#endif
    if(is_slave){
        log_e("Bus is in Slave Mode");
        err = ESP_FAIL;
    } else {
        err = i2cSetClock(num, frequency);
    }
#if !CONFIG_DISABLE_HAL_LOCKS
    //release lock
    xSemaphoreGive(lock);
#endif
    return (err == ESP_OK);
}
Logos7 commented 2 years ago

Sorry, something went wrong with line endings...

whogarden commented 2 years ago

In your Heltec LoRa32 v2, I can see that oled sda is hard wired to gpio 4 And oled scl is hard wired to gpio 15 can you insure that your code correctly define that pins?

Logos7 commented 2 years ago

Yes. I have the same pins.

whogarden commented 2 years ago

And did you set the correct level on gpio16 (oled rst)?

Logos7 commented 2 years ago

Yes.

Even reset it manually...

whogarden commented 2 years ago

without your code, I am unable to help you further...

bato3 commented 2 years ago

see Wire.begin() overload issue: https://github.com/espressif/arduino-esp32/issues/6616#issuecomment-1184167285

Tinyu-Zhao commented 2 years ago

see Wire.begin() overload issue: espressif/arduino-esp32#6616 (comment)

Thank you he played a role for me.

ramonjunquera commented 2 years ago

A variant for the begin method has been included in the ESP32 Wire library. Now we have the following syntax:

Wire.begin(int sda=-1,int scl=-1,uint32_t frequency=0U);
Wire.begin(uint8_t slaveAddr,int sda=-1,int scl=-1,uint32_t frequency=0U);

If we try to make the following call:

byte pinSDA=4;
byte pinSCL=15;
Wire.begin(pinSDA,pinSCL);

The compiler will find that the call to the begin method will detect that its first parameter is of type byte (uint8_t), therefore it will consider that the variant to call is the second...ERROR. To solve the problem, it is enough to force the type of the first parameter to int:

byte pinSDA=4;
byte pinSCL=15;
Wire.begin((int)pinSDA,pinSCL);

Cheers

sama-re commented 2 years ago

Bonjour et merci pour l'astuce. Le fait d'insérer (int) a débloqué ma situation en erreur. J'utilise un ESP32 DevKitC v4. Sous l'IDE Arduino, avec un PC, cela fonctionnait. Je viens de passer sous VScode + PlatformIO, sur Mac OS X, qui m'avait affiché cette erreur. Merci à vous tous.