diff --git a/CYD-Klipper/platformio.ini b/CYD-Klipper/platformio.ini index cc99151..efe33db 100644 --- a/CYD-Klipper/platformio.ini +++ b/CYD-Klipper/platformio.ini @@ -19,6 +19,7 @@ lib_deps = https://github.com/Bodmer/TFT_eSPI.git https://github.com/PaulStoffregen/XPT2046_Touchscreen.git bblanchon/ArduinoJson@^7.0.0 + plageoj/UrlEncode@^1.0.1 monitor_filters = esp32_exception_decoder build_flags = -DLV_CONF_PATH="../../../../src/conf/lv_conf.h" @@ -39,23 +40,13 @@ build_flags = -DSPI_FREQUENCY=55000000 -DSPI_READ_FREQUENCY=20000000 -DSPI_TOUCH_FREQUENCY=2500000 - - ### Porting options ### - # Defines the screen height + -DCYD_SCREEN_HEIGHT_PX=240 - # Defines the screen width -DCYD_SCREEN_WIDTH_PX=320 - # Defines the pixel gap used for large gaps (like between buttons) -DCYD_SCREEN_GAP_PX=8 - # Defines the minimum pixel height of a button -DCYD_SCREEN_MIN_BUTTON_HEIGHT_PX=35 - # Defines the minimum pixel width of a button -DCYD_SCREEN_MIN_BUTTON_WIDTH_PX=35 - # Defines the size of font used -DCYD_SCREEN_FONT=&lv_font_montserrat_14 - # Defines the size of font used for small text -DCYD_SCREEN_FONT_SMALL=&lv_font_montserrat_10 - # Defines the size of the sizebar -DCYD_SCREEN_SIDEBAR_SIZE_PX=40 - # Defines the screen driver - -DCYD_SCREEN_DRIVER_ESP32_2432S028R=1 \ No newline at end of file + -DCYD_SCREEN_DRIVER_ESP32_2432S028R=1 diff --git a/CYD-Klipper/src/core/data_setup.cpp b/CYD-Klipper/src/core/data_setup.cpp index b02b986..8686c30 100644 --- a/CYD-Klipper/src/core/data_setup.cpp +++ b/CYD-Klipper/src/core/data_setup.cpp @@ -6,6 +6,7 @@ #include #include #include "macros_query.h" +#include const char *printer_state_messages[] = { "Error", @@ -43,8 +44,9 @@ void unfreeze_render_thread(){ void send_gcode(bool wait, const char *gcode) { + Serial.printf("Sending gcode: %s\n", gcode); char buff[256] = {}; - sprintf(buff, "http://%s:%d/printer/gcode/script?script=%s", global_config.klipperHost, global_config.klipperPort, gcode); + sprintf(buff, "http://%s:%d/printer/gcode/script?script=%s", global_config.klipperHost, global_config.klipperPort, urlEncode(gcode).c_str()); HTTPClient client; client.begin(buff); @@ -67,7 +69,7 @@ void fetch_printer_data() { freeze_request_thread(); char buff[256] = {}; - sprintf(buff, "http://%s:%d/printer/objects/query?extruder&heater_bed&toolhead&gcode_move&virtual_sdcard&print_stats&webhooks", global_config.klipperHost, global_config.klipperPort); + sprintf(buff, "http://%s:%d/printer/objects/query?extruder&heater_bed&toolhead&gcode_move&virtual_sdcard&print_stats&webhooks&fan", global_config.klipperHost, global_config.klipperPort); HTTPClient client; client.useHTTP10(true); client.begin(buff); @@ -139,8 +141,18 @@ void fetch_printer_data() printer.position[0] = status["gcode_move"]["gcode_position"][0]; printer.position[1] = status["gcode_move"]["gcode_position"][1]; printer.position[2] = status["gcode_move"]["gcode_position"][2]; + printer.gcode_offset[0] = status["gcode_move"]["homing_origin"][0]; + printer.gcode_offset[1] = status["gcode_move"]["homing_origin"][1]; + printer.gcode_offset[2] = status["gcode_move"]["homing_origin"][2]; bool absolute_coords = status["gcode_move"]["absolute_coordinates"]; printer.absolute_coords = absolute_coords == true; + printer.speed_mult = status["gcode_move"]["speed_factor"]; + printer.extrude_mult = status["gcode_move"]["extrude_factor"]; + } + + if (status.containsKey("fan")) + { + printer.fan_speed = status["fan"]["speed"]; } if (status.containsKey("virtual_sdcard")) diff --git a/CYD-Klipper/src/core/data_setup.h b/CYD-Klipper/src/core/data_setup.h index fc0a44f..109f108 100644 --- a/CYD-Klipper/src/core/data_setup.h +++ b/CYD-Klipper/src/core/data_setup.h @@ -25,6 +25,10 @@ typedef struct _Printer { float filament_used_mm; char* print_filename; // 0 -> 1 float print_progress; + float fan_speed; // 0 -> 1 + float gcode_offset[3]; + float speed_mult; + float extrude_mult; } Printer; extern Printer printer; diff --git a/CYD-Klipper/src/ui/ip_setup.cpp b/CYD-Klipper/src/ui/ip_setup.cpp index c6a3930..ffa236e 100644 --- a/CYD-Klipper/src/ui/ip_setup.cpp +++ b/CYD-Klipper/src/ui/ip_setup.cpp @@ -80,7 +80,8 @@ void ip_init_inner(){ lv_obj_t * resetBtn = lv_btn_create(lv_scr_act()); lv_obj_add_event_cb(resetBtn, reset_btn_event_handler, LV_EVENT_ALL, NULL); - lv_obj_align(resetBtn, LV_ALIGN_CENTER, 0, 40); + lv_obj_set_height(resetBtn, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); + lv_obj_align(resetBtn, LV_ALIGN_CENTER, 0, CYD_SCREEN_GAP_PX + CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); lv_obj_t * btnLabel = lv_label_create(resetBtn); lv_label_set_text(btnLabel, "Reset"); diff --git a/CYD-Klipper/src/ui/panels/move_panel.cpp b/CYD-Klipper/src/ui/panels/move_panel.cpp index 4da42b0..d28ecba 100644 --- a/CYD-Klipper/src/ui/panels/move_panel.cpp +++ b/CYD-Klipper/src/ui/panels/move_panel.cpp @@ -19,9 +19,7 @@ static void move_printer(const char* axis, float amount) { send_gcode(true, "G91"); } - const char * space = "%20"; - - sprintf(gcode, "G1%s%s%s%.1f%sF6000", space, axis, extra, amount, space); + sprintf(gcode, "G1 %s%s%.1f F6000", axis, extra, amount); send_gcode(true, gcode); if (absolute_coords) { @@ -195,6 +193,11 @@ static void root_panel_state_update(lv_event_t * e){ } void move_panel_init(lv_obj_t* panel){ + if (printer.state == PRINTER_STATE_PRINTING){ + stats_panel_init(panel); + return; + } + last_homing_state = !printer.homed_axis; lv_obj_add_event_cb(panel, root_panel_state_update, LV_EVENT_MSG_RECEIVED, NULL); diff --git a/CYD-Klipper/src/ui/panels/panel.h b/CYD-Klipper/src/ui/panels/panel.h index ac65776..0656035 100644 --- a/CYD-Klipper/src/ui/panels/panel.h +++ b/CYD-Klipper/src/ui/panels/panel.h @@ -7,4 +7,5 @@ void temp_panel_init(lv_obj_t* panel); void print_panel_init(lv_obj_t* panel); void move_panel_init(lv_obj_t* panel); void progress_panel_init(lv_obj_t* panel); -void macros_panel_init(lv_obj_t* panel); \ No newline at end of file +void macros_panel_init(lv_obj_t* panel); +void stats_panel_init(lv_obj_t* panel); \ No newline at end of file diff --git a/CYD-Klipper/src/ui/panels/stats_panel.cpp b/CYD-Klipper/src/ui/panels/stats_panel.cpp new file mode 100644 index 0000000..417bfad --- /dev/null +++ b/CYD-Klipper/src/ui/panels/stats_panel.cpp @@ -0,0 +1,166 @@ +#include "panel.h" +#include "../ui_utils.h" +#include "../../core/data_setup.h" +#include +#include + +static void set_fan_speed_text(lv_event_t * e) { + lv_obj_t * label = lv_event_get_target(e); + char data[64]; + sprintf(data, "Fan: %.0f%%", printer.fan_speed * 100); + lv_label_set_text(label, data); +} + +static void set_fan_speed(lv_event_t * e){ + int speed = (int)lv_event_get_user_data(e); + char gcode[64]; + sprintf(gcode, "M106 S%d", speed); + send_gcode(true, gcode); +} + +const char* fan_speeds[] = { "0%", "15%", "25%", "35%" }; +const int fan_speeds_values[] = { 0, 38, 64, 90 }; + +const char* fan_speeds_2[] = { "50%", "75%", "100%"}; +const int fan_speeds_values_2[] = { 128, 192, 255 }; + +lv_button_column_t fan_speed_columns[] = { + { set_fan_speed, fan_speeds, (const void**)fan_speeds_values, 4}, + { set_fan_speed, fan_speeds_2, (const void**)fan_speeds_values_2, 3} +}; + +static void set_zoffset_text(lv_event_t * e) { + lv_obj_t * label = lv_event_get_target(e); + char data[64]; + sprintf(data, "Z Offset: %.03f", printer.gcode_offset[2]); + lv_label_set_text(label, data); +} + +static void set_zoffset(lv_event_t * e){ + char* offset = (char*)lv_event_get_user_data(e); + char gcode[64]; + sprintf(gcode, "SET_GCODE_OFFSET Z_ADJUST=%s", offset); + send_gcode(true, gcode); +} + +const char* zoffsets[] = { "-0.005", "-0.01", "-0.025", "-0.05" }; +const char* zoffsets_2[] = { "+0.005", "+0.01", "+0.025", "+0.05" }; + +lv_button_column_t zoffset_columns[] = { + { set_zoffset, zoffsets, (const void**)zoffsets, 4}, + { set_zoffset, zoffsets_2, (const void**)zoffsets_2, 4} +}; + +static void set_speed_mult_text(lv_event_t * e){ + lv_obj_t * label = lv_event_get_target(e); + char data[64]; + sprintf(data, "Speed: %.0f%%", printer.speed_mult * 100); + lv_label_set_text(label, data); +} + +static void set_speed_mult(lv_event_t * e){ + int speed = (int)lv_event_get_user_data(e); + char gcode[64]; + sprintf(gcode, "M220 S%d", speed); + send_gcode(true, gcode); +} + +static void set_speed_mult_offset(lv_event_t * e){ + int speed = (int)lv_event_get_user_data(e); + float result = printer.speed_mult * 100 + speed; + printer.speed_mult = result / 100; + char gcode[64]; + sprintf(gcode, "M220 S%.0f", result); + send_gcode(true, gcode); +} + +const char* speed_presets[] = { "50%", "100%", "150%", "200%" }; +const int speed_presets_values[] = { 50, 100, 150, 200 }; +const char* speed_presets_minus[] = { "-1%", "-5%", "-10%", "-25%" }; +const int speed_presets_minus_values[] = { -1, -5, -10, -25 }; +const char* speed_presets_plus[] = { "+1%", "+5%", "+10%", "+25%" }; +const int speed_presets_plus_values[] = { 1, 5, 10, 25 }; + +lv_button_column_t speed_mult_columns[] = { + { set_speed_mult, speed_presets, (const void**)speed_presets_values, 4}, + { set_speed_mult_offset, speed_presets_minus, (const void**)speed_presets_minus_values, 4}, + { set_speed_mult_offset, speed_presets_plus, (const void**)speed_presets_plus_values, 4} +}; + +static void set_extrude_mult_text(lv_event_t * e){ + lv_obj_t * label = lv_event_get_target(e); + char data[64]; + sprintf(data, "Flow: %.0f%%", printer.extrude_mult * 100); + lv_label_set_text(label, data); +} + +static void set_extrude_mult(lv_event_t * e){ + int speed = (int)lv_event_get_user_data(e); + char gcode[64]; + sprintf(gcode, "M221 S%d", speed); + send_gcode(true, gcode); +} + +static void set_extrude_mult_offset(lv_event_t * e){ + int speed = (int)lv_event_get_user_data(e); + float result = printer.extrude_mult * 100 + speed; + printer.extrude_mult = result / 100; + char gcode[64]; + sprintf(gcode, "M221 S%.0f", result); + send_gcode(true, gcode); +} + +const char* extrude_presets[] = { "95%", "100%", "105%", "110%" }; +const int extrude_presets_values[] = { 95, 100, 105, 110 }; +const char* extrude_offset[] = { "+5%", "+1%", "-1%", "-5%" }; +const int extrude_offset_values[] = { 5, 1, -1, -5 }; + +lv_button_column_t extrude_mult_columns[] = { + { set_extrude_mult, extrude_presets, (const void**)extrude_presets_values, 4}, + { set_extrude_mult_offset, extrude_offset, (const void**)extrude_offset_values, 4} +}; + +static void open_fan_speed_panel(lv_event_t * e){ + lv_create_fullscreen_button_matrix_popup(lv_scr_act(), set_fan_speed_text, fan_speed_columns, 2); + lv_msg_send(DATA_PRINTER_DATA, &printer); +} + +static void open_zoffset_panel(lv_event_t * e){ + lv_create_fullscreen_button_matrix_popup(lv_scr_act(), set_zoffset_text, zoffset_columns, 2); + lv_msg_send(DATA_PRINTER_DATA, &printer); +} + +static void open_speed_mult_panel(lv_event_t * e){ + lv_create_fullscreen_button_matrix_popup(lv_scr_act(), set_speed_mult_text, speed_mult_columns, 3); + lv_msg_send(DATA_PRINTER_DATA, &printer); +} + +static void open_extrude_mult_panel(lv_event_t * e){ + lv_create_fullscreen_button_matrix_popup(lv_scr_act(), set_extrude_mult_text, extrude_mult_columns, 2); + lv_msg_send(DATA_PRINTER_DATA, &printer); +} + +void create_state_button(lv_obj_t * root, lv_event_cb_t label, lv_event_cb_t button){ + lv_obj_t * btn = lv_btn_create(root); + lv_obj_set_size(btn, CYD_SCREEN_PANEL_WIDTH_PX / 2 - CYD_SCREEN_GAP_PX * 3, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); + lv_obj_add_event_cb(btn, button, LV_EVENT_CLICKED, NULL); + + lv_obj_t * label_obj = lv_label_create(btn); + lv_obj_add_event_cb(label_obj, label, LV_EVENT_MSG_RECEIVED, NULL); + lv_msg_subscribe_obj(DATA_PRINTER_DATA, label_obj, NULL); + lv_obj_align(label_obj, LV_ALIGN_CENTER, 0, 0); +} + +void stats_panel_init(lv_obj_t* panel) { + auto panel_width = CYD_SCREEN_PANEL_WIDTH_PX / 2 - CYD_SCREEN_GAP_PX * 3; + + lv_obj_t * right_panel = lv_create_empty_panel(panel); + lv_obj_set_size(right_panel, panel_width, CYD_SCREEN_HEIGHT_PX - CYD_SCREEN_GAP_PX * 2); + lv_layout_flex_column(right_panel, LV_FLEX_ALIGN_CENTER); + lv_obj_align(right_panel, LV_ALIGN_TOP_RIGHT, -1 * CYD_SCREEN_GAP_PX, CYD_SCREEN_GAP_PX); + + create_state_button(right_panel, set_fan_speed_text, open_fan_speed_panel); + create_state_button(right_panel, set_zoffset_text, open_zoffset_panel); + create_state_button(right_panel, set_speed_mult_text, open_speed_mult_panel); + create_state_button(right_panel, set_extrude_mult_text, open_extrude_mult_panel); +} \ No newline at end of file diff --git a/CYD-Klipper/src/ui/panels/temp_panel.cpp b/CYD-Klipper/src/ui/panels/temp_panel.cpp index 34a7350..3ee3633 100644 --- a/CYD-Klipper/src/ui/panels/temp_panel.cpp +++ b/CYD-Klipper/src/ui/panels/temp_panel.cpp @@ -80,15 +80,14 @@ static void keyboard_callback(lv_event_t * e){ } char gcode[64]; - const char* space = "%20"; switch (keyboard_target){ case TARGET_HOTEND: - sprintf(gcode, "M104%sS%d", space, temp); + sprintf(gcode, "M104 S%d", temp); send_gcode(true, gcode); break; case TARGET_BED: - sprintf(gcode, "M140%sS%d", space, temp); + sprintf(gcode, "M140 S%d", temp); send_gcode(true, gcode); break; case TARGET_HOTEND_CONFIG_1: @@ -156,8 +155,8 @@ static void cooldown_temp(lv_event_t * e){ return; } - send_gcode(true, "M104%20S0"); - send_gcode(true, "M140%20S0"); + send_gcode(true, "M104 S0"); + send_gcode(true, "M140 S0"); } static void btn_extrude(lv_event_t * e){ @@ -166,7 +165,7 @@ static void btn_extrude(lv_event_t * e){ } send_gcode(true, "M83"); - send_gcode(true, "G1%20E25%20F300"); + send_gcode(true, "G1 E25 F300"); } static void set_temp_via_preset(lv_event_t * e){ @@ -180,11 +179,10 @@ static void set_temp_via_preset(lv_event_t * e){ } char gcode[64]; - const char* space = "%20"; if (target <= TARGET_HOTEND_CONFIG_3) - sprintf(gcode, "M104%sS%d", space, value); + sprintf(gcode, "M104 S%d", value); else - sprintf(gcode, "M140%sS%d", space, value); + sprintf(gcode, "M140 S%d", value); send_gcode(true, gcode); } @@ -201,7 +199,7 @@ static void btn_retract(lv_event_t * e){ } send_gcode(true, "M83"); - send_gcode(true, "G1%20E-25%20F300"); + send_gcode(true, "G1 E-25 F300"); } void temp_panel_init(lv_obj_t * panel){ diff --git a/CYD-Klipper/src/ui/ui_utils.cpp b/CYD-Klipper/src/ui/ui_utils.cpp index a489d4a..26ce3c5 100644 --- a/CYD-Klipper/src/ui/ui_utils.cpp +++ b/CYD-Klipper/src/ui/ui_utils.cpp @@ -1,5 +1,6 @@ #include "lvgl.h" #include "ui_utils.h" +#include "../core/data_setup.h" lv_obj_t* lv_create_empty_panel(lv_obj_t* root) { lv_obj_t* panel = lv_obj_create(root); @@ -23,4 +24,64 @@ void lv_layout_flex_row(lv_obj_t* obj, lv_flex_align_t allign, lv_coord_t pad_co lv_obj_set_flex_align(obj, allign, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER); lv_obj_set_style_pad_column(obj, pad_column, 0); lv_obj_set_style_pad_row(obj, pad_row, 0); +} + +static void lv_fullscreen_menu_close(lv_event_t * e){ + lv_obj_t * panel = (lv_obj_t*)lv_event_get_user_data(e); + lv_obj_del(panel); +} + +void lv_create_fullscreen_button_matrix_popup(lv_obj_t * root, lv_event_cb_t title, lv_button_column_t* columns, int column_count){ + const auto full_panel_width = CYD_SCREEN_WIDTH_PX - CYD_SCREEN_GAP_PX * 3; + const auto full_panel_inner_width = full_panel_width - CYD_SCREEN_GAP_PX * 2 - 4; + const auto full_panel_height = CYD_SCREEN_HEIGHT_PX - CYD_SCREEN_GAP_PX; + const auto full_panel_inner_height = full_panel_height - CYD_SCREEN_GAP_PX * 2 - 4; + auto column_width = full_panel_inner_width / column_count - CYD_SCREEN_GAP_PX; + auto column_height = full_panel_inner_height - CYD_SCREEN_GAP_PX - CYD_SCREEN_MIN_BUTTON_HEIGHT_PX; + + lv_obj_t * panel = lv_obj_create(root); + lv_obj_set_style_pad_all(panel, CYD_SCREEN_GAP_PX, 0); + lv_obj_set_size(panel, full_panel_width, full_panel_height); + lv_obj_align(panel, LV_ALIGN_CENTER, 0, 0); + + lv_obj_t * top_menu_row = lv_create_empty_panel(panel); + lv_obj_set_size(top_menu_row, full_panel_inner_width, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); + lv_obj_align(top_menu_row, LV_ALIGN_TOP_LEFT, 0, 0); + + lv_obj_t * btn = lv_btn_create(top_menu_row); + lv_obj_set_size(btn, CYD_SCREEN_MIN_BUTTON_WIDTH_PX, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); + lv_obj_align(btn, LV_ALIGN_RIGHT_MID, 0, 0); + lv_obj_add_event_cb(btn, lv_fullscreen_menu_close, LV_EVENT_CLICKED, panel); + + lv_obj_t * label = lv_label_create(btn); + lv_label_set_text(label, LV_SYMBOL_CLOSE); + lv_obj_center(label); + + label = lv_label_create(top_menu_row); + lv_label_set_text(label, "-"); + lv_obj_align(label, LV_ALIGN_LEFT_MID, 0, 0); + lv_obj_add_event_cb(label, title, LV_EVENT_MSG_RECEIVED, NULL); + lv_msg_subsribe_obj(DATA_PRINTER_DATA, label, NULL); + + lv_obj_t * rows = lv_create_empty_panel(panel); + lv_obj_set_size(rows, full_panel_inner_width, column_height); + lv_obj_align(rows, LV_ALIGN_BOTTOM_LEFT, 0, 0); + lv_layout_flex_row(rows, LV_FLEX_ALIGN_SPACE_BETWEEN, CYD_SCREEN_GAP_PX, CYD_SCREEN_GAP_PX); + + for (int i = 0; i < column_count; i++){ + lv_obj_t * column = lv_create_empty_panel(rows); + lv_obj_clear_flag(column, LV_OBJ_FLAG_SCROLLABLE); + lv_obj_set_size(column, column_width, column_height); + lv_layout_flex_column(column, LV_FLEX_ALIGN_CENTER, CYD_SCREEN_GAP_PX, CYD_SCREEN_GAP_PX); + + for (int j = 0; j < columns[i].length; j++){ + lv_obj_t * btn = lv_btn_create(column); + lv_obj_set_size(btn, column_width, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); + lv_obj_add_event_cb(btn, columns[i].event, LV_EVENT_CLICKED, (void*)columns[i].data[j]); + + label = lv_label_create(btn); + lv_label_set_text(label, columns[i].labels[j]); + lv_obj_center(label); + } + } } \ No newline at end of file diff --git a/CYD-Klipper/src/ui/ui_utils.h b/CYD-Klipper/src/ui/ui_utils.h index 96dd2e2..0245c9e 100644 --- a/CYD-Klipper/src/ui/ui_utils.h +++ b/CYD-Klipper/src/ui/ui_utils.h @@ -3,6 +3,14 @@ #define CYD_SCREEN_PANEL_WIDTH_PX \ (CYD_SCREEN_WIDTH_PX - CYD_SCREEN_SIDEBAR_SIZE_PX) +typedef struct { + lv_event_cb_t event; + const char** labels; + const void** data; + int length; +} lv_button_column_t; + lv_obj_t* lv_create_empty_panel(lv_obj_t* root); void lv_layout_flex_column(lv_obj_t* obj, lv_flex_align_t allign = LV_FLEX_ALIGN_START, lv_coord_t pad_column = CYD_SCREEN_GAP_PX, lv_coord_t pad_row = CYD_SCREEN_GAP_PX); -void lv_layout_flex_row(lv_obj_t* obj, lv_flex_align_t allign = LV_FLEX_ALIGN_START, lv_coord_t pad_column = CYD_SCREEN_GAP_PX, lv_coord_t pad_row = CYD_SCREEN_GAP_PX); \ No newline at end of file +void lv_layout_flex_row(lv_obj_t* obj, lv_flex_align_t allign = LV_FLEX_ALIGN_START, lv_coord_t pad_column = CYD_SCREEN_GAP_PX, lv_coord_t pad_row = CYD_SCREEN_GAP_PX); +void lv_create_fullscreen_button_matrix_popup(lv_obj_t * root, lv_event_cb_t title, lv_button_column_t* columns, int column_count); \ No newline at end of file