128 x 32 OLED Display

From Sketching with Hardware at LMU Wiki
Jump to navigation Jump to search

This is the specific tutorial for the 128 x 32 OLED Display (https://www.waveshare.com/0.91inch-oled-module.htm). For general information on OLED Displays, see the Tutorial Display.

How to control it in MicroPython

The main.py shows the current time on the screen.

 1 # main.py displaying the current time
 2 from machine import Pin, SoftI2C
 3 import ssd1306
 4 from time import sleep
 5 import utime
 6 
 7 # Initialize I2C interface with the correct pins for your setup
 8 i2c = SoftI2C(scl=Pin(13), sda=Pin(12))
 9 
10 # Initialize SSD1306 OLED display
11 oled_width = 128
12 oled_height = 32  # Adjusted for 128x32 OLED display
13 oled = ssd1306.SSD1306_I2C(oled_width, oled_height, i2c)
14 
15 while True:
16     # Clear the display
17     oled.fill(0)
18     
19     # Get the current time
20     current_time = utime.localtime()
21     time_str = '{:02}:{:02}:{:02}'.format(current_time[3], current_time[4], current_time[5])
22     
23     # Display the current time
24     oled.text('Current Time:', 0, 0) # first line
25     oled.text(time_str, 0, 10) # second line
26     #oled.text("EMPTY", 0, 20) #third line
27     
28     # Update the display
29     oled.show()
30     
31     # Wait for a bit before updating again
32     sleep(1)


ssd1306.py

  1 # ssd1306.py - MicroPython SSD1306 OLED driver, I2C and SPI interfaces
  2 
  3 from micropython import const
  4 import framebuf
  5 
  6 # register definitions
  7 SET_CONTRAST = const(0x81)
  8 SET_ENTIRE_ON = const(0xa4)
  9 SET_NORM_INV = const(0xa6)
 10 SET_DISP = const(0xae)
 11 SET_MEM_ADDR = const(0x20)
 12 SET_COL_ADDR = const(0x21)
 13 SET_PAGE_ADDR = const(0x22)
 14 SET_DISP_START_LINE = const(0x40)
 15 SET_SEG_REMAP = const(0xa0)
 16 SET_MUX_RATIO = const(0xa8)
 17 SET_COM_OUT_DIR = const(0xc0)
 18 SET_DISP_OFFSET = const(0xd3)
 19 SET_COM_PIN_CFG = const(0xda)
 20 SET_DISP_CLK_DIV = const(0xd5)
 21 SET_PRECHARGE = const(0xd9)
 22 SET_VCOM_DESEL = const(0xdb)
 23 SET_CHARGE_PUMP = const(0x8d)
 24 
 25 # Subclassing FrameBuffer provides support to the graphics primitives
 26 class SSD1306(framebuf.FrameBuffer):
 27 
 28     def __init__(self, width, height, external_vcc):
 29         self.width = width
 30         self.height = height
 31         self.external_vcc = external_vcc
 32         self.pages = self.height // 8
 33         self.buffer = bytearray(self.pages * self.width)
 34         super().__init__(self.buffer, self.width, self.height, framebuf.MONO_VLSB)
 35         self.init_display()
 36 
 37     def init_display(self):
 38         for cmd in (
 39             SET_DISP | 0x00,  # display 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):  # display 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 poweron(self):
 68         self.write_cmd(SET_DISP | 0x01)
 69 
 70     def contrast(self, contrast):
 71         self.write_cmd(SET_CONTRAST)
 72         self.write_cmd(contrast)
 73 
 74     def invert(self, invert):
 75         self.write_cmd(SET_NORM_INV | (invert & 1))
 76 
 77     def show(self):
 78         xpos0 = 0
 79         xpos1 = self.width - 1
 80         self.write_cmd(SET_COL_ADDR)
 81         self.write_cmd(xpos0)
 82         self.write_cmd(xpos1)
 83         self.write_cmd(SET_PAGE_ADDR)
 84         self.write_cmd(0)
 85         self.write_cmd(self.pages - 1)
 86         self.write_data(self.buffer)
 87 
 88     def write_cmd(self, cmd):
 89         raise NotImplementedError
 90 
 91     def write_data(self, buf):
 92         raise NotImplementedError
 93 
 94 class SSD1306_I2C(SSD1306):
 95 
 96     def __init__(self, width, height, i2c, addr=0x3c, external_vcc=False):
 97         self.i2c = i2c
 98         self.addr = addr
 99         self.temp = bytearray(2)
100         self.write_list = [b'\x40', None]  # Co=0, D/C#=1
101         super().__init__(width, height, external_vcc)
102 
103     def write_cmd(self, cmd):
104         self.temp[0] = 0x80  # Co=1, D/C#=0
105         self.temp[1] = cmd
106         self.i2c.writeto(self.addr, self.temp)
107 
108     def write_data(self, buf):
109         self.write_list[1] = buf
110         self.i2c.writevto(self.addr, self.write_list)