091
[C/C++] LCD에 원하는 글자를 출력하기 본문
마이크로컨트롤러와 주변 장치를 연결하는 대표적인 통신 프로토콜에는 UART, I2C, SPI 등이 있음, 저번 글에서는 URAT에 관한 내용을 다뤘고 이번 글에서는 I2C 프로토콜을 이용하여 LCD에 출력하는 코드에 대해 설명할 예정 !
01. I2C(Inter-Intergrated Circuit) & LCD(Liqiuid Crystal Display)
(1) I2C : 두 개의 선(SDA, SCL)만으로 여러 개의 장치를 연결할 수 있는 직렬 통신 프로토콜로, SDA와 SCL은 각각 데이터 전송, 클록 신호 전송의 기능의 역할을 함, ESP32에서 Wire 라이브러리를 사용하여 쉽게 구현 가능
(2) LCD : 액정 디스플레이로, 전로 장치에서 글자, 숫자, 심볼등을 표시하는 데 사용됨. 1602 LCD는 16*2 디스플레이로 16개의 문자를 2줄로 출력 가능한 LCD를 말함, 기본 주소는 0*27, 0*3F이고, LiquidCrystal_I2C 라이브러리로 쉽게 제어 가능함
-> ESP32와 I2C LCD 연결
* ESP32에서 저 초록색 박스 안에 하얀 연결 선까지 연결하는 점프와이어의 색상은 자유롭게 해도 좋으나 필자는 알아보기 쉽게 하기 위해 색상을 맞춰줌 *
- VCC(빨간색), GND(검정색), GPIO21(하얀색, SDA), GPIO22(노란색, SCL)을 연결해주면 됨.
02. LCD에 원하는 글자를 출력하기
- LCD1602_Display.h
#ifndef LCD1602_DISPLAY_H //파일이 여러 번 포함되는 걸 방지하는 헤더 가드 코드
#define LCD1602_DISPLAY_H
#include <Wire.h>
#include <LiquidCrystal_I2C.h> // lcd와 같은 객체가 들어있는 객체
// **LCD1602_Display Class for 16x2 LCD Display**
class LCD1602_Display {
public:
LCD1602_Display(uint8_t lcd_addr = 0x27, uint8_t cols = 16, uint8_t rows = 2);
void init();
void displayText(String text, int col, int row);
void clearScreen();
private:
LiquidCrystal_I2C lcd; // LCD 객체를 선언
};
#endif
-> LCD 제어를 위한 클래스인 LCD1602_Display를 클래스를 선언만 하고, cpp(아래파일)에서 구현할 예정임.
- LCD1602_Display.cpp
#include "LCD1602_Display.h"
// 클래스의 생성자
LCD1602_Display::LCD1602_Display(uint8_t lcd_addr, uint8_t cols, uint8_t rows)
: lcd(lcd_addr, cols, rows) {}
// LCD 초기화 함수
void LCD1602_Display::init() {
lcd.init(); // lcd 초기화
lcd.backlight(); // 백라이트 켜기
}
// 특정 위치에 텍스트 출력함수
void LCD1602_Display::displayText(String text, int col, int row) {
lcd.setCursor(col, row); // 커서 위치 설정
lcd.print(text); // 텍스트 출력
}
// LCD 화면 지우기
void LCD1602_Display::clearScreen() {
lcd.clear();
}
-> 범위 지정 연산자(::)를 이용하여 cpp에서 구현해줌(추상 클래스가 아니더라도 이런 식으로 객체 지향 프로그래밍을 위해 선언과 구현파일을 나누는 경우가 많음)
- CH5-1.ino
#include <Wire.h> //I2C 통신을 위한 라이브러리 : 명시적으로 포함시켜줘야함
#include "LCD1602_Display.h" //LCD1602 디스플레이 클래스를 위한 헤더 파일
LCD1602_Display lcd(0x27, 16, 2); //주소가 0x27인 16*2 LCD 객체 생성
bool isLocalControl = false;
void setup() {
Serial.begin(115200); // 시리얼 통신 초기화 (PC<=>ESP32)
Wire.begin(21, 22); // I2C 통신 초기화 (SDA=21, SCL=22)
lcd.init(); // LCD 초기화
}
void loop() {
if(Serial.available()){
String command = Serial.readString();
if(command == "V?"){
int adcValue = analogRead(34);
float voltage = (adcValue / 4095.0) * 3.3;
Serial.print("Voltage: ");
Serial.println(voltage, 2); // 소수점 이하 2자리까지 출력하도록 지정
isLocalControl = true;
}
}
if (isLocalControl) {
lcd.clearScreen();
lcd.displayText("Local Control", 0, 0);
lcd.displayText("Voltage: " + String(voltage, 2) + "V", 0, 1);
} else {
lcd.displayText("Remote Control", 0, 0); // 리모트 컨트롤일 때 LCD에 출력
}
delay(1000);
isLocalControl = false;
}
-> LCD1602_Display.h에 포함된 Wire.h이 있음에도 명시적으로 .ino파일에 포함되지 않으면 Wire 라이브러리 함수들이 정의되지 않아서 오류가 발생하므로 별도로 포함시켜 줘야함
-> 기본을 리모트 컨트롤 상태로 두고, V?와 같은 로컬 제어 상태일 때 true값으로 만들어줌
'Programming Language > C&C++' 카테고리의 다른 글
[C/C++] ESP32에서 3가지 작업(LCD,Switch,UART) 반복처리하기 (0) | 2025.04.09 |
---|---|
[C/C++] ESP32에서 EEPROM 저장하기 (0) | 2025.04.08 |
[C/C++] ESP32와 Potentiometer를 이용하여 모드 설정 후 변경하기 (4) | 2025.03.15 |
[C/C++] ESP32와 Potentiometer를 이용하여 LED의 밝기 조절하기 (2) | 2025.03.07 |
[C/C++] 기본적인 전기/전자 기초 개념 정리 (2) | 2025.03.07 |