Graph plot problem

What do you want to achieve?

I’m trying with the same code both on the simulator for windows and on my board. I would like to get two graphs on two different lines. On the simulator everything is OK, While on my custom board it doesn’t work.
Obviously I have already tested writing/displaying static things on the screen and it works perfectly

What have you tried so far?

Code to reproduce


static lv_obj_t* chart;
static lv_chart_series_t* series;
static lv_obj_t* chart2;
static lv_chart_series_t* series2;

#define CHART_POINT_COUNT 100

static void update_chart_cb(lv_timer_t* timer) 
{
    static int t=0 ,t1 = 100;
    int new_sample = (lv_trigo_sin(t % 360) * 50) / LV_TRIGO_SIN_MAX + 50;  
    lv_chart_set_next_value(chart, series, new_sample);
    t += 10;
    int new_sample2 = (lv_trigo_sin(t1 % 360) * 50) / LV_TRIGO_SIN_MAX + 50;  
    lv_chart_set_next_value(chart2, series2, new_sample2);
    t1 += 10;
}

static void analytics_create(lv_obj_t * parent)
{
    lv_obj_set_flex_flow(parent, LV_FLEX_FLOW_COLUMN);

    chart = lv_chart_create(parent);
    lv_obj_set_size(chart, lv_pct(100), lv_pct(50));
    lv_obj_align(chart, LV_ALIGN_TOP_MID, 0, 0);
    lv_chart_set_type(chart, LV_CHART_TYPE_LINE);
    lv_chart_set_range(chart, LV_CHART_AXIS_PRIMARY_Y, 0, 100);
    lv_chart_set_point_count(chart, CHART_POINT_COUNT);
    lv_chart_set_update_mode(chart, LV_CHART_UPDATE_MODE_SHIFT); // sposta i dati
    series = lv_chart_add_series(chart, lv_palette_main(LV_PALETTE_RED), LV_CHART_AXIS_PRIMARY_Y);

    chart2 = lv_chart_create(parent);
    lv_obj_set_size(chart2, lv_pct(100), lv_pct(50));
    lv_obj_align(chart2, LV_ALIGN_BOTTOM_MID,0,0);
    lv_chart_set_type(chart2, LV_CHART_TYPE_LINE);
    lv_chart_set_range(chart2, LV_CHART_AXIS_PRIMARY_Y, 0, 100);
    lv_chart_set_point_count(chart2, CHART_POINT_COUNT);
    lv_chart_set_update_mode(chart2, LV_CHART_UPDATE_MODE_SHIFT); 
    series2 = lv_chart_add_series(chart2, lv_palette_main(LV_PALETTE_BLUE), LV_CHART_AXIS_PRIMARY_Y);

    lv_timer_create(update_chart_cb, 50, NULL); 
}

Screenshot and/or video


Environment

  • MCU/MPU/Board: STM32F746BGT6
  • LVGL version: 9.3.0

Hi

What is the parent object size? It almost seems that the parent object size was small (height), and the flex layout is adjusting the size/height of the charts…

Considering the top of screen in the image/Display you shown, it also seems that there is some issue in the flush_cb function, the top part seems to be garbled.

the monitor is a 800x480

void lv_port_disp_init()
{    
   disp_init();
   lv_display_t * disp = lv_display_create(MY_DISP_HOR_RES, MY_DISP_VER_RES);
   lv_display_set_flush_cb(disp, disp_flush); 
  lv_display_set_buffers(disp, FRAMEBUFFER1_ADDR, NULL, 800 * 480 * 2, LV_DISPLAY_RENDER_MODE_PARTIAL);

   tv = lv_tabview_create(lv_screen_active());
   lv_tabview_set_tab_bar_size(tv, 35); 
   lv_obj_add_event_cb(tv, tabview_delete_event_cb, LV_EVENT_DELETE, NULL);

   lv_obj_t * t1 = lv_tabview_add_tab(tv, "Ritmo");
   analytics_create(t1);

However if you fill the graph statically, it fills correctly

What is the size of your FRAMEBUFFER1_ADDR?

Just asking, that it seems you are setting a single buffer, and indicating that the size is 800x480x2, but with render mode set to Partial.

You are using a single framebuffer, with total screen size but in partial mode, depending on how you have your fluch_cb that could be the issue. Maybe you intended to use LV_DISP_RENDER_MODE_FULL?

Tried you code in my current development board/software, and it just works (still using 9.2.2).

I entered LV_DISP_RENDER_MODE_FULL
and indeed the series is inside the chart now.
however I see the monitor refresh rate is too high (I don’t know if I explained myself) the framebuffer is a pointer to my external SDRAM while the flush is that of the template

static void disp_flush(lv_display_t * disp_drv, const lv_area_t * area, uint8_t * px_map)
{
    if(disp_flush_enabled) {
        /*The most simple case (but also the slowest) to put all pixels to the screen one-by-one*/
        int32_t x;
        int32_t y;
        for(y = area->y1; y <= area->y2; y++) {
            for(x = area->x1; x <= area->x2; x++) {
                /*Put a pixel to the display. For example:*/
                /*put_px(x, y, *px_map)*/
                px_map++;
            }
        }
    }
    /*IMPORTANT!!!
     *Inform the graphics library that you are ready with the flushing*/
    lv_display_flush_ready(disp_drv);
}

Setting the flush this way, the problem seems to be solved. can i add other improvements? it’s the first time i use lvgl and i’m discovering everything

static void disp_flush(lv_display_t * disp_drv, const lv_area_t * area, uint8_t * px_map)
{
    if(disp_flush_enabled) 
		{
			LTDC_Layer1->CFBAR = (uint32_t)px_map;
			LTDC->SRCR = LTDC_SRCR_IMR; // Reload immediato
    }
    lv_display_flush_ready(disp_drv);
}

thanks for the support