010 - ESP32 MicroPython: 0.96 OLED in MicroPython
Introduction
In this tutorial, we will learn to use the 0.96 inch OLED display with monochrome display. This is useful for displaying something for the end user.
Its easy to use, we just need 4 wires. 2 wires for the power and another 2 wires for the i2c comunication protocol for controlling the display.
Circuit Diagram
Hardware Instruction
- Connect the OLED VCC pin to 3V3 supply pin of ESP32.
- Connect the OLED GND pin to ESP32 GND pin.
- Connect the OLED SCL pin to ESP32 GPIO D22 pin (SCL dedicated pin).
- Connect the OLED SDA pin to ESP32 GPIO D21 pin (SDA dedicated pin).
Video Demonstration
Call To Action
I hope you find this tutorial as helpful. If you have any question regarding this tutorial, please do not hesitate to write it in the comment box provided.
Please also consider supporting me in my Youtube channel by Subscribing. Please click this to Subscribe and confirm.
Thank you and have a good days ahead.
Source Code
SSD1306 Library:
Original copy of library (but with missing functions)
https://github.com/adafruit/micropython-adafruit-ssd1306/blob/master/ssd1306.py
1#MicroPython SSD1306 OLED driver, I2C and SPI interfaces created by Adafruit
2
3import time
4import framebuf
5
6# register definitions
7SET_CONTRAST = const(0x81)
8SET_ENTIRE_ON = const(0xa4)
9SET_NORM_INV = const(0xa6)
10SET_DISP = const(0xae)
11SET_MEM_ADDR = const(0x20)
12SET_COL_ADDR = const(0x21)
13SET_PAGE_ADDR = const(0x22)
14SET_DISP_START_LINE = const(0x40)
15SET_SEG_REMAP = const(0xa0)
16SET_MUX_RATIO = const(0xa8)
17SET_COM_OUT_DIR = const(0xc0)
18SET_DISP_OFFSET = const(0xd3)
19SET_COM_PIN_CFG = const(0xda)
20SET_DISP_CLK_DIV = const(0xd5)
21SET_PRECHARGE = const(0xd9)
22SET_VCOM_DESEL = const(0xdb)
23SET_CHARGE_PUMP = const(0x8d)
24
25class SSD1306:
26 def __init__(self, width, height, external_vcc):
27 self.width = width
28 self.height = height
29 self.external_vcc = external_vcc
30 self.pages = self.height // 8
31 # Note the subclass must initialize self.framebuf to a framebuffer.
32 # This is necessary because the underlying data buffer is different
33 # between I2C and SPI implementations (I2C needs an extra byte).
34 self.poweron()
35 self.init_display()
36
37 def init_display(self):
38 for cmd in (
39 SET_DISP | 0x00, # off
40 # address setting
41 SET_MEM_ADDR, 0x00, # horizontal
42 # resolution and layout
43 SET_DISP_START_LINE | 0x00,
44 SET_SEG_REMAP | 0x01, # column addr 127 mapped to SEG0
45 SET_MUX_RATIO, self.height - 1,
46 SET_COM_OUT_DIR | 0x08, # scan from COM[N] to COM0
47 SET_DISP_OFFSET, 0x00,
48 SET_COM_PIN_CFG, 0x02 if self.height == 32 else 0x12,
49 # timing and driving scheme
50 SET_DISP_CLK_DIV, 0x80,
51 SET_PRECHARGE, 0x22 if self.external_vcc else 0xf1,
52 SET_VCOM_DESEL, 0x30, # 0.83*Vcc
53 # display
54 SET_CONTRAST, 0xff, # maximum
55 SET_ENTIRE_ON, # output follows RAM contents
56 SET_NORM_INV, # not inverted
57 # charge pump
58 SET_CHARGE_PUMP, 0x10 if self.external_vcc else 0x14,
59 SET_DISP | 0x01): # on
60 self.write_cmd(cmd)
61 self.fill(0)
62 self.show()
63
64 def poweroff(self):
65 self.write_cmd(SET_DISP | 0x00)
66
67 def contrast(self, contrast):
68 self.write_cmd(SET_CONTRAST)
69 self.write_cmd(contrast)
70
71 def invert(self, invert):
72 self.write_cmd(SET_NORM_INV | (invert & 1))
73
74 def show(self):
75 x0 = 0
76 x1 = self.width - 1
77 if self.width == 64:
78 # displays with width of 64 pixels are shifted by 32
79 x0 += 32
80 x1 += 32
81 self.write_cmd(SET_COL_ADDR)
82 self.write_cmd(x0)
83 self.write_cmd(x1)
84 self.write_cmd(SET_PAGE_ADDR)
85 self.write_cmd(0)
86 self.write_cmd(self.pages - 1)
87 self.write_framebuf()
88
89 def fill(self, col):
90 self.framebuf.fill(col)
91
92 def pixel(self, x, y, col):
93 self.framebuf.pixel(x, y, col)
94
95 def scroll(self, dx, dy):
96 self.framebuf.scroll(dx, dy)
97
98 def text(self, string, x, y, col=1):
99 self.framebuf.text(string, x, y, col)
100
101 # Missing from current files in github:
102 # https://github.com/adafruit/micropython-adafruit-ssd1306/blob/master/ssd1306.py
103 def hline(self, x, y, w, col):
104 self.framebuf.hline(x, y, w, col)
105 def vline(self, x, y, h, col):
106 self.framebuf.vline(x, y, h, col)
107 def line(self, x1, y1, x2, y2, col):
108 self.framebuf.line(x1, y1, x2, y2, col)
109 def rect(self, x, y, w, h, col):
110 self.framebuf.rect(x, y, w, h, col)
111 def fill_rect(self, x, y, w, h, col):
112 self.framebuf.fill_rect(x, y, w, h, col)
113 def blit(self, fbuf, x, y):
114 self.framebuf.blit(fbuf, x, y)
115
116class SSD1306_I2C(SSD1306):
117 def __init__(self, width, height, i2c, addr=0x3c, external_vcc=False):
118 self.i2c = i2c
119 self.addr = addr
120 self.temp = bytearray(2)
121 # Add an extra byte to the data buffer to hold an I2C data/command byte
122 # to use hardware-compatible I2C transactions. A memoryview of the
123 # buffer is used to mask this byte from the framebuffer operations
124 # (without a major memory hit as memoryview doesn't copy to a separate
125 # buffer).
126 self.buffer = bytearray(((height // 8) * width) + 1)
127 self.buffer[0] = 0x40 # Set first byte of data buffer to Co=0, D/C=1
128 self.framebuf = framebuf.FrameBuffer1(memoryview(self.buffer)[1:], width, height)
129 super().__init__(width, height, external_vcc)
130
131 def write_cmd(self, cmd):
132 self.temp[0] = 0x80 # Co=1, D/C#=0
133 self.temp[1] = cmd
134 self.i2c.writeto(self.addr, self.temp)
135
136 def write_framebuf(self):
137 # Blast out the frame buffer using a single I2C transaction to support
138 # hardware I2C interfaces.
139 self.i2c.writeto(self.addr, self.buffer)
140
141 def poweron(self):
142 pass
143
144class SSD1306_SPI(SSD1306):
145 def __init__(self, width, height, spi, dc, res, cs, external_vcc=False):
146 self.rate = 10 * 1024 * 1024
147 dc.init(dc.OUT, value=0)
148 res.init(res.OUT, value=0)
149 cs.init(cs.OUT, value=1)
150 self.spi = spi
151 self.dc = dc
152 self.res = res
153 self.cs = cs
154 self.buffer = bytearray((height // 8) * width)
155 self.framebuf = framebuf.FrameBuffer1(self.buffer, width, height)
156 super().__init__(width, height, external_vcc)
157
158 def write_cmd(self, cmd):
159 self.spi.init(baudrate=self.rate, polarity=0, phase=0)
160 self.cs.high()
161 self.dc.low()
162 self.cs.low()
163 self.spi.write(bytearray([cmd]))
164 self.cs.high()
165
166 def write_framebuf(self):
167 self.spi.init(baudrate=self.rate, polarity=0, phase=0)
168 self.cs.high()
169 self.dc.high()
170 self.cs.low()
171 self.spi.write(self.buffer)
172 self.cs.high()
173
174 def poweron(self):
175 self.res.high()
176 time.sleep_ms(1)
177 self.res.low()
178 time.sleep_ms(10)
179 self.res.high()
Example 1, Simple OLED demo:
1# Simple demonstration of 0.96 OLED in MicroPython
2# Author: George Bantique, TechToTinker
3# Date: September 30, 2020
4import ssd1306
5import machine
6
7scl = machine.Pin(22, machine.Pin.OUT, machine.Pin.PULL_UP)
8sda = machine.Pin(21, machine.Pin.OUT, machine.Pin.PULL_UP)
9i2c = machine.I2C(scl=scl, sda=sda, freq=400000)
10oled = ssd1306.SSD1306_I2C(128, 64, i2c, addr=0x3C)
11
12def print_text(msg, x, y, clr):
13 if clr:
14 oled.fill(0)
15 oled.text(msg, x, y)
16 oled.show()
17
18print_text('Hello', 10, 10, 0)
19print_text('Welcome', 20, 20, 0)
20print_text('TechToTinker', 20, 20, 1)
Posts in this series
- 026 - ESP32 MicroPython: MFRC522 RFID Module
- 025 - ESP32 MicroPython: ESP32 Bluetooth Low Energy
- 024 - ESP32 MicroPython: How to Use SD Card in MicroPython
- 023 - ESP32 MicroPython: Binary Clock
- 022 - ESP32 MicroPython: MQTT Part 2: Subscribe
- 021 - ESP32 MicroPython: MQTT Part 1: Publish
- 020 - ESP32 MicroPython: RESTful APIs | Demo READ and WRITE
- 019 - ESP32 MicroPython: OpenWeather | RESTful APIs
- 018 - ESP32 MicroPython: Thingspeak | RESTful APIs
- 017 - ESP32 MicroPython: DHT Values Auto Updates using AJAX
- 016 - ESP32 MicroPython: Web Server | ESP32 Access Point
- 015 - ESP32 MicroPython: Web Server | ESP32 Station Mode in MicroPython
- 014 - ESP32 MicroPython: SIM800L GSM Module in MicroPython
- 013 - ESP32 MicroPython: UART Serial in MicroPython
- 012 - ESP32 MicroPython: HC-SR04 Ultrasonic Sensor in MicroPython
- 011 - ESP32 MicroPython: DHT11, DHT22 in MicroPython
- 009 - ESP32 MicroPython: Non-blocking Delays and Multithreading | Multitasking
- 008 - ESP32 MicroPython: Hardware Timer Interrupts
- 007 - ESP32 MicroPython: How to make some sound with MicroPython
- 006 - ESP32 MicroPython: How to control servo motor with MicroPython
- 005 - ESP32 MicroPython: Pulse Width Modulation
- 004 - ESP32 MicroPython: External Interrupts
- 003 - ESP32 MicroPython: General Purpose Input Output | GPIO Pins
- 001 - ESP32 MicroPython: What is MicroPython
- 000 - ESP32 MicroPython: How to Get Started with MicroPython
No comments yet!