Close Menu
  • Articles
    • Learn Electronics
    • Product Review
    • Tech Articles
  • Electronics Circuits
    • 555 Timer Projects
    • Op-Amp Circuits
    • Power Electronics
  • Microcontrollers
    • Arduino Projects
    • STM32 Projects
    • AMB82-Mini IoT AI Camera
    • BLE Projects
  • IoT Projects
    • ESP8266 Projects
    • ESP32 Projects
    • ESP32 MicroPython
    • ESP32-CAM Projects
    • LoRa/LoRaWAN Projects
  • Raspberry Pi
    • Raspberry Pi Projects
    • Raspberry Pi Pico Projects
    • Raspberry Pi Pico W Projects
  • Electronics Calculator
Facebook X (Twitter) Instagram
  • About Us
  • Disclaimer
  • Privacy Policy
  • Contact Us
  • Advertise With Us
Facebook X (Twitter) Instagram Pinterest YouTube LinkedIn
How To Electronics
  • Articles
    • Learn Electronics
    • Product Review
    • Tech Articles
  • Electronics Circuits
    • 555 Timer Projects
    • Op-Amp Circuits
    • Power Electronics
  • Microcontrollers
    • Arduino Projects
    • STM32 Projects
    • AMB82-Mini IoT AI Camera
    • BLE Projects
  • IoT Projects
    • ESP8266 Projects
    • ESP32 Projects
    • ESP32 MicroPython
    • ESP32-CAM Projects
    • LoRa/LoRaWAN Projects
  • Raspberry Pi
    • Raspberry Pi Projects
    • Raspberry Pi Pico Projects
    • Raspberry Pi Pico W Projects
  • Electronics Calculator
How To Electronics
Home » Interfacing SSD1306 OLED Display with Raspberry Pi Pico
Raspberry Pi Raspberry Pi Pico Projects

Interfacing SSD1306 OLED Display with Raspberry Pi Pico

Mamtaz AlamBy Mamtaz AlamUpdated:May 26, 20234 Mins Read
Share Facebook Twitter LinkedIn Telegram Reddit WhatsApp
OLED Display Raspberry Pi Pico
Share
Facebook Twitter LinkedIn Pinterest Email Reddit Telegram WhatsApp

Overview

In this tutorial we will learn about the Interfacing of SSD1306 OLED Display with Raspberry Pi Pico. The OLED displays are one of the most attractive displays available for a microcontroller. It has a good view angle and pixel density which makes it reliable for displaying small level graphics.

The SSD1306 OLED display is available in both I2C & SPI Modules. But in this tutorial, we will use the 0.96″ I2C OLED Display as it requires only 2 wires for Interfacing. The Raspberry Pi Pico that comes with an RP2040 microcontroller has two Pairs of I2C Pins. You can use any of the I2C Pins of Raspberry Pi Pico for Interfacing SSD1306 OLED Display.

We will use Micropython code here to used OLED Display with Pico Board. The MicroPython IDE requires the SSD1306 Driver Code. After writing the driver code, we can write anything and display it on OLED Display. We will display the Analog value voltage from the Potentiometer on OLED Display. But before that we recommend you to go through Raspberry Pi Pico Getting Started Guide and also about the way of using the I2C Pin.



Bill of Materials

You cany purchase the required components for this tutorial from the following Amazon link.

S.N.Components NameQuantityPurchase Links
1Raspberry Pi Pico1Amazon | AliExpress
20.96" I2C OLED Display1Amazon | AliExpress
3Potentiometer1Amazon | AliExpress
4Breadboard1Amazon | AliExpress
5Jumper Wires10Amazon | AliExpress

SSD1306 OLED Display

The OLED displays are one of the most attractive displays available for a microcontroller because of their viewing angle and pixel density. This SSD1306 is a 0.96/1.3 inch blue OLED display module. You can interface this display module with any microcontroller using SPI/IIC protocols. It is having a resolution of 128×64. The package includes a display board, a display,4 pin male header pre-soldered to board.

OLED Display

OLED (Organic Light-Emitting Diode) is a self-light-emitting technology composed of a thin, multi-layered organic film placed between an anode and cathode. In contrast to LCD technology, OLED does not require a backlight. OLED possesses high application potential for virtually all types of displays and is regarded as the ultimate technology for the next generation of flat-panel displays.




Interfacing SSD1306 OLED Display with Raspberry Pi Pico

Now let us learn how we can interface SSD1306 OLED Display with Raspberry Pi Pico. The Raspberry Pi Pico Board has two pair of I2C Pins. You can use any of the pair of I2C Pins for interfacing applications. To learn more about the I2C Pins use & Applications you can use our Raspberry Pi Pico I2C Guide.

In this example we will feed the input value of analog voltage from Potentiometer to analog Pin GP28 of Raspberry Pi Pico. Then we will display the analog voltage on OLED Screen. The schematic is very simple and easy to use.

OLED Display Raspberry Pi Pico

Connect the SDA & SCL Pin of OLED Display to PICO GP8 & GP9 Pin respectively. Connect the VCC & GND pin of OLED Display to 3.3V & GND Pin of Pico. You can use a breadboard to Assemble the entire circuit.


OLED Display Raspberry Pi Pico Code

In order to program the Raspberry Pi Pico Board, we will use MicroPython programming language. MicroPython is similar to Python. You can either use Thonny IDE or the uPyCraft IDE for programming and testing the board.

I prefer uPyCraft IDE for programming. The programming here is divided into two main parts:
1. SSD1306.py
2. Main.py

This is because the OLED Display requires SSD1306 Driver Code first. We have to write the code for the SSD1306 Driver first. After uploading the SSD1306 Code, we can then run the main.py code.


SSD1306.py

So in uPyCraft IDE, create a new file. Copy the following code & save the file by the name ssd1306.py.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# MicroPython SSD1306 OLED driver, I2C and SPI interfaces
 
from micropython import const
import framebuf
 
# register definitions
SET_CONTRAST = const(0x81)
SET_ENTIRE_ON = const(0xA4)
SET_NORM_INV = const(0xA6)
SET_DISP = const(0xAE)
SET_MEM_ADDR = const(0x20)
SET_COL_ADDR = const(0x21)
SET_PAGE_ADDR = const(0x22)
SET_DISP_START_LINE = const(0x40)
SET_SEG_REMAP = const(0xA0)
SET_MUX_RATIO = const(0xA8)
SET_COM_OUT_DIR = const(0xC0)
SET_DISP_OFFSET = const(0xD3)
SET_COM_PIN_CFG = const(0xDA)
SET_DISP_CLK_DIV = const(0xD5)
SET_PRECHARGE = const(0xD9)
SET_VCOM_DESEL = const(0xDB)
SET_CHARGE_PUMP = const(0x8D)
 
# Subclassing FrameBuffer provides support for graphics primitives
# http://docs.micropython.org/en/latest/pyboard/library/framebuf.html
class SSD1306(framebuf.FrameBuffer):
    def __init__(self, width, height, external_vcc):
        self.width = width
        self.height = height
        self.external_vcc = external_vcc
        self.pages = self.height // 8
        self.buffer = bytearray(self.pages * self.width)
        super().__init__(self.buffer, self.width, self.height, framebuf.MONO_VLSB)
        self.init_display()
 
    def init_display(self):
        for cmd in (
            SET_DISP | 0x00,  # off
            # address setting
            SET_MEM_ADDR,
            0x00,  # horizontal
            # resolution and layout
            SET_DISP_START_LINE | 0x00,
            SET_SEG_REMAP | 0x01,  # column addr 127 mapped to SEG0
            SET_MUX_RATIO,
            self.height - 1,
            SET_COM_OUT_DIR | 0x08,  # scan from COM[N] to COM0
            SET_DISP_OFFSET,
            0x00,
            SET_COM_PIN_CFG,
            0x02 if self.width > 2 * self.height else 0x12,
            # timing and driving scheme
            SET_DISP_CLK_DIV,
            0x80,
            SET_PRECHARGE,
            0x22 if self.external_vcc else 0xF1,
            SET_VCOM_DESEL,
            0x30,  # 0.83*Vcc
            # display
            SET_CONTRAST,
            0xFF,  # maximum
            SET_ENTIRE_ON,  # output follows RAM contents
            SET_NORM_INV,  # not inverted
            # charge pump
            SET_CHARGE_PUMP,
            0x10 if self.external_vcc else 0x14,
            SET_DISP | 0x01,
        ):  # on
            self.write_cmd(cmd)
        self.fill(0)
        self.show()
 
    def poweroff(self):
        self.write_cmd(SET_DISP | 0x00)
 
    def poweron(self):
        self.write_cmd(SET_DISP | 0x01)
 
    def contrast(self, contrast):
        self.write_cmd(SET_CONTRAST)
        self.write_cmd(contrast)
 
    def invert(self, invert):
        self.write_cmd(SET_NORM_INV | (invert & 1))
 
    def show(self):
        x0 = 0
        x1 = self.width - 1
        if self.width == 64:
            # displays with width of 64 pixels are shifted by 32
            x0 += 32
            x1 += 32
        self.write_cmd(SET_COL_ADDR)
        self.write_cmd(x0)
        self.write_cmd(x1)
        self.write_cmd(SET_PAGE_ADDR)
        self.write_cmd(0)
        self.write_cmd(self.pages - 1)
        self.write_data(self.buffer)
 
 
class SSD1306_I2C(SSD1306):
    def __init__(self, width, height, i2c, addr=0x3C, external_vcc=False):
        self.i2c = i2c
        self.addr = addr
        self.temp = bytearray(2)
        self.write_list = [b"\x40", None]  # Co=0, D/C#=1
        super().__init__(width, height, external_vcc)
 
    def write_cmd(self, cmd):
        self.temp[0] = 0x80  # Co=1, D/C#=0
        self.temp[1] = cmd
        self.i2c.writeto(self.addr, self.temp)
 
    def write_data(self, buf):
        self.write_list[1] = buf
        self.i2c.writevto(self.addr, self.write_list)
 
 
class SSD1306_SPI(SSD1306):
    def __init__(self, width, height, spi, dc, res, cs, external_vcc=False):
        self.rate = 10 * 1024 * 1024
        dc.init(dc.OUT, value=0)
        res.init(res.OUT, value=0)
        cs.init(cs.OUT, value=1)
        self.spi = spi
        self.dc = dc
        self.res = res
        self.cs = cs
        import time
 
        self.res(1)
        time.sleep_ms(1)
        self.res(0)
        time.sleep_ms(10)
        self.res(1)
        super().__init__(width, height, external_vcc)
 
    def write_cmd(self, cmd):
        self.spi.init(baudrate=self.rate, polarity=0, phase=0)
        self.cs(1)
        self.dc(0)
        self.cs(0)
        self.spi.write(bytearray([cmd]))
        self.cs(1)
 
    def write_data(self, buf):
        self.spi.init(baudrate=self.rate, polarity=0, phase=0)
        self.cs(1)
        self.dc(1)
        self.cs(0)
        self.spi.write(buf)
        self.cs(1)

Now hit download & run button. So you will be able to see the SSD1306 driver saved in the Raspberry Pi Pico.



main.py

Open a new tab again in the uPyCraft IDE. Copy the following code and paste it on the uPyCraft IDE Window. Save the file by the name main.py.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# Display Image & text on I2C driven ssd1306 OLED display
from machine import Pin, I2C
from ssd1306 import SSD1306_I2C
import framebuf
import machine
import utime
 
sensor_temp = machine.ADC(28)
conversion_factor = 3.3 / (65535)
 
WIDTH  = 128                                            # oled display width
HEIGHT = 64                                             # oled display height
 
i2c = I2C(0, scl=Pin(9), sda=Pin(8), freq=200000)       # Init I2C using pins GP8 & GP9 (default I2C0 pins)
print("I2C Address      : "+hex(i2c.scan()[0]).upper()) # Display device address
print("I2C Configuration: "+str(i2c))                   # Display I2C config
 
 
oled = SSD1306_I2C(WIDTH, HEIGHT, i2c)                  # Init oled display
 
# Raspberry Pi logo as 32x32 bytearray
buffer = bytearray(b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00|?\x00\x01\x86@\x80\x01\x01\x80\x80\x01\x11\x88\x80\x01\x05\xa0\x80\x00\x83\xc1\x00\x00C\xe3\x00\x00~\xfc\x00\x00L'\x00\x00\x9c\x11\x00\x00\xbf\xfd\x00\x00\xe1\x87\x00\x01\xc1\x83\x80\x02A\x82@\x02A\x82@\x02\xc1\xc2@\x02\xf6>\xc0\x01\xfc=\x80\x01\x18\x18\x80\x01\x88\x10\x80\x00\x8c!\x00\x00\x87\xf1\x00\x00\x7f\xf6\x00\x008\x1c\x00\x00\x0c \x00\x00\x03\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
 
while True:
    reading = sensor_temp.read_u16() * conversion_factor
    # Load the raspberry pi logo into the framebuffer (the image is 32x32)
    fb = framebuf.FrameBuffer(buffer, 32, 32, framebuf.MONO_HLSB)
 
    # Clear the oled display in case it has junk on it.
    oled.fill(0)
 
    # Blit the image from the framebuffer to the oled display
    oled.blit(fb, 96, 0)
      
    
    # Add some text
    oled.text("ADC: ",5,8)
    oled.text(str(round(reading,2)),40,8)
 
 
    # Finally update the oled display so the image & text is displayed
    oled.show()

Now again hit download & run button. The code will be saved to Raspberry Pi Pico Board.

Now you are ready to go. The OLED Display will immediately start showing the Raspberry Pi Logo along with the Analog voltage value from the potentiometer.

You can rotate the potentiometer knob and see the OLED Display showing the different values.

SSD1306 OLED Display Raspberry Pi Pico

This is how you can display the text or logo in an OLED Display using MicroPython Code. So interfacing SSD1306 OLED Display with Raspberry Pi Pico is so easy as this tutorial.


Video Tutorial & Guide

Raspberry Pi Pico Complete Guide| Pinout+Features+ADC+I2C+OLED+Internal Temperature Sensor+DHT11
Watch this video on YouTube.

Share. Facebook Twitter Pinterest LinkedIn Tumblr Email Reddit Telegram WhatsApp
Previous ArticleHow to use ADC in Raspberry Pi Pico | ADC Example Code
Next Article Read Temperature Sensor Value from Raspberry Pi Pico

Related Posts

ADXL375 Accelerometer with Raspberry Pi Pico & MicroPython

ADXL375 Accelerometer with Raspberry Pi Pico & MicroPython

Updated:July 24, 2025
Interface BMI160 with Raspberry Pi Pico & MicroPython

Interface BMI160 with Raspberry Pi Pico & MicroPython

Updated:February 2, 20253K
Shift Register 74HC595 with Raspberry Pi Pico & MicroPython

Shift Register 74HC595 with Raspberry Pi Pico & MicroPython

Updated:February 2, 202513K
Interfacing XBee Module with Raspberry Pi Pico & MicroPython

Interfacing XBee Module with Raspberry Pi Pico & MicroPython

Updated:February 2, 20253K
Modbus RTU with Raspberry Pi Pico & Micropython

Modbus RTU with Raspberry Pi Pico & MicroPython

Updated:February 2, 20258K
Fever Detector with MLX90640 & OpenCV Raspberry Pi

Thermal Fever Detector with MLX90640 & OpenCV Raspberry Pi

Updated:February 2, 20256K
Add A Comment

CommentsCancel reply

Latest Posts
ESP32 Fingerprint Attendance System with Live Web Dashboard

ESP32 Fingerprint Attendance System with Live Web Dashboard

June 21, 2026
IoT Based PM & Air Quality Monitoring System using ESP32

IoT Based PM & Air Quality Monitoring System using ESP32

June 14, 2026
DIY ESP32 MLX90640 IR Thermal Camera with Live Web Display

DIY ESP32 MLX90640 IR Thermal Camera with Live Web Display

May 10, 2026
IoT Activity Tracker with ESP32 & Accelerometer Gyroscope

IoT Activity Tracker with ESP32 & Accelerometer/Gyroscope

May 2, 2026
A Guide to Sourcing Obsolete ICs for Vintage Projects

Beyond AliExpress: A Guide to Sourcing Obsolete ICs for Vintage Projects

April 21, 2026

ESP32 IoT Vehicle Motion Analyzer with MPU6050 & LIS3MDL

April 27, 2026
Building a Smart Sensor Node with a BLE Microcontroller

Building a Smart Sensor Node with a BLE Microcontroller

February 26, 2026
High-Accuracy Pitch, Roll, Yaw with ESP32 & BNO08x IMU

High-Accuracy Pitch, Roll, Yaw with ESP32 & BNO08x IMU

April 27, 2026
Top Posts & Pages
  • ESP32 Fingerprint Attendance System with Live Web Dashboard
    ESP32 Fingerprint Attendance System with Live Web Dashboard
  • ESP32 CAN Bus Tutorial | Interfacing MCP2515 CAN Module with ESP32
    ESP32 CAN Bus Tutorial | Interfacing MCP2515 CAN Module with ESP32
  • IoT AC Energy Meter with PZEM-004T & ESP32 WebServer
    IoT AC Energy Meter with PZEM-004T & ESP32 WebServer
  • 12V DC to 220V AC Inverter Circuit & PCB
    12V DC to 220V AC Inverter Circuit & PCB
  • LD2410 Sensor with ESP32 - Human Presence Detection
    LD2410 Sensor with ESP32 - Human Presence Detection
  • Buck Converter: Basics, Working, Design & Application
    Buck Converter: Basics, Working, Design & Application
  • IoT Based Patient Health Monitoring on ESP32 Web Server
    IoT Based Patient Health Monitoring on ESP32 Web Server
  • How to use INA226 DC Current Sensor with Arduino
    How to use INA226 DC Current Sensor with Arduino
Categories
  • Arduino Projects (197)
  • Articles (60)
    • Learn Electronics (19)
    • Product Review (15)
    • Tech Articles (28)
  • Electronics Circuits (46)
    • 555 Timer Projects (21)
    • Op-Amp Circuits (7)
    • Power Electronics (13)
  • IoT Projects (205)
    • ESP32 MicroPython (7)
    • ESP32 Projects (82)
    • ESP32-CAM Projects (15)
    • ESP8266 Projects (76)
    • LoRa/LoRaWAN Projects (22)
  • Microcontrollers (38)
    • AMB82-Mini IoT AI Camera (4)
    • BLE Projects (18)
    • STM32 Projects (19)
  • Raspberry Pi (93)
    • Raspberry Pi Pico Projects (57)
    • Raspberry Pi Pico W Projects (12)
    • Raspberry Pi Projects (24)
Follow Us
  • Facebook
  • Twitter
  • Pinterest
  • Instagram
  • YouTube
About Us

“‘How to Electronics’ is a vibrant community for electronics enthusiasts and professionals. We deliver latest insights in areas such as Embedded Systems, Power Electronics, AI, IoT, and Robotics. Our goal is to stimulate innovation and provide practical solutions for students, organizations, and industries. Join us to transform learning into a joyful journey of discovery and innovation.

Copyright © How To Electronics. All rights reserved.
  • About Us
  • Disclaimer
  • Privacy Policy
  • Contact Us
  • Advertise With Us

Type above and press Enter to search. Press Esc to cancel.

Ad Blocker Enabled!
Ad Blocker Enabled!
Looks like you're using an ad blocker. Please allow ads on our site. We rely on advertising to help fund our site.