I2C bus running at 100kHz and 400kHz at same time?

I have a Leonardo connected to Adafruit 128x32 OLED display and it's working fine. I wanted to look at the I2C SCL line on my scope and I noticed the bus speed appears to be jumping between 100khz and 400khz. Here's a video of my scope: - YouTube
Is it really going back and forth between the two bus speeds? That doesn't make any sense, but I don't know what else to make of the scope output. Here's my sketch:

#include <Wire.h>
#include <Adafruit_GFX.h>     // http://github.com/adafruit/Adafruit-GFX-Library
#include <Adafruit_SSD1306.h> // http://github.com/adafruit/Adafruit_SSD1306

#define OLED_RESET 8
Adafruit_SSD1306 display(OLED_RESET);


#if (SSD1306_LCDHEIGHT != 32)
 #error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif

void setup()  {                
  Serial.begin(9600);
  delay(4000);
  
  // by default, we'll generate the high voltage from the 3.3v line internally! (neat!)
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3C (for the 128x32)

  display.clearDisplay();  
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  display.println("HELLO THERE");
  display.setCursor(0,9);
  display.println("HAVE A NICE DAY");
  display.setTextSize(2);
  display.setCursor(0,18);
  display.println("more stuff");
  display.display();
  delay(4000);
  pinMode(13, OUTPUT);
}

void loop()  {
  display.clearDisplay();   // clears the screen and buffer
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  display.println("TIME TIME TIME TIME");
  display.setTextSize(2);
  display.setCursor(0,18);
  char buff[12];
  display.println(ltoa(millis()/100, buff, 10));
  display.display();
  
  Serial.println(millis());

  digitalWrite(13, HIGH);
  delay(100);
  digitalWrite(13, LOW);
  delay(50);   
}

Check the library : Adafruit_SSD1306/Adafruit_SSD1306.cpp at master · adafruit/Adafruit_SSD1306 · GitHub
Search for "400", the line where the TWBR register is changed. That is the I2C control register.
So the I2C is indeed temporary increased to 400kHz. And afterwards the original speed is set with : TWBR = twbrbackup;

Peter_n:
Check the library : Adafruit_SSD1306/Adafruit_SSD1306.cpp at master · adafruit/Adafruit_SSD1306 · GitHub
Search for "400", the line where the TWBR register is changed. That is the I2C control register.
So the I2C is indeed temporary increased to 400kHz. And afterwards the original speed is set with : TWBR = twbrbackup;

I wonder why the library is doing that. On line 509 there's the code

#ifndef __SAM3X8E__
    uint8_t twbrbackup = TWBR;
    TWBR = 12; // upgrade to 400KHz!
#endif

As a test I commented out TWBR = 12; and the bus stays at 100MHz now. And the OLED display still works.

ScottG:
As a test I commented out TWBR = 12; and the bus stays at 100MHz now. And the OLED display still works.

100 KHz :smiley:

Sure it still works, it just takes 4 times as long to send data to it. if it's not an issue for your application, let it be like that.

Otherwise, nice find - i would never expect to see something like this happen - i'm wondering what a slow 100 KHz-only device on the bus would get out of the 400 KHz signaling...

// Per.

I think I'll leave it alone for now and let it use 400KHz. At least now I know what's going on.

It's my understanding that with higher bus rates, the PCB traces are more critical. I have a PCB board getting made now where the I2C signals run across it to a few devices. I did a little research on how to lay-out high speed signal traces, so hopefully I did a good job. I'll see how well the PCB performs when I get it back in a couple weeks.

I think you'll be safe with 400kHz, that's pretty slow by electronics/PCB standards.


Rob

Graynomad:
I think you'll be safe with 400kHz, that's pretty slow by electronics/PCB standards.


Rob

Good to know. Thanks.