Uncategorized

SSD1306 OLED programming notes

Raspberry Pi: control OLED display 128 × 64 with Python (I2C)
April 16, 2018Sebastian16 commentsRaspberry PiDisplay , Python , Raspberry Pi

In principle there is a Raspberry Pi yes without any input / output devices – depending on what you do with it. Sometimes, however, it is quite practical to have some information displayed on a display. In this post we want a small 0.96 ” OLED display with 128×64 pixels Control via the I2C interface.

Raspberry Pi with connected 0.96 ″ OLED display

Content [ hide ]

Prepare Raspberry Pi
Connect OLED display
Find address
Python code
Integrate library
Example 1: Hello world
Example 2: Format fonts
Example 3: Drawing shapes
Example 4: Image files
Example 5: Invert image
Others

Prepare Raspberry Pi
The prerequisite for all of the following is that your Raspberry Pi is ready for operation. I have already described here how to get the image on an SD card and set up the RPi.

The I2C interface on the Raspberry Pi is deactivated by default. To switch it on , we connect via SSH and start the configuration interface of the Raspberry Pi:

$ sudo raspi-config

There we go to point 5 ( Interfacing Options) -> P5 ( I2C) -> ENTERand confirm the query with whether we want to activate I2C . Then we leave raspi-config.

Now we install a few more packages that we need for our script and restart the RPi:

$ sudo apt-get install python-smbus i2c-tools git python-pil
$ sudo reboot

Connect OLED display

With a few jumpers we connect the Raspberry Pi to the OLED display. With my display it doesn’t matter whether you use 5V or 3.3V. Check that better with yours again.

Raspberry Pi: Connect OLED display via I2C
Raspberry Pi: Connect OLED display via I2C

Find address

Since I2C is a bus system for several participants, all of them also have a bus address. With these small displays, something like a standard has become established. For almost everyone, the address is 0x3C. This can easily be checked by issuing the following command:

$ i2cdetect -y 1

As output, we then receive a table that we can see as the address of the only bus participant 3c:

pi @ raspberrypi: ~ $ i2cdetect -y 1
0 1 2 3 4 5 6 7 8 9 abcdef
00 : – – – – – – – – – – – – –
10 : – – – – – – – – – – – – – – – –
20 : – – – – – – – – – – – – – – – –
30 : – – – – – – – – – – – – 3c – – –
40 : – – – – – – – – – – – – – – – –
50 : – – – – – – – – – – – – – – – –
60 : – – – – – – – – – – – – – – – –
70 : – – – – – – – –

The address 0x3cis already pre-selected in the Python library we use, so we do not have to pay any attention to the address.

Python code

Integrate library

We use a small Python library on Github to control the display advantage. We clone them and have everything we need:

$ git clone https://github.com/BLavery/lib_oled96

We change to the directory lib_oled96 and create a new script file there:

$ cd lib_oled96
$ touch display.py
$ chmod 777 display.py

Then we open the file we just created in any editor and start programming:

$ nano display.py

Example 1: Hello world

Raspberry Pi: OLED display example “Hello World”
Raspberry Pi: OLED display example “Hello World”

#! / usr / bin / env python
# coding = utf-8

# Import libraries
from lib_oled96 import ssd1306
from smbus import SMBus

# Set up the display
i2cbus = SMBus ( 1 ) # 0 = Raspberry Pi 1, 1 = Raspberry Pi> 1
oled = ssd1306 ( i2cbus )

# A few shortcuts to detoxify the code
draw = oled. canvas

# Clear display to start
oled. cls ( )
oled. display ( )

# Hello World
draw. text ( ( 20 , 16 ) , “hello” , fill = 1 )
draw. text ( ( 60 , 40 ) , “Welt!” , fill = 1 )

# Write issues on display
oled. display ( )

The classic in programming simply writes a few words on the display. Lines 1-10 in the script provide the basic functionalities and line 13 only serves to make the code a bit slimmer. It becomes interesting from line 16, because this is where the real output on the display begins. The command used here oled.cls()deletes the entire content and oled.display()writes the previous output on the OLED display.

All display information is collected until it is oled.display()transferred to the display with the command .

The actual text output is then generated on lines 20 and 21. The syntax is draw.text((, ), , [], []). The information , here represents the coordinates on the display, based on the upper left corner. The word “hello” is shifted 20 pixels to the right and 16 pixels down. The word “world” then accordingly by 60 pixels to the right and 40 pixels down. Line 24 creates the display again.

We simply copy the code into the editor, save and close it ( Strg+X) and execute the script:

$ ./display.py

Example 2: Format fonts

Raspberry Pi: OLED display example “Hello World” with formatted font
Raspberry Pi: OLED display example “Hello World” with formatted font

#! / usr / bin / env python
# coding = utf-8
# Import libraries
from lib_oled96 import ssd1306
from smbus import SMBus
from PIL import ImageFont
# Set up the display
i2cbus = SMBus ( 1 ) # 0 = Raspberry Pi 1, 1 = Raspberry Pi> 1
oled = ssd1306 ( i2cbus )
# A few shortcuts to detoxify the code
draw = oled. canvas
# Set fonts
FreeSans12 = ImageFont . truetype ( ‘FreeSans.ttf’ , 12 )
FreeSans20 = ImageFont . truetype ( ‘FreeSans.ttf’ , 20 )
# Clear display to start
oled. cls ( )
oled. display ( )
# Hello World
draw. text ( ( 20 , 16 ) , “hello” , font = FreeSans12 , fill = 1 )
draw. text ( ( 60 , 40 ) , “Welt!” , font = FreeSans20 , fill = 1 )
# Write issues on display
oled. display ( )

We go one step further and format the output font. To do this, we add elements from the PIL library (line 7) to our script, define the fonts (lines 17 and 18) and apply them to the text as formatting (lines 25 and 26).

Example 3: Drawing shapes

Raspberry Pi: OLED display example with shapes
Raspberry Pi: OLED display example with shapes

#! / usr / bin / env python
# coding = utf-8
# Import libraries
from lib_oled96 import ssd1306
from smbus import SMBus
# Set up the display
i2cbus = SMBus ( 1 ) # 0 = Raspberry Pi 1, 1 = Raspberry Pi> 1
oled = ssd1306 ( i2cbus )
# A few shortcuts to detoxify the code
draw = oled. canvas
# Clear display to start
oled. cls ( )
oled. display ( )
# Draw shapes
draw. line ( ( 4 , 2 , 20 , oled. height – 1 ) , fill = 1 ) # diagonal line
draw. rectangle ( ( 22 , 2 , 30 , oled. height – 1 ) , outline = 1 , fill = 0 ) # rectangle
draw. rectangle ( ( 32 , 2 , 40 , oled. height – 1 ) , outline = 0 , fill = 1 ) # rectangle, filled
draw. ellipse ( ( 42 , 2 , 60 , oled. height – 1 ) , outline = 1 , fill = 0 ) # Ellipse
draw. line ( ( 76 , 2 , 76 , 63 ) , fill = 1 ) # vertical line
draw. arc ( ( 62 , 2 , 90 , 63 ) , – 90 , 90 , fill = 1 ) # arc
draw. polygon ( [ ( 92 , 63 ) , ( 110 , 63 ) , ( 101 , 2 ) ] , outline = 1 , fill = 0 ) # polygon (triangle)
# Write issues on display
oled. display ( )

We already have everything that is needed for drawing shapes on board. Various basic forms are available. The following list shows x1 , y1the start coordinates and x2, y2the end coordinates:

lines: draw.line((x1, y1, x2, y2), fill=1)
Rectangle (frame only): draw.rectangle((x1, y1, x2, y2), outline=1, fill=0)
Rectangle (filled in): draw.rectangle((x1, y1, x2, y2), outline=1, fill=1)
Ellipse: draw.ellipse((x1, y1, x2, y2), outline=1, fill=0)
Polygon: draw.polygon([(x1, y1), (x2, y2), (x3, y3)], outline=1, fill=0)

The corner points are specified as an array. (x1, y1) first corner, (x2, y2) second corner, (x3, y3) third corner, …

Arch: draw.arc((x1, y1, x2, y2), α1, α2, fill=1)
α1, α2 stand for the start angle and the end angle, calculated clockwise, starting at 3:00 a.m. The space required for an arch is the same as that for an ellipse, but only the specified angle is drawn.
By the way: with oled.heightand oled.widthyou can draw across the entire width of the screen.

Example 4: Image files

Raspberry Pi: Show OLED display example image file
Raspberry Pi: Show OLED display example image file

#! / usr / bin / env python
# coding = utf-8

# Import libraries
from lib_oled96 import ssd1306
from smbus import SMBus
from PIL import Image

# Set up the display
i2cbus = SMBus ( 1 ) # 0 = Raspberry Pi 1, 1 = Raspberry Pi> 1
oled = ssd1306 ( i2cbus )

# A few shortcuts to detoxify the code
draw = oled. canvas

# Clear display to start
oled. cls ( )
oled. display ( )

# Output image file
draw. bitmap ( ( 32 , 0 ) , Image . open ( ‘pi_logo.png’ ) , fill = 1 )

# Write issues on display
oled. display ( )

The PIL library is required again to be able to display an image. The mode of operation is otherwise the same as before. The coordinates, path to the image file and formatting must be specified.

Example 5: Invert image

Raspberry Pi: Invert OLED display example
Raspberry Pi: Invert OLED display example

#! / usr / bin / env python
# coding = utf-8

# Import libraries
from lib_oled96 import ssd1306
from smbus import SMBus
from PIL import Image

# Set up the display
i2cbus = SMBus ( 1 ) # 0 = Raspberry Pi 1, 1 = Raspberry Pi> 1
oled = ssd1306 ( i2cbus )

# A few shortcuts to detoxify the code
draw = oled. canvas

# Clear display to start
oled. cls ( )
oled. display ( )

# Output image file
draw. rectangle ( ( 32 , 0 , 95 , 63 ) , outline = 1 , fill = 1 )
draw. bitmap ( ( 32 , 0 ) , Image . open ( ‘pi_logo.png’ ) , fill = 0 )

# Write issues on display
oled. display ( )
To invert an image, we draw a filled rectangle in the background and place it next to fillthe image 0.

Others

In principle, we now have everything we need to fill our display with life. If you need further inspiration just have a look at the examples that came with the Git repository.

A note about the pictures: My display is not defective and neither is my camera. In reality, the display makes a wonderful color that is simply difficult to capture flicker-free due to the repetitions of the image.

about Last articles

Sebastian
Sebastian
… is a state-certified technician for electrical engineering, focusing on process automation and energy technology. The subjects of automation and programming particularly impressed him.

It is also available for every technical gimmick 😉
16 comments
Avatar
AnswerMartin Schäder July 31, 2018
am a bloody beginner … very well described, thanks

Avatar
AnswerBernhard September 4, 2018
Hm, this cabling is due to SCL / SDA 5V – that’s actually too much for the Pi, which only tolerates 3.3V. Well, as long as the Oled library only writes on the I2C bus, that shouldn’t be a problem

Does the display also work if VCC is connected to pin 1 (3.3V)?

Avatar
AnswerMichael November 4, 2018
Yep, at least with my OPi (light) …

Avatar
AnswerLars December 5, 2018
Thank you for the great tutorial, it helped me a lot.
Is the I2C address of the display fixed or can you also set it to operate several displays on one bus?

Sebastian
Sebastian answers December 5, 2018
I mean that would be fixed, but can be changed by soldering a resistor.
However, I am not sure, and it may well be that I am confusing it. Unfortunately I cannot check this at the moment because my display is permanently installed.

Avatar
AnswerBen March 1, 2019
Hello Sebastian,

First of all, thank you for the detailed and understandable for a layman.
Unfortunately my OLED display just doesn’t want to be controlled.
Everything works fine until I want to call your first example or the first example from the lib_oled96 folder.
Then I always get the following error message:

Traceback (most recent call last):
File “/home/pi/Desktop/lib_oled96/example1-oled96-rpi.py”, line 20, in
oled.display ()
File “/ home / pi / Desktop / lib_oled96 / lib_oled96. py “, line 85, in display
const.PAGEADDR, 0x00, self.pages-1) # Page start / end address
file” /home/pi/Desktop/lib_oled96/lib_oled96.py “, line 63, in _command
self.bus .write_i2c_block_data (self.addr, self.cmd_mode, list (cmd))
OSError: [Errno 121] Remote I / O error

If I enter this error message in Google, I get results, but they are all in English and deal with problems that I cannot translate to my problem to find a solution. I have the last afternoon and half night around my ears to somehow solve this (including completely new set up of the Raspberry Pi Zero W). All pins are wired exactly like you are, all libraries are installed as described in the instructions, etc.

Do you have an idea how I can fix the error? Is it maybe some “little thing” that I missed?

Thanks in advance!

Sebastian
Sebastian answers March 1, 2019
Hi,
I haven’t had this case yet. What you find on the Internet usually says that you should check the connections, maybe check whether the display is properly supplied with voltage.
Have you checked whether the address of your display is the same as mine? Otherwise you have to adjust them in the script.

Avatar
AnswerBen March 1, 2019
Hello,
first of all thanks for the answer.
I just checked everything again. Everything is wired exactly the same and the i2c bus is also in the instructions on 0x3c.
I also just measured the voltage supply again, there are 5.03V (also VV to 5V and GND to GND is correct)

Avatar
Answerriker1 April 16, 2019
Hi
can you control the contrast / dimming here?
Thank you

Sebastian
Sebastian answers April 16, 2019
Hi,
yes you can. Try it out oled._command(const.SETCONTRAST, 0xFF), the value after the comma 0… 255 may be in hexadecimal notation.

However, I have not yet tested this with this library, but only in the Perl variant, which I described in another article.

Avatar
AnswerLinus August 12, 2019
Hello Sebastian!!
I am one of the young hobbyists.
I have now bought an oled display and wanted to try it out immediately.
I connected it to my Raspberry Pi 3 B +, just plugged the VCC cable into pin number 1.
Already with the first project only blue and black dots are shown on my display 🙁
What should I do? I went through your text again but didn’t find any errors.
Is it perhaps due to the (probably) newer Raspian version?
LG
Linus

Sebastian
Sebastian answers August 12, 2019
Hi Linus,
I can’t quite follow you. If you only connect pin 1, how is that supposed to work?
Otherwise, I have never seen anything like this so I cannot judge it from a distance. However, one cannot rule out 100% that a new display could not be broken.

Avatar
AnswerLinus August 12, 2019

Thanks for your feedback Sebastian.
I connected the contacts of the OLED display as in the drawing, only connected the VCC contact not to pin 4 (5V), but to pin 1 (3.3V).

Avatar
AnswerK0NRAD September 25, 2019

Great instructions!
I have a problem with a 128 × 32 OLED display.
After I have wired everything, when i2cdetect -y 1 is called, the table appears completely filled with hex values, if I swap SCL and SCA, the table builds up slowly but does not show an address.
At first I thought of a defective module, but I tried three more with the same result.
Do you have any idea why this could be?

Avatar
AnswerZarhan December 14, 2019

Thank you for the contribution.
for me the ad works very well. However, the display stays on when I shut down the Pi. The other difficulty is that the display does not start automatically after the restart. I tried crontab @reboot. It does not work. If you have a tip for me please? Many thanks in advance,

Sebastian
Sebastian answers December 14, 2019
That is normal. The display shows the last content until you delete it or remove the tension.

Leave a message
Your email address will not be published. Required fields are marked with * .

Comment

.END

Categories: Uncategorized

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s