![Работа с OLED дисплей и ESP8266 с MicroPython](http://ardudevelop.eu/wp-content/uploads/2024/10/IMG_20241029_223235.png)
Въведение:
В тази статия ще разгледаме как да използваме OLED SSD1306 дисплей с ESP8266 и MicroPython. OLED дисплеите са компактни и ефективни, като предоставят висока разделителна способност и ниско енергийно потребление. Ще обясним необходимите стъпки за свързване и настройка, както и основни функции за изчертаване на текст и графики върху дисплея.
За целта на тази статия ще използваме процесора ESP8266 с OLED дисплей който е закачен директно на платформата. Може да прочетете повече за него в нашето ревю: ESP8266 с OLED дисплей.
Ако все още не сте инсталирали MicroPython на вашия ESP8266, вижте нашето ръководство за инсталация в статията ни: Как да инсталирате MicroPython на ESP8266.
Използвана библиотека SSD1306:
OLED дисплеите използват библиотеката ssd1306
в MicroPython, която трябва да бъде качена в ESP8266. За да го направите, запазете библиотеката като ssd1306.py
, след което я качете на контролера с помощта на инструмент като ampy или WebREPL. Веднъж качена, библиотеката може лесно да бъде използвана чрез импортиране в кода ви с import ssd1306
. Може да свалите библиотеката от тук: SSD1306.
# 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_IREF_SELECT = const(0xAD)
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, # display off
# address setting
SET_MEM_ADDR,
0x00, # horizontal
# resolution and layout
SET_DISP_START_LINE, # start at line 0
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
SET_IREF_SELECT,
0x30, # enable internal IREF during display on
# charge pump
SET_CHARGE_PUMP,
0x10 if self.external_vcc else 0x14,
SET_DISP | 0x01, # display on
): # on
self.write_cmd(cmd)
self.fill(0)
self.show()
def poweroff(self):
self.write_cmd(SET_DISP)
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 rotate(self, rotate):
self.write_cmd(SET_COM_OUT_DIR | ((rotate & 1) << 3))
self.write_cmd(SET_SEG_REMAP | (rotate & 1))
def show(self):
x0 = 0
x1 = self.width - 1
if self.width != 128:
# narrow displays use centred columns
col_offset = (128 - self.width) // 2
x0 += col_offset
x1 += col_offset
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)
Намиране на I2C адреса на OLED дисплея:
За да се свърже правилно OLED дисплеят, е важно първо да се установи неговият I2C адрес. Ето код за сканиране на I2C устройството:
import machine
# Change this if you are using other ports
I2C_SDA_PIN = 5
I2C_SCL_PIN = 4
i2c=machine.I2C(sda=machine.Pin(I2C_SDA_PIN), scl=machine.Pin(I2C_SCL_PIN), freq=400000)
print('Scanning I2C bus.')
devices = i2c.scan() # this returns a list of devices
device_count = len(devices)
if device_count == 0:
print('No i2c device found.')
else:
print(device_count, 'devices found.')
for device in devices:
print('Decimal address:', device, ", Hex address: ", hex(device))
Обикновено I2C адресът на дисплея е 0x3c
, но проверката е важна, особено при различни модели.
Основен код работа с OLED дисплей и ESP8266 с MicroPython
from machine import Pin,I2C
import ssd1306
from time import sleep
#import framebuf
i2c=I2C(scl=Pin(4),sda=Pin(5), freq=400000)
oled=ssd1306.SSD1306_I2C(128,64,i2c,0x3c)
print("oled address = " , i2c.scan()) # print OLED I2C address
oled.fill(0) # clear LCD
oled.show() # send data to oled
oled.rect(0, 0, 128, 64, 1) # drow frame on Oled dislpay
oled.show() # send data to oled
sleep(1)
oled.fill(0)
oled.pixel(10 , 10 , 1) # flash only one pixel
oled.show() # send data to oled
print(str(oled.pixel(10 , 10))) # check pixel is flash or not
sleep(1)
oled.fill(0)
oled.hline(5, 32, 50, 1) # draw horizontal line x=5px, y=32px, width=50px, colour=1
oled.show()
sleep(1)
oled.fill(0)
oled.vline(64, 10, 25, 1) # draw vertical line x=64px, y=10px, height=25px, colour=1
oled.show()
sleep(1)
oled.fill(0)
oled.line(0, 0, 127, 63, 1) # draw a line from 0,0 to 127,63
oled.show()
sleep(1)
oled.fill(0)
oled.rect(10, 10, 107, 43, 1) # draw a rectangle outline 10,10 to 117,53, colour=1
oled.show()
sleep(1)
oled.fill(0)
oled.fill_rect(10, 10, 107, 43, 1) # draw a solid rectangle 10,10 to 117,53, colour=1 fill_rectangle
oled.show()
sleep(1)
oled.fill(0)
oled.text('Hello World', 10, 30, 1) # draw some text at x=10, y=30, colour=1
oled.show()
sleep(1)
oled.fill(0)
oled.fill_rect(0, 0, 32, 32, 1)
oled.fill_rect(2, 2, 28, 28, 0)
oled.vline(9, 8, 22, 1)
oled.vline(16, 2, 22, 1)
oled.vline(23, 8, 22, 1)
oled.fill_rect(26, 24, 2, 4, 1)
oled.text('MicroPython', 40, 0, 1)
oled.text('SSD1306', 40, 12, 1)
oled.text('OLED 128x64', 40, 24, 1)
oled.show()
#oled.contrast(255) # dimm display
#oled.poweron() # oled power on
#oled.poweroff() # oled power off
#oled.invert(1) # invert black text to white fon
#oled.invert(0) # invert white text to black fon
#oled.rotate(True) # rotate 180 degrees
#oled.rotate(False) # rotate 0 degrees
Подробно обяснение на кода стъпка по стъпка:
Импортиране на модули:
from machine import Pin, I2C
import ssd1306
from time import sleep
Импортираме нужните библиотеки – Pin
и I2C
за контрол на пиновете, ssd1306
за работа с дисплея и sleep
за забавяния между операциите.
Инициализация на I2C и OLED дисплея:
i2c = I2C(scl=Pin(4), sda=Pin(5), freq=400000)
oled = ssd1306.SSD1306_I2C(128, 64, i2c, 0x3c)
Създаваме I2C обект с пинове 4
и 5
за връзка с OLED и настройваме честотата на 400 kHz. Дефинираме OLED дисплея с резолюция 128×64 пиксела и задаваме адреса му 0x3c
.
Проверка на I2C устройството:
print("oled address = ", i2c.scan())
Извежда адреса на свързаното I2C устройство, за да потвърди, че OLED дисплеят е правилно свързан.
Изчистване на дисплея:
oled.fill(0)
oled.show()
oled.fill(0)
нулира екрана, а oled.show()
прилага промените, изчиствайки OLED дисплея.
Рисуване на рамка:
oled.rect(0, 0, 128, 64, 1)
oled.show()
Създава рамка с координати от (0, 0)
до (128, 64)
, след което я показва.
Активиране на пиксел:
oled.pixel(10, 10, 1)
oled.show()
Активира единичен пиксел в позиция (10, 10)
и го показва на дисплея. Това може да се използва за проверка на отделни пиксели.
Рисуване на хоризонтална линия:
oled.hline(5, 32, 50, 1)
oled.show()
Извежда хоризонтална линия с дължина 50 пиксела на позиция (5, 32)
.
Рисуване на вертикална линия:
oled.vline(64, 10, 25, 1)
oled.show()
Създава вертикална линия на позиция (64, 10)
с височина 25 пиксела.
Рисуване на диагонална линия:
oled.line(0, 0, 127, 63, 1)
oled.show()
Начертава диагонална линия от (0, 0)
до (127, 63)
.
Очертание на правоъгълник:
oled.rect(10, 10, 107, 43, 1)
oled.show()
Създава правоъгълник с очертания от позиция (10, 10)
до (117, 53)
.
Запълнен правоъгълник:
oled.fill_rect(10, 10, 107, 43, 1)
oled.show()
Рисува запълнен правоъгълник в същия регион.
Текстово съобщение:
oled.text('Hello World', 10, 30, 1)
oled.show()
Показва текст в позиция (10, 30)
.
Демо фигура с текст:
oled.fill_rect(0, 0, 32, 32, 1)
oled.fill_rect(2, 2, 28, 28, 0)
oled.vline(9, 8, 22, 1)
oled.vline(16, 2, 22, 1)
oled.vline(23, 8, 22, 1)
oled.fill_rect(26, 24, 2, 4, 1)
oled.text('MicroPython', 40, 0, 1)
oled.text('SSD1306', 40, 12, 1)
oled.text('OLED 128x64', 40, 24, 1)
oled.show()
Това е сложна комбинация от форми и линии, последвана от текст. Демонстрира детайлна графика с MicroPython.
(По избор) Функции за управление на контраста и екрана:
# oled.contrast(255)
# oled.poweron()
# oled.poweroff()
# oled.invert(1)
# oled.invert(0)
# oled.rotate(True)
# oled.rotate(False)
Тези функции предоставят опции за управление на контраста, включване/изключване на дисплея, инверсия на цветовете и завъртане на екрана. Може да ги пробвате един по един за да разберете какво правят те.
Заключение:
Използването на OLED дисплей с ESP8266 и MicroPython осигурява лесен и гъвкав начин за визуализиране на данни. С библиотеката ssd1306
можете лесно да добавяте графики и текст, което прави този дисплей идеален за IoT проекти и прототипи. Офицялен наръчник тук.