Blog Archive

Arduino Indonesia. Gambar tema oleh Storman. Diberdayakan oleh Blogger.

Supported by Electronics 3 in 1

1. Jasa pencetakan PCB single layer dengan harga paling murah.

(Metode Pembuatan dengan Transfer Toner)
>PCB design sendiri (siap cetak) : Rp.150,-/Cm2
>PCB design dari kami : Rp.250,-/Cm2

(Metode Sablon Full Masking dan Silk Screen minimal pemesanan 100 Pcs)
>PCB design sendiri (siap cetak) : Rp.200,-/Cm2
>PCB design dari kami : Rp.250,-/Cm2

2. Jasa perancangan, perakitan, dan pembuatan trainer pembelajaran elektronika untuk SMK dan Mahasiswa.

3. Jasa perancangan, perakitan, dan pembuatan berbagai macam kontroller, sensor, aktuator, dan tranduser.
>Design Rangkaian / Sistem Elektronika
>Design Rangkaian / Sistem Instrumentasi
>Design Rangkaian / Sistem Kendali
>Kerjasama Riset (data atau peralatan)
>Kerjasama Produksi Produk-Produk KIT Elektronika
>Produksi Instrumentasi Elektronika

4. Jasa Pembuatan Proyek, Tugas Akhir, Tugas Laboratorium, PKM, Karya Ilmiah, SKRIPSI, dll

Like My Facebook

Popular Posts

Jumat, 02 Januari 2026

MicroPython OLED SSD1306 ESP32/ESP8266 - Cara Scroll Text dan Menggambar Bentuk

Pada artikel ini, Arduino Indonesia akan membahas fungsi-fungsi tambahan untuk mengontrol display OLED menggunakan MicroPython pada modul ESP32 atau ESP8266. Anda akan mempelajari cara melakukan scroll horizontal dan vertikal pada seluruh layar, serta teknik menggambar bentuk-bentuk grafis dasar.

Diagram Rangkaian – ESP32

Gunakan diagram skematik berikut sebagai panduan jika Anda menggunakan papan ESP32:

 

 

Diagram Rangkaian – ESP8266 NodeMCU

Gunakan diagram skematik berikut sebagai panduan jika Anda menggunakan papan ESP8266 NodeMCU:

 


Baca juga: MicroPython ESP32/ESP8266 - Cara Mengontrol Modul Relay Menggunakan Web Server

Library SSD1306 OLED

Library untuk menulis ke layar OLED tidak termasuk dalam paket standar MicroPython. Oleh karena itu, Anda perlu mengunggah file library-nya terlebih dahulu ke papan ESP32 atau 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()

 

Ikuti langkah-langkah di bawah ini sesuai dengan IDE yang Anda gunakan:

- Mengunggah Library OLED dengan uPyCraft IDE

- Mengunggah Library OLED dengan Thonny IDE

Mengunggah Library OLED dengan uPyCraft IDE

Bagian ini menjelaskan cara mengunggah library menggunakan uPyCraft IDE. Jika Anda menggunakan Thonny IDE, silakan langsung ke bagian berikutnya.

1. Buat file baru dengan menekan tombol New File.  

2. Salin kode library OLED ke dalam file tersebut.

Catatan: Library untuk layar OLED SSD1306 ini dikembangkan oleh Adafruit dan tidak lagi diperbarui. Saat ini, library tersebut masih berfungsi dengan baik. Namun, kami akan memperbarui panduan ini jika ditemukan library serupa yang memiliki kinerja setara.

3. Setelah menyalin kode, simpan file dengan menekan tombol Save (Simpan).

4. Beri nama file tersebut "ssd1306.py" lalu tekan OK.

 


5. Klik tombol Download and Run.

 

File akan tersimpan dalam folder perangkat dengan nama "ssd1306.py", seperti yang ditunjukkan pada gambar di bawah ini.

 


Sekarang, Anda dapat menggunakan fungsi-fungsi dari library ini dalam kode Anda dengan melakukan impor library.

Mengunggah Library OLED dengan Thonny IDE

Jika Anda menggunakan Thonny IDE, ikuti langkah-langkah berikut:

1. Salin kode library ke dalam file baru.

2. Simpan file tersebut dengan nama ssd1306.py.

3. Navigasi ke menu Device > Upload current script with the current name.

 


Selesai. Library telah berhasil diunggah ke papan Anda. Untuk memastikan proses unggah berhasil, ketik perintah berikut di Shell:

 

%lsdevice

 

Perintah tersebut akan menampilkan daftar file yang tersimpan di papan Anda. Pastikan file ssd1306.py termasuk dalam daftar tersebut.



Setelah library berhasil diunggah ke papan, Anda dapat menggunakan fungsionalitasnya dalam kode dengan mengimpor library tersebut.

Fungsi Pengguliran (Scroll) OLED pada MicroPython

Library ssd1306.py menyediakan fungsi scroll(x, y). Fungsi ini menggulirkan layar sebanyak x piksel ke kanan dan y piksel ke bawah.

Menggulir Layar OLED Secara Horizontal

Pada beberapa kondisi, Anda mungkin perlu menampilkan beberapa tampilan berbeda di layar OLED. Contohnya, tampilan pertama menampilkan pembacaan sensor, dan tampilan kedua menunjukkan status GPIO.

Pengguliran Horizontal

Fungsi scroll_in_screen(screen) berikut menggulirkan seluruh konten layar dari kanan ke kiri.

 

def scroll_in_screen(screen):

  for i in range (0, oled_width+1, 4):

    for line in screen:

      oled.text(line[2], -oled_width+i, line[1])

    oled.show()

    if i!= oled_width:

      oled.fill(0)

 

Fungsi ini menerima sebuah argumen berupa list dari list. Contoh:

 

screen1 = [[0, 0 , screen1_row1], [0, 16, screen1_row2], [0, 32, screen1_row3]]

 

Setiap elemen list utama berisi tiga data: koordinat x, koordinat y, dan pesan teks [x, y, pesan].

 

Sebagai contoh, kita akan menampilkan tiga baris pada layar pertama dengan pesan-pesan berikut.

 

screen1_row1 = "Screen 1, row 1"

screen1_row2 = "Screen 1, row 2"

screen1_row3 = "Screen 1, row 3"

 

Kemudian, untuk membuat layar Anda bergulir dari kiri ke kanan, Anda hanya perlu memanggil fungsi scroll_in_screen() dan memberikan list dari list sebagai argumennya:

 

scroll_in_screen(screen1)

 

Gulir Keluar Secara Horizontal

Untuk menggulirkan layar keluar (scroll out), Anda dapat menggunakan fungsi scroll_out_screen(speed). Fungsi ini menggulirkan seluruh konten layar keluar dari area tampilan OLED. Argumen yang diterima adalah angka yang mengatur kecepatan pengguliran. Nilai speed harus merupakan pembagi dari 128 (oled_width).

 

def scroll_out_screen(speed):

  for i in range ((oled_width+1)/speed):

    for j in range (oled_height):

      oled.pixel(i, j, 0)

    oled.scroll(speed,0)

    oled.show()

 

Selanjutnya, Anda dapat menggabungkan kedua fungsi tersebut untuk membuat perpindahan antar-layar dengan efek gulir. Contoh penerapannya:

 

scroll_in_screen(screen1)

scroll_out_screen(4)

scroll_in_screen(screen2)

scroll_out_screen(4)

 

Pengguliran Horizontal Kontinu

Jika Anda ingin menggulirkan layar masuk dan keluar secara berkelanjutan, gunakan fungsi scroll_screen_in_out(screen) sebagai alternatif.

 

def scroll_screen_in_out(screen):

  for i in range (0, (oled_width+1)*2, 1):

    for line in screen:

      oled.text(line[2], -oled_width+i, line[1])

    oled.show()

    if i!= oled_width:

      oled.fill(0)

 

Fungsi ini dapat digunakan untuk melakukan perpindahan antar-layar, atau untuk menggulirkan konten yang sama secara berulang.

 

scroll_screen_in_out(screen1)

scroll_screen_in_out(screen2)

scroll_screen_in_out(screen3)

 

Menggulir Layar OLED Secara Vertikal

Gulir Masuk Vertikal

Fungsi scroll_in_screen_v(screen) menggulirkan masuk seluruh konten layar dari bawah ke atas.

 

def scroll_in_screen_v(screen):

  for i in range (0, (oled_height+1), 1):

    for line in screen:

      oled.text(line[2], line[0], -oled_height+i+line[1])

    oled.show()

    if i!= oled_height:

      oled.fill(0)

 

Gulir Keluar Vertikal

Anda dapat menggunakan fungsi scroll_out_screen_v(speed) untuk menggulirkan layar keluar secara vertikal. Sama seperti fungsi horizontal, fungsi ini menerima argumen kecepatan gulir yang harus merupakan bilangan pembagi dari 64 (oled_height).

 

def scroll_out_screen_v(speed):

  for i in range ((oled_height+1)/speed):

    for j in range (oled_width):

      oled.pixel(j, i, 0)

    oled.scroll(0,speed)

    oled.show()

 

Pengguliran Vertikal Kontinu

Untuk menggulirkan layar masuk dan keluar secara vertikal secara terus-menerus, gunakan fungsi scroll_in_out_screen_v(screen).

 

def scroll_screen_in_out_v(screen):

  for i in range (0, (oled_height*2+1), 1):

    for line in screen:

      oled.text(line[2], line[0], -oled_height+i+line[1])

    oled.show()

    if i!= oled_height:

      oled.fill(0)

 

Skrip MicroPython untuk Pengguliran Layar OLED

Skrip berikut menerapkan semua fungsi yang telah dijelaskan sebelumnya. Anda dapat mengunggah kode di bawah ini ke papan untuk melihat semua efek pengguliran.

 

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)


screen1_row1 = "Screen 1, row 1"

screen1_row2 = "Screen 1, row 2"

screen1_row3 = "Screen 1, row 3"


screen2_row1 = "Screen 2, row 1"

screen2_row2 = "Screen 2, row 2"


screen3_row1 = "Screen 3, row 1"


screen1 = [[0, 0 , screen1_row1], [0, 16, screen1_row2], [0, 32, screen1_row3]]

screen2 = [[0, 0 , screen2_row1], [0, 16, screen2_row2]]

screen3 = [[0, 40 , screen3_row1]]


# Scroll in screen horizontally from left to right

def scroll_in_screen(screen):

  for i in range (0, oled_width+1, 4):

    for line in screen:

      oled.text(line[2], -oled_width+i, line[1])

    oled.show()

    if i!= oled_width:

      oled.fill(0)


# Scroll out screen horizontally from left to right

def scroll_out_screen(speed):

  for i in range ((oled_width+1)/speed):

    for j in range (oled_height):

      oled.pixel(i, j, 0)

    oled.scroll(speed,0)

    oled.show()


# Continuous horizontal scroll

def scroll_screen_in_out(screen):

  for i in range (0, (oled_width+1)*2, 1):

    for line in screen:

      oled.text(line[2], -oled_width+i, line[1])

    oled.show()

    if i!= oled_width:

      oled.fill(0)


# Scroll in screen vertically

def scroll_in_screen_v(screen):

  for i in range (0, (oled_height+1), 1):

    for line in screen:

      oled.text(line[2], line[0], -oled_height+i+line[1])

    oled.show()

    if i!= oled_height:

      oled.fill(0)


# Scroll out screen vertically

def scroll_out_screen_v(speed):

  for i in range ((oled_height+1)/speed):

    for j in range (oled_width):

      oled.pixel(j, i, 0)

    oled.scroll(0,speed)

    oled.show()


# Continous vertical scroll

def scroll_screen_in_out_v(screen):

  for i in range (0, (oled_height*2+1), 1):

    for line in screen:

      oled.text(line[2], line[0], -oled_height+i+line[1])

    oled.show()

    if i!= oled_height:

      oled.fill(0)


while True:


  # Scroll in, stop, scroll out (horizontal)

  scroll_in_screen(screen1)

  sleep(2)

  scroll_out_screen(4)


  scroll_in_screen(screen2)

  sleep(2)

  scroll_out_screen(4)


  scroll_in_screen(screen3)

  sleep(2)

  scroll_out_screen(4)


  # Continuous horizontal scroll

  scroll_screen_in_out(screen1)

  scroll_screen_in_out(screen2)

  scroll_screen_in_out(screen3)


  # Scroll in, stop, scroll out (vertical)

  scroll_in_screen_v(screen1)

  sleep(2)

  scroll_out_screen_v(4)


  scroll_in_screen_v(screen2)

  sleep(2)

  scroll_out_screen_v(4)


  scroll_in_screen_v(screen3)

  sleep(2)

  scroll_out_screen_v(4)


  # Continuous verticall scroll

  scroll_screen_in_out_v(screen1)

  scroll_screen_in_out_v(screen2)

  scroll_screen_in_out_v(screen3)

 

Menggambar Bentuk pada OLED dengan MicroPython

Untuk menggambar bentuk di layar OLED menggunakan MicroPython, kita akan memanfaatkan Adafruit_GFX MicroPython Library.

Library Adafruit GFX

Library Adafruit GFX digunakan untuk menggambar bentuk-bentuk grafis pada layar OLED. Library ini tidak termasuk dalam paket standar MicroPython, sehingga Anda perlu mengunggahnya terlebih dahulu ke papan ESP32 atau ESP8266.

 

class GFX:


    def __init__(self, width, height, pixel, hline=None, vline=None):

        # Create an instance of the GFX drawing class.  You must pass in the

        # following parameters:

        #  - width = The width of the drawing area in pixels.

        #  - height = The height of the drawing area in pixels.

        #  - pixel = A function to call when a pixel is drawn on the display.

        #            This function should take at least an x and y position

        #            and then any number of optional color or other parameters.

        #  You can also provide the following optional keyword argument to

        #  improve the performance of drawing:

        #  - hline = A function to quickly draw a horizontal line on the display.

        #            This should take at least an x, y, and width parameter and

        #            any number of optional color or other parameters.

        #  - vline = A function to quickly draw a vertical line on the display.

        #            This should take at least an x, y, and height paraemter and

        #            any number of optional color or other parameters.

        self.width = width

        self.height = height

        self._pixel = pixel

        # Default to slow horizontal & vertical line implementations if no

        # faster versions are provided.

        if hline is None:

            self.hline = self._slow_hline

        else:

            self.hline = hline

        if vline is None:

            self.vline = self._slow_vline

        else:

            self.vline = vline


    def _slow_hline(self, x0, y0, width, *args, **kwargs):

        # Slow implementation of a horizontal line using pixel drawing.

        # This is used as the default horizontal line if no faster override

        # is provided.

        if y0 < 0 or y0 > self.height or x0 < -width or x0 > self.width:

            return

        for i in range(width):

            self._pixel(x0+i, y0, *args, **kwargs)


    def _slow_vline(self, x0, y0, height, *args, **kwargs):

        # Slow implementation of a vertical line using pixel drawing.

        # This is used as the default vertical line if no faster override

        # is provided.

        if y0 < -height or y0 > self.height or x0 < 0 or x0 > self.width:

            return

        for i in range(height):

            self._pixel(x0, y0+i, *args, **kwargs)


    def rect(self, x0, y0, width, height, *args, **kwargs):

        # Rectangle drawing function.  Will draw a single pixel wide rectangle

        # starting in the upper left x0, y0 position and width, height pixels in

        # size.

        if y0 < -height or y0 > self.height or x0 < -width or x0 > self.width:

            return

        self.hline(x0, y0, width, *args, **kwargs)

        self.hline(x0, y0+height-1, width, *args, **kwargs)

        self.vline(x0, y0, height, *args, **kwargs)

        self.vline(x0+width-1, y0, height, *args, **kwargs)


    def fill_rect(self, x0, y0, width, height, *args, **kwargs):

        # Filled rectangle drawing function.  Will draw a single pixel wide

        # rectangle starting in the upper left x0, y0 position and width, height

        # pixels in size.

        if y0 < -height or y0 > self.height or x0 < -width or x0 > self.width:

            return

        for i in range(x0, x0+width):

            self.vline(i, y0, height, *args, **kwargs)


    def line(self, x0, y0, x1, y1, *args, **kwargs):

        # Line drawing function.  Will draw a single pixel wide line starting at

        # x0, y0 and ending at x1, y1.

        steep = abs(y1 - y0) > abs(x1 - x0)

        if steep:

            x0, y0 = y0, x0

            x1, y1 = y1, x1

        if x0 > x1:

            x0, x1 = x1, x0

            y0, y1 = y1, y0

        dx = x1 - x0

        dy = abs(y1 - y0)

        err = dx // 2

        ystep = 0

        if y0 < y1:

            ystep = 1

        else:

            ystep = -1

        while x0 <= x1:

            if steep:

                self._pixel(y0, x0, *args, **kwargs)

            else:

                self._pixel(x0, y0, *args, **kwargs)

            err -= dy

            if err < 0:

                y0 += ystep

                err += dx

            x0 += 1


    def circle(self, x0, y0, radius, *args, **kwargs):

        # Circle drawing function.  Will draw a single pixel wide circle with

        # center at x0, y0 and the specified radius.

        f = 1 - radius

        ddF_x = 1

        ddF_y = -2 * radius

        x = 0

        y = radius

        self._pixel(x0, y0 + radius, *args, **kwargs)

        self._pixel(x0, y0 - radius, *args, **kwargs)

        self._pixel(x0 + radius, y0, *args, **kwargs)

        self._pixel(x0 - radius, y0, *args, **kwargs)

        while x < y:

            if f >= 0:

                y -= 1

                ddF_y += 2

                f += ddF_y

            x += 1

            ddF_x += 2

            f += ddF_x

            self._pixel(x0 + x, y0 + y, *args, **kwargs)

            self._pixel(x0 - x, y0 + y, *args, **kwargs)

            self._pixel(x0 + x, y0 - y, *args, **kwargs)

            self._pixel(x0 - x, y0 - y, *args, **kwargs)

            self._pixel(x0 + y, y0 + x, *args, **kwargs)

            self._pixel(x0 - y, y0 + x, *args, **kwargs)

            self._pixel(x0 + y, y0 - x, *args, **kwargs)

            self._pixel(x0 - y, y0 - x, *args, **kwargs)


    def fill_circle(self, x0, y0, radius, *args, **kwargs):

        # Filled circle drawing function.  Will draw a filled circule with

        # center at x0, y0 and the specified radius.

        self.vline(x0, y0 - radius, 2*radius + 1, *args, **kwargs)

        f = 1 - radius

        ddF_x = 1

        ddF_y = -2 * radius

        x = 0

        y = radius

        while x < y:

            if f >= 0:

                y -= 1

                ddF_y += 2

                f += ddF_y

            x += 1

            ddF_x += 2

            f += ddF_x

            self.vline(x0 + x, y0 - y, 2*y + 1, *args, **kwargs)

            self.vline(x0 + y, y0 - x, 2*x + 1, *args, **kwargs)

            self.vline(x0 - x, y0 - y, 2*y + 1, *args, **kwargs)

            self.vline(x0 - y, y0 - x, 2*x + 1, *args, **kwargs)


    def triangle(self, x0, y0, x1, y1, x2, y2, *args, **kwargs):

        # Triangle drawing function.  Will draw a single pixel wide triangle

        # around the points (x0, y0), (x1, y1), and (x2, y2).

        self.line(x0, y0, x1, y1, *args, **kwargs)

        self.line(x1, y1, x2, y2, *args, **kwargs)

        self.line(x2, y2, x0, y0, *args, **kwargs)


    def fill_triangle(self, x0, y0, x1, y1, x2, y2, *args, **kwargs):

        # Filled triangle drawing function.  Will draw a filled triangle around

        # the points (x0, y0), (x1, y1), and (x2, y2).

        if y0 > y1:

            y0, y1 = y1, y0

            x0, x1 = x1, x0

        if y1 > y2:

            y2, y1 = y1, y2

            x2, x1 = x1, x2

        if y0 > y1:

            y0, y1 = y1, y0

            x0, x1 = x1, x0

        a = 0

        b = 0

        y = 0

        last = 0

        if y0 == y2:

            a = x0

            b = x0

            if x1 < a:

                a = x1

            elif x1 > b:

                b = x1

            if x2 < a:

                a = x2

            elif x2 > b:

                b = x2

            self.hline(a, y0, b-a+1, *args, **kwargs)

            return

        dx01 = x1 - x0

        dy01 = y1 - y0

        dx02 = x2 - x0

        dy02 = y2 - y0

        dx12 = x2 - x1

        dy12 = y2 - y1

        if dy01 == 0:

            dy01 = 1

        if dy02 == 0:

            dy02 = 1

        if dy12 == 0:

            dy12 = 1

        sa = 0

        sb = 0

        if y1 == y2:

            last = y1

        else:

            last = y1-1

        for y in range(y0, last+1):

            a = x0 + sa // dy01

            b = x0 + sb // dy02

            sa += dx01

            sb += dx02

            if a > b:

                a, b = b, a

            self.hline(a, y, b-a+1, *args, **kwargs)

        sa = dx12 * (y - y1)

        sb = dx02 * (y - y0)

        while y <= y2:

            a = x1 + sa // dy12

            b = x0 + sb // dy02

            sa += dx12

            sb += dx02

            if a > b:

                a, b = b, a

            self.hline(a, y, b-a+1, *args, **kwargs)

            y += 1

 

Ikuti instruksi sebelumnya tentang cara menginstal library, namun khusus untuk library GFX. Simpan file library GFX dengan nama gfx.py. Setelah itu, Anda dapat menggunakan fungsionalitas library dengan mengimpornya ke dalam kode. Secara ringkas, berikut adalah langkah-langkah untuk menggambar bentuk:

1. Impor library dan modul yang diperlukan: Sertakan library ssd1306 dan gfx, serta modul Pin dan SoftI2C.


from machine import Pin, SoftI2C

import ssd1306

from time import sleep

import gfx

 

Selanjutnya, tentukan konfigurasi pin untuk ESP32.

 

i2c = SoftI2C(scl=Pin(22), sda=Pin(21))

 

Jika Anda menggunakan ESP8266, gunakan konfigurasi pin berikut sebagai gantinya:

 

i2c = SoftI2C(scl=Pin(5), sda=Pin(4))

 

Kami menggunakan layar OLED berukuran 128×64 piksel. Jika Anda menggunakan layar OLED dengan resolusi berbeda, sesuaikan nilai berikut pada baris kode di bawah:

 

oled_width = 128

oled_height = 64

 

Buat sebuah objek ssd1306 dengan nama oled.

 

oled = ssd1306.SSD1306_I2C(oled_width, oled_height, i2c)

 

Selanjutnya, buat objek gfx untuk menggambar bentuk. Dalam contoh ini, objek tersebut diberi nama graphics. Argumen yang diperlukan adalah lebar dan tinggi area gambar. Karena kita ingin menggambar pada seluruh area OLED, gunakan lebar (oled_width) dan tinggi (oled_height) dari OLED. Argumen tambahan yang harus diberikan adalah fungsi dari layar kita yang bertugas menggambar piksel, yaitu oled.pixel.

 

graphics = gfx.GFX(oled_width, oled_height, oled.pixel)

 

Setelah itu, Anda dapat menggunakan fungsi-fungsi menggambar yang akan kami tunjukkan berikutnya untuk menampilkan bentuk.

Menggambar Garis


Gunakan metode line(x0, y0, x1, y1, color) pada objek gfx untuk membuat garis. Koordinat (x0, y0) menunjukkan titik awal garis, sedangkan (x1, y1) menunjukkan titik akhir garis. Jangan lupa untuk selalu memanggil oled.show() agar bentuk benar-benar ditampilkan pada layar OLED. Berikut contohnya:

 

graphics.line(0, 0, 127, 20, 1)

oled.show()

 

Persegi Panjang (Rectangle)

 

Untuk menggambar persegi panjang, gunakan metode rect(x0, y0, width, height, color) pada objek gfx. Koordinat (x0, y0) menunjukkan sudut kiri atas dari persegi panjang. Selanjutnya, tentukan lebar (width), tinggi (height), dan warna (color) persegi panjang tersebut. Contoh:

 

graphics.rect(10, 10, 50, 30, 1)

oled.show()

 

Persegi Panjang Terisi (Filled Rectangle)


Anda dapat menggunakan metode fill_rect(x0, y0, width, height, color) untuk menggambar persegi panjang yang terisi penuh. Metode ini menerima argumen yang sama dengan rect().

 

graphics.rect(10, 10, 50, 30, 1)

oled.show()

 

Lingkaran (Circle)


Gambar sebuah lingkaran menggunakan metode circle(x0, y0, radius, color). Koordinat (x0, y0) menunjukkan titik pusat lingkaran. Berikut contohnya:

 

graphics.circle(64, 32, 10, 1)

oled.show()

 

Lingkaran Terisi (Filled Circle)


Gambar lingkaran terisi menggunakan metode fill_circle(x0, y0, radius, color).

 

graphics.fill_circle(64, 32, 10, 1)

oled.show() 

 

Segitiga (Triangle)


Terdapat juga metode untuk menggambar segitiga: triangle(x0, y0, x1, y1, x2, y2, color). Metode ini menerima argumen berupa koordinat setiap sudut dan warnanya.

 

graphics.triangle(10,10,55,20,5,40,1)

oled.show() 

 

Segitiga Terisi (Filled Triangle)


Gunakan metode fill_triangle(x0, y0, x1, y1, x2, y2, color) untuk menggambar segitiga yang terisi penuh.

 

graphics.fill_triangle(10,10,55,20,5,40,1)

oled.show()

 

Skrip MicroPython – Menggambar Bentuk

Skrip berikut mengimplementasikan semua metode menggambar yang telah ditunjukkan sebelumnya.

 

from machine import Pin, SoftI2C

import ssd1306

from time import sleep

import gfx


# 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)


graphics = gfx.GFX(oled_width, oled_height, oled.pixel)


while True:


  graphics.line(0, 0, 127, 20, 1)

  oled.show()

  sleep(1)

  oled.fill(0)


  graphics.rect(10, 10, 50, 30, 1)

  oled.show()

  sleep(1)

  oled.fill(0)


  graphics.fill_rect(10, 10, 50, 30, 1)

  oled.show()

  sleep(1)

  oled.fill(0)



  graphics.circle(64, 32, 10, 1)

  oled.show()

  sleep(1)

  oled.fill(0)


  graphics.fill_circle(64, 32, 10, 1)

  oled.show()

  sleep(1)

  oled.fill(0)


  graphics.triangle(10,10,55,20,5,40,1)

  oled.show()

  sleep(1)

  oled.fill(0)


  graphics.fill_triangle(10,10,55,20,5,40,1)

  oled.show()

  sleep(1)

  oled.fill(0)

 

Baca juga: Tutorial MicroPython MQTT - Cara Publish Data Sensor DHT11/DHT22 di ESP32 & ESP8266 

Dalam praktik, hasil dan kendala yang ditemui bisa berbeda tergantung perangkat, konfigurasi, versi library, dan sistem yang digunakan.

0 on: "MicroPython OLED SSD1306 ESP32/ESP8266 - Cara Scroll Text dan Menggambar Bentuk"