Lv_chart_get_x_start_point but to Y axys

I need to obtain the first value on the Y-axis displayed in a chart. This information will allow me to adjust the zoom and scroll position to encompass the highest and lowest values, thereby showing all points between them with greater detail.

So do you need to get the min/max y value in pixels to know how much you can zoom?
If so, maybe an auto-zoom feature could be useful too.

1 Like

exacly, so imagine we have a chart being ploted every 500ms and sometimes the value would be high and sometimes low and what i need to is aways show the highest and lowest point (from the amount of points the chart have like 240 that how much i have)

It just came to my mind that for that you don’t need to know the actual Y coordinates. You just need to calculate the min and max value of the series values and set the range of the chart accordingly by lv_chart_set_range(chart, LV_CHART_AXIS_PRIMARY_Y, min, max);

1 Like

This situation prompted me to ponder two questions:

  1. Is it feasible to update the chart range rapidly, perhaps every 500 milliseconds? (Based on my tests, it seems unlikely, as I haven’t been able to achieve it.)
  2. Additionally, how can I determine the minimum and maximum values of the series without having knowledge of the most recent data point?

Yes, it should work, as the range change mean only a simple redraw.

lv_chart_get_y_array(chart, ser) returns the array in which the values are stored. You can just use a for loop the find the min and max values.

1 Like

so i came up with this code

static void event_cb(lv_event_t * e)
{
lv_event_code_t code = lv_event_get_code(e);
lv_obj_t * chart = lv_event_get_target(e);

if(code == LV_EVENT_VALUE_CHANGED) {
    lv_obj_invalidate(chart);
}
if(code == LV_EVENT_REFR_EXT_DRAW_SIZE) {
    lv_coord_t * s = lv_event_get_param(e);
    *s = LV_MAX(*s, 20);
}
else if(code == LV_EVENT_DRAW_POST_END) {
    int32_t id = lv_chart_get_pressed_point(chart);
    if(id == LV_CHART_POINT_NONE) return;

    LV_LOG_USER("Selected point %d", (int)id);

    lv_chart_series_t * ser = lv_chart_get_series_next(chart, NULL);
    while(ser) {
        lv_point_t p;
        lv_chart_get_point_pos_by_id(chart, ser, id, &p);

        lv_coord_t * y_array = lv_chart_get_y_array(chart, ser);
        lv_coord_t value = y_array[id];

        char buf[16];
        lv_snprintf(buf, sizeof(buf), LV_SYMBOL_DUMMY"$%d", value);

        lv_draw_rect_dsc_t draw_rect_dsc;
        lv_draw_rect_dsc_init(&draw_rect_dsc);
        draw_rect_dsc.bg_color = lv_color_black();
        draw_rect_dsc.bg_opa = LV_OPA_50;
        draw_rect_dsc.radius = 3;
        draw_rect_dsc.bg_img_src = buf;
        draw_rect_dsc.bg_img_recolor = lv_color_white();

        lv_area_t a;
        a.x1 = chart->coords.x1 + p.x - 20;
        a.x2 = chart->coords.x1 + p.x + 20;
        a.y1 = chart->coords.y1 + p.y - 30;
        a.y2 = chart->coords.y1 + p.y - 10;

        lv_draw_ctx_t * draw_ctx = lv_event_get_draw_ctx(e);
        lv_draw_rect(draw_ctx, &draw_rect_dsc, &a);

        ser = lv_chart_get_series_next(chart, ser);
    }
}
else if(code == LV_EVENT_RELEASED) {
    lv_obj_invalidate(chart);
}

}

static void update_chart_values(lv_timer_t *timer)
{
lv_obj_t *chart = timer->user_data;
lv_chart_series_t *ser1 = lv_chart_get_series_next(chart, NULL);

/* Update chart values */
uint32_t i;
for (i = 0; i < 120; i++) {
    lv_chart_set_next_value(chart, ser1, lv_rand(1, 100) * i);
}

/* Calculate the new minimum and maximum values */
int *y_array = lv_chart_get_y_array(chart, ser1);
int minY = y_array[0];
int maxY = y_array[0];
for (i = 1; i < 120; i++) {
    if (y_array[i] < minY) {
        minY = y_array[i];
    }
    if (y_array[i] > maxY) {
        maxY = y_array[i];
    }
}

/* Set the new range of the y-axis */
lv_chart_set_range(chart, LV_CHART_AXIS_PRIMARY_Y, minY, maxY);

}

/**

  • Show the value of the pressed points
    /
    void lv_example_chart_4(void)
    {
    /
    Create a chart */
    lv_obj_t *chart;
    chart = lv_chart_create(lv_scr_act());
    lv_obj_set_size(chart, 480, 220);
    lv_obj_center(chart);

    lv_obj_add_event_cb(chart, event_cb, LV_EVENT_ALL, NULL);
    lv_obj_refresh_ext_draw_size(chart);
    lv_chart_set_point_count(chart, 120);

    /* Zoom in a little in X */
    lv_chart_set_zoom_x(chart, 800);

    /* Add two data series */
    lv_chart_series_t *ser1 = lv_chart_add_series(chart, lv_palette_main(LV_PALETTE_RED), LV_CHART_AXIS_PRIMARY_Y);
    uint32_t i;
    for (i = 0; i < 120; i++) {
    lv_chart_set_next_value(chart, ser1, lv_rand(1, 20) * i);
    }
    int *y_array = lv_chart_get_y_array(chart, ser1);

    /* Calculate the minimum and maximum values */
    int minY = y_array[0];
    int maxY = y_array[0];
    for (i = 1; i < 120; i++) {
    if (y_array[i] < minY) {
    minY = y_array[i];
    }
    if (y_array[i] > maxY) {
    maxY = y_array[i];
    }
    }

    /* Set the range of the y-axis */
    lv_chart_set_range(chart, LV_CHART_AXIS_PRIMARY_Y, minY, maxY);

    /* Create a timer to update the values and range */
    lv_timer_create(update_chart_values, 500, chart);
    }

I think it is updating the range but would need to zoom in the values between lowest and highest values updating that zoom and scroll postion acording with the range woudl that be possible