Lv_label_set_text_fmt() outputting f on display and not the actual text

Description

I don’t get the expected output when I format the string as in the example code below.

What MCU/Processor/Board and compiler are you using?

VSCode, ESP-IDF, ESP32-Wroom-32E-Devkit4, IL9488 480x320, FT6X06.

I’m using [lv_port_esp32 @ 78428b8]

What do you experience?

The code compiles, and flashes. I put in

ESP_LOGI(TAG, "RAM left %d", esp_get_free_heap_size());

before and after the code and reports RAM left 107060. So I don’t think I am running out of ram.

What do you expect?

I expect to see “987.65” and not “f” on the LCD.
I have a dropdown on the same screen and responding as should. Other text labels are displaying just fine.

Code to reproduce

scale_readout = lv_label_create(parent, NULL);
lv_obj_add_style(scale_readout, LV_LABEL_PART_MAIN, &style_scale_medium);
lv_obj_align(scale_readout, NULL, LV_ALIGN_IN_BOTTOM_LEFT, 0, 0);
lv_label_set_align(scale_readout, LV_LABEL_ALIGN_CENTER);
lv_label_set_text_fmt(scale_readout, "%.2f", 987.65);

You might have floats disabled in lv_conf.h

#else   /*!LV_SPRINTF_CUSTOM*/
#  define LV_SPRINTF_DISABLE_FLOAT 1
#endif  /*LV_SPRINTF_CUSTOM*/

Set it to 0 and test again if you have not changed it already

I have it set as:

#else   /*!LV_SPRINTF_CUSTOM*/
#  define LV_SPRINTF_DISABLE_FLOAT 0
#endif  /*LV_SPRINTF_CUSTOM*/

Thx, so that is not the problem, at least I hope so.

I would double check that the project gets recompiled when you edit lv_conf.h. There is a chance you are editing the wrong file.

Also ensure LV_SPRINTF_CUSTOM is disabled (set to 0). If it is enabled, our (s)printf implementation is not being used, and you would need to consult the docs for yours.

Ok, so to check, I introduced a typo in the lv_conf.h, and you are correct. The build proceeds without any errors.

In my current project, Main folder I have CMakeLists.txt:

idf_component_register(
    SRCS "main.c""gui_smartbin.c""
    INCLUDE_DIRS "."
REQUIRES nvs_flash lvgl_esp32_drivers lvgl lv_examples lvgl_tft lvgl_touch)

target_compile_definitions(${COMPONENT_LIB} PUBLIC "-DLV_LVGL_H_INCLUDE_SIMPLE"
)

In my Project folder CMakeLists.txt:

# The following lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)

include($ENV{IDF_PATH}/tools/cmake/project.cmake)
list(APPEND EXTRA_COMPONENT_DIRS components/lv_port_esp32/components/lv_examples components/lv_port_esp32/components/lvgl components/lv_port_esp32/components/lvgl_esp32_drivers/lvgl_tft components/lv_port_esp32/components/lvgl_esp32_drivers/lvgl_touch components/lv_port_esp32/components/lvgl_esp32_drivers)

project(test_lvgl_implementation)

In the Projects Main folder I have copied the lv_conf_template.h and renamed to lv_conf.h

It is thus not in the ProjectFolder/components/lv_port_esp32/components/lvgl/ folder, where the original lv_conf_template.h is to be found.

I do not want it in the components folder so that remains pure to the repository.
They do state in the docs, to copy lv_conf.h NEXT TO the lgvl folder.
This does not make sense as it would then leave it in lv_port_esp32/components/ folder.

I think this is where I’m coming undone. If I #include lv_conf.h in my main.c I get multiple warnings of redefines, so that doesn’t force it to be compiled in either.

Perhaps you can guide me in the correct direction.

@Carlos_Diaz Can you help with this?

I tried moving lv_conf.h to every conceivable position in my project tree, and it is not being compiled or linked in. I can confirm this by entering a typo that should cause the compiler to fail.

I had an intense look at the lv_conf_internal.h, and none the wiser.

I just cannot figure out how to get the compiler to actually see and compile the lv_conf.h.

I checked my MenuConfig (KConfig) and all is properly set up there.
The vl_conf.h I’m using is for v7.8.1-dev, and differs from previous versions.

I have intentionally introduced errors into lv_conf_internal.h and can confirm that it dos not complain at include “lv_conf.hm”.
This should be “lv_conf.h”

LV_CONF_INCLUDE_SIMPLE is defined, as I tested this part of the header file too, and it worked properly.

/**
 * GENERATED FILE, DO NOT EDIT IT!
 * @file lv_conf_internal.h
 * Make sure all the defines of lv_conf.h have a default value
**/

#ifndef LV_CONF_INTERNAL_H
#define LV_CONF_INTERNAL_H
/* clang-format off */

#include <stdint.h>

/* Add ESP-IDF related includes */
#if defined (ESP_PLATFORM)
#  include "sdkconfig.h"
#  include "esp_attr.h"
#endif

/* Handle special Kconfig options */
#include "lv_conf_kconfig.h"

#ifdef CONFIG_LV_CONF_SKIP
#define LV_CONF_SKIP
#endif

/* If "lv_conf.h" is available from here try to use it later.*/
#if defined __has_include
#  if __has_include("lv_conf.h")
#   ifndef LV_CONF_INCLUDE_SIMPLE
#    define LV_CONF_INCLUDE_SIMPLE
#   endif
#  endif
#endif

/*If lv_conf.h is not skipped include it*/
#if !defined(LV_CONF_SKIP)
#  if defined(LV_CONF_PATH)											/*If there is a path defined for lv_conf.h use it*/
#    define __LV_TO_STR_AUX(x) #x
#    define __LV_TO_STR(x) __LV_TO_STR_AUX(x)
#    include __LV_TO_STR(LV_CONF_PATH)
#    undef __LV_TO_STR_AUX
#    undef __LV_TO_STR
#  elif defined(LV_CONF_INCLUDE_SIMPLE)        /*Or simply include lv_conf.h is enabled*/
#    include "lv_conf.hm"  /*INTRODUCED ERROR HERE*/
#  else
#    include "../../lv_conf.hm"                 /*Else assume lv_conf.h is next to the lvgl folder */
#  endif
#endif

/* clang-format off */

Just hoping to move on …

I somehow forgot to think about the fact that you are using lv_port_esp32. You may be able to just change the setting in menuconfig. It seems to be one of the options in the Kconfig. Have you tried that?

@embeddedt sure, I will take a look at this as soon as I can. @wreyford I will open an issue on lv_port_esp32 as a reminder, as @embeddedt pointed out, the LVGL main repo now includes a Kconfig file, which is used by ESP-IDF to configure LVGL via menuconfig, so it’s no longer needed to work on the lv_conf.h file directly. Let me know if you can achieve printing the float number by configuring LVGL with the menuconfig interface.

I’m working on updating the README file of the lv_port_esp32 to point this out.

Sorry I did not realize that the lv_conf.h was not required if using KConfig.
I had everything set up correctly in KConfig, but the LV_CONF_SKIP had no text next to bool, thus it was not showing up in the IDF-MenuConfig.

This is quite important info and could have saved newbies like me many hours, but I have a much better understanding of the build process too now, so all for the good.

I have adapted it to the following:

# Define CONFIG_LV_CONF_SKIP so we can use LVGL
    # without lv_conf.h file, the lv_conf_internal.h and
    # lv_conf_kconfig.h files are used instead.
    config LV_CONF_SKIP
        bool "Define CONFIG_LV_CONF_SKIP so we can use LVGL without lv_conf.h file"
        default y
        help Define CONFIG_LV_CONF_SKIP so we can use LVGL
             without lv_conf.h file, the lv_conf_internal.h and
             lv_conf_kconfig.h files are used instead.

With this change it now shows up in the IDF MenuConfig.
lv_conf_skip_idf_menuconfig
In Text Settings, disable float is not selected:
diasble_float_idf_menuconfig

So I removed all traces of lv_conf.h, applied above changes, and compiled,

and still I’m getting f on the screen instead of the float value.

I will keep on looking into it to see why this is the case. There is also the need to add to the KConfig the ability to add custom fonts, as we manually did in the lv_conf.h.

Ok, I think I have found the offending code in the lv_conf_internal.h
At line 1394:

#else   /*!LV_SPRINTF_CUSTOM*/
#ifndef LV_SPRINTF_DISABLE_FLOAT
#  ifdef CONFIG_LV_SPRINTF_DISABLE_FLOAT
#    define LV_SPRINTF_DISABLE_FLOAT CONFIG_LV_SPRINTF_DISABLE_FLOAT
#  else
#    define  LV_SPRINTF_DISABLE_FLOAT 1
#  endif
#endif
#endif  /*LV_SPRINTF_CUSTOM*/

If I change line 1394 as follows:

#else   /*!LV_SPRINTF_CUSTOM*/
#ifndef LV_SPRINTF_DISABLE_FLOAT
#  ifdef CONFIG_LV_SPRINTF_DISABLE_FLOAT
#    define LV_SPRINTF_DISABLE_FLOAT CONFIG_LV_SPRINTF_DISABLE_FLOAT
#  else
#    define  LV_SPRINTF_DISABLE_FLOAT 0
#  endif
#endif
#endif  /*LV_SPRINTF_CUSTOM*/

That is from #define LV_SPRINTF_DISABLE_FLOAT 1 to define LV_SPRINTF_DISABLE_FLOAT 0.

This solves the issue, and now works as expected.

If you agree, can you please make the necessary code changes in the repo.

1 Like

There is a logic problem on our end here.

lv_conf_internal.h is autogenerated. It uses the default value from lv_conf_template.h if the CONFIG_XXX value is not defined.

In this case, we have chosen to disable floating point support by default (value is 1) in lv_conf_template.h to reduce code size. However, when used in lv_conf_internal.h, we want the default value to be 0.

The best solution would be to get Kconfig to output CONFIG_LV_SPRINTF_DISABLE_FLOAT = 0 if it is not selected, however, I don’t think there is any option for Kconfig to do this.

Thanks for taking the time to investigate the issue, and sorry for the time you expended with the issue because of the lack of documentation. I will try to solve it asap.

I think it’s not, boolean symbols with n value are not defined (generated), I can handle it in lv_conf_kconf.h, will send a PR soon.