Add an OLED display to Raspberry PI Pico with MicroPython

4.8
(16)

Last Updated on 2nd September 2023 by peppe8o

In this tutorial, I’m going to show you how to use an I2C OLED display (SSD1306) with Raspberry PI Pico. Please note that, if you have an LCD display, you must refer to my Using I2C LCD display With Raspberry PI Pico and MicroPython tutorial.

OLED displays with Raspberry PI Pico allow a cool way to show your program’s data and present them with a more flexible device.

OLED Display Features

OLED (organic light-emitting diode) displays are low power consumption output devices able to show text and images by controlling every single pixel. They usually require only a 0.04W power that can be supplied without problems from Raspberry PI Pico VCC output.

They usually can work in a wide range of operating temperatures, spacing from -40°C to 85°C.

The most common size is 128×64 pixels (0.96 inches), but also the 128×32 pixels (0.91 inches) is available from e-stores. Their screens are usually mono-color or bi-color. The mono-color ones are made of blue or white pixels, while the bi-color models usually have an upper part yellow and the lower one blue. In this tutorial, I’m going to use the bi-color model, but this applies also to the mono-color ones.

The pixels are indexed by a cartesian spacial reference, with the x-axis moving on the horizontal side and the y-axis moving on the vertical one. Both coordinates start from their 0 on top-left side of the screen:

ssd1306-oled-axes

The datasheet can be found on Adafruit pages.

SSD1306 OLED Pinout

The I2C version pins are defined according to the following table:

PIN LabelDescription
VCCThis PIN goes to the positive power source
GNDThis PIN goes to the ground reference
SCL (or SCK)This PIN is the clock reference for I2C communication
SDAThis PIN is used for data transferring according to I2C protocol

What We Need

As usual, I suggest adding from now to your favourite e-commerce shopping cart all the needed hardware, so that at the end you will be able to evaluate overall costs and decide if to continue with the project or remove them from the shopping cart. So, hardware will be only:

Check hardware prices with the following links:

amazon raspberry pi pico box
amazon i2c oled box
Amazon Dupont Wiring box
Amazon Breadboard box

Step-by-Step Procedure

Wiring Diagram

Please arrange cabling according to the following picture, according to Raspberry PI Pico pinout. Please note that in some displays the SCL may be named SCK.

raspberry-pi-pico-oled-ssd1306-wiring-diagram

Please find below some pictures from my test lab:

raspberry-pi-pico-oled-details
raspberry-pi-pico-oled-details01
raspberry-pi-pico-oled-details02

Get my the OLED library and my Oled Code for Raspberry PI Pico

Connect RPI Pico to Thonny (you can refer to my tutorial about First steps with Raspberry PI Pico).

Please download and add the SSD1306.py library in your Raspberry PI Pico root folder, according to Adding external modules to MicroPython with Raspberry PI Pico tutorial. You can get it from the official MicroPython github page or from my download area with the following link:

Download my pico-oled-peppe8o.py script on your computer and open it with Thonny.

Please remember that when you’ll need to execute it without a computer plugged into RPI Pico, you will need to keep the code saved in Raspberry PI Pico as “main.py”.

The following paragraphs will describe my code line by line. In the end, you will find the script expected results.

pico-oled-peppe8o.py Code

Having the ssd1306 library in our Raspberry PI Pico makes the code really simple to understand and use.

We firstly import the required libraries, including the ssd1306 saved in your Raspberry PI Pico root folder (or one of the paths allowed for importing modules):

from machine import Pin, I2C
import ssd1306

Then, we setup the I2C connection with the SSD1306 OLED display. According to the previous wiring diagram, it will be as the following:

i2c = I2C(0, sda=Pin(16), scl=Pin(17))
display = ssd1306.SSD1306_I2C(128, 64, i2c)

The simpler property allows you to write text in your display, also setting the row and column with the display.text(text_string, x, y). You can pre-set as many text statements as you want and the related position. The text will be displayed only with the final display.show() statement which sends the data to the OLED display.

display.text('Hello,', 0, 0)
display.text('peppe8o.com', 0, 16)
display.text('readers!', 0, 32)

display.show()

The result will be the following:

ex01-rpi-pico-oled

Please consider that once the script finishes its run, the display will keep the memory of what was shown until it will receive a new show() command or until it will be powered off.

Another interesting command, is the display.fill() statement. It will set to 1 (on) or to 0 (off) all the Oled pixels:

  • display.fill(0) -> off
  • display.fill(1) -> on

Of course, also this requires a following display.show() line to correctly appear in your display.

SSD1306 with Raspberry PI Pico Examples

In this section, I will show you a number of examples with the related results available from the screen. In the following code, I will show only the display statements to set, you will keep in your script the initial setup part and the final display.show() to get it working.

Display Invert

It allows you to set what to show in your OLED display and then invert the pixel status. The following code:

display.text('Hello,', 0, 0)
display.text('peppe8o.com', 0, 16)
display.text('readers!', 0, 32)
display.invert(1)

This will result in the following picture. Please note that the following picture has flickering problems due to my smartphone camera not filtering the different framerate compared with the display, but the real result will show a clear image:

ex02-rpi-pico-oled

Display Rotate

It allows rotating the display by 180 degrees. The code:

display.text('Hello,', 0, 0)
display.text('peppe8o.com', 0, 16)
display.text('readers!', 0, 32)
display.rotate(False)

This will result in the following:

ex03-rpi-pico-oled

Display Pixel

It allows you to control a single pixel at a defined position (for example x=0 and y=10, with color set to 1)

display.pixel(0, 10, 1)
ex04-rpi-pico-oled

Display Hline (and Display Vline)

These statements allow you to draw a horizontal (or vertical) line in your display. Again, the first 2 variables set the position (x=0, y=8). Then we set the width (60 means that our line will be 60px large) and the final 1 set the color:

display.hline(0, 8, 60, 1)
ex05-rpi-pico-oled

Display Rect

This will draw a rectangle in your display. This statement requires the x,y starting position for your rectangle and then the x,y end position. The final “1” will set, as usual, the color:

display.rect(10, 10, 107, 43, 1)
ex06-rpi-pico-oled

Display Fill_rect

Similar to the previous command, it will also make the rectangle filled with all the internal pixels powered on:

display.fill_rect(10, 10, 60, 50, 1)

Again, please excuse me for the flickering on my picture… 🙁 :

ex07-rpi-pico-oled

Display Line

This creates a simple generic line, again specifying the start position (x,y) and the end position (x,y):

display.line(0, 30, 100, 50, 1)
ex08-rpi-pico-oled

Micropython Logo

By mixing the previous commands, you can create also complex images, as the example referenced in MicroPython ssd1306 page:

display.fill(0)
display.fill_rect(0, 0, 32, 32, 1)
display.fill_rect(2, 2, 28, 28, 0)
display.vline(9, 8, 22, 1)
display.vline(16, 2, 22, 1)
display.vline(23, 8, 22, 1)
display.fill_rect(26, 24, 2, 4, 1)
display.text('MicroPython', 40, 0, 1)
display.text('SSD1306', 40, 12, 1)
display.text('OLED 128x64', 40, 24, 1)
display.show()
exMicropython-rpi-pico-oled

Custom Pictures

With SSD1306 OLED display we can also print custom images. As example, we’ll transform the peppe8o.com logo from jpg to a PBM file, in order to get the file shown in our SSD1306 OLED display.

The following file transformation will be performed with GIMP, the open source photo editor. But you can do it also with other professional software.

My starting file is the following:

logo peppe8o 512x512

Open this file with GIMP and resize it to the desired size (limited by your Oled display, that is 128×64 in our case. I will resize my logo to 60×61 with the GIMP function available from the Image menu -> Scale Image. The result is the following:

Logo2D_white_60x61

When there are parts with light colors, they may not appear correctly in your display, so managing the color curves to get a more dark picture is a good idea (in GIMP, Colors -> Curves and the move the curve to get a higher contrast). The following is the result:

Logo2D_white_60x61_dark

Now, we’ll use the GIMP function Image -> Mode -> Indexed function to convert the image colors indexed with black/white palette. The following are the settings to use:

gimp-indexed-mode-settings-oled

And this will be the result:

Logo2D_white_60x61_dark_indexed

Now you can export this image to the PBM format with GIMP File -> Export by setting the correct file extension.

Upload the resulting image into your Raspberry PI Pico storage (my file is named “Logo2D_white.pbm”) and use the following code:

with open('Logo2D_white.pbm', 'rb') as f:
    f.readline() # The first 3 lines of PBM files are info not related to the image
    f.readline() # the 3 readlines remove these lines
    f.readline() # You can check this by opening the PBM file with a notepad
    data = bytearray(f.read())
fbuf = framebuf.FrameBuffer(data, 60, 61, framebuf.MONO_HLSB)
display.blit(fbuf, 0, 12, 0)

Please note that in the “framebuf.FrameBuffer(data, 60, 61, framebuf.MONO_HLSB)” line I’ve used the dimensions of my scaled image (60×61). The “display.blit(fbuf, 0, 12, 0)” will add our image starting from x=0 and y=12 position. You will get the following result. Again, sorry for the flickering effect. I promise that the real result will be better.

excustomlogo-rpi-pico-oled

What’s Next

Interested to do more with your Raspberry PI Pico? Try to look at my Raspberry PI Pico tutorials for useful and funny projects!

Enjoy!

How useful was this post?

Click on a star to rate it anonymously!

Average rating 4.8 / 5. Vote count: 16

No votes so far! Be the first to rate this post.

We are sorry that this post was not useful for you!

Let us improve this post!

Tell us how we can improve this post?