در این آموزش شما یاد خواهید گرفت چگونه توسط فریمور میکروپایتون و با برد ESP32 یا ESP8266، از صفحه نمایش SSD1306 OLED – 0.96 inch استفاده کنید. به عنوان مثال، ما به شما نشان خواهیم داد چگونه یک پیغام ساده !Hello, World’ را نمایش دهید.
پیشنیازها
برای دنبال کردن این آموزش، نیاز دارید که فریمور میکروپایتون در برد ESP32 یا ESP8266 نصب باشد. همچنین برای نوشتن و آپلود کد در بردتان، به یک IDE احتیاج دارید. ما استفاده از Thonny IDE یا uPyCraft IDE را پیشنهاد میکنیم.
معرفی نمایشگر OLED
در این آموزش ما از SSD1306 OLED – 0.96 inch استفاده میکنیم که ۱۲۸×۶۴ پیکسل است و از پروتکل ارتباطی I2C استفاده میکند.
ارتباطات I2C
برای نمایشگر I2C OLED، ارتباطاتی که باید ایجاد کنید، عبارتند از:
قطعات مورد نیاز
لیست قطعاتی که برای این پروژه نیاز دارید:
نمایشگر OLED – 0.96 inch
ESP32 یا ESP8266
بردبرد
سیم جامپر
شماتیک – ESP32
اگر از برد ESP32 استفاده میکنید، از شماتیک دیاگرام زیر استفاده کنید.
شماتیک – ESP8266
اگر از برد ESP8266 استفاده میکنید، از شماتیک دیاگرام زیر استفاده کنید.
کتابخانه SSD1306 OLED
کتابخانه نوشتن در نمایشگر OLED به صورت پیشفرض قسمتی از کتابخانه استاندارد میکروپایتون نیست. پس نیاز است که شما کتابخانه را در برد ESP32/ESP8266 آپلود کنید.
کد کتابخانه:
import time
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)
class SSD1306:
def __init__(self, width, height, external_vcc):
self.width = width
self.height = height
self.external_vcc = external_vcc
self.pages = self.height // 8
# Note the subclass must initialize self.framebuf to a framebuffer.
# This is necessary because the underlying data buffer is different
# between I2C and SPI implementations (I2C needs an extra byte).
self.poweron()
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 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_framebuf()
def fill(self, col):
self.framebuf.fill(col)
def pixel(self, x, y, col):
self.framebuf.pixel(x, y, col)
def scroll(self, dx, dy):
self.framebuf.scroll(dx, dy)
def text(self, string, x, y, col=1):
self.framebuf.text(string, x, y, col)
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)
# Add an extra byte to the data buffer to hold an I2C data/command byte
# to use hardware-compatible I2C transactions. A memoryview of the
# buffer is used to mask this byte from the framebuffer operations
# (without a major memory hit as memoryview doesn't copy to a separate
# buffer).
self.buffer = bytearray(((height // 8) * width) + 1)
self.buffer[0] = 0x40 # Set first byte of data buffer to Co=0, D/C=1
self.framebuf = framebuf.FrameBuffer1(memoryview(self.buffer)[1:], width, height)
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_framebuf(self):
# Blast out the frame buffer using a single I2C transaction to support
# hardware I2C interfaces.
self.i2c.writeto(self.addr, self.buffer)
def poweron(self):
pass
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
self.buffer = bytearray((height // 8) * width)
self.framebuf = framebuf.FrameBuffer1(self.buffer, width, height)
super().__init__(width, height, external_vcc)
def write_cmd(self, cmd):
self.spi.init(baudrate=self.rate, polarity=0, phase=0)
self.cs.high()
self.dc.low()
self.cs.low()
self.spi.write(bytearray([cmd]))
self.cs.high()
def write_framebuf(self):
self.spi.init(baudrate=self.rate, polarity=0, phase=0)
self.cs.high()
self.dc.high()
self.cs.low()
self.spi.write(self.buffer)
self.cs.high()
def poweron(self):
self.res.high()
time.sleep_ms(1)
self.res.low()
time.sleep_ms(10)
self.res.high()
دستورالعملهای بعدی را برای IDE مورد استفاده خود دنبال کنید:
- A. آپلود کتابخانه OLED با uPyCraft IDE
- B. آپلود کتابخانه OLED با Thonny IDE
A. آپلود کتابخانه OLED با uPyCraft IDE
در این بخش به شما یاد میدهیم چگونه با استفاده از uPyCraft IDE یک کتابخانه را آپلود کنید.
۱- برای ایجاد فایل جدید روی New File کلیک کنید.
۲- کد کتابخانه OLED را در آن فایل کپی کنید.
۳- بعد از کپی کردن کد، برای ذخیره فایل روی Save کلیک کنید.
این فایل جدید را “ssd1306.py” بنامید و روی ok کلیک کنید.
۵- روی Download and Run کلیک کنید.
همانطور که در شکل مشخص شده، فایل باید در پوشه دستگاه با نام “ssd1306.py” ذخیره شود.
اکنون میتوانید با وارد کردن کتابخانه، از قابلیت های آن در کد خود استفاده کنید.
B. آپلود کتابخانه OLED با Thonny IDE
اگر از Thonny IDE استفاده میکنید، دستورات زیر را دنبال کنید:
۱- کد کتابخانه را در یک فایل جدید کپی کنید.
۲- فایل را به عنوان ssd1306.py ذخیره کنید.
۳- به مسیر زیر بروید.
Device > Upload current script with the current name
تمام. کتابخانه در برد شما آپلود شده است. برای اینکه مطمئن شود که کتابخانه با موفقیت آپلود شده است، میتوانید در Shell تایپ کنید:
%lsdevice
این دستور باید فایلهایی که در حال حاضر در برد شما ذخیره هستند را نشان دهد. یکی از آنها باید فایل ssd1306.py باشد.
پس از آپلود کتابخانه به برد، شما میتوانید با وارد کردن کتابخانه، از قابلیتهای آن در کدتان استفاده کنید.
کد
بعد از آپلود کتابخانه به ESP32 یا ESP8266، کد زیر را در فایل main.py کپی کنید. این کد پیغام ‘Hello, World !’ را سه بار در نمایشگر چاپ میکند.
from machine import Pin, SoftI2C
import ssd1306
from time import sleep
# ESP32 Pin assignment
i2c = SoftI2C(scl=Pin(22), sda=Pin(21))
# ESP8266 Pin assignment
#i2c = SoftI2C(scl=Pin(5), sda=Pin(4))
oled_width = 128
oled_height = 64
oled = ssd1306.SSD1306_I2C(oled_width, oled_height, i2c)
oled.text('Hello, World 1!', 0, 0)
oled.text('Hello, World 2!', 0, 10)
oled.text('Hello, World 3!', 0, 20)
oled.show()
کد چگونه کار میکند
با وارد کردن ماژولهایی شروع کنید که برای کار با GPIO ها و فرستادن اطلاعات به OLED توسط ارتباط I2C لازم هستند. شما نیاز دارید که کلاسهای Pin و SoftI2C را از ماژول machine وارد کنید.
from machine import Pin, SoftI2C
همچنین نیاز دارید کتابخانه OLED را که قبلا با نام ssd1306.py آپلود کردید، وارد کنید.
import ssd1306
پینهای I2C در ESP32 به صورت پیشفرض (SCL)GPIO 22 و (SDA)GPIO 21 هستند اما پینهای I2C در ESP8266 به صورت پیشفرض (SLC)GPIO 5 و (SDA)GPIO 4 هستند.
اگر برد شما ESP32 است، خط زیر را استفاده کنید:
# ESP32 Pin assignment
i2c = SoftI2C(scl=Pin(22), sda=Pin(21))
اگر از برد ESP8266 استفاده میکنید، خط قبلی را کامنت کنید و خط زیر را از حالت کامنت خارج کنید.
#ESP8266 Pin assignment
i2c = SoftI2C(scl=Pin(5), sda=Pin(4))
عرض و طول OLED را روی متغیرهای زیر تعریف کنید:
oled_width = 128
oled_height = 64
پس از آن یک آبجکت SSD1306_I2C که oled نام دارد، ایجاد کنید. این آبجکت طول و عرض و پینهای I2C که قبلا تعریف کرده بودید را میپذیرد.
oled = ssd1306.SSD1306_I2C(oled_width, oled_height, i2c)
بعد از راهاندازی اولیه نمایشگر OLED، برای نوشتن متن فقط باید از تابع ()text در آبجکت oled استفاده کنید. بعد از تابع ()text باید متد ()show را فراخوانی کنید تا OLED بهروزرسانی شود.
oled.text('Hello, World 1!', 0, 0)
oled.text('Hello, World 2!', 0, 10)
oled.text('Hello, World 3!', 0, 20)
oled.show()
متد ()text به ترتیب آرگومانهای زیر را میپذیرد:
- Message: باید از نوع رشته باشد.
- X position: جایی که متن شروع میشود.
- Y position: جایی که متن به صورت عمودی نمایش داده میشود.
- Text color: میتواند سیاه یا سفید باشد و رنگ پیشفرض سفید است. این پارامتر اختیاری است.
سیاه=۰
سفید=۱
برای مثال، خط زیر پیغام ‘!Hello, World 1’ را سفید چاپ میکند. متن از x = 0 و y = 0 شروع میشود.
oled.text('Hello, World 1!', 0, 0)
خط بعدی کد، متن را در خط بعد (y =10) مینویسد.
oled.text('Hello, World 2!', 0, 10)
در نهایت، برای اعمال تغییرات، از متد show () روی آبجکت oled استفاده کنید.
oled.show()
نمایش عملی
کد را بردتان آپلود کنید. نمایشگر OLED شما باید به شکل زیر باشد:
توابع دیگر OLED
کتابخانه متدهای دیگری برای تعامل با صفحه نمایش OLED ارائه میدهد.
پر کردن صفحه
برای پر کردن کل صفحه با سفید، از تابع ()fill به شکل زیر استفاده کنید:
oled.fill(1)
oled.show()
برای پاک کردن صفحه، از متد ()fill با آرگومان ۰ استفاده کنید.(تمام پیکسلها را سیاه تنظیم میکند.)
oled.fill(0)
oled.show()
رسم یک پیکسل
برای رسم پیکسل، از متد ()pixel و سپس از متد ()show استفاده کنید. متد pixel آرگومانهای زیر را میپذیرد:
- X coordinate: مکان افقی پیکسل
- Y coordinate: مکان عمودی پیکسل
- Pixel color: میتواند سفید یا سیاه باشد.
سیاه=۰
سفید=۱
برای مثال، برای رسم یک پیکسل سفید در بالا گوشه سمت چپ، داریم:
oled.pixel(0, 0, 1)
oled.show()
رنگهای معکوس
شما میتوانید رنگهای OLED را معکوس کنید. با استفاده از متد ()invert، سفید را با مشکی عوض کنید و بالعکس.
oled.invert(True)
برای برگشت به رنگهای اصلی از دستور زیر استفاده کنید:
oled.invert(False)
نمایش داده از سنسورها
تابع ()text، فقط متغیرهایی از نوع رشته را میپذیرد. مقادیر خوانده شده از سنسور نیز معمولا به صورت متغیرهای int یا float ذخیره میشوند.
مقادیر خوانده شده از سنسور به صورت متغیرهای int یا float ذخیره شدهاند و برای نمایش آنها، باید به String تبدیل شوند. برای تبدیل داده به نوع string، شما میتوانید از تابع ()str استفاده کنید.
temperature = 12.34
temperature_string = str(temperature)
سپس شما میتوانید متغیر temperature_string را با استفاده از متدهای ()text و ()show درOLED نمایش دهید.
oled.text(temperature_string, 0, 0)
oled.show()
جمعبندی
این آموزش سریع به شما نشان داد که چگونه از قابلیتهای اساسی OLED استفاده کنید، توسط میکروپایتون و با برد ESP32 و ESP8266 متن بنویسید و پیکسل رسم کنید. حالا شما میتوانید از OLED برای نمایش پیغام یا خواندن سنسورها، در پروژههای خودتان استفاده کنید.