• Util

LVGL

Dicas sobre o LVGL.

Dicas gerais

Dicas gerais sobre o lvgl.

float

Para poder usar o e exibir strings com float (exemplo: lv_label_set_text_fmt(dial, "%f", freq);) você precisa editar o arquivo de configuração lv_conf.h do lvgl:

-#  define LV_SPRINTF_USE_FLOAT 0
+#  define LV_SPRINTF_USE_FLOAT 1

Orientação do LCD (landscape/ portrait)

Para alteramos a orientação do LCD de horizontal para vertical será necessário fazermos as seguintes mudanças no código do main.c:

/*************************************************/
/* LCD / LVGL                                    */
/*************************************************/

- #define LV_HOR_RES_MAX          (320)
- #define LV_VER_RES_MAX          (240)
+ #define LV_HOR_RES_MAX          (240)
+ #define LV_VER_RES_MAX          (320)
void my_input_read(lv_indev_drv_t * drv, lv_indev_data_t*data) {
  ...
  ...
-   data->point.x = px;
-   data->point.y = py;
+   data->point.x = py;
+   data->point.y = 320 - px;
}
int main(void) {
  ....
  ....

  /* LCd, touch and lvgl init*/
  configure_lcd();
+ ili9341_set_orientation(ILI9341_FLIP_Y | ILI9341_SWITCH_XY);

  ...
}

Tip

Com isso o LCD passa a ter as dimensões 240x320 e para o LVGL não existe diferença nenhuma.

Desativando scroll

Se por algum motivo na sua tela estiver aparecendo uma barra de scroll e você não quer isso, tente o seguinte comando:

lv_obj_clear_flag(lv_scr_act(), LV_OBJ_FLAG_SCROLLABLE);

A ideia do comando

Mudando a cor do fundo

Para mudarmos a cor do background basta alterarmos a cor do background da tela principal:

    // configura um fundo vermelho.
    lv_obj_t * screen = lv_scr_act();
    lv_obj_set_style_bg_color(screen, lv_palette_main(LV_PALETTE_RED), LV_PART_MAIN );

Cores

Para criar ou usar uma cor consulte:

https://docs.lvgl.io/master/overview/color.html#palette

Multiplas telas

No LVGL podemos criar multiplas telas e associar ao mesmo display, as telas podem ser exibidas conforme necessário. Os widgets são associados a uma tela, então quando a tela em questão for exibida apenas os widgets associados a ela serão ativados.

// declarar a tela como global e estática
static lv_obj_t * scr1;  // screen 1
static lv_obj_t * scr2;  // screen 2

static void task_lcd(void *pvParameters) {
    // Criando duas telas
    scr1  = lv_obj_create(NULL);
    scr2  = lv_obj_create(NULL);

    // ....
}

Para dizer em qual tela os widgets serão associados, basta substituir o lv_scr_act() usado na criação dos widgets pela tela em questão:

- lv_obj_t * btn1 = lv_btn_create(lv_scr_act());
+ lv_obj_t * btn1 = lv_btn_create(scr1);          // botao criado na primeira tela

Para exibir uma das telas use a função lv_scr_load(lv_obj_t * scr) como demonstrado a seguir:

static void task_update(void *pvParameters) {
    for (;;)  {
        lv_scr_load(scr1); // exibe tela 1
        vTaskDelay(500);
        lv_scr_load(scr2); // exibe tela 2
        vTaskDelay(500);
    }
}

Tip

Você pode modificar as funções que criam os widgets na tela para receber como parametro o screen associado a eles:

- void lv_ex_btn_1(void) {
+ void create_scr(lv_obj_t * screen) {
    lv_obj_t * label;

-   lv_obj_t * btn1 = lv_btn_create(lv_scr_act());
+   lv_obj_t * btn1 = lv_btn_create(screen);
    lv_obj_add_event_cb(btn1, event_handler, LV_EVENT_ALL, NULL);
    lv_obj_align(btn1, LV_ALIGN_CENTER, 0, -40);

    label = lv_label_create(btn1);
    lv_label_set_text(label, "Corsi");
    lv_obj_center(label);

-   lv_obj_t * btn2 = lv_btn_create(lv_scr_act());
+   lv_obj_t * btn2 = lv_btn_create(screen);
    lv_obj_add_event_cb(btn2, event_handler, LV_EVENT_ALL, NULL);
    lv_obj_align(btn2, LV_ALIGN_CENTER, 0, 40);
    lv_obj_add_flag(btn2, LV_OBJ_FLAG_CHECKABLE);
    lv_obj_set_height(btn2, LV_SIZE_CONTENT);

    label = lv_label_create(btn2);
    lv_label_set_text(label, "Toggle");
    lv_obj_center(label);
}

static void task_lcd(void *pvParameters) {
    int px, py;

+   scr1  = lv_obj_create(NULL);
-   lv_ex_btn_1();
+   create_scr(scr1);
+   lv_scr_load(scr1);

    ...
}

Tip

Você pode fazer a transição entre telas dado um evento de um botão!

Tip

Uma alternativa para mudar de tela utilizando efeito de scroll tente usar o widget Tile view, eu testei o exemplo do site aqui e funciona bem:

https://docs.lvgl.io/master/widgets/extra/tileview.html#tileview-with-content

Exibindo uma imagem

Warning

Esse procedimento não funciona com imagens no formato PNG sem fundo, a imagem precisa ter fundo, mesmo que branco.

Exibindo uma imagem estática no LCD, sem interação.

Tip

Se quiser usar uma imagem como botão utilize o widget Image button:

Usar o conversor online disponível em https://lvgl.io/tools/imageconverter e seguir os passos:

  • No site configurar:
    • File names: Nome que quer dar para imagem, exemplo: img1
    • True Color: On
    • Output Format: C Array

Clicar em Convert e salvar o arquivo no computador (fora da pasta do projeto);

  • Mudar a extensão do arquivo baixo de .c para .h

  • Abrir o arquivo e editar a primeira linha:

- #include "lvgl/lvgl.h"
+ #include "lvgl.h"
  • Adicionar o arquivo da imagem no projeto do MicrochipStudio (pode arrastar)

  • No main.c incluir o .h da imagem.

#include "img1.h"
  • Agora basta executar as linhas de código a seguir para exibir a imagem:
lv_obj_t * img = lv_img_create(lv_scr_act());
lv_img_set_src(img, &img1);
lv_obj_align(img, LV_ALIGN_CENTER, 0, 0);

Info

  • Para testar, incluir as linhas na task_lcd
  • No exemplo o nome da imagem utilizada no site foi img1
  • Alinhamos a imagem no centro da tela

Imagem

Se quiser usar um botão como imagem você pode usar o exemplo a seguir:

void lv_img_button(void) {
    LV_IMG_DECLARE(imgBtnHome);

    static lv_style_t style_def;

    lv_style_init(&style_def); /*Darken the button when pressed and make it wider*/
    static lv_style_t style_pr;
    lv_style_init(&style_pr);
    lv_style_set_img_recolor_opa(&style_pr, LV_OPA_30);
    lv_style_set_img_recolor(&style_pr, lv_color_black());

    lv_obj_t * btnPausePlay = lv_imgbtn_create(lv_scr_act());
    lv_imgbtn_set_src(btnPausePlay, LV_IMGBTN_STATE_RELEASED, NULL, NULL, &imgBtnHome);
    lv_obj_add_style(btnPausePlay, &style_def, 0);
    lv_obj_add_style(btnPausePlay, &style_pr, LV_STATE_PRESSED);
    lv_obj_align(btnPausePlay, LV_ALIGN_CENTER, 0, 0);  
}

O imgBtnHome eu gerei a partir da imagem a seguir: