본문 바로가기
라즈베리파이_피코_피코 W/마이크로파이썬

10. 라즈베리파이 피코 OLED제어

by 땜블리 2023. 3. 4.
728x90
반응형
SMALL

안녕하세요 땜블리 입니다.

라즈베리파이 피코 베이직 트레이닝 보드를 이용한 OLED제어를 진행 하겠습니다.

베이직 트레이닝 보드는 아래에서 확인이 가능합니다.

https://ttcw.tistory.com/4

 

라즈베리파이 피코 베이직 트레이닝보드 구성

라즈베리파이 피코 보드의 펌웨어실습을 위한 베이직 트레이닝보드를 소개 합니다. 현재 네이버 스마트스토어에서 판매가 진행되고 있습니다. 라즈베리파이 피코 베이직 트레이닝 보드 라즈베

ttcw.tistory.com

1) OLED 제어 구동 원리

(1) 동작설명

OLED(유기 발광 다이오드)는 유기 화합물 층으로 이루어진 LED 반도체 소자 중 하나입니다.

128x64 OLED 디스플레이는 단순한 도트 매트릭스 그래픽 디스플레이입니다.

128 개의 열과 64 개의 행이있어 총 128x64 = 8192 픽셀을 표시합니다.

이 픽셀의 LED를 켜고 끄면 모든 모양의 그래픽 이미지를 표시 할 수 있습니다.

2) OLED 기본 문구 출력 제어

(1) 동작설명

ssd1306 드라이버를 사용하여 OLEDText를 표시 합니다.

i2c = I2C(1,scl=Pin(15), sda=Pin(14)) I2C pin 설정

oled = ssd1306.SSD1306_I2C(128,64,i2c,0x3c) OLED pin 설정

oled.fill(1) 화면을 흰색으로 채웁니다.

oled.fill(0) 화면을 검정색으로 채웁니다.

oled.show() 화면을 보여 줍니다.

oled.text("picoSensorBoard",0,0) 0,0좌표에 picoSensorBoard 를 표시 합니다.

(2) 코드작성

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

main.py

import oledText

oledText.py

from machine import UART, Pin, I2C, ADC, PWM,SPI
from time import sleep
import ssd1306
import dht
i2c = I2C(1,scl=Pin(15), sda=Pin(14))#I2C설정
oled = ssd1306.SSD1306_I2C(128,64,i2c,0x3c)#OLED설정
uart0 = UART(0, baudrate=115200, bits=8, parity=None, stop=1, tx=Pin(16), rx=Pin(17))# UART 설정
uart0.write("pico sensorBoard Test\n")

oled.fill(1)
oled.show()
sleep(1)
oled.fill(0)
oled.show()
sleep(1)

while True:              
    oled.fill(0)
    oled.text("picoSensorBoard",0,0)
    oled.text("picoS/Board",10,15)
    oled.text("picoS/Board",20,30)
    oled.text("picoS/Board",30,45)
    oled.show()  
    sleep(0.5)
반응형

(3) 동작결과

 

3) OLED에 현재 온도/습도, CdS/가변저항 데이터 출력 제어

 

(1) 코드작성

dht.py

import sys

if sys.platform.startswith("esp"):
    from esp import dht_readinto
elif sys.platform == "mimxrt":
    from mimxrt import dht_readinto
elif sys.platform == "rp2":
    from rp2 import dht_readinto
elif sys.platform == "pyboard":
    from pyb import dht_readinto
else:
    from machine import dht_readinto


class DHTBase:
    def __init__(self, pin):
        self.pin = pin
        self.buf = bytearray(5)

    def measure(self):
        buf = self.buf
        dht_readinto(self.pin, buf)
        if (buf[0] + buf[1] + buf[2] + buf[3]) & 0xFF != buf[4]:
            raise Exception("checksum error")


class DHT11(DHTBase):
    def humidity(self):
        return self.buf[0]

    def temperature(self):
        return self.buf[2]


class DHT22(DHTBase):
    def humidity(self):
        return (self.buf[0] << 8 | self.buf[1]) * 0.1

    def temperature(self):
        t = ((self.buf[2] & 0x7F) << 8 | self.buf[3]) * 0.1
        if self.buf[2] & 0x80:
            t = -t
        return t

ssd1306.py

상단 참조

main.py

import oledT_H

oledT_H.py

from machine import UART, Pin, I2C, ADC, PWM,SPI
from time import sleep
import ssd1306
import dht
led1 = Pin(2,Pin.OUT)
led2 = Pin(3,Pin.OUT)
CdS_adc = ADC(Pin(27))
vr_adc = ADC(Pin(26)) 
i2c = I2C(1,scl=Pin(15), sda=Pin(14))#I2C설정
oled = ssd1306.SSD1306_I2C(128,64,i2c,0x3c)#OLED설정
dhtIn = Pin(7,Pin.IN) # 온/습도 센서 설정
dhtOut = dht.DHT11(dhtIn)# 온/습도 센서 설정
uart0 = UART(0, baudrate=115200, bits=8, parity=None, stop=1, tx=Pin(16), rx=Pin(17))# UART 설정
uart0.write("pico sensorBoard Test\n")

oled.fill(1)
oled.show()
led1.value(0)
led2.value(0)
sleep(1)
oled.fill(0)
oled.show()
led1.value(1)
led2.value(1)
sleep(1)
    
temp=0
humi=0
def tempHumiSensor():
    global temp, humi
    dhtOut.measure()
    temp = dhtOut.temperature()
    humi = dhtOut.humidity()
    sleep(0.5)
    
VRData=0
def adcInput(ch):
    global VRData
    if ch ==0: #VR
        VRData = vr_adc.read_u16()
        VRDataV = (3.3/65535) * VRData
        VRDataV = round(VRDataV,2)
        return VRDataV
    elif ch ==1: #CdS
        CdSData = CdS_adc.read_u16()
        CdSDataV = (3.3/65535) * CdSData
        CdSDataV = round(CdSDataV,2)
        return CdSDataV
        
while True:         
               
    tempHumiSensor()
    print('Temperature = {}C   Humidity = {}%'.format(temp,humi))
    print('VR  Volt    = {}V   CdS Volt  = {}V\n'.format(adcInput(0),adcInput(1)))
      
    oled.fill(0)
    oled.text("Temp(C) : ",0,0)
    oled.text(str(temp),80,0)
    oled.text("Humi(%) : ",0,12)
    oled.text(str(humi),80,12)
    oled.text("CdS(V)  : ",0,24)
    oled.text(str(adcInput(1)),80,24)
    oled.text("VR(V)   : ",0,36)
    oled.text(str(adcInput(0)),80,36)
    oled.show()  
    sleep(0.5)

(3) 동작결과

온습도 데이터와 CDS ,VR 값이 OLED에 표시 됩니다.

 

 

728x90
반응형
LIST

댓글