OLED Displays SSD1306

Showroom for MicroPython related hardware projects.
Target audience: Users wanting to show off their project!
domgiles
Posts: 10
Joined: Fri Aug 08, 2014 2:54 pm

OLED Displays SSD1306

Post by domgiles » Thu Sep 04, 2014 5:44 pm

I'm a big fan of the Adafruit Displays
https://www.adafruit.com/products/931
They are nice and bright, Don't take up much space and you have choice of SPI or I2C.

I've seen some references to porting the SSD1306 but Kenneth hasn't seen my requests for the code. Has anyone managed to get hold of this code or ported their own variant of it?

Thanks

Dom

Turbinenreiter
Posts: 288
Joined: Sun May 04, 2014 8:54 am

Re: OLED Displays SSD1306

Post by Turbinenreiter » Fri Sep 05, 2014 8:33 am


domgiles
Posts: 10
Joined: Fri Aug 08, 2014 2:54 pm

Re: OLED Displays SSD1306

Post by domgiles » Sun Sep 07, 2014 4:06 pm

Thanks... I'll see if I can start porting it to the i2c variant of the OLED displays. Less wires is always a good thing. ;)

Dom

neal_crook
Posts: 3
Joined: Tue Oct 14, 2014 10:37 pm

Re: OLED Displays SSD1306

Post by neal_crook » Tue Oct 14, 2014 10:40 pm

Using that code as the starting point I have my I2C OLED display up and running (my first bit of Python on this board!)

I'll make it a bit tidier and try to submit it upstream to the original author

Neal.

neal_crook
Posts: 3
Joined: Tue Oct 14, 2014 10:37 pm

Re: OLED Displays SSD1306

Post by neal_crook » Wed Oct 15, 2014 9:44 pm

https://github.com/khenderick/micropython-drivers

now includes support for both SPI and I2C.

My display board has been running the "scrolling cursors" for >3hours with no problems.

Neal.

domgiles
Posts: 10
Joined: Fri Aug 08, 2014 2:54 pm

Re: OLED Displays SSD1306

Post by domgiles » Wed Oct 22, 2014 6:32 pm

Just curious... How are you finding the performance? I can't decide whether its a limitation of the CPU or something with the SSD1306 chipset or the code its self. But the repainting of the screen takes a while...

neal_crook
Posts: 3
Joined: Tue Oct 14, 2014 10:37 pm

Re: OLED Displays SSD1306

Post by neal_crook » Thu Oct 23, 2014 9:02 pm

To benchmark the I2C interface you need an I2C device present (which I have) because the protocol requires acks from the slave.
You can benchmark the SPI interface without a device present (lucky as I don't have one) because the protocol has no ack anywhere.
Using a stopwatch I timed the "scrolling cursors" for 1000 frames (1000 buffer updates)
I2c: 0.087 s/frame
SPI: 0.066 s/frame

Sanity check (I2C):

Assume all of the time is taken in I2C bus operations
6 x self.write_command = 6 x (device_id + ctrl_byte + command_byte)
1 x self.i2c_send = 1 x (device_id + ctrl_byte + 128*64/8)

Each byte on I2C takes 9 bit-times (8-bit data + ack). Each transaction has an overhead of ~2 bit-times (start/stop). These are all writes.
6 x ((3*9) + 2)
1 x ((1026*9) + 2)
= 9410 bit-times
@400kHz = 0.0235s

So (assuming correct maths) that suggests there is a significant processing overhead as well as the bus operations. I haven't put a scope on the pins to verify that baudrate=400000 really corresponds to SCL running at 400kHz.

[Hmm. That makes me realise that a 400kHz clock rate actually corresponds to a baud (symbol) rate of 200kHz. Maybe I have set this up wrongly.. but it works reliably]

I ran another benchmark in which I just call the .display() method repeatedly 1000 times, again timed with a stopwatch
I2C: 0.023 s/frame
SPI: 0.001 s/frame (really, too fast to time by hand)

This is a good correlation with the theoretical time taken for I2C bus activity and suggests that the previous timings break down like this, per frame:
I2C: 0.064s compute time + 0.023s bus time
SPI: 0.064s compute time + ~0.002s bus time

Conclusions: (i) computation time is non-trivial for the scrolling cursors code and (ii) SPI @16MHz is much faster than I2C at 400kHz (as well as having less protocol overhead on the bus) (iii) that extra wire is worth its soldering time!

The .display() method always does a complete buffer update. It would be possible to maintain 2 buffers, compute the difference between them and do a more selective update of a sub-region of the display. That turns into a trade-off between memory/compute time and bus transfer time.

Hope that answers your question

regards,

Neal.


Conclusions:

domgiles
Posts: 10
Joined: Fri Aug 08, 2014 2:54 pm

Re: OLED Displays SSD1306

Post by domgiles » Fri Oct 24, 2014 3:41 pm

So I must be doing something very wrong. I'm not seeing that... I'm currently running on SPI. It may be the way I'm handing the interrupts from other parts of the code thats giving me the impression thats its the display thats taking its time... I am rendering fonts.

I'll try and put together a little test case.

User avatar
kfricke
Posts: 342
Joined: Mon May 05, 2014 9:13 am
Location: Germany

Re: OLED Displays SSD1306

Post by kfricke » Fri Nov 28, 2014 2:45 pm

On my 128x32 pixel display this library does not work as intended...

The height of 32 pixels does not seem to be taken into account correctly. Every second line seems to be skipped from the buffer, starting at the missing lin 0. Or at least something like that. The drawable region is only 16 pixels high and offset by 16 from the bottom of the display (at least from my point of view; correct physical orientation can be derived from my attached photos).

In my photos you can see your original example from github (matched to 32 instead of 64 pixel height) and an example with the following drawing operations only:

Code: Select all

for x in range(128):
    display.set_pixel(x, x % 32, True)
Attachments
my_example.jpg
my_example.jpg (79.42 KiB) Viewed 19480 times
orig_example.jpg
orig_example.jpg (86.94 KiB) Viewed 19480 times

User avatar
kfricke
Posts: 342
Joined: Mon May 05, 2014 9:13 am
Location: Germany

Re: OLED Displays SSD1306

Post by kfricke » Fri Nov 28, 2014 10:28 pm

Stupid, was my fault. I did miss line where you do set the height of 64 pixels in the call to the constructor of the SSD1306 object.

Post Reply