""" OLED_SSD1306 via I2C This program communicates with the OLED_SSD1306 via I2C. It uses a class SSD1306 that inherits from FrameBuffer. Connection: SCL - GP17, SDA - GP16 """ import time import framebuf from machine import I2C, Pin class SSD1306(framebuf.FrameBuffer): """Class for SSD1306 Graphic LCD controller which inherits class FrameBuffer from module framebuf. """ DEV_ADDR = 0x3C SCREEN_WIDTH = 128 SCREEN_HEIGHT = 64 SCREEN_PAGE_NUM = 8 WHITE = 1 BLACK = 0 def __init__(self): # Instantiate i2c with SCL - GP17, SDA - GP16 self.i2c = I2C(0, scl = Pin(17), sda = Pin(16), freq = 100_000) self.ssd1306_init() # send initialization commands # Instantiate a frame buffer self.buffer = bytearray(self.SCREEN_WIDTH * self.SCREEN_HEIGHT // 8) super().__init__(self.buffer, self.SCREEN_WIDTH, self.SCREEN_HEIGHT, framebuf.MONO_VLSB) def send_data(self, data): """Write a byte of data to SSD1306""" self.i2c.writeto(self.DEV_ADDR, bytearray([0xC0, data])) def send_command(self, cmd): """Write a byte of command to SSD1306""" self.i2c.writeto(self.DEV_ADDR, bytearray([0x80, cmd])) def ssd1306_init(self): """Initialize SSD1306""" INIT_SEQ = ( 0xae, # turn off oled panel 0x00, # set low column address 0x10, # set high column address 0x40, # set start line address 0x20, 0x02, # page addressing mode 0xc8, # top-down segment (4th quadrant) 0x81, # set contrast control register 0xcf, 0xa1, # set segment re-map 95 to 0 0xa6, # set normal display 0xa8, # set multiplex ratio(1 to 64) 0x3f, # 1/64 duty 0xd3, # set display offset 0x00, # not offset 0xd5, # set display clock divide ratio/oscillator frequency 0x80, # set divide ratio 0xd9, # set pre-charge period 0xf1, 0xda, # set com pins hardware configuration 0x12, 0xdb, # set vcomh 0x40, 0x8d, # set Charge Pump enable/disable 0x14, # set(0x10) disable 0xaf # turn on oled panel ) time.sleep_ms(100) for command in INIT_SEQ: self.send_command(command) def setRegion(self, x0, x1, y): """Set active region to x0, x1, y, y. The maximum region can be set is a page.""" self.send_command(0x21) # set column self.send_command(x0) # starting column self.send_command(x1) # end column self.send_command(0x22) # set page self.send_command(y) # starting page self.send_command(y) # end page def flush(self): """Write the buffer to the display one page at a time""" for page in range(self.SCREEN_PAGE_NUM): self.setRegion(0, self.SCREEN_WIDTH - 1, page) for column in range(self.SCREEN_WIDTH): self.send_data(self.buffer[page * self.SCREEN_WIDTH + column]) """The rest of the code will only be executed when program execution starts from this file. """ if __name__ == '__main__': # Initialize the SSD1306 controller ssd1306 = SSD1306() # Write a message ssd1306.fill(ssd1306.BLACK) ssd1306.text('Hello from', 0, 5, ssd1306.WHITE) ssd1306.text('MicroPython!', 20, 16, ssd1306.WHITE) # Draw nested rectangles x = 10 y = 30 w = ssd1306.SCREEN_WIDTH - 20 h = ssd1306.SCREEN_HEIGHT - 30 c = ssd1306.WHITE while h > 0: ssd1306.fill_rect(x, y, w, h, c) x += 2 y += 2 w -= 4 h -= 4 c = ssd1306.WHITE if c == ssd1306.BLACK else ssd1306.BLACK # Write the frame buffer out to the display ssd1306.flush()