Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SSD1306 and SH1106 compatibility #1

Closed
xes opened this issue Jan 24, 2015 · 30 comments
Closed

SSD1306 and SH1106 compatibility #1

xes opened this issue Jan 24, 2015 · 30 comments

Comments

@xes
Copy link
Collaborator

xes commented Jan 24, 2015

Hi! Thank you for this nice piece of software!
I'm trying to use this to drive an SH1106 with a cubie board but i should change it a little bit since
the only thing i can obtain now is some line and a display filled with noise just like in the image here:
adafruit/Adafruit_SSD1306#14

The SH1106 controller has an internal RAM of 132x64 pixel (while the SSD1306 has 128x64 pixel).
It seems, that the 128x64 OLED is centered in most cases within the 132x64 area, that means pixel (2,0) in ram is pixel (0,0) on the display.
Now ebay is filled with these oled displays (often with an unclear description saying SH1106/SSD1306) and after digging a lot on the web, i have found there is now way to use them with a raspberry or a cubie board.
Do you think you could give me some help or add an option to support both display models?

Ref:
http://forum.arduino.cc/index.php?topic=265557.0
http://forum.arduino.cc/index.php?topic=256374.0
http://www.mikrokontroler.pl/system/files/SH1106.PDF

@rm-hull
Copy link
Owner

rm-hull commented Jan 24, 2015

Well, it's going to be difficult to test without access to a device, but if you haven't already tried, first thing I would try would be to alter:

https://github.com/rm-hull/ssd1306/blob/master/ssd1306.py#L90

to be 132 rather than 128.

When you switch it on, presumably the display is initially blank?

If you're just getting noise when it does the drawing, then this implies that the commands are just wrong and it didn't initialize properly, and/or the memory is mapped different to the SSD1306.

I'll have a go and see if i can get hold of a device ... and a cubie-board

@xes
Copy link
Collaborator Author

xes commented Jan 24, 2015

This is my display:
http://www.ebay.com/itm/Blue-1-3-I2C-IIC-128X64-OLED-LCD-Display-Module-for-Arduino-STM32-AVR-M45-/121409368984?ssPageName=ADME:L:OC:IT:3160

Initialization seems to be correct but any of the tests of example.py produces just noise and a few parts of lines in the upper part of display due the different memory mapping.
I would like to add the proper memory mapping in python like it has been done here for arduino:
https://github.com/wonho-maker/Adafruit_SH1106/blob/master/Adafruit_SH1106.cpp#L509
But unfortunately i don't know how to integrate this in your ssd1306.py and it seems there is nothing else that could be used to drive this display.
Thank you for your time, any help will be very appreciated.

@rm-hull
Copy link
Owner

rm-hull commented Jan 24, 2015

Looking at https://github.com/wonho-maker/Adafruit_SH1106/blob/master/Adafruit_SH1106.cpp#L555-L570 (this is the I2C part), it looks to be writing to the memory in pages, whereas the roughly equivalent code in the SSD1306 repo (https://github.com/rm-hull/ssd1306/blob/master/ssd1306.py#L137-L156) assembles a buffer, then blasts this all in, in one go.

If you run the example.py is the display completely random, or is there any structure at all? Could you upload a photo of the screen in this state (you can drag/drop pics onto the github comment area)

@xes
Copy link
Collaborator Author

xes commented Jan 25, 2015

Running example.py without any change i obtain this:
sh1106_noise2

As you can see, you can recognize a structure in the upper part.

I may suppose that the right result should be this:
https://learn.adafruit.com/system/assets/assets/000/017/607/medium800/raspberry_pi_DSC00468_copy.jpg?1403645755

@xes
Copy link
Collaborator Author

xes commented Jan 27, 2015

Sorry to bother you again, have you any suggestion or any idea how to fix this?
The worst thing is that looking at the result it seems that the solution is really not so far...

@rm-hull
Copy link
Owner

rm-hull commented Jan 28, 2015

See if you can get this running: https://github.com/adamyoung600/WRX_HUD/tree/master/Hardware/SH1106

If that works, but it doesn't serve your needs, I'll have a go at porting the display logic into this library

@xes
Copy link
Collaborator Author

xes commented Jan 28, 2015

Great! Thank you very much! That lib works and has a correct memory - display mapping.
I have just tried the test:
https://github.com/adamyoung600/WRX_HUD/blob/master/TestSH1106FontTest.py
And it can draw 8 lines of text without any noise or position shift.
Finally something that could drive this oled!
Obviously that lib don't has any draw function like your's, and can only display some text or an image file. For the future i hope you would port the support for SH1106 in your library.
While waiting for further improvements... ;) many thanks again for your time and help.

@rm-hull
Copy link
Owner

rm-hull commented Feb 1, 2015

Ok, I'll have a look at porting the guts of that memory mapping into this library... on the basis that I haven't got one of those devices, can I assume you are willing to test this & provide feedback for me please?

@xes
Copy link
Collaborator Author

xes commented Feb 2, 2015

For sure! I will test any new version and give you feedback with great pleasure!

@rm-hull
Copy link
Owner

rm-hull commented Feb 6, 2015

There's a new branch called sh1106-compat where I've done a fair bit of refactoring in order to slot in the new driver for this device. Don't know how familiar you are with git, but you'll need to checkout that branch, and pull (give me a shout if not and I'll guide you though it).

The driver code is now in the oled package, but the example.py should work exactly as before.

In order to try out the new device, alter example.py at line 11: change ssd1306(...) to sh1106(...) - see https://github.com/rm-hull/ssd1306/blob/sh1106-compat/example.py#L11

All I've done so far is just copy the init from https://github.com/adamyoung600/WRX_HUD/blob/master/Hardware/SH1106/SH1106LCD.py#L77, and simplified the display logic: not saying this will fix it, but its a first step

If you could test it please, and attach any pics of what is displayed.

Cheers
Richard

@xes
Copy link
Collaborator Author

xes commented Feb 6, 2015

hi!
first test completed. Fixed one error:

File "ssd1306-sh1106-compat/oled/device.py", line 120, in init
const.DISPLAYOOFF,
AttributeError: class const has no attribute 'DISPLAYOOFF

The result is:
1

@rm-hull
Copy link
Owner

rm-hull commented Feb 6, 2015

doh.... added you as a collaborator so you have r+w access - if you could just fix & push any obvious errors I make

@rm-hull
Copy link
Owner

rm-hull commented Feb 7, 2015

Added some SH1106 specific display code - can you pull the latest from this branch, modify example.py at line 11, test & report back please - again, a pic would be most useful

@xes
Copy link
Collaborator Author

xes commented Feb 7, 2015

No-go..
File "./example.py", line 11, in
device = sh1106(port=1, address=0x3C)
File "/usr/local/oled_src/tests/ssd1306-sh1106-compat/oled/device.py", line 108, in init
const.DISPLAYON)
File "/usr/local/oled_src/tests/ssd1306-sh1106-compat/oled/device.py", line 70, in command
self.bus.write_i2c_block_data(self.addr, self.cmd_mode, list(cmd))
IOError: [Errno 70] Communication error on send

The problem seems to be at line 87 of device.py:
super(sh1106, self).init(port, address, 0x80)

Replacing 0x80 with 0x00 to go back at the previous commit i obtain the attached image.
(can't understand this thing comparing with https://github.com/adamyoung600/WRX_HUD/blob/master/Hardware/SH1106/SH1106LCD.py#L57)

2

@rm-hull
Copy link
Owner

rm-hull commented Feb 7, 2015

That's interesting that 0x80 for the command mode doesn't work...

What happens if you change the sense of the while loop into a for loop at lines 124-137 of device.py to something like:

            buf = []
            for x in xrange(self.width):
                buf.append(
                    pix[(x, i + 0)] & 0x01 |
                    pix[(x, i + 1)] & 0x02 |
                    pix[(x, i + 2)] & 0x04 |
                    pix[(x, i + 3)] & 0x08 |
                    pix[(x, i + 4)] & 0x10 |
                    pix[(x, i + 5)] & 0x20 |
                    pix[(x, i + 6)] & 0x40 |
                    pix[(x, i + 7)] & 0x80)

@rm-hull
Copy link
Owner

rm-hull commented Feb 7, 2015

Also, that weird artifact on the first line... if you change line 121 to read:

# move to given page, then reset the column address
self.command(page, 0x10, 0x00)

And then get rid of lines 141-142

@rm-hull
Copy link
Owner

rm-hull commented Feb 7, 2015

Errm..in prev comment, that should be:

self.command(page, 0x00, 0x10)

@xes
Copy link
Collaborator Author

xes commented Feb 7, 2015

Changes applied. Perfetct!!! (preparing photo)

@rm-hull
Copy link
Owner

rm-hull commented Feb 7, 2015

Nearly there... it's not still doing the x -= 1 after the buf.append is it?

Can you commit the changes you made?

@xes
Copy link
Collaborator Author

xes commented Feb 7, 2015

Sorry i did a little copy-paste mess that produced previous photo.
Here the correct result of the changes you have suggested:
4

@rm-hull
Copy link
Owner

rm-hull commented Feb 7, 2015

👍 Fantastic!

I'll merge this to master as soon as you've committed.

Pondering about writing a setup.py and reorg the directory tree slightly, but that is for another day I think.

Thanks for your efforts in making this work - much appreciated.

@xes
Copy link
Collaborator Author

xes commented Feb 7, 2015

Commit done. The only mistery remaining is the one about the command mode.. Anyway it works!! :-)
Many thanks for your help!!
I hope this could be useful to many others stumbled in this model of display.

@xes
Copy link
Collaborator Author

xes commented Feb 7, 2015

There is still something to fix. To draw the biggest rectangle i have to use:
draw.rectangle((2, 0, 129, 63)
To me it seems there is an x shift of 2px.

@rm-hull
Copy link
Owner

rm-hull commented Feb 7, 2015

I remember reading this: https://github.com/adamyoung600/WRX_HUD/blob/master/Hardware/SH1106/SH1106LCD.py#L157, and then recalled your very first comment about the x-shift 2px.

You could try at line 122 of device.py:

self.command(page, 0x02, 0x10)

This I think will offset the column accordingly... and then you may possibly have to reduce the width in the initializer method from 132 down to 130 (or maybe 128 even, if there are 2 missing pixels at the right hand edge as well).

I have rebased the code onto master, so consider the sh1106-compat branch dead now - any commits you make, please do so on the master branch directly.

@xes
Copy link
Collaborator Author

xes commented Feb 7, 2015

In fact:
self.command(page, 0x02, 0x10)
is correct.

Now i'm still trying to understand the real pixel size that i think is 128x64.
The 2 pixel shift should explain the 2+128+2 = 132 memory mapping.
So i have changed line 88 to:
self.width=128
and added in example.py:
+# Draw a rectangle of the same size of screen
+draw.rectangle((0, 0, device.width-1, device.height-1), outline=255, fill=0)
To check display size.

What do you think about?

@rm-hull
Copy link
Owner

rm-hull commented Feb 8, 2015

I guess the chip's memory supports "upto" 132 pixels, but there are only 128 physical pixels on the display in each row, so presumably the designers thought it would be easier/cheaper (for them, not us!) to center the display in memory, rather than change the design.

Adding a bounding rectangle to the example.py script is definitely a good idea

@xes
Copy link
Collaborator Author

xes commented Feb 8, 2015

Commit done. Thank you again and have a good night!

@tscha70
Copy link

tscha70 commented Mar 8, 2022

It took me almost two years to understand that it takes only this (line 451 to 454) to make it work with the SSD1306-driver for the ATTiny85 - so happy, that it works finally! Thanks a lot!!!
image

And this is the result:
Codebase is from: https://www.tinyjoypad.com/tinyjoypad_attiny85
SH1106 1.3" - Display -- great quality
image

@tscha70
Copy link

tscha70 commented Mar 8, 2022

it seems to be more stable if I write to the buffer before and after the main loop:
(see line 452 and 467)
image

@tscha70
Copy link

tscha70 commented Mar 9, 2022

There is an even better solution from Daniel C. (Électro L.I.B)

"However,here is my real method to use SSH1106 screens!
Change the value at line 110 to (0x02)! The program will be much better optimized!"

100 SSD1306.ssd1306_send_command(0xb0 + Y_);
110 SSD1306.ssd1306_send_command(0x02);// (0x02) for SSH1106 (0x00) for SSD1306
120 SSD1306.ssd1306_send_command(0x02);
130 SSD1306.ssd1306_send_command(0x10);
140 SSD1306.ssd1306_send_data_start();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants