// Grafik Routinen #define GRAFIK #include "handlebme280.h" #include "main.h" #include "grafik.h" #define DRAW_BUF_SIZE (SCREEN_WIDTH * SCREEN_HEIGHT / 10 * (LV_COLOR_DEPTH / 8)) uint32_t draw_buf[DRAW_BUF_SIZE / 4]; static lv_obj_t * chart; static lv_coord_t bmewert[MAXREADINGS]; static lv_coord_t bmewert_hum[MAXREADINGS]; void setup_grafik(void) { lv_init(); lv_display_t * disp; disp = lv_tft_espi_create(SCREEN_WIDTH, SCREEN_HEIGHT, draw_buf, sizeof(draw_buf)); for (int i = 0; i < MAXREADINGS; i++) { bmewert[i] = 0; bmewert_hum[i] = 30; } } void buildarc(ARC arc) { lv_obj_set_size(arc.arc, arc.size, arc.size); lv_arc_set_rotation(arc.arc, 180); lv_arc_set_bg_angles(arc.arc, 0, 180); lv_arc_set_value(arc.arc, arc.value); lv_obj_align(arc.arc, LV_ALIGN_LEFT_MID, arc.x, arc.y); lv_obj_remove_style(arc.arc, NULL, LV_PART_KNOB); // Style this arc static lv_style_t style_arc; lv_style_init(&style_arc); lv_style_set_arc_width(&style_arc, 20); lv_style_set_arc_rounded(&style_arc, false); lv_obj_add_style(arc.arc, &style_arc, LV_PART_MAIN); lv_obj_add_style(arc.arc, &style_arc, LV_PART_INDICATOR); lv_obj_t * low_label = lv_label_create(arc.arc); char valuelow[10]; sprintf(valuelow, "%d", arc.lowvalue); lv_label_set_text(low_label, valuelow); lv_obj_align(low_label, LV_ALIGN_LEFT_MID, 5, 8); static lv_style_t style_low_label; lv_style_init(&style_low_label); lv_style_set_text_font(&style_low_label, &lv_font_montserrat_10); lv_obj_add_style(low_label, &style_low_label, 0); lv_obj_t * value_label = lv_label_create(arc.arc); char value[10]; sprintf(value, arc.valformat, arc.value); // Serial.println(value); lv_label_set_text(value_label, value); lv_obj_align(value_label, LV_ALIGN_LEFT_MID, 38 + arc.value_offset, 0); static lv_style_t style_value_label; lv_style_init(&style_value_label); lv_style_set_text_font(&style_value_label, &lv_font_montserrat_18); lv_obj_add_style(value_label, &style_value_label, 0); lv_obj_t * high_label = lv_label_create(arc.arc); char valuehigh[10]; sprintf(valuehigh, "%d", arc.highvalue); lv_label_set_text(high_label, valuehigh); lv_obj_align(high_label, LV_ALIGN_LEFT_MID, 90, 8); static lv_style_t style_high_label; lv_style_init(&style_high_label); lv_style_set_text_font(&style_high_label, &lv_font_montserrat_10); lv_obj_add_style(high_label, &style_high_label, 0); /* lv_obj_t * unit_label = lv_label_create(arc.arc); lv_label_set_text(unit_label, arc.unit); lv_obj_align(unit_label, LV_ALIGN_LEFT_MID, 48, 8); static lv_style_t style_unit_label; lv_style_init(&style_unit_label); lv_style_set_text_font(&style_unit_label, &lv_font_montserrat_12); lv_obj_add_style(unit_label, &style_unit_label, 0); */ } void lv_create_main_gui(void) { // Create a text label aligned on top: https://docs.lvgl.io/master/widgets/label.html time_label = lv_label_create(lv_screen_active()); lv_label_set_text(time_label, "17:30"); lv_obj_align(time_label, LV_ALIGN_TOP_MID, 0, 8); // Set font type and font size. More information: https://docs.lvgl.io/master/overview/font.html static lv_style_t style_time_label; lv_style_init(&style_time_label); lv_style_set_text_font(&style_time_label, &lv_font_montserrat_28); lv_obj_add_style(time_label, &style_time_label, 0); // Create a text label aligned on top: https://docs.lvgl.io/master/widgets/label.html date_label = lv_label_create(lv_screen_active()); lv_label_set_text(date_label, "Dienstag, 12. Dezember 2024"); lv_obj_align(date_label, LV_ALIGN_TOP_MID, 0, 38); // Set font type and font size. More information: https://docs.lvgl.io/master/overview/font.html static lv_style_t style_date_label; lv_style_init(&style_date_label); lv_style_set_text_font(&style_date_label, &lv_font_montserrat_12); lv_obj_add_style(date_label, &style_date_label, 0); /* Refresh-Symbol anzeigen lv_obj_t * refresh_label = lv_label_create(lv_screen_active()); lv_label_set_text(refresh_label, LV_SYMBOL_REFRESH); lv_obj_align(refresh_label, LV_ALIGN_CENTER, 0, -45); */ // Text als Überschrift an die Axen lv_obj_t * feuchte_label = lv_label_create(lv_screen_active()); lv_label_set_text(feuchte_label, "Feuchte"); lv_obj_align(feuchte_label, LV_ALIGN_RIGHT_MID, -3, 20); // Set font type and font size. More information: https://docs.lvgl.io/master/overview/font.html static lv_style_t style_feuchte_label; lv_style_init(&style_feuchte_label); lv_style_set_text_font(&style_feuchte_label, &lv_font_montserrat_10); lv_obj_add_style(feuchte_label, &style_feuchte_label, 0); lv_obj_t * temp_label = lv_label_create(lv_screen_active()); lv_label_set_text(temp_label, "Temperatur"); lv_obj_align(temp_label, LV_ALIGN_LEFT_MID, 3, 20); // Set font type and font size. More information: https://docs.lvgl.io/master/overview/font.html static lv_style_t style_temp_label; lv_style_init(&style_temp_label); lv_style_set_text_font(&style_temp_label, &lv_font_montserrat_10); lv_obj_add_style(temp_label, &style_temp_label, 0); /*Create an Arc*/ lv_obj_t * aTemp = lv_arc_create(lv_screen_active()); arcTemp.arc = aTemp; buildarc(arcTemp); lv_obj_t * aHum = lv_arc_create(lv_screen_active()); arcHum.arc = aHum; buildarc(arcHum); lv_obj_set_style_bg_color(lv_screen_active(), lv_color_hex(BACKGROUND_COLOR), LV_PART_MAIN); } void setValuetoArc(ARC arc, float value) { int r = arc.highvalue - arc.lowvalue; int v = (value - arc.lowvalue) * 100 / r; arc.value = v; lv_arc_set_value(arc.arc, arc.value); lv_obj_t * value_label = lv_obj_get_child(arc.arc, 1); char valuestr[10]; sprintf(valuestr, arc.valformat, value); lv_label_set_text(value_label, valuestr); if( strcmp(arc.name, "humi") == 0) { if (value < arc.green) { lv_obj_set_style_arc_color(arc.arc, lv_palette_main(LV_PALETTE_GREEN), LV_PART_INDICATOR); } else if (value < arc.yellow) { lv_obj_set_style_arc_color(arc.arc, lv_palette_main(LV_PALETTE_YELLOW), LV_PART_INDICATOR); } else { lv_obj_set_style_arc_color(arc.arc, lv_palette_main(LV_PALETTE_RED), LV_PART_INDICATOR); } } } #define CONTAINER_WIDTH SCREEN_WIDTH #define CONTAINER_HEIGHT SCREEN_HEIGHT-145 #define LEFTAXIS_WIDTH 25 #define RIGHTAXIS_WIDTH 15 #define CHART_WIDTH (CONTAINER_WIDTH - LEFTAXIS_WIDTH - RIGHTAXIS_WIDTH - 40) #define CHART_HEIGHT (CONTAINER_HEIGHT) void drawChart() { Serial.println("draw_chart "); // Create a container to display the chart and scale lv_obj_t * container_row = lv_obj_create(lv_screen_active()); lv_obj_set_size(container_row, CONTAINER_WIDTH, CONTAINER_HEIGHT); lv_obj_align(container_row, LV_ALIGN_BOTTOM_MID, 0, 0); // Set the container in a flexbox row layout aligned center lv_obj_set_flex_flow(container_row, LV_FLEX_FLOW_ROW); lv_obj_set_flex_align(container_row, LV_FLEX_ALIGN_CENTER,LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER); lv_obj_set_scrollbar_mode(container_row, LV_SCROLLBAR_MODE_OFF); static lv_style_t style_container_row; lv_style_set_pad_row(&style_container_row, 0); //lv_style_set_bg_color(&style_container_row, lv_palette_lighten(LV_PALETTE_LIGHT_BLUE, 4)); lv_obj_add_style(container_row, &style_container_row, 0); lv_obj_set_style_border_side(container_row, LV_BORDER_SIDE_BOTTOM, LV_PART_MAIN); lv_obj_set_style_bg_color(container_row, lv_color_hex(BACKGROUND_COLOR), LV_PART_MAIN); // linke Axe lv_obj_t * scaleT = lv_scale_create(container_row); lv_obj_set_size(scaleT, 30, 75); lv_scale_set_mode(scaleT, LV_SCALE_MODE_VERTICAL_LEFT); static const char * scaleT_labels[5] = {"10°C", "15°C", "20°C", "25°C", "30°C"}; lv_scale_set_text_src(scaleT, scaleT_labels); lv_scale_set_label_show(scaleT, true); lv_scale_set_total_tick_count(scaleT, 21); lv_scale_set_major_tick_every(scaleT, 5); lv_obj_set_style_length(scaleT, 0, LV_PART_ITEMS); lv_obj_set_style_length(scaleT, 0, LV_PART_INDICATOR); lv_obj_set_style_line_width(scaleT, 0, LV_PART_ITEMS); lv_obj_set_style_line_width(scaleT, 0, LV_PART_INDICATOR); lv_obj_set_style_line_width(scaleT, 0, LV_PART_MAIN); lv_scale_set_range(scaleT, 10, 30); static lv_style_t style_scaleT; lv_style_init(&style_scaleT); lv_style_set_text_font(&style_scaleT, &lv_font_montserrat_10); lv_style_set_text_color(&style_scaleT, lv_color_hex(0x0000FF)); // lv_style_set_bg_color(&style_scaleT, lv_color_hex(0xFF00FF)); lv_obj_add_style(scaleT, &style_scaleT, 0); // Create a chart chart = lv_chart_create(container_row); lv_obj_set_size(chart, CHART_WIDTH, CHART_HEIGHT); lv_chart_set_type(chart, LV_CHART_TYPE_LINE); /*Show lines and points too*/ lv_chart_set_point_count(chart, MAXREADINGS); lv_chart_set_div_line_count(chart, 5, 5); lv_chart_set_range(chart, LV_CHART_AXIS_SECONDARY_Y, 40, 100); lv_chart_set_range(chart, LV_CHART_AXIS_PRIMARY_Y, 10, 30); lv_obj_set_style_size(chart, 0, 0, LV_PART_INDICATOR); // No points on line lv_obj_set_scrollbar_mode(chart, LV_SCROLLBAR_MODE_OFF); lv_obj_set_style_border_width(chart, 0, LV_PART_MAIN); // No border lv_obj_set_style_bg_color(chart, lv_color_hex(BACKGROUND_COLOR), LV_PART_MAIN); // lv_obj_set_style_pad_right(chart, -10, LV_PART_MAIN); // No border /*Add data series*/ lv_chart_series_t * ser1 = lv_chart_add_series(chart, lv_palette_main(LV_PALETTE_BLUE), LV_CHART_AXIS_PRIMARY_Y); lv_chart_set_ext_y_array(chart, ser1, (lv_coord_t *)bmewert); lv_chart_series_t * ser2 = lv_chart_add_series(chart, lv_palette_main(LV_PALETTE_RED), LV_CHART_AXIS_SECONDARY_Y); lv_chart_set_ext_y_array(chart, ser2, (lv_coord_t *)bmewert_hum); lv_chart_refresh(chart); /*Required after direct set*/ // rechte Axe lv_obj_t * scale = lv_scale_create(container_row); lv_obj_set_size(scale, 30, 75); lv_scale_set_mode(scale, LV_SCALE_MODE_VERTICAL_RIGHT); static const char * scale_labels[5] = {"40%", "55%", "70%", "85%", "100%"}; lv_scale_set_text_src(scale, scale_labels); lv_scale_set_label_show(scale, true); lv_scale_set_total_tick_count(scale, 21); lv_scale_set_major_tick_every(scale, 5); lv_obj_set_style_length(scale, 0, LV_PART_ITEMS); lv_obj_set_style_length(scale, 0, LV_PART_INDICATOR); lv_obj_set_style_line_width(scale, 0, LV_PART_ITEMS); lv_obj_set_style_line_width(scale, 1, LV_PART_INDICATOR); lv_obj_set_style_line_width(scale, 0, LV_PART_MAIN); lv_obj_set_style_bg_color(scale, lv_color_hex(BACKGROUND_COLOR), LV_PART_MAIN); lv_scale_set_range(scale, 40, 100); static lv_style_t style_scale; lv_style_init(&style_scale); lv_style_set_text_font(&style_scale, &lv_font_montserrat_10); lv_style_set_text_color(&style_scale, lv_color_hex(0xFF0000)); lv_obj_add_style(scale, &style_scale, 0); /* // Label an der Axe lv_obj_t * unitxAx_label = lv_label_create(container_row); lv_label_set_text(unitxAx_label, "°C"); lv_obj_align(unitxAx_label, LV_ALIGN_TOP_RIGHT, -20, 8); static lv_style_t style_unitxAx_label; lv_style_init(&style_unitxAx_label); lv_style_set_text_font(&style_unitxAx_label, &lv_font_montserrat_12); lv_obj_add_style(unitxAx_label, &style_unitxAx_label, 0); */ /* ganz rechts unten die Version anzeigen */ lv_obj_t * version_label = lv_label_create(chart); char ver[20]; sprintf(ver, "V %s %s", VERSION, VDATE); lv_label_set_text(version_label, ver); lv_obj_align(version_label, LV_ALIGN_BOTTOM_RIGHT, 0, 9); // Set font type and font size. More information: https://docs.lvgl.io/master/overview/font.html static lv_style_t style_version_label; lv_style_init(&style_version_label); lv_style_set_text_font(&style_version_label, &lv_font_montserrat_8); lv_style_set_text_color(&style_version_label, lv_palette_main(LV_PALETTE_GREY)); lv_obj_add_style(version_label, &style_version_label, LV_PART_MAIN); } void updatechartData(float value, float humvalue) { int i = 0; for (i = 0; i < MAXREADINGS - 1; i++) { bmewert[i] = bmewert[i + 1]; bmewert_hum[i] = bmewert_hum[i + 1]; } bmewert[MAXREADINGS - 1] = value; bmewert_hum[MAXREADINGS - 1] = humvalue; lv_chart_refresh(chart); }