What do you want to achieve?
I’ve got whole screen redraws happening during initial start of the values of the gauge in the middle (its code is attached). After around 60% the screen doesnt redraw until 0%. What could be causing this?
What have you tried so far?
Remove parts of the code.
Code to reproduce
#include "lvgl.h"
#include <stdio.h>
typedef struct
{
lv_obj_t *root;
lv_obj_t *scale;
lv_obj_t *arc_red;
lv_obj_t *dyn;
lv_obj_t *arc_val;
lv_obj_t *lbl_value;
lv_obj_t *lbl_name;
int32_t min, max, value, redline;
uint16_t start_deg;
uint16_t sweep_deg;
const char *unit;
const char *name;
} simple_arc_gauge_t;
void simple_arc_gauge_create(simple_arc_gauge_t *g, lv_obj_t *parent,
const char *name, const char *unit,
int32_t min, int32_t max, int32_t redline);
void simple_arc_gauge_set_value(simple_arc_gauge_t *g, int32_t v);
void simple_arc_gauge_set_limits(simple_arc_gauge_t *g, int32_t min, int32_t max);
void simple_arc_gauge_set_redline(simple_arc_gauge_t *g, int32_t redline);
void simple_arc_gauge_set_unit(simple_arc_gauge_t *g, const char *unit);
void simple_arc_gauge_set_name(simple_arc_gauge_t *g, const char *name);
static inline int32_t clamp32(int32_t v, int32_t lo, int32_t hi)
{
if (v < lo) return lo;
if (v > hi) return hi;
return v;
}
static inline lv_coord_t min2(lv_coord_t a, lv_coord_t b) { return a < b ? a : b; }
static int16_t value_to_angle(const simple_arc_gauge_t *g, int32_t v)
{
if (g->max == g->min) return g->start_deg;
float t = (float)(v - g->min) / (float)(g->max - g->min);
if (t < 0.f) t = 0.f;
if (t > 1.f) t = 1.f;
return (int16_t)(g->start_deg + (float)g->sweep_deg * t);
}
#ifndef GAUGE_REG_CAP
#define GAUGE_REG_CAP 8
#endif
typedef struct { lv_obj_t *root; simple_arc_gauge_t *g; } gauge_reg_t;
static gauge_reg_t s_gauge_reg[GAUGE_REG_CAP];
static void reg_add(lv_obj_t *root, simple_arc_gauge_t *g)
{
for (int i = 0; i < GAUGE_REG_CAP; i++) {
if (!s_gauge_reg[i].root) { s_gauge_reg[i].root = root; s_gauge_reg[i].g = g; return; }
}
}
static void reg_del(lv_obj_t *root)
{
for (int i = 0; i < GAUGE_REG_CAP; i++) {
if (s_gauge_reg[i].root == root) { s_gauge_reg[i].root = NULL; s_gauge_reg[i].g = NULL; return; }
}
}
static simple_arc_gauge_t *reg_get(lv_obj_t *root)
{
for (int i = 0; i < GAUGE_REG_CAP; i++) if (s_gauge_reg[i].root == root) return s_gauge_reg[i].g;
return NULL;
}
static void layout_update(simple_arc_gauge_t *g)
{
lv_coord_t w = lv_obj_get_content_width(g->root);
lv_coord_t h = lv_obj_get_content_height(g->root);
lv_coord_t s = min2(w, h);
const lv_coord_t pad_outer = s / 16;
const lv_coord_t pad_label = s / 8;
lv_coord_t scale_size = s - pad_outer * 2 - pad_label / 3;
if (scale_size < 10) scale_size = 10;
lv_obj_set_size(g->scale, scale_size, scale_size);
lv_obj_center(g->scale);
lv_obj_set_y(g->scale, pad_label / 2);
lv_coord_t thick = scale_size / 18;
if (thick < 3) thick = 3;
lv_obj_set_size(g->arc_val, scale_size, scale_size);
lv_obj_set_style_arc_width(g->arc_val, thick, LV_PART_INDICATOR);
lv_obj_set_style_arc_width(g->arc_val, thick, LV_PART_MAIN);
lv_obj_set_size(g->arc_red, scale_size, scale_size);
lv_obj_set_style_arc_width(g->arc_red, thick, LV_PART_INDICATOR);
lv_obj_set_style_arc_width(g->arc_red, thick, LV_PART_MAIN);
lv_obj_align(g->lbl_name, LV_ALIGN_TOP_MID, 0, 0);
lv_obj_align(g->lbl_value, LV_ALIGN_CENTER, 0, 0);
}
static void setup_static(simple_arc_gauge_t *g)
{
lv_obj_set_style_pad_all(g->root, 0, 0);
lv_obj_set_style_pad_all(g->scale, 0, 0);
lv_obj_set_style_pad_all(g->arc_red, 0, 0);
lv_obj_set_style_pad_all(g->arc_val, 0, 0);
lv_obj_set_style_pad_all(g->lbl_value, 0, 0);
lv_obj_set_style_pad_all(g->lbl_name, 0, 0);
lv_scale_set_mode(g->scale, LV_SCALE_MODE_ROUND_INNER);
lv_scale_set_rotation(g->scale, g->start_deg);
lv_scale_set_angle_range(g->scale, g->sweep_deg);
lv_scale_set_range(g->scale, g->min, g->max);
lv_scale_set_total_tick_count(g->scale, 21);
lv_scale_set_major_tick_every(g->scale, 5);
lv_scale_set_label_show(g->scale, true);
lv_obj_set_style_length(g->scale, 8, LV_PART_ITEMS);
lv_obj_set_style_line_width(g->scale, 1, LV_PART_ITEMS);
lv_obj_set_style_length(g->scale, 14, LV_PART_INDICATOR);
lv_obj_set_style_line_width(g->scale, 2, LV_PART_INDICATOR);
lv_obj_set_style_translate_y(g->scale, 6, LV_PART_INDICATOR);
lv_obj_set_style_bg_opa(g->arc_red, LV_OPA_TRANSP, LV_PART_MAIN);
lv_obj_set_style_bg_opa(g->arc_red, LV_OPA_TRANSP, LV_PART_KNOB);
lv_obj_set_style_arc_opa(g->arc_red, LV_OPA_20, LV_PART_MAIN);
lv_obj_set_style_arc_opa(g->arc_red, LV_OPA_COVER, LV_PART_INDICATOR);
lv_obj_set_style_arc_color(g->arc_red, lv_palette_main(LV_PALETTE_RED), LV_PART_INDICATOR);
lv_obj_set_style_arc_color(g->arc_red, lv_palette_main(LV_PALETTE_RED), LV_PART_MAIN);
lv_obj_set_style_bg_opa(g->arc_val, LV_OPA_TRANSP, LV_PART_MAIN);
lv_obj_set_style_bg_opa(g->arc_val, LV_OPA_TRANSP, LV_PART_KNOB);
lv_obj_set_style_arc_opa(g->arc_val, LV_OPA_TRANSP, LV_PART_MAIN);
lv_obj_set_style_arc_opa(g->arc_val, LV_OPA_COVER, LV_PART_INDICATOR);
lv_obj_set_style_arc_color(g->arc_val, lv_palette_main(LV_PALETTE_GREEN), LV_PART_INDICATOR);
lv_arc_set_rotation(g->arc_red, 0);
lv_arc_set_bg_angles(g->arc_red, g->start_deg, g->start_deg + g->sweep_deg);
int16_t red_a1 = value_to_angle(g, clamp32(g->redline, g->min, g->max));
int16_t red_a2 = value_to_angle(g, g->max);
lv_arc_set_angles(g->arc_red, red_a1, red_a2);
lv_arc_set_rotation(g->arc_val, 0);
lv_arc_set_bg_angles(g->arc_val, g->start_deg, g->start_deg + g->sweep_deg);
lv_obj_set_style_bg_opa(g->root, LV_OPA_TRANSP, 0);
lv_obj_set_style_bg_opa(g->scale, LV_OPA_TRANSP, 0);
}
static void root_event_cb(lv_event_t *e)
{
lv_event_code_t code = lv_event_get_code(e);
lv_obj_t *root = lv_event_get_target(e);
simple_arc_gauge_t *g = reg_get(root);
if (!g) return;
if (code == LV_EVENT_SIZE_CHANGED) {
layout_update(g);
} else if (code == LV_EVENT_DELETE) {
reg_del(root);
}
}
void simple_arc_gauge_create(simple_arc_gauge_t *g, lv_obj_t *parent,
const char *name, const char *unit,
int32_t min, int32_t max, int32_t redline)
{
g->start_deg = 135;
g->sweep_deg = 270;
g->name = name;
g->unit = unit;
g->min = min;
g->max = (max == min) ? (min + 1) : max;
g->value = min;
g->redline = clamp32(redline, g->min, g->max);
g->root = lv_obj_create(parent);
lv_obj_remove_flag(g->root, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_set_style_bg_opa(g->root, LV_OPA_TRANSP, 0);
lv_obj_set_style_pad_all(g->root, 0, 0);
g->scale = lv_scale_create(g->root);
g->lbl_name = lv_label_create(g->root);
g->dyn = g->scale;
g->arc_red = lv_arc_create(g->scale);
g->arc_val = lv_arc_create(g->scale);
g->lbl_value = lv_label_create(g->scale);
// Labels
lv_obj_set_style_text_align(g->lbl_value, LV_TEXT_ALIGN_CENTER, 0);
lv_obj_set_style_text_font (g->lbl_value, lv_theme_get_font_normal(g->lbl_value), 0);
lv_obj_set_style_text_align(g->lbl_name, LV_TEXT_ALIGN_CENTER, 0);
lv_obj_set_style_text_font (g->lbl_name, lv_theme_get_font_small(g->lbl_name), 0);
lv_label_set_text(g->lbl_name, g->name ? g->name : "");
lv_obj_remove_flag(g->arc_red, LV_OBJ_FLAG_CLICKABLE);
lv_obj_remove_flag(g->arc_val, LV_OBJ_FLAG_CLICKABLE);
setup_static(g);
layout_update(g);
simple_arc_gauge_set_value(g, g->value);
reg_add(g->root, g);
lv_obj_add_event_cb(g->root, root_event_cb, LV_EVENT_SIZE_CHANGED, NULL);
lv_obj_add_event_cb(g->root, root_event_cb, LV_EVENT_DELETE, NULL);
}
void simple_arc_gauge_set_value(simple_arc_gauge_t *g, int32_t v)
{
int32_t v_clamped = v;
if (v_clamped < g->min) v_clamped = g->min;
if (v_clamped > g->max) v_clamped = g->max;
if (v_clamped == g->value) return;
g->value = v_clamped;
int16_t a1 = g->start_deg;
int16_t a2;
if (g->max != g->min) {
float t = (float)(g->value - g->min) / (float)(g->max - g->min);
if (t < 0.f) t = 0.f;
if (t > 1.f) t = 1.f;
a2 = (int16_t)(g->start_deg + (float)g->sweep_deg * t);
} else {
a2 = a1;
}
lv_arc_set_angles(g->arc_val, a1, a2);
lv_label_set_text_fmt(g->lbl_value, "%d %s", (int)g->value, g->unit ? g->unit : "");
}
void simple_arc_gauge_set_limits(simple_arc_gauge_t *g, int32_t min, int32_t max)
{
if (max == min) max = min + 1;
g->min = min;
g->max = max;
g->value = clamp32(g->value, min, max);
g->redline = clamp32(g->redline, min, max);
lv_scale_set_range(g->scale, g->min, g->max);
int16_t red_a1 = value_to_angle(g, g->redline);
int16_t red_a2 = value_to_angle(g, g->max);
lv_arc_set_angles(g->arc_red, red_a1, red_a2);
simple_arc_gauge_set_value(g, g->value);
}
void simple_arc_gauge_set_redline(simple_arc_gauge_t *g, int32_t redline)
{
g->redline = clamp32(redline, g->min, g->max);
int16_t red_a1 = value_to_angle(g, g->redline);
int16_t red_a2 = value_to_angle(g, g->max);
lv_arc_set_angles(g->arc_red, red_a1, red_a2);
}
void simple_arc_gauge_set_unit(simple_arc_gauge_t *g, const char *unit)
{
g->unit = unit;
lv_label_set_text_fmt(g->lbl_value, "%d %s", (int)g->value, g->unit ? g->unit : "");
}
void simple_arc_gauge_set_name(simple_arc_gauge_t *g, const char *name)
{
g->name = name;
lv_label_set_text(g->lbl_name, g->name ? g->name : "");
}
Screenshot and/or video
Environment
- MCU/MPU/Board: STM32H743IIT6 custom board + LTDC + SDRAM
- LVGL version: 9.4.0