OLED

    This page is to Setup and Config ESP32
 

Hardware and Software

Hardware : ESP32, Oled SSD1306
    
Software : MicroPython
  

Notes



How to Create Icon for Oled

  • Copy Free Icon from Gogole https://www.flaticon.com/free-icon/rain_365921
  • Open on Gimp 
  • Save as .c header format and open on Text Editor
  • Copy Hex Code to .py file

Connect Hardware by I2C

  • from machine import Pin,I2C 
  • import ssd1306 
  • i2c = I2C(scl=Pin(15), sda=Pin(14), freq=100000)
  •  lcd=ssd1306.SSD1306_I2C(128,64,i2c)

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Driver SSD1306 

      
  1. # 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.height == 32 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) 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.temp[0] = self.addr << 1 self.temp[1] = 0x40 # Co=0, D/C#=1 self.i2c.start() self.i2c.write(self.temp) self.i2c.write(buf) self.i2c.stop() 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)

Examples

 
  1. from machine import Pin,I2C import ssd1306 i2c = I2C(scl=Pin(15), sda=Pin(14), freq=100000) lcd=ssd1306.SSD1306_I2C(128,64,i2c) iconwineglass = [ 0x00, 0x20, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x80, 0x20, 0x00, 0x00, 0xc0, 0x60, 0x18, 0x00, 0x40, 0x00, 0x08, 0x00, 0x30, 0x18, 0x06, 0x00, 0x20, 0x18, 0x06, 0x00, 0xc0, 0x60, 0x18, 0x00, 0x80, 0x20, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x03, 0xff, 0xff, 0xff, 0x03, 0x03, 0x00, 0x00, 0x3f, 0x03, 0x00, 0x00, 0x3f, 0x03, 0x00, 0x00, 0xc3, 0x03, 0x00, 0x00, 0xc3, 0x03, 0x00, 0x00, 0xc3, 0x03, 0x00, 0x00, 0xc3, 0x03, 0x00, 0x00, 0xc3, 0x03, 0x00, 0x00, 0xc3, 0x03, 0x00, 0x00, 0x3f, 0x03, 0x00, 0x00, 0x3f, 0x04, 0x00, 0x00, 0x00, 0x0c, 0x00, 0xe0, 0x00, 0x08, 0x00, 0x40, 0x00, 0x30, 0x00, 0x18, 0x00, 0x20, 0x00, 0x10, 0x00, 0xc0, 0xff, 0x07, 0x00, 0x80, 0xff, 0x07, 0x00 ] testgamp = [ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x06, 0x00, 0x00, 0x60, 0xf8, 0xff, 0xff, 0x1f, 0xf8, 0xff, 0xff, 0x1f, 0xe0, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x07, 0x40, 0x00, 0x00, 0x02, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x0c, 0x30, 0x00, 0x00, 0x0c, 0x30, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xf0, 0x0f, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0xfc, 0x3f, 0x00, 0x00, 0xfc, 0x3f, 0x00 ] testicon = [ 0xc0, 0x03, 0x20, 0x04, 0x10, 0x08, 0x10, 0x08, 0x1c, 0x38, 0x22, 0x44, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x02, 0x40, 0xfc, 0x3f, 0x00, 0x00, 0x12, 0x81, 0x89, 0x44, 0x44, 0x22, 0x22, 0x11 ] testicon2 = [ 0x80, 0x0f, 0x40, 0x10, 0x60, 0x30, 0x90, 0x48, 0x08, 0x80, 0xc8, 0x83, 0x20, 0x84, 0x10, 0x48, 0x10, 0x08, 0x1c, 0x38, 0x22, 0x44, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x02, 0x40, 0xfc, 0x3f ] def printBits(value): ret = [9,9,9,9, 9,9,9,9] for x in range(0,8): temp = value & 0x0001 # mask all but bit 0 if temp == 0x0001: #print("Bit ", x, " = 1") ret[x] = 1 else: #print("Bit ", x, " = 0") ret[x] = 0 value = value >> 1 # shift right repeat test return ret def showIcon(iconShow, xgap=0, ygap=0): for y, row in enumerate(iconShow): #for y, row in enumerate(icontest): for x, c in enumerate(row): retbin = printBits(c) #print("Y / X :", y,"/",x," -- retbin ", retbin, "=", c) for o in range(8): if retbin[o] == 0: #lcd.pixel((x * 8) + (7-o) + xgap , y + ygap, 0) lcd.pixel((x * 8) + (7-o) + xgap , y + ygap, 0) #pass else: #pass #lcd.pixel((x * 8) + (7-o) + xgap, y + ygap, 1) lcd.pixel((x * 8) + (7-o) + xgap, y + ygap, 1) # def showIcon2(iconShow, imagewidth, xgap=0, ygap=0): posx = 0 posy = 0 for x, c in enumerate(iconShow): retbin = printBits(c) #print(x, "Y / X :", posy,"/",posx," -- retbin ", retbin, "=", c) for o in range(8): lcd.pixel((posx) + xgap , posy + ygap, retbin[o]) posx = posx + 1 if (posx > (imagewidth-1)): posx = 0 posy = posy + 1 charStr = "Tell me WINE" lcd.text(charStr, int((128-(len(charStr)*8))/2), 4) lcd.rect(0, 0, 127, 15, 1) lcd.rect(0, 16, 127, 48, 1) showIcon2( iconwineglass, 32, 4, 20) showIcon2( testicon2, 16, 50, 24) showIcon2( testicon, 16, 55, 44) showIcon2( testgamp, 32, 90, 20) lcd.show() #display pix