1. Display 필요성
라즈베리파이 피코보드를 사용하다 보면, 여러 가지 정보를 출력할 필요가 있기도 하다.
PC와 연결하여 사용할 때는, 다음과 같이 print 명령을 이용할 수 있고, 그 결과로 다음과 같이 Thonny IDE의 아랫부분에 위치한 Shell 부분에 출력값이 표시된다.(아래는 내장 온도센서를 이용한 온도 출력 사례이다.)
그런데, 피코 보드는 PC와 별개로 독립적으로 구성된 회로를 자동으로 제어하는 것을 사용목적으로 하기 때문에, PC와 연결되지 않은 채 단독으로 사용할 경우가 만하. 이러한 경우에는 PC 화면으로 출력이 불가능하므로, 무엇인가 정보를 확인하거나, 사용자에게 정보를 전달하려면 PC 화면과는 전혀 별개의 정보를 표시할 수 있는 방법이 필요하게 된다.
이럴 때 사용할 수 있는 가장 간편하고, 저렴한 방법이 다음과 같은 소형 액정 LCD나 OLED 형태의 모듈형 디스플레이 장치이다. 이들을 사용하면 라즈베리파이 피코 보드를 독립적으로 사용하면서 필요한 정보 표시 need를 어느 정도는 해결해 줄 수 있다.
특히 다음 형태의 액정은 16×2 형태로 총 32자를 동시에 표시할 수 있는데, 과거 아두이노 시절부터 널리 사용되어 오던 장치로 익숙하기도 하고, 특히 개당 수천 원 정도로 저렴하기도 해서, 사용에 부담이 없으면서도 간단한 정보 출력 문제를 해결해 줄 수 있다. 반면 OLED의 경우 좀 더 작은 글자 표시가 가능하고 색상 발현 등의 장점이 있기는 하나, 아직까지 가격이 비싸고 대체로 소형인 것으로 알려져 있다.
2. I2C와 SPI 기초지식
이러한 액정과 같은 주변기기를 사용하는 과정에서, 라즈베리파이 피코 보드와 액정과 같은 주변기기 간 정보를 전달하는 통신 방식에 대해 알아 둘 필요가 있다. 부품을 구입하거나 할 때 이를 구분해서 구입해야 하기 때문이다.
주로 많이 사용되고, 실제로 알 필요가 있는 것은 I2C (Inter-Integrated Circuit) 와 SPI (Serial Peripheral Interface)이다.
I2C (Inter-Integrated Circuit)는 필립스에서 1980년대에 개발한 것으로 알려져 있는 직렬 통신 버스(=회로망 및 정보교환체계) 방식인데, 전원 선을 제외하고는 단 2개의 회선만을 이용하여 통신하는 방식이다. 이렇게 연결할 수 있는 장치의 종류들을 매우 다양하며, 하나의 I2C 버스에 여러 개의 주변장치를 동시에 연결할 수 있는데, 최대로 연결될 수 있는 장치의 수는 해당 시스템에서 사용하는 addressing system 사용에 따라 달라진다. 또한 I2C는 단지 2선만이 사용되므로, 이런 장치들은 제작비용이 낮고, 전력 소모도 작으며, 시스템이 동작 중일 때도 장치들을 I2C 버스에 추가하거나 제거하는 것이 가능한 것으로 알려져 있다.
라즈베리파이 피코 보드에 연결하려는 액정의 경우 I2C 단자는 다음과 같다. 총 4개의 선이 연결되나, 이중 전원선인 Vcc와 GND를 제외하면, Data Channel을 위한 SDA 선과, Clock 기능을 하는 SCL의 2선으로 통신이 이루어진다.
참고로, 라즈베리파이 피코 보드에는 총 2개의 I2C bus가 있으며(I2C0과 I2C1), 이들 중 모두를 사용 가능하며, 각각의 I2C에 최대 128개 장치를 연결할 수 있는데, 각 장치를 사용할 때 해당 장치의 I2C Bus 내 주소를 기재해야 하며, 만일 모르는 경우에는ㄴ 프로그램 내에서 i2c.scan( ) 명령어로 확인할 수 있다.
I2C 버스에 SDA와 SCL 핀을 연결할 때는 동일한 I2C Bus에 속한 핀을 사용하여야 한다.
반면, SPI (Serial Peripheral Interface)는 다음과 같이 총 6개(4+2개)의 배선으로 연결되는 방식인데, 나름 과거에 주로 사용되던 병렬형 통신 방식보다 선의 수가 대폭 적어서 상대적으로 단순하기는 하나, 노이즈에 대한 논란이 있고, 이론적으로는 무제한의 장치를 SPI 버스에 연결 가능하다고 하나, 각각의 장치별로 개별적인 CS Line이 필요해서 현실적으로 동시에 접속시킬 수 있는 장치의 수가 제한(피코는 물리적으로 최대 23개 가능) 되는 불리한 점도 있다.
SCK : Clock
SI : SIgnal Input(RX)
SO : Signal Output(TX)
CS ; Chip Select – 여러 SPI를 하나의 SPI 버스에 연결하는 데 사용
Vcc : 전원
GND : Ground
만일 SPI를 이용해 액정을 라즈베리 피코 보드와 연결하는 경우에는 다음과 같은 형태가 된다.
액정과 같은 주변장치 중에는 I2C나 SPI를 모두 지원하는 경우도 있고, I2C나 SPI 중 한 가지 만을 지원하는 경우도 있다. 만일 원하는 장치가 I2C를 지원한다면, 가급적 I2C를 지원하는 장치를 사용할 것이 배선도 간결해지고, 프로그램도 조금 더 간단해져서 I2C를 사용하는 장치로 선택할 것을 권한다.
3. 1602A LCD
라즈베리파이 재단의 공식 튜토리얼에는 액정 연결에 대한 내용을 소개하면서, I2C와 SPI를 모두 사용할 수 있는 미국산인 sparkFun 사의 serLCD라는 제품을 소개하고 있다.
이 제품은 디스플레이 내부의 컨트롤러 칩으로 ATmega328P AVR microcontroller를 사용하는데, 통신방식으로는 I2C와 SPI, 그리고 Serial을 모두 지원한다. 또한 소프트웨어적으로 I2C의 주소와, 화면의 Contrast를 변경할 수 있는 등의 기능이 있다. 특히, open-source firmware를 사용하기에 관련 정보도 많은 것으로 알려져 있다. 피코 보드에서는 i2c.writeto(장치 주소, out_string) 명령으로 곧바로 출력이 가능하여 사용도 간편한 편인데, 국내에서는 널리 사용되지 않아 구입하기 어렵고, 해외구매 형태로 구입해야 하는 경우에도 직구 시 개당 약 3만 원 정도(21.5$)로 고가이고, 이를 국내 업체를 통해 구매 대행하는 경우에는 업체에 따라 개당 5-10만 원에 이를 정도로 상대적으로 고가에 판매되고 있다. 해외 직구하려는 경우 다음을 참조하면 된다.
https://www.sparkfun.com/products/16397
반면 국내에서는 과거 아두이노 보드 시절부터 널리 사용되어 오던 1602A라는 액정이 있다.
이 제품은 디스플레이 내부의 컨트롤러칩으로 HD44780 이란 칩을 사용하는 것으로 알려져 있다.
(참고 – 위의 sparkfun사에서도 serLCD v.2.5라는 제품도 함께 판매하는데, 이 제품 역시 HD44780 컨트롤러를 사용한다.)
또한 이 제품은 기본적으로 SPI 단자를 지원하지만
다음과 같이 Adpter 보드가 붙은 i2C형 제품도 많이 공급되고 있다.
특히 이 제품은 국내에서도 판매되며, 불과 3000-4000원 정도에도 구입이 가능하다. (SPI형 제품은 더 저렴하다.) (주의 : 해외 직구 시는 가격이 거의 일정하나, 국내에서는 업체별로 판매가가 3000원~20000원선으로 매우 다양하므로, 국내에서 구입 시는 주의할 필요가 있다.)
내가 찾아본 국내 판매처 중 현재(20203.8) 기준으로 가장 저렴한 판매처는 다음이다. 그러나 각자의 구입 시는 변동될 수도 있으므로, 가격비교를 해보길 바란다.
http://itempage3.auction.co.kr/DetailView.aspx?ItemNo=B201211635&frm3=V2
4. 1602A LCD 사용을 위한 Library 추가
그런데, 이 1602A는 액정 사용에 필요한 일반적 기능들은 모두 제공하지만, HD44780 계열 칩을 사용하기 때문에 위의 serLCD와 다르게 사용해야 한다.
먼저 HD44780 호환 컨트롤러 칩 사용을 위한 다음 2개의 library를 피코 보드에 저장하고, 프로그램에서도 이들 라이브러리 사용을 선언해 주어야 한다. 이들 Library는 다음과 같이 MIT에서 개발하여 Github에 공개한 opensource로 개발자 정보만 기재하면 자유로이 사용이 가능하다.
Library를 피코보드에 추가하는 방법은 다음 링크를 이용해 Github에서 다음 2개의 파일을 다운로드/열기해서 해당 내용을 그대로 복사하여 Thonny IDE에 붙여 넣은 후, 동일한 이름으로 저장하되, 저장 시의 저장 장소 지정을 사용하려는 피코 보드로 지정해 주면 된다.
https://github.com/T-622/RPI-PICO-I2C-LCD/blob/main/pico_i2c_lcd.py
https://github.com/T-622/RPI-PICO-I2C-LCD/blob/main/lcd_api.py
이렇게 해주면 이제 1602A 액정(또는 HD44780호환 칩을 사용하는 액정 LCD들)을 자유롭게 사용할 수 있게 준비가 된 것이다.
5. LCD 사용을 위한 코딩 방법
이렇게 피코 보드에 위에 언급한 2개의 Library 파일을 저장해 둔 상태에서 액정 사용을 위해 코딩하는 방법은 다음과 같다.
먼저, Library 사용을 선언해 준다.
import machine
from lcd_api import LcdApi –> 피코 보드에 저장해둔 Library
from pico_i2c_lcd import I2cLcd –> 피코 보드에 저장해둔 Library
그리고, I2C 버스용으로 사용할 2개의 핀을 선언해 주고, 이를 토대로 i2c 버스 사용을 선언해 준다.
이중 마지막 줄의 괄호 내에 있는 첫 값인 0은 I2C Bus 2개 중 첫 번째인 I2C0을 사용함을 지정하는 것이다.
따라서 실제 SDA와 SCL 용으로 사용하는 핀들은 i2C0에 해당되는 핀을 피운 맵을 잘 보고 골라서 사용해야 한다.
sda=machine.Pin(0)
scl=machine.Pin(1)
i2c=machine.I2C(0,sda=sda, scl=scl, freq=400000)
다음에는 1602A 액정의 크기와 주소를 선언해 준다.
I2C_ADDR = 0x27 –> 미리 확인해 둔 주소로 모르는 경우 i2c.scan( )으로 확인 가능
totalRows = 2 –> 2개의 행을 가짐을 선언
totalColumns = 16 –> 가로로 16자씩으로 구성됨을 선언
lcd = I2cLcd(i2c, I2C_ADDR, totalRows, totalColumns)
이후, 다양한 명령어를 이용하여 출력한다. 사용이 가능한 일반 명령은 다음과 같은데, 이름에서 그 의미를 쉽게 알 수 있다. 참고로 이들은 피코 보드에 추가해 두었던 lcd.api 내에 선언되어 있다.
lcd.clear()
lcd.show_cursor()
lcd.hide_cursor()
lcd.blink_cursor_on()
lcd.blink_cursor_off()
lcd.display_on()
lcd.display_off()
lcd.backlight_off()
lcd.backlight_on()
lcd.move_to(행번호, 열 번호)
lcd.putchar(“글자”)
lcd.putstr(“문자열”)
6. LCD 사용 예제
위에서 소개한 내용을 토대로 액정 디스플레이의 다양한 기능을 보여주는 간단한 예제 Code를 작성했다.
import machine
import utime
from lcd_api import LcdApi
from pico_i2c_lcd import I2cLcd
sda=machine.Pin(0)
scl=machine.Pin(1)
i2c=machine.I2C(0,sda=sda, scl=scl, freq=400000)
I2C_ADDR = 0x27
totalRows = 2
totalColumns = 16
lcd = I2cLcd(i2c, I2C_ADDR, totalRows, totalColumns)
lcd.putstr("Hello World!")
lcd.move_to(0,1)
lcd.putstr("I2C address"+str(i2c.scan()))
utime.sleep(1)
lcd.clear()
lcd.putstr("Let me show functions")
utime.sleep(1)
while True:
for i in range(9):
lcd.clear()
if i == 0:
print("cursor is on")
lcd.show_cursor()
lcd.putstr("Cursor is on")
if i == 1:
print("cursor is off")
lcd.hide_cursor()
lcd.putstr("Cursor is off")
if i == 2:
print("Turning blink cursor on")
lcd.blink_cursor_on()
lcd.putstr("Cursor blinking - ON")
if i == 3:
print("Turning blink cursor off")
lcd.blink_cursor_off()
lcd.putstr("Cursor blinking - OFF")
if i == 4:
print("Turning backlight off")
lcd.putstr("Next, backlight - off")
utime.sleep(1)
lcd.backlight_off()
lcd.clear()
lcd.putstr("Backlight off")
if i == 5:
print("Turning backlight on")
lcd.backlight_on()
lcd.putstr("Backlight on")
if i == 6:
lcd.putstr("Next, display - turn off.")
utime.sleep(1)
print("Turning display off")
lcd.display_off()
lcd.clear()
lcd.putstr("Display off")
if i == 7:
print("Turning display on")
lcd.display_on()
lcd.putstr("Display on")
if i == 8:
print("Move Cursor and Put a Character")
for j in range(16):
for k in range(2):
lcd.move_to(j,k)
lcd.putchar("a")
utime.sleep(0.3)
utime.sleep(1)
실행 결과는 다음과 같다.
액정에 글자를 보여주고, 위에 소개한 명령들을 차례대로 보여준다.

