Bug in oled-wing-adafruit library


#1

Running some code to test mesh stability and a work around when it goes down I ran into some issues when I added the Adafruit oled display. It manifested itself when my indicator LEDs were not working correctly anymore.

After some head-scratching I discovered that display.display() takes between 67 and 71ms. That seems awfully long. The commands before that to clear and write to the display take much less than a millisecond.

Not sure where in the library to look to find that long delay

I am running this on a Xenon using the featherwing oled display mounted on a featherwing tripler. It is the only peripheral.

display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.println("HB Count " + String(heartbeatCount));
display.setCursor(0,8);
display.println("Display Update Time " + String(displayTime));  // up to here is less than a millisecond 	
displayTimer = millis();
display.display(); // this call takes 67 to 71 milliseconds to complete
displayTime = millis() - displayTimer;  

#2

The oled-wing-adafruit library is inheriting from Adafruit_SSD1306 and there you’ll find the implementation of ::display()
https://build.particle.io/libs/Adafruit_SSD1306/0.0.2/tab/Adafruit_SSD1306.cpp#433

There would be potential for minimal improvement by using Wire.write(buffer[i],16) instead of doing that in a for() loop for the I2C version.
For SPI there would be even greater potential for improvement when writing the full buffer via SPI.transfer(buffer[0], NULL, SSD1306_LCDWIDTH*SSD1306_LCDHEIGHT/8).


#3

Also clearDisplay and updating the display only write to the buffer in RAM. The display() method takes the copy in RAM and write out the data to the display by I2C.


#4

I see, the clear display and updates are just putting the data together in RAM before communicating with the display.

I took a look at the link @ScruffR sent me. I don’t see a lot delays there.

So how much data is being sent? Is the serial clock running really slow? You should be able to send a whole boatload of data in 70ms, way more than it takes to update that small display.

I realise there are more pressing issues at the moment but is this something that can be fixed eventually or something we just have to work around?


#5

The I2C communication takes time. You are sending 512 bytes one-by-one over a somewhat slow interface :wink:

The default I2C speed is 100kHz, you are sending 4096 bit plus some extra for sync, acknowlege, … all that takes time.


#6

Wow, I didn’t realise it was running that slow.

I see the default for the I2C bus is 100kHz but also see that it can be changed. What I don’t know is how to override the library setting the speed, it just calls Wire.begin(). Can I just use set.Speed() after display.setup() to experiment? Or do I actually need to change it in the library?


#7

You can try overriding the speed, but it’s not guaranteed that the display supports the higher speed. You’d have to check.


#8

According to the data sheet it looks like I2C minimum cycle time is 2.5us which is 400 kHz. I’ll give a try and see what breaks. :slight_smile:

Tried adding Wire.setSpeed(400000); or Wire.setSpeed(CLOCK_SPEED_400KHZ); and it makes no difference, always 70ms update time. I guess the library overrides that speed.

Duh, you have to set the speed before calling display.setup(); not after. Now it works and I have an update time of 21ms. Still not as fast as I’d like but much better. :grinning:

Thank you @ScruffR.