实现触摸屏Arduino ESP32:使用LVGL实现触摸屏界面美化

概述

上一篇已经完成了对显示触摸屏的驱动,能够正常的显示和触摸了。这篇引入一个嵌入式GUI:LVGL。这也正是我的最终目的。

LVGL

官网的介绍:

LVGL is an open-source graphics library providing everything you need to create embedded GUI with easy-to-use graphical elements, beautiful visual effects and low memory footprint.
LVGL是一个开源图形库,提供创建嵌入式GUI所需的一切,具有易于使用的图形元素、优美的视觉效果和较低的内存占用。

官方demo动图:

没啥好介绍的,可以去官方文档里看LVGL文档。还提供PDF版本。

引入LVGL

LVGL库可以直接兼容Arduino。

  1. 在github上直接把LVGL库下载下来。
  2. 将解压出来的LVGL库复制进上一篇中说的 sketchbook 目录下的 libraries 文件夹下。
  3. 将LVGL目录下的 lv_conf_template.h 文件改名为 lv_conf.h,放在和LVGL库文件夹同层的地方。

  4. 打开 lv_conf.h ,修改至少这三个地方。第一个,将图中的 0 修改为 1

    第二个,根据屏幕的分辨率设置色深。

    第三个,将外部定义时钟的宏打开,以使用Arduino的时钟函数接口。

    至此底层的移植就已经完成了。还是非常简单友好的。

示例代码

官方提供了一个基于Arduino平台和TFT-eSPI库的示例代码。上面的步骤完成之后,重启Arduino IDE就可以在示例里找到了。

打开之后,需要修改的地方只有一个。如下图。官方使用的就是TFT-eSPI库来驱动显示屏,所以这里需要使用TFT-eSPI库提供的接口做出一些操作。
原数据
上一篇中,最后烧录进去的是TFT-eSPI库提供的 Touch_calibrate 例程,上图中圈起来要修改的地方也正是基于这个。
打开这个例程。

烧录进去之后,会出现下面这个画面,这个时候需要触摸箭头指向的四个角。

在四个角都触摸完毕之后,串口会输出一段数据,如下图。这就是需要在LVGL例程中需要修改的五个数据。也就是上图中框起来的五个数据。

将原例程中的五个数据修改为串口输入的五个数据。

示例测试

官方提供了示例 lv_demo_weights(),但是需要额外的操作,这里先简单测试一下是否可用。将下图中的#if 0修改为#if 1,即在屏幕中央绘制一个 label 组件,内容是LVGL版本信息。

在头文件处,将 lv_demo.h 注释掉。

然后点击上传即可。上传完成后就可以在屏幕上看到通过LVGL绘制出来的 label 组件了。

添加测试代码

将下图中函数代码复制进工程中,放在 setup() 函数上面就行,随便哪。

void lv_example_btn(void)
{
    /*Properties to transition*/
    static lv_style_prop_t props[] = {
            LV_STYLE_TRANSFORM_WIDTH, LV_STYLE_TRANSFORM_HEIGHT, LV_STYLE_TEXT_LETTER_SPACE};

    /*Transition descriptor when going back to the default state.
     *Add some delay to be sure the press transition is visible even if the press was very short*/
    static lv_style_transition_dsc_t transition_dsc_def;
    lv_style_transition_dsc_init(&transition_dsc_def, props, lv_anim_path_overshoot, 250, 100, NULL);

    /*Transition descriptor when going to pressed state.
     *No delay, go to presses state immediately*/
    static lv_style_transition_dsc_t transition_dsc_pr;
    lv_style_transition_dsc_init(&transition_dsc_pr, props, lv_anim_path_ease_in_out, 250, 0, NULL);

    /*Add only the new transition to he default state*/
    static lv_style_t style_def;
    lv_style_init(&style_def);
    lv_style_set_transition(&style_def, &transition_dsc_def);

    /*Add the transition and some transformation to the presses state.*/
    static lv_style_t style_pr;
    lv_style_init(&style_pr);
    lv_style_set_transform_width(&style_pr, 10);
    lv_style_set_transform_height(&style_pr, -10);
    lv_style_set_text_letter_space(&style_pr, 10);
    lv_style_set_transition(&style_pr, &transition_dsc_pr);

    lv_obj_t * btn1 = lv_btn_create(lv_scr_act());
    lv_obj_align(btn1, LV_ALIGN_CENTER, 0, -80);
    lv_obj_add_style(btn1, &style_pr, LV_STATE_PRESSED);
    lv_obj_add_style(btn1, &style_def, 0);

    lv_obj_t * label = lv_label_create(btn1);
    lv_label_set_text(label, "btn1");

        /*Init the style for the default state*/
    static lv_style_t style;
    lv_style_init(&style);

    lv_style_set_radius(&style, 3);

    lv_style_set_bg_opa(&style, LV_OPA_100);
    lv_style_set_bg_color(&style, lv_palette_main(LV_PALETTE_BLUE));
    lv_style_set_bg_grad_color(&style, lv_palette_darken(LV_PALETTE_BLUE, 2));
    lv_style_set_bg_grad_dir(&style, LV_GRAD_DIR_VER);

    lv_style_set_border_opa(&style, LV_OPA_40);
    lv_style_set_border_width(&style, 2);
    lv_style_set_border_color(&style, lv_palette_main(LV_PALETTE_GREY));

    lv_style_set_shadow_width(&style, 8);
    lv_style_set_shadow_color(&style, lv_palette_main(LV_PALETTE_GREY));
    lv_style_set_shadow_ofs_y(&style, 8);

    lv_style_set_outline_opa(&style, LV_OPA_COVER);
    lv_style_set_outline_color(&style, lv_palette_main(LV_PALETTE_BLUE));

    lv_style_set_text_color(&style, lv_color_white());
    lv_style_set_pad_all(&style, 10);

    /*Init the pressed style*/
    static lv_style_t style_pr_2;
    lv_style_init(&style_pr_2);

    /*Ad a large outline when pressed*/
    lv_style_set_outline_width(&style_pr_2, 30);
    lv_style_set_outline_opa(&style_pr_2, LV_OPA_TRANSP);

    lv_style_set_translate_y(&style_pr_2, 5);
    lv_style_set_shadow_ofs_y(&style_pr_2, 3);
    lv_style_set_bg_color(&style_pr_2, lv_palette_darken(LV_PALETTE_BLUE, 2));
    lv_style_set_bg_grad_color(&style_pr_2, lv_palette_darken(LV_PALETTE_BLUE, 4));

    /*Add a transition to the the outline*/
    static lv_style_transition_dsc_t trans;
    static lv_style_prop_t props2[] = {LV_STYLE_OUTLINE_WIDTH, LV_STYLE_OUTLINE_OPA};
    lv_style_transition_dsc_init(&trans, props2, lv_anim_path_linear, 300, 0, NULL);

    lv_style_set_transition(&style_pr_2, &trans);

    lv_obj_t * btn2 = lv_btn_create(lv_scr_act());
    lv_obj_remove_style_all(btn2);                          /*Remove the style coming from the theme*/
    lv_obj_add_style(btn2, &style, 0);
    lv_obj_add_style(btn2, &style_pr_2, LV_STATE_PRESSED);
    lv_obj_set_size(btn2, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
    lv_obj_center(btn2);

    lv_obj_t * label2 = lv_label_create(btn2);
    lv_label_set_text(label2, "Button");
    lv_obj_center(label2);
}

然后在之前测试的地方把原来的 label 代码注释,调用上方的函数。最后烧录。

效果如下图:

小结

至此LVGL就已经成功引入到ESP32上了。之后就可以直接通过LVGL的组件接口来进行界面的绘制了。
不过Arduino虽然引入很简单很方便,但是编辑器的功能上跟记事本差不多,没有联想之类的功能。这对LVGL这个API众多的库的编写很不友好,所以我们可以将Arduino作为编译器和烧录工具,正常的代码编写最好还是使用外部的编辑器,或者使用VS、CodeBlock等工具来编写、预览,然后再黏贴到Arduino中。下篇用VS进行模拟。

物联沃分享整理
物联沃-IOTWORD物联网 » 实现触摸屏Arduino ESP32:使用LVGL实现触摸屏界面美化

发表评论