diff --git a/Power_Pico/User/GUI/screens/ui_ChartPage.c b/Power_Pico/User/GUI/screens/ui_ChartPage.c new file mode 100644 index 0000000..8b4fd7c --- /dev/null +++ b/Power_Pico/User/GUI/screens/ui_ChartPage.c @@ -0,0 +1,309 @@ +// This file was generated by SquareLine Studio +// SquareLine Studio version: SquareLine Studio 1.5.3 +// LVGL version: 9.2.2 +// Project name: PowerPico + +#include "../ui.h" + +lv_obj_t * ui_ChartPage = NULL; +static lv_obj_t * ui_DataChart = NULL; +static lv_obj_t * ui_DataChart_Xaxis = NULL; +static lv_obj_t * ui_DataChart_Yaxis1 = NULL; +static lv_obj_t * ui_DataChart_Yaxis2 = NULL; +static lv_obj_t * ui_PanelVol = NULL; +static lv_obj_t * ui_PanelCur = NULL; +static lv_obj_t * ui_LabelVol = NULL; +static lv_obj_t * ui_LabelVolUnit = NULL; +static lv_obj_t * ui_LabelCur = NULL; +static lv_obj_t * ui_LabelCurUnit = NULL; +static lv_obj_t * ui_StateBtn = NULL; +static lv_obj_t * ui_StateLabel = NULL; +static lv_obj_t * ui_TickVolUnit = NULL; +static lv_obj_t * ui_TickCurUnit = NULL; + +static lv_timer_t * chart_update_timer = NULL; // 定时器 +static bool is_chart_running = true; + +#define POINTS_NUM 32 +// 模拟数据数组 +// 数据数组 +static lv_coord_t ui_DataChart_vol_array[POINTS_NUM] = {0}; // 初始为空 +static lv_coord_t ui_DataChart_cur_array[POINTS_NUM] = {0}; // 初始为空 +static uint8_t data_index = 0; + +// event funtions + +// 清空图表数据 +static void clear_chart_data(void) { + for (int i = 0; i < POINTS_NUM; i++) { + ui_DataChart_vol_array[i] = 0; + ui_DataChart_cur_array[i] = 0; + } + lv_chart_refresh(ui_DataChart); +} + + +// btn event +static void _ui_Chart_Btn_cb(lv_event_t * e) { + // check btn state + lv_event_code_t code = lv_event_get_code(e); + LV_LOG_WARN("Chart btn event code: %d", code); + is_chart_running = !is_chart_running; + + if(is_chart_running) { + lv_label_set_text(ui_StateLabel, LV_SYMBOL_PLAY); + clear_chart_data(); + } + else { + lv_label_set_text(ui_StateLabel, LV_SYMBOL_PAUSE); + } + +} + +// 定时器回调函数:更新图表数据 +static void _chart_update_cb(lv_timer_t * timer) { + if (!is_chart_running) return; + // 获取图表对象 + lv_obj_t * chart = lv_timer_get_user_data(timer); + + // 获取数据系列 + lv_chart_series_t * vol_series = lv_chart_get_series_next(chart, NULL); + lv_chart_series_t * cur_series = lv_chart_get_series_next(chart, vol_series); + + // 添加新数据 + lv_chart_set_next_value(chart, vol_series, 3); // 模拟电压数据 + lv_chart_set_next_value(chart, cur_series, 3); // 模拟电流数据 + + // 模拟数据间隙 + uint16_t point_count = lv_chart_get_point_count(chart); + uint16_t start_index = lv_chart_get_x_start_point(chart, vol_series); + lv_coord_t * vol_array = lv_chart_get_y_array(chart, vol_series); + lv_coord_t * cur_array = lv_chart_get_y_array(chart, cur_series); + + vol_array[(start_index + 1) % point_count] = LV_CHART_POINT_NONE; + cur_array[(start_index + 1) % point_count] = LV_CHART_POINT_NONE; + + // 动态调整坐标轴范围 + lv_coord_t max_vol = 0; + lv_coord_t max_cur = 0; + + for (uint16_t i = 0; i < point_count; i++) { + if (vol_array[i] != LV_CHART_POINT_NONE && vol_array[i] > max_vol) { + max_vol = vol_array[i]; + } + if (cur_array[i] != LV_CHART_POINT_NONE && cur_array[i] > max_cur) { + max_cur = cur_array[i]; + } + } + + // 动态调整图表范围,增加一定的缓冲区(+1) + lv_coord_t new_vol_range = max_vol * 1.5; + lv_coord_t new_cur_range = max_cur * 1.5; + + lv_chart_set_range(chart, LV_CHART_AXIS_PRIMARY_Y, 0, new_vol_range); // 电压轴 + lv_chart_set_range(chart, LV_CHART_AXIS_SECONDARY_Y, 0, new_cur_range); // 电流轴 + + // 动态调整坐标轴范围 + lv_scale_set_range(ui_DataChart_Yaxis1, 0, new_vol_range); // 更新左侧电压坐标轴 + lv_scale_set_range(ui_DataChart_Yaxis2, 0, new_cur_range); // 更新右侧电流坐标轴 + + // 刷新图表 + lv_chart_refresh(chart); + +} + +#include "key.h" +void ui_chart_page_key_handler(uint8_t key_id) +{ + if(key_id == KEYB_NUM) { + PageManager_next(); + } +} + +// build funtions + +void ui_ChartPage_screen_init(void) +{ + ui_ChartPage = lv_obj_create(NULL); + lv_obj_remove_flag(ui_ChartPage, LV_OBJ_FLAG_SCROLLABLE); /// Flags + + ui_DataChart = lv_chart_create(ui_ChartPage); + lv_obj_set_width(ui_DataChart, 180); + lv_obj_set_height(ui_DataChart, 180); + lv_obj_set_x(ui_DataChart, 0); + lv_obj_set_y(ui_DataChart, 10); + lv_obj_set_align(ui_DataChart, LV_ALIGN_TOP_MID); + lv_obj_add_flag(ui_DataChart, LV_OBJ_FLAG_OVERFLOW_VISIBLE); /// Flags + lv_obj_remove_flag(ui_DataChart, LV_OBJ_FLAG_SCROLLABLE); /// Flags + lv_obj_add_flag(ui_DataChart, LV_OBJ_FLAG_OVERFLOW_VISIBLE); //make scales visible - Should it be forced to True? + //lv_obj_remove_flag( ui_DataChart, LV_OBJ_FLAG_SCROLLABLE ); //no chart-zoom in LVGL9 - Shouldn't it be forced to False? + lv_chart_set_type(ui_DataChart, LV_CHART_TYPE_LINE); + lv_chart_set_point_count(ui_DataChart, POINTS_NUM); + lv_chart_set_range(ui_DataChart, LV_CHART_AXIS_PRIMARY_Y, 0, 5); + lv_obj_set_style_radius(ui_DataChart, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_line_color(ui_DataChart, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_line_opa(ui_DataChart, 128, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_DataChart_Xaxis = lv_scale_create(ui_DataChart); + lv_scale_set_mode(ui_DataChart_Xaxis, LV_SCALE_MODE_HORIZONTAL_BOTTOM); + lv_obj_set_size(ui_DataChart_Xaxis, lv_pct(100), 50); + lv_obj_set_align(ui_DataChart_Xaxis, LV_ALIGN_BOTTOM_MID); + lv_obj_set_y(ui_DataChart_Xaxis, 50 + lv_obj_get_style_pad_bottom(ui_DataChart, + LV_PART_MAIN) + lv_obj_get_style_border_width(ui_DataChart, LV_PART_MAIN)); + lv_obj_set_style_line_width(ui_DataChart_Xaxis, 0, LV_PART_MAIN); + lv_obj_set_style_line_width(ui_DataChart_Xaxis, 1, LV_PART_ITEMS); //LVGL-9.1 ticks are thicker by default + lv_obj_set_style_line_width(ui_DataChart_Xaxis, 1, LV_PART_INDICATOR); + lv_obj_set_style_length(ui_DataChart_Xaxis, 0, LV_PART_ITEMS); //minor tick length + lv_obj_set_style_length(ui_DataChart_Xaxis, 5, LV_PART_INDICATOR); //major tick length + lv_scale_set_range(ui_DataChart_Xaxis, 0, 5 > 0 ? 5 - 1 : 0); + lv_scale_set_total_tick_count(ui_DataChart_Xaxis, (5 > 0 ? 5 - 1 : 0) * 10 + 1); + lv_scale_set_major_tick_every(ui_DataChart_Xaxis, 10 >= 1 ? 10 : 1); + lv_scale_set_label_show(ui_DataChart_Xaxis, false); + ui_DataChart_Yaxis1 = lv_scale_create(ui_DataChart); + lv_scale_set_mode(ui_DataChart_Yaxis1, LV_SCALE_MODE_VERTICAL_LEFT); + lv_obj_set_size(ui_DataChart_Yaxis1, 10, lv_pct(100)); + lv_obj_set_align(ui_DataChart_Yaxis1, LV_ALIGN_LEFT_MID); + lv_obj_set_x(ui_DataChart_Yaxis1, -10 - lv_obj_get_style_pad_left(ui_DataChart, + LV_PART_MAIN) - lv_obj_get_style_border_width(ui_DataChart, LV_PART_MAIN) + 2); + lv_obj_set_style_line_width(ui_DataChart_Yaxis1, 0, LV_PART_MAIN); + lv_obj_set_style_line_width(ui_DataChart_Yaxis1, 1, LV_PART_ITEMS); + lv_obj_set_style_line_width(ui_DataChart_Yaxis1, 1, LV_PART_INDICATOR); + lv_obj_set_style_length(ui_DataChart_Yaxis1, 5, LV_PART_ITEMS); //minor tick length + lv_obj_set_style_length(ui_DataChart_Yaxis1, 10, LV_PART_INDICATOR); //major tick length + lv_scale_set_range(ui_DataChart_Yaxis1, 0, 5); + lv_scale_set_total_tick_count(ui_DataChart_Yaxis1, (5 > 0 ? 5 - 1 : 0) * 2 + 1); + lv_scale_set_major_tick_every(ui_DataChart_Yaxis1, 2 >= 1 ? 2 : 1); + ui_DataChart_Yaxis2 = lv_scale_create(ui_DataChart); + lv_scale_set_mode(ui_DataChart_Yaxis2, LV_SCALE_MODE_VERTICAL_RIGHT); + lv_obj_set_size(ui_DataChart_Yaxis2, 25, lv_pct(100)); + lv_obj_set_align(ui_DataChart_Yaxis2, LV_ALIGN_RIGHT_MID); + lv_obj_set_x(ui_DataChart_Yaxis2, 25 + lv_obj_get_style_pad_right(ui_DataChart, + LV_PART_MAIN) + lv_obj_get_style_border_width(ui_DataChart, LV_PART_MAIN) + 1); + lv_obj_set_style_line_width(ui_DataChart_Yaxis2, 0, LV_PART_MAIN); + lv_obj_set_style_line_width(ui_DataChart_Yaxis2, 1, LV_PART_ITEMS); + lv_obj_set_style_line_width(ui_DataChart_Yaxis2, 1, LV_PART_INDICATOR); + lv_obj_set_style_length(ui_DataChart_Yaxis2, 5, LV_PART_ITEMS); //minor tick length + lv_obj_set_style_length(ui_DataChart_Yaxis2, 10, LV_PART_INDICATOR); //major tick length + lv_scale_set_total_tick_count(ui_DataChart_Yaxis2, (5 > 0 ? 5 - 1 : 0) * 2 + 1); + lv_scale_set_major_tick_every(ui_DataChart_Yaxis2, 2 >= 1 ? 2 : 1); + + lv_obj_set_style_bg_color(ui_DataChart, lv_color_hex(0xFFFFFF), LV_PART_INDICATOR | LV_STATE_DEFAULT); + lv_obj_set_style_bg_opa(ui_DataChart, 0, LV_PART_INDICATOR | LV_STATE_DEFAULT); + + //This workaround (an invisible outline) is needed because without it chart overflow-visible doesn't work in LVGL-9.1 + lv_obj_set_style_outline_pad(ui_DataChart, LV_MAX3(50, 10, 25), + LV_PART_MAIN | LV_STATE_DEFAULT); //workaround for ineffective 'overflow visible' flag + lv_obj_set_style_outline_width(ui_DataChart, -1, LV_PART_MAIN | LV_STATE_DEFAULT); + ui_PanelVol = lv_obj_create(ui_ChartPage); + lv_obj_set_width(ui_PanelVol, 80); + lv_obj_set_height(ui_PanelVol, 35); + lv_obj_set_x(ui_PanelVol, -30); + lv_obj_set_y(ui_PanelVol, -5); + lv_obj_set_align(ui_PanelVol, LV_ALIGN_BOTTOM_MID); + lv_obj_remove_flag(ui_PanelVol, LV_OBJ_FLAG_SCROLLABLE); /// Flags + lv_obj_set_style_bg_color(ui_PanelVol, lv_color_hex(0xE36666), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_bg_opa(ui_PanelVol, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_PanelCur = lv_obj_create(ui_ChartPage); + lv_obj_set_width(ui_PanelCur, 100); + lv_obj_set_height(ui_PanelCur, 35); + lv_obj_set_x(ui_PanelCur, 60); + lv_obj_set_y(ui_PanelCur, -5); + lv_obj_set_align(ui_PanelCur, LV_ALIGN_BOTTOM_MID); + lv_obj_remove_flag(ui_PanelCur, LV_OBJ_FLAG_SCROLLABLE); /// Flags + lv_obj_set_style_bg_color(ui_PanelCur, lv_color_hex(0x42AA49), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_bg_opa(ui_PanelCur, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_LabelVol = lv_label_create(ui_ChartPage); + lv_obj_set_width(ui_LabelVol, LV_SIZE_CONTENT); /// 1 + lv_obj_set_height(ui_LabelVol, LV_SIZE_CONTENT); /// 1 + lv_obj_set_x(ui_LabelVol, -40); + lv_obj_set_y(ui_LabelVol, -12); + lv_obj_set_align(ui_LabelVol, LV_ALIGN_BOTTOM_MID); + lv_label_set_text(ui_LabelVol, "17.23"); + lv_obj_set_style_text_font(ui_LabelVol, &lv_font_montserrat_18, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_LabelVolUnit = lv_label_create(ui_ChartPage); + lv_obj_set_width(ui_LabelVolUnit, LV_SIZE_CONTENT); /// 1 + lv_obj_set_height(ui_LabelVolUnit, LV_SIZE_CONTENT); /// 1 + lv_obj_set_x(ui_LabelVolUnit, -10); + lv_obj_set_y(ui_LabelVolUnit, -12); + lv_obj_set_align(ui_LabelVolUnit, LV_ALIGN_BOTTOM_MID); + lv_label_set_text(ui_LabelVolUnit, "V"); + lv_obj_set_style_text_font(ui_LabelVolUnit, &lv_font_montserrat_18, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_LabelCur = lv_label_create(ui_ChartPage); + lv_obj_set_width(ui_LabelCur, LV_SIZE_CONTENT); /// 1 + lv_obj_set_height(ui_LabelCur, LV_SIZE_CONTENT); /// 1 + lv_obj_set_x(ui_LabelCur, 45); + lv_obj_set_y(ui_LabelCur, -12); + lv_obj_set_align(ui_LabelCur, LV_ALIGN_BOTTOM_MID); + lv_label_set_text(ui_LabelCur, "17.23"); + lv_obj_set_style_text_font(ui_LabelCur, &lv_font_montserrat_18, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_LabelCurUnit = lv_label_create(ui_ChartPage); + lv_obj_set_width(ui_LabelCurUnit, LV_SIZE_CONTENT); /// 1 + lv_obj_set_height(ui_LabelCurUnit, LV_SIZE_CONTENT); /// 1 + lv_obj_set_x(ui_LabelCurUnit, 85); + lv_obj_set_y(ui_LabelCurUnit, -12); + lv_obj_set_align(ui_LabelCurUnit, LV_ALIGN_BOTTOM_MID); + lv_label_set_text(ui_LabelCurUnit, "mA"); + lv_obj_set_style_text_font(ui_LabelCurUnit, &lv_font_montserrat_18, LV_PART_MAIN | LV_STATE_DEFAULT); + + ui_StateBtn = lv_button_create(ui_ChartPage); + lv_obj_set_width(ui_StateBtn, 35); + lv_obj_set_height(ui_StateBtn, 35); + lv_obj_set_x(ui_StateBtn, -90); + lv_obj_set_y(ui_StateBtn, -5); + lv_obj_set_align(ui_StateBtn, LV_ALIGN_BOTTOM_MID); + lv_obj_add_flag(ui_StateBtn, LV_OBJ_FLAG_CHECKABLE | LV_OBJ_FLAG_SCROLL_ON_FOCUS); /// Flags + lv_obj_remove_flag(ui_StateBtn, LV_OBJ_FLAG_SCROLLABLE); /// Flags + lv_obj_set_style_bg_color(ui_StateBtn, lv_color_hex(0xF03737), LV_PART_MAIN | LV_STATE_CHECKED); + lv_obj_set_style_bg_opa(ui_StateBtn, 255, LV_PART_MAIN | LV_STATE_CHECKED); + + ui_StateLabel = lv_label_create(ui_StateBtn); + lv_obj_set_width(ui_StateLabel, LV_SIZE_CONTENT); /// 1 + lv_obj_set_height(ui_StateLabel, LV_SIZE_CONTENT); /// 1 + lv_obj_set_align(ui_StateLabel, LV_ALIGN_CENTER); + lv_label_set_text(ui_StateLabel, LV_SYMBOL_PLAY); + + ui_TickVolUnit = lv_label_create(ui_ChartPage); + lv_obj_set_width(ui_TickVolUnit, LV_SIZE_CONTENT); /// 1 + lv_obj_set_height(ui_TickVolUnit, LV_SIZE_CONTENT); /// 1 + lv_obj_set_align(ui_TickVolUnit, LV_ALIGN_CENTER); + lv_obj_set_pos(ui_TickVolUnit, -105, 75); + lv_label_set_text(ui_TickVolUnit, "V"); + + ui_TickCurUnit = lv_label_create(ui_ChartPage); + lv_obj_set_width(ui_TickCurUnit, LV_SIZE_CONTENT); /// 1 + lv_obj_set_height(ui_TickCurUnit, LV_SIZE_CONTENT); /// 1 + lv_obj_set_align(ui_TickCurUnit, LV_ALIGN_CENTER); + lv_obj_set_pos(ui_TickCurUnit, 105, 75); + lv_label_set_text(ui_TickCurUnit, "mA"); + + + // 设置图表为循环更新模式 + lv_chart_set_update_mode(ui_DataChart, LV_CHART_UPDATE_MODE_CIRCULAR); + + // 添加数据系列 + lv_chart_series_t * ui_DataChart_series_1 = lv_chart_add_series(ui_DataChart, lv_color_hex(0xE36666), + LV_CHART_AXIS_PRIMARY_Y); + lv_chart_set_ext_y_array(ui_DataChart, ui_DataChart_series_1, ui_DataChart_vol_array); + + lv_chart_series_t * ui_DataChart_series_2 = lv_chart_add_series(ui_DataChart, lv_color_hex(0x42AA49), + LV_CHART_AXIS_SECONDARY_Y); + lv_chart_set_ext_y_array(ui_DataChart, ui_DataChart_series_2, ui_DataChart_cur_array); + + // btn event + lv_obj_add_event_cb(ui_StateBtn, _ui_Chart_Btn_cb, LV_EVENT_CLICKED, NULL); + + // timer + chart_update_timer = lv_timer_create(_chart_update_cb, 100, ui_DataChart); // 每100ms更新一次数据 + + +} + +void ui_ChartPage_screen_destroy(void) +{ + lv_timer_del(chart_update_timer); +} diff --git a/Power_Pico/User/GUI/screens/ui_ChartPage.h b/Power_Pico/User/GUI/screens/ui_ChartPage.h new file mode 100644 index 0000000..73afc98 --- /dev/null +++ b/Power_Pico/User/GUI/screens/ui_ChartPage.h @@ -0,0 +1,24 @@ +// This file was generated by SquareLine Studio +// SquareLine Studio version: SquareLine Studio 1.5.3 +// LVGL version: 9.2.2 +// Project name: PowerPico + +#ifndef UI_CHARTPAGE_H +#define UI_CHARTPAGE_H + +#ifdef __cplusplus +extern "C" { +#endif + +// SCREEN: ui_ChartPage +extern void ui_ChartPage_screen_init(void); +extern void ui_ChartPage_screen_destroy(void); +extern lv_obj_t * ui_ChartPage; +void ui_chart_page_key_handler(uint8_t key_id); + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif + diff --git a/Power_Pico/User/GUI/ui.c b/Power_Pico/User/GUI/ui.c index 654bd2b..7d678a5 100644 --- a/Power_Pico/User/GUI/ui.c +++ b/Power_Pico/User/GUI/ui.c @@ -3,6 +3,7 @@ #include "./ui.h" #include "./screens/ui_mainPage.h" +#include "./screens/ui_chartPage.h" ///////////////////// VARIABLES //////////////////// @@ -15,6 +16,13 @@ Page_t pages[] = { .key_event_handler = ui_main_page_key_handler, .name = "Main Page" }, + { + .init = ui_ChartPage_screen_init, + .deinit = ui_ChartPage_screen_destroy, + .page_obj = &ui_ChartPage, + .key_event_handler = ui_chart_page_key_handler, + .name = "Chart Page" + }, // 可以在这里添加更多页面 }; @@ -47,5 +55,5 @@ void ui_init(void) PageManager_load_init_screen(); //timer - lv_timer_t * ui_MainTimer = lv_timer_create(main_timer, 1000, NULL); + // lv_timer_t * ui_MainTimer = lv_timer_create(main_timer, 1000, NULL); }