آموزش میکروپایتون: صفحه نمایش OLED با ESP32 و ESP8266

در این آموزش شما یاد خواهید گرفت چگونه توسط فریمور میکروپایتون و با برد 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، ارتباطاتی که باید ایجاد کنید، عبارتند از:

ارتباطات I2C OLED

قطعات مورد نیاز

لیست قطعاتی که برای این پروژه نیاز دارید:

نمایشگر OLED – 0.96 inch
ESP32 یا ESP8266
بردبرد
سیم جامپر

شماتیک – ESP32

اگر از برد ESP32 استفاده می‌کنید، از شماتیک دیاگرام زیر استفاده کنید.

ESP32 – OLED

شماتیک – ESP8266

اگر از برد ESP8266 استفاده می‌کنید، از شماتیک دیاگرام زیر استفاده کنید.

ESP8266 – OLED

کتابخانه 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 کلیک کنید.

نصب SSD1306

۵- روی Download and Run کلیک کنید.

همان‌طور که در شکل مشخص شده، فایل باید در پوشه دستگاه با نام “ssd1306.py” ذخیره شود.

SSD1306 نصب شده

اکنون می‎‌توانید با وارد کردن کتابخانه، از قابلیت های آن در کد خود استفاده کنید.

B. آپلود کتابخانه OLED با Thonny IDE

اگر از Thonny IDE استفاده می‌کنید، دستورات زیر را دنبال کنید:

۱- کد کتابخانه را در یک فایل جدید کپی کنید.

۲- فایل را به عنوان ssd1306.py ذخیره کنید.

۳- به مسیر زیر بروید.
Device > Upload current script with the current name

آپلود اسکریپت فعلی

تمام. کتابخانه در برد شما آپلود شده است. برای اینکه مطمئن شود که کتابخانه با موفقیت آپلود شده است، میتوانید در Shell تایپ کنید:

%lsdevice

این دستور باید فایل‌هایی که در حال حاضر در برد شما ذخیره هستند را نشان دهد. یکی از آن‌ها باید فایل ssd1306.py باشد.

lsdevice

پس از آپلود کتابخانه به برد، شما می‌توانید با وارد کردن کتابخانه، از قابلیت‌های آن در کدتان استفاده کنید.

کد

بعد از آپلود کتابخانه به 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 شما باید به شکل زیر باشد:

نمایش ‘!Hello, World’

توابع دیگر 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 برای نمایش پیغام یا خواندن سنسورها، در پروژه‌های خودتان استفاده کنید.

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

قبلا حساب کاربری ایجاد کرده اید؟
گذرواژه خود را فراموش کرده اید؟
Loading...