ESP32에서 LVGL을 사용하는 단계별 가이드
LVGL(Light and Versatile Graphics Library)은 임베디드 시스템에 매력적이고 상호작용성이 뛰어난 사용자 인터페이스를 제공하도록 설계된 오픈 소스 임베디드 그래픽 사용자 인터페이스(GUI) 라이브러리입니다. LVGL GUI 라이브러리를 사용하면 개발자는 ESP32에서 인상적인 그래픽 인터페이스를 쉽게 제작하여 사용자 경험을 향상시킬 수 있습니다. ESP32에서 LVGL GUI 라이브러리를 사용하는 방법에 대한 이 튜토리얼은 "Arduino IDE에서 ESP32를 사용하여 LCD 디스플레이 제어"를 기반으로 합니다. LCD 화면을 사용하기 전에 TFT_eSPI 라이브러리가 3.5인치 LCD 화면을 제대로 구동하는지 확인하는 것이 좋습니다.
LVGL 및 lv_examples 라이브러리 설치
- Arduino IDE를 엽니다.
- "도구" 메뉴로 이동하여 "라이브러리 관리..."를 선택합니다.
- 라이브러리 관리자의 검색 상자에 "lvgl"을 입력하고 Enter 키를 누릅니다.
- 라이브러리 관리자에 사용 가능한 LVGL 라이브러리가 표시됩니다. "lvgl" 라이브러리를 찾아 오른쪽의 "설치" 버튼을 클릭하세요. 설치가 완료될 때까지 기다리세요.
- 같은 과정을 반복하여 "lv_examples"를 검색하여 설치하세요.
LVGL 구성
- Arduino IDE에서 프로젝트를 엽니다.
- "스케치" 메뉴 -> "스케치 폴더 표시"로 이동하여 프로젝트가 있는 폴더를 엽니다.
- 프로젝트 폴더의 상위 디렉터리로 이동하여 "libraries" 폴더를 찾아 해당 폴더로 이동합니다.
- "lvgl" 폴더로 이동하여 "lv_conf_template.h" 파일을 찾아 복사합니다.
- 상위 디렉터리, 즉 "libraries" 폴더로 돌아갑니다.
- "libraries" 폴더에 복사한 "lv_conf_template.h" 파일을 붙여넣고 이름을 "lv_conf.h"로 바꿉니다.
lv_conf.h 파일을 다음과 같이 수정합니다.
10 line 1로 설정
#if 1 /*Set it to "1" to enable content*/
23번째 줄에 모니터 크기를 입력합니다.
#define LV_HOR_RES_MAX (480)
#define LV_VER_RES_MAX (320)
303번째 줄에서 LV_TICK_CUSTOM을 1로 설정합니다.
#define LV_TICK_CUSTOM 1
384번째 줄에서 나열된 모든 글꼴을 1로 설정합니다.
#define LV_FONT_MONTSERRAT_8 1
#define LV_FONT_MONTSERRAT_10 1
#define LV_FONT_MONTSERRAT_12 1
#define LV_FONT_MONTSERRAT_14 1
#define LV_FONT_MONTSERRAT_16 1
#define LV_FONT_MONTSERRAT_18 1
#define LV_FONT_MONTSERRAT_20 1
#define LV_FONT_MONTSERRAT_22 1
#define LV_FONT_MONTSERRAT_24 1
#define LV_FONT_MONTSERRAT_26 1
#define LV_FONT_MONTSERRAT_28 1
#define LV_FONT_MONTSERRAT_30 1
#define LV_FONT_MONTSERRAT_32 1
#define LV_FONT_MONTSERRAT_34 1
#define LV_FONT_MONTSERRAT_36 1
#define LV_FONT_MONTSERRAT_38 1
#define LV_FONT_MONTSERRAT_40 1
#define LV_FONT_MONTSERRAT_42 1
#define LV_FONT_MONTSERRAT_44 1
#define LV_FONT_MONTSERRAT_46 1
#define LV_FONT_MONTSERRAT_48 1
lv_examples 구성
LVGL 구성과 마찬가지로 "lv_examples" 폴더를 찾아 복사하여 "libraries" 폴더에 붙여넣고 이름을 "lv_ex_conf.h"로 바꿉니다.
lv_ex_conf.h 파일을 다음과 같이 수정합니다.
라인 10에서 1로 설정
#if 1 /*Set it to "1" to enable the content*/
여기서는 성능 테스트에 사용되는 benchmark와 music을 활성화하고, 음악 플레이어인 music을 활성화하려면 다음 값을 1로 설정합니다.
#define LV_USE_DEMO_BENCHMARK 1
#define LV_USE_DEMO_MUSIC 1
메인 파일 작성
다음 내용이 포함된 main.ino 파일을 엽니다.
#include <Arduino.h>
//#include "./includes/oled.h"
#include <lvgl.h>
#include <TFT_eSPI.h>
#include <lv_examples.h>
// extern Adafruit_SH1106G display;
TFT_eSPI tft = TFT_eSPI(); /* TFT instance */
static lv_disp_buf_t disp_buf;
static lv_color_t buf[LV_HOR_RES_MAX * 10];
#if USE_LV_LOG != 0
/* Serial debugging */
void my_print(lv_log_level_t level, const char *file, uint32_t line, const char *dsc)
{
Serial.printf("%s@%d->%s\r\n", file, line, dsc);
Serial.flush();
}
#endif
/* Display flushing */
void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p)
{
uint32_t w = (area->x2 - area->x1 + 1);
uint32_t h = (area->y2 - area->y1 + 1);
tft.startWrite();
tft.setAddrWindow(area->x1, area->y1, w, h);
tft.pushColors(&color_p->full, w * h, true);
tft.endWrite();
lv_disp_flush_ready(disp);
}
/*Read the touchpad*/
bool my_touchpad_read(lv_indev_drv_t *indev_driver, lv_indev_data_t *data)
{
uint16_t touchX, touchY;
bool touched = tft.getTouch(&touchX, &touchY, 600);
if (!touched)
{
data->state = LV_INDEV_STATE_REL;
}
else
{
data->state = LV_INDEV_STATE_PR;
/*Set the coordinates*/
data->point.x = touchX;
data->point.y = touchY;
Serial.print("Data x");
Serial.println(touchX);
Serial.print("Data y");
Serial.println(touchY);
}
return false; /*Return `false` because we are not buffering and no more data to read*/
}
void setup()
{
// put your setup code here, to run once:
// Serial.begin(9600);
// //testdrawcircle();
// display.begin(i2c_Address,true);
// testdrawbitmap(logo16_glcd_bmp, LOGO16_GLCD_HEIGHT, LOGO16_GLCD_WIDTH);
Serial.begin(115200); /* prepare for possible serial debug */
lv_init();
#if USE_LV_LOG != 0
lv_log_register_print_cb(my_print); /* register print function for debugging */
#endif
tft.begin(); /* TFT init */
tft.setRotation(1); /* Landscape orientation */
uint16_t calData[5] = {275, 3620, 264, 3532, 1};
tft.setTouch(calData);
lv_disp_buf_init(&disp_buf, buf, NULL, LV_HOR_RES_MAX * 10);
/*Initialize the display*/
lv_disp_drv_t disp_drv;
lv_disp_drv_init(&disp_drv);
disp_drv.hor_res = 480;
disp_drv.ver_res = 320;
disp_drv.flush_cb = my_disp_flush;
disp_drv.buffer = &disp_buf;
lv_disp_drv_register(&disp_drv);
/*Initialize the (dummy) input device driver*/
lv_indev_drv_t indev_drv;
lv_indev_drv_init(&indev_drv);
indev_drv.type = LV_INDEV_TYPE_POINTER;
indev_drv.read_cb = my_touchpad_read;
lv_indev_drv_register(&indev_drv);
// lv_demo_benchmark();
lv_demo_music();
}
void loop()
{
// put your main code here, to run repeatedly:
// testdrawcircle();
// Serial.println("hello");
// delay(1000);
// Serial.println(getCpuFrequencyMhz());
// delay(1000);
lv_task_handler();
delay(5);
}
위 코드의 105행과 106행은 각각 benchmark와 music에 대한 테스트 코드입니다. 최종 결과는 이 글의 시작 부분에 있는 그림에 나와 있습니다. 벤치마크 테스트는 다음과 같습니다.
원문 튜토리얼 출처는 이곳을 따라가시면 만나실 수 있습니다. 재미있는 프로젝트가 많습니다.
How to use LVGL library – Arduino on an ESP-32 and SPI LCD
LVGL Tutorials for STM32 and ESP32 | Build GUI with LVGL
시간이 많은 건지, 머리가 좋은 건지 모르겠지만 잘하는 건 사실입니다.
'ESP32' 카테고리의 다른 글
ESP32 무선 개발 보드 T-릴레이 5V 8 채널 릴레이 모듈 (2) | 2025.08.11 |
---|---|
ESP32-S3 Wi-Fi 및 블루투스 모듈 개발 보드 (1) | 2025.07.18 |
ESP32 기반 무선 스마트워치 (2) | 2025.07.16 |
ESP32 와이파이 연결 상태를 유지 (0) | 2025.05.27 |
ESP32 전원 공급 완벽 가이드: 안전하고 효율적인 3가지 방법 (3) | 2025.04.29 |
ESP32가 IoT 및 임베디드 환경에서 주목받는 이유 (1) | 2025.04.28 |
ESP32 마스터하기: 초보자를 위한 혁신적인 임베디드 개발 가이드 (0) | 2025.04.25 |
ESP32 빠르게 시작하기: 초보자를 위한 ESP32 개발 가이드 (4) | 2025.03.27 |
더욱 좋은 정보를 제공하겠습니다.~ ^^