Problem with SH1106 display - rp2040 - I2C buses

Hey, guys. Can anyone help me with something? In my project, I would like to display the distance data from the laser sensors vl53IoX on the SH1106 display. To control the display I use U8g2lib.h library. Everything is controlled via rp2040, which has two I2C buses. Sensors are connected to the I2C0 bus on pins 5 and 8 and display to the I2C1 on pins 14 a 15. I am programming it through Arduino IDE. I would like the sensors to be on one bus and the display on the other. I have a minor problem with the display functioning on the second I2C1 bus.

If I am using the SW I2C bus (I2C1, pins 15 and 14), sensor data or Hello World is displayed on the screen, but with the wrong display rendering.

U8G2_SH1106_128X64_NONAME_1_SW_I2C u8g2(U8G2_R0,15,14,U8X8_PIN_NONE);


If I am using the HW I2C bus (I2C0) on predefined pins 4 and 5, the display works only with Hello World, not with sensors, but rendering is okay.

U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE);

Here is the code, I need help setting it to use the second bus I2C1 on the pins I need (14 and 15) and to render the display normally. I will be grateful for any advice. Thanks :slight_smile:

#include <Wire.h>

#include <Adafruit_VL53L0X.h>
#include <U8g2lib.h>


#define SDA0_PIN 8
#define SCL0_PIN 5


#define SDA1_PIN 14
#define SCL1_PIN 15


#define SHT_LOX1 7
#define SHT_LOX2 6


#define LOX1_ADDRESS 0x37
#define LOX2_ADDRESS 0x38

Adafruit_VL53L0X lox1 = Adafruit_VL53L0X();
Adafruit_VL53L0X lox2 = Adafruit_VL53L0X();


U8G2_SH1106_128X64_NONAME_1_SW_I2C u8g2(U8G2_R0,15,14,U8X8_PIN_NONE);

//U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE);

 

//#define U8G2_HAVE_2ND_HW_I2C 


int vzdialenostL = 0;
int vzdialenostP = 0;
VL53L0X_RangingMeasurementData_t measure1, measure2;

void setID() {
    
    digitalWrite(SHT_LOX1, LOW);
    digitalWrite(SHT_LOX2, LOW);
    delay(10);

   
    digitalWrite(SHT_LOX1, HIGH);
    delay(10);

    
    if (!lox1.begin(LOX1_ADDRESS, &Wire)) {
        Serial.println(F("Nepodarilo sa inicializovaĹĄ senzor LOX1!"));
        while (1);
    }

    
    digitalWrite(SHT_LOX2, HIGH);
    delay(10);

    
    if (!lox2.begin(LOX2_ADDRESS, &Wire)) {
        Serial.println(F("Nepodarilo sa inicializovaĹĄ senzor LOX2!"));
        while (1);
    }
}

void read_dual_sensors() {
    lox1.rangingTest(&measure1, false);
    lox2.rangingTest(&measure2, false);

    Serial.print(F("Senzor 1: "));
    if (measure1.RangeStatus != 4) {
        vzdialenostL = measure1.RangeMilliMeter;
        Serial.print(vzdialenostL);
    } else {
        vzdialenostL = -1;
        Serial.print(F("Mimo rozsahu"));
    }

    Serial.print(F(" mm, Senzor 2: "));
    if (measure2.RangeStatus != 4) {
        vzdialenostP = measure2.RangeMilliMeter;
        Serial.print(vzdialenostP);
    } else {
        vzdialenostP = -1;
        Serial.print(F("Mimo rozsahu"));
    }

    Serial.println(F(" mm"));
}

void displayReadings() {


   //u8g2.clearBuffer();
    u8g2.setFont(u8g2_font_6x10_tr);

    u8g2.firstPage();
  do {
    u8g2.setCursor(0, 12);
    
      u8g2.print("Senzor 1: ");
      if (vzdialenostL != -1) {
          u8g2.print(vzdialenostL);
          u8g2.print(" mm");
      } else {
          u8g2.print("Mimo rozsahu");
      }

      u8g2.setCursor(0, 28);
      u8g2.print("Senzor 2: ");
      if (vzdialenostP != -1) {
          u8g2.print(vzdialenostP);
          u8g2.print(" mm");
      } else {
          u8g2.print("Mimo rozsahu");
      }
      } while ( u8g2.nextPage() );
    

  
    //u8g2.sendBuffer();

}

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

    pinMode(SHT_LOX1, OUTPUT);
    pinMode(SHT_LOX2, OUTPUT);

    // Reset sensors
    digitalWrite(SHT_LOX1, LOW);
    digitalWrite(SHT_LOX2, LOW);
    delay(10);

     
    Wire.setSDA(SDA0_PIN);
    Wire.setSCL(SCL0_PIN);
    Wire.begin();  


    //Wire1.setSDA(SDA1_PIN);
    //Wire1.setSCL(SCL1_PIN);
    //Wire1.begin();  

    u8g2.begin();

    Serial.println(F("Inicializácia..."));
    setID();

}

void loop() {
    read_dual_sensors();
    displayReadings();
    delay(500);
}

have a look at
scans all Wire and Wire interfaces on Pico

sample serial monitor output running on a Pico

GY-91 on pins 4 and 5 and a BMP280 on pins 14 and 15

I2C Scan
Wire0 SDA: 0 SCL: 1
No I2C devices found

Wire1 SDA: 2 SCL: 3
No I2C devices found

Wire0 SDA: 4 SCL: 5
I2C device found at address 0x68
I2C device found at address 0x76
Scan Complete

Wire1 SDA: 6 SCL: 7
No I2C devices found

Wire0 SDA: 8 SCL: 9
No I2C devices found

Wire1 SDA: 10 SCL: 11
No I2C devices found

Wire0 SDA: 12 SCL: 13
No I2C devices found

Wire1 SDA: 14 SCL: 15
I2C device found at address 0x76
Scan Complete

Wire0 SDA: 16 SCL: 17
No I2C devices found

Wire1 SDA: 18 SCL: 19
No I2C devices found

Wire0 SDA: 20 SCL: 21
No I2C devices found

Wire1 SDA: 26 SCL: 27
No I2C devices found

All Scans Successful!

-------------------------------------------------
with a DS3231 RTC

Wire1 SDA: 26 SCL: 27
I2C device found at address 0x57
I2C device found at address 0x68
Scan Complete

All Scans Successful!

I2C Scan

Wire0 SDA: 0 SCL: 1

No I2C devices found

Wire1 SDA: 2 SCL: 3

No I2C devices found

Wire0 SDA: 4 SCL: 5

No I2C devices found

Wire1 SDA: 6 SCL: 7

No I2C devices found

Wire0 SDA: 8 SCL: 9

No I2C devices found

Wire1 SDA: 10 SCL: 11

No I2C devices found

Wire0 SDA: 12 SCL: 13

No I2C devices found

Wire1 SDA: 14 SCL: 15

I2C device found at address 0x3C

Scan Complete

Wire0 SDA: 16 SCL: 17

No I2C devices found

Wire1 SDA: 18 SCL: 19

No I2C devices found

Wire0 SDA: 20 SCL: 21

No I2C devices found

Wire1 SDA: 26 SCL: 27

No I2C devices found

All Scans Successful!

through the scanner everything is fine, I just don't know how to control the display on the other bus or how to at least fix the bad rendering.

With RP2040, you have plenty of RAM memory, so there is no need or point using the _1_ or _2_ constructor methods or the .firstPage() and .nextPage() methods.

Use the _F_ constructor method and the .clearBuffer() and .sendBuffer() methods.

I can see that you have tried these already, so I guess this won't fix the problem, but I guess you may be confused and are trying anything to make this work. But the _1_ and _2_ methods are only used with chips with very little RAM memory like Uno/Nano V3 and similar. For chips with lots of memory, they make things more complex for no benefit.

I used both methods and it didn't help at all.

Never the less, my recommendation stands. Ignore it if you prefer.

Are you absolutely certain this is a SH1106 display? Maybe it would be worthwhile checking if it works any better with SH1306 or other similar constructors.

now I tried to use this method to clear and send the buffer, but nothing happens to the display. Is this code correct?

void displayReadings() {


   u8g2.clearBuffer();
    u8g2.setFont(u8g2_font_6x10_tr);


    u8g2.setCursor(0, 12);
    
      u8g2.print("Senzor 1: ");
      if (vzdialenostL != -1) {
          u8g2.print(vzdialenostL);
          u8g2.print(" mm");
      } else {
          u8g2.print("Mimo rozsahu");
      }

      u8g2.setCursor(0, 28);
      u8g2.print("Senzor 2: ");
      if (vzdialenostP != -1) {
          u8g2.print(vzdialenostP);
          u8g2.print(" mm");
      } else {
          u8g2.print("Mimo rozsahu");
      }
      
    u8g2.sendBuffer();

}

It looks ok.

Did you try example sketches from the u8g2 library? Did they display correctly?

Yes. I have tried a few examples, rendered Hello World but incorrectly, the text jumps.

I think it's because of SW. Because on HW the text is nicely rendered, but I can't use it on pins 15 and 14 on another bus, because I don't know how to use HW on the I2C1 bus

Ah, try:

U8G2_SH1106_128X64_NONAME_F_2ND_HW_I2C u8g2(U8G2_R0,U8X8_PIN_NONE);

This works beautifully on predefined pins 26 and 27 of the second bus. Would I still need to somehow make it work on pins 14 and 15 ?

Maybe

Wire1.setSDA(14);
Wire1.setSCL(15);

Thank you, it works.