아두이노 프로젝트를 진행하다 보면, 기기의 현재 상태나 사용 중인 데이터등을 눈으로 확인해야 하는 경우가 자주 발생한다. 시리얼 모니터를 통해 아두이노와 연결된 PC에서 확인하는 것이 가장 간단한 방법이겠지만 PC와 연결되어있지 않는 경우라면 시각적 피드백을 해줄 다른 대안이 필요할 것이다.
그중, I2C LCD 모듈을 활용하여 화면을 출력하는 간단한 예제들을 적용해보고 스위치를 통해 LCD 화면을 제어하는 코드를 작성해 보았다.
1. 회로 구성
내가 사용한 모듈은 16x2 I2C LCD 모듈이다.
LCD 모듈에는 12개의 핀이 내장되어있어 이들 각각을 배선하여 컨트롤해야 하지만 I2C 컨버터가 포함된 모듈에서는 단 4개의 핀으로 LCD를 컨트롤할 수 있어 간편하게 사용이 가능하다.
아두이노에서 I2C 통신을 지원하는 단자는 A4(SDA)와 A5(SCL)이다. 따라서 I2C 통신을 통해 LCD를 제어하기위해 아래와 같이 각 단자를 LCD모듈에 연결해 주었다.
추가적으로 스위치를 통해 LCD 화면을 제어하기 위해, 스위치를 아두이노 D5단자에 연결해주었다.
2. 코드 작성
I2C LCD모듈을 사용하기 위해 Frank de Brabander의 LiquidCrystal I2C 라이브러리를 사용했다. 해당 라이브러리는 아두이노 IDE의 라이브러리 매니저에서 찾을 수 있으며, 아래 GitHub 링크에서도 다운로드 가능하다.
(링크 : https://github.com/johnrickman/LiquidCrystal_I2C)
16x2 LCD 모듈은 아래 그림과 같이 16x2개의 화면에 데이터를 표시할 수 있다.
LiquidCrystal I2C 라이브러리에서는 이들 각각을 (열, 행)과 같은 형태의 좌표로 다뤄 데이터를 출력하는 방식이다.
LiquidCrystal I2C라이브러리의 함수들과 각각의 기능들을 아래 표에 정리해놨다.
이제 간단한 예제를 통해 LCD에 글자를 출력해보자.
아래 코드는 Hello, World!라는 글자를 LCD의 두 줄에 출력되도록 작성한 코드이다.
#include <LiquidCrystal_I2C.h> //LiquidCrysta_I2C 라이브러리 포함
LiquidCrystal_I2C lcd(0x27, 16, 2); // I2C lcd 주소값 확인 , 16x2 LCD
void setup() {
lcd.init(); // lcd 초기화
lcd.backlight(); // lcd 백라이트 on
lcd.setCursor(5, 0); // 커서를 5,0 위치에 이동
lcd.print("Hello,"); // 5,1위치 부터 "Hello," 글자 출력
lcd.setCursor(5, 1); // 커서를 5,1 위치에 이동
lcd.print("World!"); // 5,1위치 부터 "World!" 출력
}
void loop() {
}
lcd.setCursor를 통해 글자를 작성할 좌표를 지정한 이후, lcd.print를 통해 출력할 글자를 적으면 아래와 같이 LCD에 해당 글자가 출력되는 형태이다.
만약, LCD에 화면이 정상적으로 출력되지 않는다면, 다음 두 가지 원인을 의심해 볼 수 있다.
1. LCD 주소값 확인
LCD모듈에는 고유한 주소값이 사용된다. 이 주소값에는 일반적으로 "0x27" 또는 "0x3F"가 사용된다.
만약 LiquidCrystal_I2C lcd를 통해 객체를 생성할 때, 0x27을 이용해서 출력이 안될 경우 0x3F를 이용해 보자.
2. 화면 선명도 조절
I2C 컨버터 모듈에 가변저항을 통해 LCD 화면의 선명도를 조절할 수 있다. 정상적으로 코드를 업로드해도 화면에 흰색 네모만 출력될 경우 가변저항을 드라이버로 돌리며 선명도를 조절해 보자.
3. 스위치로 LCD 화면 조작 하기
LCD에 출력할 데이터는 문자열뿐만 아니라 아두이노 내부에서 사용되고 있는 변수들도 출력이 가능하다.
아래 코드는 스위치를 누를 때마다 count라는 변수에 숫자를 1씩 추가하여 해당 변수를 LCD 화면에 출력하는 코드이다.
#include <LiquidCrystal_I2C.h> //LiquidCrysta_I2C 라이브러리 포함
LiquidCrystal_I2C lcd(0x27, 16, 2); // I2C lcd 주소값 확인 , 16x2 LCD
const int sw = 5; // D5핀을 스위치로 사용
int count=0; // count 변수 선언 및 초기화
bool lastSwState = LOW; // 이전 스위치 상태를 저장할 변수, 초기값은 LOW
void setup() {
pinMode(sw, INPUT); // 스위치 핀을 인풋으로 설정
lcd.init(); // lcd 초기화
lcd.backlight(); // lcd 백라이트 on
lcd.setCursor(5, 0);
lcd.print("Count:");
lcd.setCursor(5, 1);
lcd.print(count); // count 값을 LCD에 출력
}
void loop() {
bool currentSwState = digitalRead(sw); // 현재 스위치 상태 읽기
if (lastSwState == HIGH && currentSwState == LOW) // 스위치를 눌렀다 땔 경우
{
count++; // count 값에 1을 더함
lcd.clear(); // LCD 화면 초기화
lcd.setCursor(5, 0);
lcd.print("Count:");
lcd.setCursor(5, 1);
lcd.print(count); // count 값을 LCD에 출력
}
lastSwState = currentSwState; // 현재 상태를 이전 상태로 업데이트
delay(100); // 디바운싱을 위한 100ms 대기
}
코드가 작동하는 방식은 다음과 같다.
먼저, lastSwState와 currentSwState 변수를 통해 스위치가 눌렀다 떼어지는 순간을 감지하여 if문이 동작한다.
if문 안에서는 count 변수에 숫자를 1 더하고 해당숫자를 LCD에 출력한다. LCD에 새로운 숫자를 출력하기 전에는 lcd.clear를 통해 화면을 초기화해주었다.
마지막으로 100ms을 대기하여 스위치 바운싱을 방지해주었다.
코드를 업로드하여 실행시킨 모습이다. 스위치를 누를 때마다 숫자가 한 개씩 올라가는 걸 확인할 수 있다.
이렇게 간단한 예제들을 통해 아두이노로 LCD를 제어해 보았다.
앞으로 다양한 프로젝트에서 완성된 형태의 기기를 만들 때, LCD를 통해 정보를 직관적으로 표시할 수 있을 것이다.
다음 포스팅에서는 무게 센서인 로드셀을 통해 LCD 화면에 무게를 표시하는 코드를 작성해 볼 예정이다.