라즈베리파이 피코 보드에서 소형 0.96인치 1306 OLED 디스플레이 사용 방법 및 주의사항

라즈베리파이 피코 보드에서 소형 0.96인치  1306 OLED  디스플레이 사용 방법 및 주의사항

1. SSD 1306 OLED

앞선 글에서 라즈베리파이 피코 보드에서 1602A라는 16×2 LCD를 이용하여 출력하는 방법에 대해 소개한 바 있다. https://blog.naver.com/mythee1/223188515992

이번 글에서는 LCD 대신 소형 OLED 모듈에 라즈베리파이 피코 보드에서 출력하는 방법을 소개한다.

시중에서 라즈베리 파이나 아두이노에서 사용하는 용도로 구하기 쉬운 OLED 디스플레이로는 0.91인치 단색 OLED가 보편적인데, 현재는 가격이 많이 낮아져서 개당 수천원 정도에도 구입이 가능해졌다. 이들은 대개 드라이버칩 때문에 SSD1306 OLED라고 부르는데, 간혹 외형상으로 구분하기 어려운 1315 모듈도 있는데, 하위 호환성이 있다고는 하나 드물게 동작에 문제가 있다고 하는 경우도 있기 때문에, SSD 1306 표기를 확인하고 구입하는 것이 좋다.

이들 제품은 해상도에 따라 128 x 64의 해상도를 가지는 제품과, 화면 세로폭이 절반인 128×32의 해상도를 가지는 제품으로 나뉜다. 동일한 SSD1306 OLED 칩셋인 것을 확인하고 구입하면, 128×32의 경우라도 사용 시 화면 해상도 설정만 변경하면 128×64와 동일한 방식으로 사용이 가능하다.

이들의 통신방식은 다음 사진들과 같이 I2C여서, 전원 선을 포함하여 총 4개의 선으로 라즈베리파이 피코와 연결되게 된다.

2. SSD 1306 OLED 해상도

이들 모듈은 매우 소형이어서, 128×64 해상도 제품의 경우 가로 x 세로 크기가 대략 2.5 x 2.5cm 정도 수준으로 작지만, 상당히 고해상도여서 가로로 16자 x 세로로 8줄로 구성된 128자의 글자를 한 번에 화면에 표시할 수 있다.

해상도 128×32인 제품의 경우, 문자 표기 때에는 가로로 16자를 표시할 수 있는 것은 동일하고, 세로로 4줄까지 표시할 수 있어 64자의 글자를 한 번에 화면에 표시할 수 있어, 비록 글자 자체의 크기는 작지만 앞서 소개했던 16×2 LCD의 동시 표시가능글자 32자보다 월등히 많은 정보를 동시에 표시할 수 있는 장점이 있다.

3. SSD 1306 OLED 사용을 위한 Library 준비

이러한 1306 OLED를 라즈베리파이 피코 보드에서 사용하려면, 전용의 라이브러리(SSD1306.py)를 미리 피코 보드에 저장해 두어야 한다. 이 라이브러리는 여러 버전이 있기는 하지만, 가장 기본적인 버전은 다음 링크를 이용하여 Github에서 다운로드할 수 있다.

https://github.com/adafruit/micropython-adafruit-ssd1306/blob/master/ssd1306.py

이 링크를 열면 다음과 같은 화면이 나오는데, 이 부분의 Code를 처음부터 끝부분까지 선택하여 복사한 후,

ThonnyIDE를 열고 새 창을 만들어 붙여 넣는다.

그리고, 라즈베리파이 피코 보드가 PC에 연결된 상태에서, 이 Code를 그대로 라즈베리파이 피코 보드에 SSD1306.py라는 이름으로 저장해 주면 된다. 그러면 이제 OLED 모듈을 이용할 준비가 된 것이다.

4. OLED 모듈과 라즈베리피코보드의 연결

이 OLED는 I2C 방식 통신을 이용한다. I2C에 대한 기본적 사항에 대해서는 앞선 글을 참조하기 바란다.

https://blog.naver.com/mythee1/223188515992

배선에는 총 4선이 필요한데, 다음과 같이 배선했다.

OLED의 전원선 Vcc – 라즈베리피코보드의 3.3V 출력이 나오는 물리번호 36번 핀에

OLED의 GND는 라즈베리 피코 보드의 GND 중 하나인 38번 핀을 연결했다.

I2C 통신의 Data 선인 SDA 선은 물리번호 1번(GP0)에 연결했다.

I2C 통신의 Clock 선인 SCL 선은 SDA 선이 연결된 것과 동일한 I2C0 채널의 SCL 선인 물리번호 2번(GP1)에 연결했다. 배선한 모습은 다음과 같다.

다음 핀맵을 참고하면 이해에 도움이 될듯하다.

5. OLED 사용을 위한 파이썬 코딩

OLED에 출력하려면 먼저 미리 저장해둔 OLED 라이브러리의 사용을 선언해 주어야 한다. 다른 필수 라이브러리도 함께 사용을 선언해 준다.

from machine import Pin, I2C

from ssd1306 import SSD1306_I2C

import utime

그 다음으로 I2C 통신 사용을 선언해 준다. 미리 핀을 연결한 대로 다음과 같이 선언한다.

sda=machine.Pin(0)

scl=machine.Pin(1)

i2c=machine.I2C(0,sda=sda, scl=scl, freq=400000)

이렇게 3줄로 쓰는 대신 다음과 같이 1줄로 표기하는 것도 가능하다. 개인 취향대로 한다.

i2c=I2C(0,scl=Pin(1),sda=Pin(0),freq=200000)

그 다음은 OLED의 사용과 해상도를 선언해 준다.

WIDTH =128

HEIGHT= 64 (128×32 모듈은 32로 표기)

oled = SSD1306_I2C(WIDTH, HEIGHT, i2c)

그런데, OLED의 경우에는 LCD에서 사용을 선언할 때 I2C 주소를 지정해 두었던 것과 달리 I2C 주소를 지정하지 않는다. 이는 ssd1306.py 라이브러리 내에서 OLED 모듈의 I2C 주소를 다음과 같이 Ox3C로 고정해 두었기 때문이다.

그 다음은 실제 출력 명령들을 이용하여 출력하면 된다. 문장이나 변수를 출력할 때는 oled.text(변수, 수평위치, 수직위치) 방식으로 표시하면 된다. 화면상 위치번호는 왼쪽 최상단이, 0,0에 해당되고, 오른쪽 가장 아래가 127.63에 해당된다.

그런데, 한 가지 기억할 것은, OLED의 경우, 출력 명령 그 자체로 화면에 표시되는 게 아니라, 표시한 것이 화면에 나타나도록 하려면 show() 명령을 바로 붙여서 사용해야 한다는 점이다.

즉, “hello”라는 글자를 화면 왼쪽 최상단에 표시하려면 다음과 같이 두 개의 명령어를 사용해야 한다.

oled.text(“Hello!”, 0, 0)

oled.show()

5. 주요 명령어

사용이 가능한 주요 명령어들은 다음과 같다.

화면 지우기는 oled.fill( ) 명령어를 사용한다.

oled.fill(0)를 사용하면 어두운 상태로 화면이 지워지며, oled.fill(1)은 반전 상태로 화면을 지운다.

화면 출력은 oled.text(“Hello!”, 시작가로위치, 시작세로위치)를 이용한다.

글자들은 통상의 경우 8X8의 해상도를 가지는 크기로 표기된다. (가로 16자 x 세로 8자 출력)

화면상 클자의 Contrast는 oled.contrast(1~9) 명령으로 조절할 수 있는데, 개인적으로는 3~5 정도가 읽기에 좋았다.

화면을 반전시키는 명령어는 oled.invert( )로, 인자 값이 1이면 화면이 반전되며, 0 이면 반전이 취소된다.

화면 자체를 켜거나 끄는 명령어는 oled.poweroff( )와 oled.poweron( )를 인자 없이 사용하면 된다.

위의 명령어들의 결과를 실제 화면에 나타내려면 oled.show( ) 를 추가해 주어야 한다. (On/Off 제외)

그리고, OLED에서는 선을 그리는 명령어들도 있다.

먼저 수평방향으로 선을 긋는 명령인 hline과 수직 방향으로 선을 긋는 vline 명령이 있고, 특정 위치에서 시작해서, 임의의 방향으로 선을 연결해 주는 line 명령이 있다. 그리고 사각형선을 그려주는 rect 명령이 있다.

(물론 결과를 나타내려면 show( ) 명령이 동반되어야 한다.)

oled.hline(시작수평위치, 시작수직위치, 수평이동수,1)

oled.vline(시작수평위치, 시작수직위치, 수직이동수,1)

oled.line(시작수평위치, 시작수직위치, 수평이동수, 수직이동수,1)

oled.rect(시작수평위치, 시작수직위치, 수평이동수, 수직이동수,1)

(명령속의 마지막 인자 1은 실선을 의미한다. 0으로 설정하면 선이 보이지 않는다.)

그런데 여기서 기억할 중요한 사항이 있다. 이렇게 선 그리기 명령에서는 명령이 시작되는 점의 위치는 절대 위치이지만, 그 뒤에 나오는 것은 절대 위치가 아니라 상대 위치라는 점이다.

또한 해상도 영역 밖의 위치에 해당되는 위치를 지정해서 그리기 명령을 지정하면, 해상도 영역 밖을 표시해 주지는 못하지만, 마치 해상도 영역 밖의 공간도 실제 하는 것처럼 그리기 동작이 이루어진다는 점이다.

다음 예제 사진들을 참고하면 OLED 모듈의 이러한 특성을 이해하는 데 도움이 될 듯하다.

6. 예제

위에 소개한 내용을 토대로, 다음과 같은 에제 Code를 만들어 동작시켜보았다.

from machine import Pin, I2C
from ssd1306 import SSD1306_I2C
import utime

WIDTH =128
HEIGHT= 64
i2c=I2C(0,scl=Pin(1),sda=Pin(0),freq=200000)
oled = SSD1306_I2C(WIDTH,HEIGHT,i2c)
oled.init_display()
while True:
    oled.fill(0)
    oled.text("Hello!", 0, 0)
    oled.show()
    utime.sleep(2)   
       
    oled.fill(0)
    oled.text("OLED Clearing", 0, 0)
    oled.show()
    utime.sleep(2)
for k in range(9):
        oled.fill(0)
        oled.text("< Normal mode >",0,0)
        oled.text("Contrast Setting",0,16)
        oled.text(str(k),0,32)
        oled.contrast(k)
        oled.show()
        utime.sleep(0.5)


    oled.invert(1)
for k in range(9):
        oled.fill(0)
        oled.text("< Invert mode >",0,0)
        oled.text("Contrast Setting",0,16)
        oled.text(str(k),0,32)
        oled.contrast(k)
        oled.show()
        utime.sleep(0.5)
    oled.invert(0)


    oled.fill(0)
    oled.text("OLED Turning off", 0, 0)
    oled.show()
    utime.sleep(2)
    oled.poweroff()
    utime.sleep(2)
    oled.poweron()
    oled.fill(0)
    oled.text("OLED Turned on", 0, 0)
    oled.show()
    utime.sleep(2)
           
    oled.fill(0)
    oled.text("123456789012345678",0,0)
    oled.text("012345678901234567",0,8)
    oled.text("901234567890123456",0,16)
    oled.text("890123456789012345",0,24)
    oled.text("789012345678901234",0,32)
    oled.text("678901234567890123",0,40)
    oled.text("567890123456789012",0,48)
    oled.text("456789012345678901",0,56)
    oled.text("345678909876543210",0,64)
    oled.show()
    utime.sleep(3)
for k in range(6):
        oled.fill(0)    
        oled.hline(0,k*10,126,1)
        oled.show()
        utime.sleep(0.2)
for k in range(12):
        oled.fill(0)    
        oled.vline(k*10,0, 64,1)
        oled.show()
        utime.sleep(0.2)

    oled.fill(0)    
    oled.line(10,10,120,64,1)
    oled.line(120,10,10,64,1)
    oled.show()
    utime.sleep(2)

    oled.fill(0)    
    oled.rect(0,0,128,64,1)
    oled.show()
    utime.sleep(2)

동작 결과는 다음과 같다.

한편 해상도가 128×32인 모듈도 동일하게 연결하고, 위의 Code에서 해당도만 조절하여 작동시켜 보았으며, 동작 결과는 다음과 같다.