Interface do display OLED SSD1306 com Raspberry Pi Pico

Tempo de leitura: 6 minutes

Visão geral

Neste tutorial, aprenderemos sobre a interface do display OLED SSD1306 com o Raspberry Pi Pico. Os visores OLED são um dos visores mais atraentes disponíveis para um microcontrolador. Possui um bom ângulo de visão e densidade de pixels, o que o torna confiável para a exibição de gráficos de pequeno nível.

O display OLED SSD1306 está disponível nos módulos I2C e SPI. Mas neste tutorial, usaremos o display I2C OLED de 0,96″, pois ele requer apenas 2 fios para a interface. O Raspberry Pi Pico que vem com um microcontrolador RP2040 tem dois pares de pinos I2C. Você pode usar qualquer um dos pinos I2C do Raspberry Pi Pico para fazer a interface do display OLED SSD1306.

Usaremos o código Micropython aqui para usar o Display OLED com Pico Board. O MicroPython IDE requer o código do driver SSD1306. Depois de escrever o código do driver, podemos escrever qualquer coisa e exibi-lo no display OLED. Exibiremos o valor analógico da tensão do potenciômetro no display OLED. Mas antes disso, recomendamos que você consulte o Guia de introdução do Raspberry Pi Pico e também sobre como usar o pino I2C.

 

Lista de Materiais

Você pode comprar a Placa Raspberry Pi Pico junto com o Módulo de Display OLED no link a seguir.

NOME DOS COMPONENTESDESCRIÇÃOQUANTIDADE
Raspberry Pi PicoRP2040 Based Raspberry Pi Pico Microcontroller1
OLED Display0.96″ SSD1306 I2C OLED Display1
PotenciômetroPotenciômetro 10K1

 

Display OLED SSD1306

Os visores OLED são um dos visores mais atraentes disponíveis para um microcontrolador devido ao seu ângulo de visão e densidade de pixels. Este SSD1306 é um módulo de Display OLED azul de 0,96/1,3 polegadas. Você pode fazer a interface deste módulo de exibição com qualquer microcontrolador usando protocolos SPI/IIC. Ele está tendo uma resolução de 128×64. O pacote inclui uma placa de exibição, uma tela, cabeçote macho de 4 pinos pré-soldado à placa.

OLED (Organic Light-Emitting Diode) é uma tecnologia de auto-emissão de luz composta por um filme orgânico fino e multicamadas colocado entre um ânodo e um cátodo. Em contraste com a tecnologia LCD, o OLED não requer luz de fundo. O OLED possui alto potencial de aplicação para virtualmente todos os tipos de monitores e é considerado a tecnologia de ponta para a próxima geração de monitores de tela plana.

 

Interface do display OLED SSD1306 com Raspberry Pi Pico

Agora vamos aprender como podemos fazer a interface do display OLED SSD1306 com o Raspberry Pi Pico. A placa Raspberry Pi Pico tem dois pares de pinos I2C. Você pode usar qualquer um dos pares de pinos I2C para aplicativos de interface. Para saber mais sobre o uso e os aplicativos dos pinos I2C, você pode usar nosso Guia I2C do Raspberry Pi Pico.

Neste exemplo, alimentaremos o valor de entrada da tensão analógica do potenciômetro para o pino analógico GP28 do Raspberry Pi Pico. Em seguida, exibiremos a tensão analógica na tela OLED. O esquema é muito simples e fácil de usar.

Conecte o pino SDA e SCL do display OLED ao pino PICO GP8 e GP9 respectivamente. Conecte o pino VCC e GND do display OLED a 3,3V e pino GND do Pico. Você pode usar uma placa de ensaio para montar todo o circuito.

 

Display OLED com código Raspberry Pi Pico

Para programar o Raspberry Pi Pico Board, usaremos a linguagem de programação MicroPython. MicroPython é semelhante ao Python. Você pode usar o Thonny IDE ou o uPyCraft IDE para programar e testar a placa.

Eu prefiro uPyCraft IDE para programação. A programação aqui é dividida em duas partes principais:
1. SSD1306.py
2. Main.py

 

Isso ocorre porque o display OLED requer o código do driver SSD1306 primeiro. Temos que escrever o código para o driver SSD1306 primeiro. Depois de enviar o código SSD1306, podemos executar o código main.py.

SSD1306.py

Portanto, no uPyCraft IDE, crie um newfile. Copie o código a seguir e salve o arquivo com o nome ssd1306.py.

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

Agora clique no botão de download e execução. Assim você poderá ver o driver SSD1306 salvo no Raspberry Pi Pico.

 

main.py

Abra uma nova guia novamente no uPyCraft IDE. Copie o código a seguir e cole-o na janela uPyCraft IDE. Salve o arquivo com o nome main.py.

# Display Image & text on I2C driven ssd1306 OLED display 
from machine import Pin, I2C
from ssd1306 import SSD1306_I2C
import framebuf
import machine
import utime
 
sensor_temp = machine.ADC(28)
conversion_factor = 3.3 / (65535)
 
WIDTH  = 128                                            # oled display width
HEIGHT = 64                                             # oled display height
 
i2c = I2C(0, scl=Pin(9), sda=Pin(8), freq=200000)       # Init I2C using pins GP8 & GP9 (default I2C0 pins)
print("I2C Address      : "+hex(i2c.scan()[0]).upper()) # Display device address
print("I2C Configuration: "+str(i2c))                   # Display I2C config
 
 
oled = SSD1306_I2C(WIDTH, HEIGHT, i2c)                  # Init oled display
 
# Raspberry Pi logo as 32x32 bytearray
buffer = bytearray(b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00|?\x00\x01\x86@\x80\x01\x01\x80\x80\x01\x11\x88\x80\x01\x05\xa0\x80\x00\x83\xc1\x00\x00C\xe3\x00\x00~\xfc\x00\x00L'\x00\x00\x9c\x11\x00\x00\xbf\xfd\x00\x00\xe1\x87\x00\x01\xc1\x83\x80\x02A\x82@\x02A\x82@\x02\xc1\xc2@\x02\xf6>\xc0\x01\xfc=\x80\x01\x18\x18\x80\x01\x88\x10\x80\x00\x8c!\x00\x00\x87\xf1\x00\x00\x7f\xf6\x00\x008\x1c\x00\x00\x0c \x00\x00\x03\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
 
while True:
    reading = sensor_temp.read_u16() * conversion_factor
    # Load the raspberry pi logo into the framebuffer (the image is 32x32)
    fb = framebuf.FrameBuffer(buffer, 32, 32, framebuf.MONO_HLSB)
 
    # Clear the oled display in case it has junk on it.
    oled.fill(0)
 
    # Blit the image from the framebuffer to the oled display
    oled.blit(fb, 96, 0)
       
    
    # Add some text
    oled.text("ADC: ",5,8)
    oled.text(str(round(reading,2)),40,8)
 
 
    # Finally update the oled display so the image & text is displayed
    oled.show()

Agora, novamente, clique no botão de download e execução. O código será salvo no Raspberry Pi Pico Board.

Agora você está pronto para ir. O Display OLED começará a exibir imediatamente o logotipo do Raspberry Pi junto com o valor da tensão analógica do potenciômetro.

Você pode girar o botão do potenciômetro e ver o display OLED mostrando os diferentes valores.

É assim que você pode exibir o texto ou logotipo em um display OLED usando código MicroPython. Portanto, a interface do display OLED SSD1306 com o Raspberry Pi Pico é tão fácil quanto este tutorial.