Closed mleibman closed 3 years ago
Hi @mleibman,
Version 1.2.10 includes the increased I2C transmission size upgrade you requested. We've added a new function called i2cWriteMultiple
to do that. It defaults to using a transfer size of 32 bytes, but you can increase that (if your hardware will allow it) by calling setI2CTransactionSize
.
At 400kHz on an ATmega328, a full drawBitmap
now takes around 16ms.
Best wishes,
Paul
I've tried using this library with a Wemos D1 mini and a Wemos OLED Shield since this is one of the major libraries out there that handles the 64x48 resolution displays, but I have found it to be way too slow.
On a 160Mhz ESP8266 MCU, the display update time (just the .display() call) took 118ms. As noted in issue #11 , the library uses the default 100KHz I2C bus speed. Changing it to 700+KHz decreased the update time to 17ms. Not bad, considering the ESP8266 has only a software I2C (more on that later), but still too slow, especially considering the tiny screen size.
It is only when I looked deeper into how the data was sent to the display that I noticed that it was sending the screen data one byte at a time, each with the overhead of the I2c address + control & command byte, so for each byte of the screen data, it was sending 3 bytes on the wire. In addition to that, it was sending 12 (6*2) extra messages to set the page and column address for the page of data being sent, so that extra time on the wire.
All of this seems completely unnecessary, especially considering that SSD1306 supports plain horizontal addressing mode that matches the memory buffer structure in
screenmemory
and auto-increments the current address pointer with rollover to the beginning. We can easily set this mode in thebegin()
method:Then we could just write the entire block in pretty much one go. Well, technically two, since the protocol requires the first byte to be ack'ed:
Doing this speeds things up quite a bit, bringing it down to 5ms. As mentioned earlier, ESP8266 doesn't have a hardware I2C. Using a faster software I2C implementation (https://github.com/pasko-zh/brzo_i2c), the time went down to 3-4ms, but I didn't want to bring in yet another library, so I decided to stick with the above implementation.
Looking at the Arduino's Wire API (https://www.arduino.cc/en/Reference/Wire), they mention that the default implementation only has a 32-byte buffer, and if we were to send more in one transmission, it would be discarded. So I suppose that may have served the reason for this implementation. Still, Adafruit's SSD1306 library (https://github.com/adafruit/Adafruit_SSD1306) does at least some batching and sends data 16 bytes at a time, so the overhead is much smaller. Plus, it uses the horizontal mode addressing, so the extra transmissions to set the page and column sizes are not needed.