diff --git a/config/CreatBot_D1000/base.cfg b/config/CreatBot_D1000/base.cfg index 2177830ad..8178a6d73 100644 --- a/config/CreatBot_D1000/base.cfg +++ b/config/CreatBot_D1000/base.cfg @@ -376,7 +376,7 @@ gcode: {% set client = printer['gcode_macro _CLIENT_VARIABLE']|default({}) %} {% set filament_insert = True if client.filament_sensor|default("") == "" else True if not printer[client.filament_sensor].enabled - else printer[client.filament_sensor].filament_detected|default(False) %} + else printer[client.filament_sensor].filament_detected|default(False) %} {% set printing = printer.print_stats.state == "printing" %} {% if filament_insert or printing == False %} SET_SERVO SERVO=switch_nozzle angle=135 @@ -406,7 +406,7 @@ gcode: {% set client = printer['gcode_macro _CLIENT_VARIABLE']|default({}) %} {% set filament_insert = True if client.filament_sensor1|default("") == "" else True if not printer[client.filament_sensor1].enabled - else printer[client.filament_sensor1].filament_detected|default(False) %} + else printer[client.filament_sensor1].filament_detected|default(False) %} {% set printing = (printer.print_stats.state == "printing") %} {% if filament_insert or printing == False %} SET_SERVO SERVO=switch_nozzle angle=135 @@ -847,7 +847,7 @@ gcode: {% set sv = printer.save_variables.variables %} {% set door_function = sv.door_detect|default("Disabled") %} {% set door_state = printer['gcode_button _door_detection'].state|default('released')|lower %} - + {% if door_function == 'Pause Print' and door_state == 'released' %} RESPOND TYPE=command MSG="action:prompt_begin" RESPOND TYPE=command MSG="action:prompt_text Please close the door and click Resume to proceed." @@ -980,9 +980,9 @@ gcode: RUN_SHELL_COMMAND CMD=_CLEAR_PLR SAVE_VARIABLE VARIABLE=last_file VALUE='"{ filename }"' SAVE_VARIABLE VARIABLE=filepath VALUE='"{ filepath }"' - {% set zero_vars = ['power_resume_x', 'power_resume_y', 'power_resume_z'] %} + {% set zero_vars = ['power_resume_position', 'power_resume_line'] %} {% for var in zero_vars %} - SAVE_VARIABLE VARIABLE={var} VALUE=0 + SAVE_VARIABLE VARIABLE={var} VALUE=0 {% endfor %} SAVE_VARIABLE VARIABLE=was_interrupted VALUE=False @@ -998,9 +998,9 @@ gcode: {% set park_dz = client.custom_park_dz|default(2.0)|abs %} RESPOND TYPE=command MSG="action:prompt_end" SET_GCODE_OFFSET Z=0 MOVE=0 - {% set z_height = params.Z_HEIGHT|default(sv.power_resume_z)|float %} {% set is_paused = sv.power_loss_paused|default(False) %} - {% set last_file = params.GCODE_FILE|default(sv.last_file)|string %} + {% set filepath = params.GCODE_FILE|default(sv.filepath)|string %} + {% set last_file = filepath.split('/')[-1] %} {% set hotend = sv.power_resume_extruder|default("extruder")%} {% set z_offset = sv.nozzle_z_offset_val|default(0)|float %} {% set z_offset_total = park_dz if is_paused else 0 %} @@ -1010,7 +1010,7 @@ gcode: SET_STEPPER_ENABLE STEPPER=stepper_z ENABLE=1 G4 P300 M118 Recovery in progress, please wait - RUN_SHELL_COMMAND CMD=_POWER_LOSS_RECOVERY PARAMS="{z_height} \"{last_file}\" \"{z_offset_total}\"" + RUN_SHELL_COMMAND CMD=_POWER_LOSS_RECOVERY PARAMS="{z_offset_total}" SDCARD_PRINT_FILE FILENAME=.plr/"{last_file}" SAVE_VARIABLE VARIABLE=was_interrupted VALUE=False diff --git a/config/CreatBot_D1000_V0/base.cfg b/config/CreatBot_D1000_V0/base.cfg index dbdc2b0f0..9ed9a8543 100644 --- a/config/CreatBot_D1000_V0/base.cfg +++ b/config/CreatBot_D1000_V0/base.cfg @@ -308,7 +308,7 @@ gcode: {% set client = printer['gcode_macro _CLIENT_VARIABLE']|default({}) %} {% set filament_insert = True if client.filament_sensor|default("") == "" else True if not printer[client.filament_sensor].enabled - else printer[client.filament_sensor].filament_detected|default(False) %} + else printer[client.filament_sensor].filament_detected|default(False) %} {% set printing = printer.print_stats.state == "printing" %} {% if filament_insert or printing == False %} SET_SERVO SERVO=switch_nozzle angle=135 @@ -338,7 +338,7 @@ gcode: {% set client = printer['gcode_macro _CLIENT_VARIABLE']|default({}) %} {% set filament_insert = True if client.filament_sensor1|default("") == "" else True if not printer[client.filament_sensor1].enabled - else printer[client.filament_sensor1].filament_detected|default(False) %} + else printer[client.filament_sensor1].filament_detected|default(False) %} {% set printing = (printer.print_stats.state == "printing") %} {% if filament_insert or printing == False %} SET_SERVO SERVO=switch_nozzle angle=135 @@ -893,9 +893,9 @@ gcode: RUN_SHELL_COMMAND CMD=_CLEAR_PLR SAVE_VARIABLE VARIABLE=last_file VALUE='"{ filename }"' SAVE_VARIABLE VARIABLE=filepath VALUE='"{ filepath }"' - {% set zero_vars = ['power_resume_x', 'power_resume_y', 'power_resume_z'] %} + {% set zero_vars = ['power_resume_position', 'power_resume_line'] %} {% for var in zero_vars %} - SAVE_VARIABLE VARIABLE={var} VALUE=0 + SAVE_VARIABLE VARIABLE={var} VALUE=0 {% endfor %} SAVE_VARIABLE VARIABLE=was_interrupted VALUE=False @@ -911,9 +911,9 @@ gcode: {% set park_dz = client.custom_park_dz|default(2.0)|abs %} RESPOND TYPE=command MSG="action:prompt_end" SET_GCODE_OFFSET Z=0 MOVE=0 - {% set z_height = params.Z_HEIGHT|default(sv.power_resume_z)|float %} {% set is_paused = sv.power_loss_paused|default(False) %} - {% set last_file = params.GCODE_FILE|default(sv.last_file)|string %} + {% set filepath = params.GCODE_FILE|default(sv.filepath)|string %} + {% set last_file = filepath.split('/')[-1] %} {% set hotend = sv.power_resume_extruder|default("extruder")%} {% set z_offset = sv.nozzle_z_offset_val|default(0)|float %} {% set z_offset_total = park_dz if is_paused else 0 %} @@ -923,7 +923,7 @@ gcode: SET_STEPPER_ENABLE STEPPER=stepper_z ENABLE=1 G4 P300 M118 Recovery in progress, please wait - RUN_SHELL_COMMAND CMD=_POWER_LOSS_RECOVERY PARAMS="{z_height} \"{last_file}\" \"{z_offset_total}\"" + RUN_SHELL_COMMAND CMD=_POWER_LOSS_RECOVERY PARAMS="{z_offset_total}" SDCARD_PRINT_FILE FILENAME=.plr/"{last_file}" SAVE_VARIABLE VARIABLE=was_interrupted VALUE=False diff --git a/config/CreatBot_D600Pro2/base.cfg b/config/CreatBot_D600Pro2/base.cfg index 47b36e0bf..e5c6e4d91 100644 --- a/config/CreatBot_D600Pro2/base.cfg +++ b/config/CreatBot_D600Pro2/base.cfg @@ -848,7 +848,7 @@ gcode: {% set sv = printer.save_variables.variables %} {% set door_function = sv.door_detect|default("Disabled") %} {% set door_state = printer['gcode_button _door_detection'].state|default('released')|lower %} - + {% if door_function == 'Pause Print' and door_state == 'released' %} RESPOND TYPE=command MSG="action:prompt_begin" RESPOND TYPE=command MSG="action:prompt_text Please close the door and click Resume to proceed." @@ -981,9 +981,9 @@ gcode: RUN_SHELL_COMMAND CMD=_CLEAR_PLR SAVE_VARIABLE VARIABLE=last_file VALUE='"{ filename }"' SAVE_VARIABLE VARIABLE=filepath VALUE='"{ filepath }"' - {% set zero_vars = ['power_resume_x', 'power_resume_y', 'power_resume_z'] %} + {% set zero_vars = ['power_resume_position', 'power_resume_line'] %} {% for var in zero_vars %} - SAVE_VARIABLE VARIABLE={var} VALUE=0 + SAVE_VARIABLE VARIABLE={var} VALUE=0 {% endfor %} SAVE_VARIABLE VARIABLE=was_interrupted VALUE=False @@ -999,9 +999,9 @@ gcode: {% set park_dz = client.custom_park_dz|default(2.0)|abs %} RESPOND TYPE=command MSG="action:prompt_end" SET_GCODE_OFFSET Z=0 MOVE=0 - {% set z_height = params.Z_HEIGHT|default(sv.power_resume_z)|float %} {% set is_paused = sv.power_loss_paused|default(False) %} - {% set last_file = params.GCODE_FILE|default(sv.last_file)|string %} + {% set filepath = params.GCODE_FILE|default(sv.filepath)|string %} + {% set last_file = filepath.split('/')[-1] %} {% set hotend = sv.power_resume_extruder|default("extruder")%} {% set z_offset = sv.nozzle_z_offset_val|default(0)|float %} {% set z_offset_total = park_dz if is_paused else 0 %} @@ -1011,7 +1011,7 @@ gcode: SET_STEPPER_ENABLE STEPPER=stepper_z ENABLE=1 G4 P300 M118 Recovery in progress, please wait - RUN_SHELL_COMMAND CMD=_POWER_LOSS_RECOVERY PARAMS="{z_height} \"{last_file}\" \"{z_offset_total}\"" + RUN_SHELL_COMMAND CMD=_POWER_LOSS_RECOVERY PARAMS="{z_offset_total}" SDCARD_PRINT_FILE FILENAME=.plr/"{last_file}" SAVE_VARIABLE VARIABLE=was_interrupted VALUE=False diff --git a/config/CreatBot_D600Pro2_V0/base.cfg b/config/CreatBot_D600Pro2_V0/base.cfg index 8a6517d20..4f10bf87a 100644 --- a/config/CreatBot_D600Pro2_V0/base.cfg +++ b/config/CreatBot_D600Pro2_V0/base.cfg @@ -335,7 +335,7 @@ gcode: {% set x_offset = sv.nozzle_x_offset_val|default(0)|float %} {% set y_offset = sv.nozzle_y_offset_val|default(0)|float %} {% set z_offset = sv.nozzle_z_offset_val|default(0)|float %} - {% set x_offset = x_offset - 59 %} + {% set x_offset = x_offset - 59 %} {% set client = printer['gcode_macro _CLIENT_VARIABLE']|default({}) %} {% set filament_insert = True if client.filament_sensor1|default("") == "" else True if not printer[client.filament_sensor1].enabled @@ -888,9 +888,9 @@ gcode: RUN_SHELL_COMMAND CMD=_CLEAR_PLR SAVE_VARIABLE VARIABLE=last_file VALUE='"{ filename }"' SAVE_VARIABLE VARIABLE=filepath VALUE='"{ filepath }"' - {% set zero_vars = ['power_resume_x', 'power_resume_y', 'power_resume_z'] %} + {% set zero_vars = ['power_resume_position', 'power_resume_line'] %} {% for var in zero_vars %} - SAVE_VARIABLE VARIABLE={var} VALUE=0 + SAVE_VARIABLE VARIABLE={var} VALUE=0 {% endfor %} SAVE_VARIABLE VARIABLE=was_interrupted VALUE=False @@ -906,9 +906,9 @@ gcode: {% set park_dz = client.custom_park_dz|default(2.0)|abs %} RESPOND TYPE=command MSG="action:prompt_end" SET_GCODE_OFFSET Z=0 MOVE=0 - {% set z_height = params.Z_HEIGHT|default(sv.power_resume_z)|float %} {% set is_paused = sv.power_loss_paused|default(False) %} - {% set last_file = params.GCODE_FILE|default(sv.last_file)|string %} + {% set filepath = params.GCODE_FILE|default(sv.filepath)|string %} + {% set last_file = filepath.split('/')[-1] %} {% set hotend = sv.power_resume_extruder|default("extruder")%} {% set z_offset = sv.nozzle_z_offset_val|default(0)|float %} {% set z_offset_total = park_dz if is_paused else 0 %} @@ -918,7 +918,7 @@ gcode: SET_STEPPER_ENABLE STEPPER=stepper_z ENABLE=1 G4 P300 M118 Recovery in progress, please wait - RUN_SHELL_COMMAND CMD=_POWER_LOSS_RECOVERY PARAMS="{z_height} \"{last_file}\" \"{z_offset_total}\"" + RUN_SHELL_COMMAND CMD=_POWER_LOSS_RECOVERY PARAMS="{z_offset_total}" SDCARD_PRINT_FILE FILENAME=.plr/"{last_file}" SAVE_VARIABLE VARIABLE=was_interrupted VALUE=False diff --git a/config/CreatBot_F430NX/base.cfg b/config/CreatBot_F430NX/base.cfg index ec410b263..f40c2d214 100644 --- a/config/CreatBot_F430NX/base.cfg +++ b/config/CreatBot_F430NX/base.cfg @@ -206,7 +206,7 @@ kick_start_time: 1.0 pin: PC6 max_power: 0.8 heater: -stepper: stepper_x, stepper_z, dual_carriage +stepper: stepper_x, stepper_z, dual_carriage idle_speed: 0.5 [delayed_gcode INIT_LIGHT] @@ -501,7 +501,7 @@ gcode: {% set client = printer['gcode_macro _CLIENT_VARIABLE']|default({}) %} {% set filament_insert = True if client.filament_sensor1|default("") == "" else True if not printer[client.filament_sensor1].enabled - else printer[client.filament_sensor1].filament_detected|default(False) %} + else printer[client.filament_sensor1].filament_detected|default(False) %} {% set printing = (printer.print_stats.state == "printing") %} {% if filament_insert or printing == False %} {% if "x" not in printer.toolhead.homed_axes %} @@ -1163,9 +1163,9 @@ gcode: RUN_SHELL_COMMAND CMD=_CLEAR_PLR SAVE_VARIABLE VARIABLE=last_file VALUE='"{ filename }"' SAVE_VARIABLE VARIABLE=filepath VALUE='"{ filepath }"' - {% set zero_vars = ['power_resume_x', 'power_resume_y', 'power_resume_z'] %} + {% set zero_vars = ['power_resume_position', 'power_resume_line'] %} {% for var in zero_vars %} - SAVE_VARIABLE VARIABLE={var} VALUE=0 + SAVE_VARIABLE VARIABLE={var} VALUE=0 {% endfor %} SAVE_VARIABLE VARIABLE=was_interrupted VALUE=False @@ -1181,9 +1181,9 @@ gcode: {% set park_dz = client.custom_park_dz|default(2.0)|abs %} RESPOND TYPE=command MSG="action:prompt_end" SET_GCODE_OFFSET Z=0 MOVE=0 - {% set z_height = params.Z_HEIGHT|default(sv.power_resume_z)|float %} {% set is_paused = sv.power_loss_paused|default(False) %} - {% set last_file = params.GCODE_FILE|default(sv.last_file)|string %} + {% set filepath = params.GCODE_FILE|default(sv.filepath)|string %} + {% set last_file = filepath.split('/')[-1] %} {% set hotend = sv.power_resume_extruder|default("extruder")%} {% set z_offset = sv.nozzle_z_offset_val|default(0)|float %} {% set z_offset_total = park_dz if is_paused else 0 %} @@ -1193,7 +1193,7 @@ gcode: SET_STEPPER_ENABLE STEPPER=stepper_z ENABLE=1 G4 P300 M118 Recovery in progress, please wait - RUN_SHELL_COMMAND CMD=_POWER_LOSS_RECOVERY PARAMS="{z_height} \"{last_file}\" \"{z_offset_total}\"" + RUN_SHELL_COMMAND CMD=_POWER_LOSS_RECOVERY PARAMS="{z_offset_total}" SDCARD_PRINT_FILE FILENAME=.plr/"{last_file}" SAVE_VARIABLE VARIABLE=was_interrupted VALUE=False diff --git a/klippy/chelper/__init__.py b/klippy/chelper/__init__.py index fa1261be9..8e408fdd5 100644 --- a/klippy/chelper/__init__.py +++ b/klippy/chelper/__init__.py @@ -94,7 +94,7 @@ defs_trapq = """ , double accel_t, double cruise_t, double decel_t , double start_pos_x, double start_pos_y, double start_pos_z , double axes_r_x, double axes_r_y, double axes_r_z - , double start_v, double cruise_v, double accel); + , double start_v, double cruise_v, double accel, double taskline); void trapq_finalize_moves(struct trapq *tq, double print_time , double clear_history_time); void trapq_set_position(struct trapq *tq, double print_time diff --git a/klippy/chelper/itersolve.c b/klippy/chelper/itersolve.c index 0dbc6c512..98a76ddab 100644 --- a/klippy/chelper/itersolve.c +++ b/klippy/chelper/itersolve.c @@ -41,6 +41,7 @@ itersolve_gen_steps_range(struct stepper_kinematics *sk, struct move *m int is_dir_change = 0, have_bracket = 0, check_oscillate = 0; double target = sk->commanded_pos + (sdir ? half_step : -half_step); double last_time=start, low_time=start, high_time=start + SEEK_TIME_RESET; + stepcompress_set_taskline(sk->sc, m->taskline); if (high_time > end) high_time = end; for (;;) { diff --git a/klippy/chelper/stepcompress.c b/klippy/chelper/stepcompress.c index 310f2bf31..a0b85d973 100644 --- a/klippy/chelper/stepcompress.c +++ b/klippy/chelper/stepcompress.c @@ -38,6 +38,7 @@ struct stepcompress { uint64_t last_step_clock; struct list_head msg_queue; uint32_t oid; + uint32_t taskline; int32_t queue_step_msgtag, set_next_step_dir_msgtag; int sdir, invert_sdir; // Step+dir+step filter @@ -52,13 +53,14 @@ struct step_move { uint32_t interval; uint16_t count; int16_t add; + uint32_t taskline; }; struct history_steps { struct list_node node; uint64_t first_clock, last_clock; int64_t start_position; - int step_count, interval, add; + int step_count, interval, add, taskline; }; @@ -113,6 +115,7 @@ compress_bisect_add(struct stepcompress *sc) int32_t add = 0, minadd = -0x8000, maxadd = 0x7fff; int32_t bestinterval = 0, bestcount = 1, bestadd = 1, bestreach = INT32_MIN; int32_t zerointerval = 0, zerocount = 0; + int32_t taskline = sc->taskline; for (;;) { // Find longest valid sequence with the given 'add' @@ -124,7 +127,7 @@ compress_bisect_add(struct stepcompress *sc) nextcount++; if (&sc->queue_pos[nextcount-1] >= qlast) { int32_t count = nextcount - 1; - return (struct step_move){ interval, count, add }; + return (struct step_move){ interval, count, add, taskline }; } nextpoint = minmax_point(sc, sc->queue_pos + nextcount - 1); int32_t nextaddfactor = nextcount*(nextcount-1)/2; @@ -192,8 +195,8 @@ compress_bisect_add(struct stepcompress *sc) } if (zerocount + zerocount/16 >= bestcount) // Prefer add=0 if it's similar to the best found sequence - return (struct step_move){ zerointerval, zerocount, 0 }; - return (struct step_move){ bestinterval, bestcount, bestadd }; + return (struct step_move){ zerointerval, zerocount, 0, taskline }; + return (struct step_move){ bestinterval, bestcount, bestadd, taskline }; } @@ -276,6 +279,13 @@ stepcompress_set_invert_sdir(struct stepcompress *sc, uint32_t invert_sdir) } } +void __visible +stepcompress_set_taskline(struct stepcompress *sc, uint32_t taskline) +{ + if (taskline != sc->taskline) + sc->taskline = taskline; +} + // Helper to free items from the history_list static void free_history(struct stepcompress *sc, uint64_t end_clock) @@ -321,6 +331,12 @@ stepcompress_get_step_dir(struct stepcompress *sc) return sc->next_step_dir; } +uint32_t +stepcompress_get_taskline(struct stepcompress *sc) +{ + return sc->taskline; +} + // Determine the "print time" of the last_step_clock static void calc_last_step_print_time(struct stepcompress *sc) @@ -351,10 +367,10 @@ add_move(struct stepcompress *sc, uint64_t first_clock, struct step_move *move) uint64_t last_clock = first_clock + ticks; // Create and queue a queue_step command - uint32_t msg[5] = { - sc->queue_step_msgtag, sc->oid, move->interval, move->count, move->add + uint32_t msg[6] = { + sc->queue_step_msgtag, sc->oid, move->interval, move->count, move->add, move->taskline }; - struct queue_message *qm = message_alloc_and_encode(msg, 5); + struct queue_message *qm = message_alloc_and_encode(msg, 6); qm->min_clock = qm->req_clock = sc->last_step_clock; if (move->count == 1 && first_clock >= sc->last_step_clock + CLOCK_DIFF_MAX) qm->req_clock = first_clock; @@ -368,6 +384,7 @@ add_move(struct stepcompress *sc, uint64_t first_clock, struct step_move *move) hs->start_position = sc->last_position; hs->interval = move->interval; hs->add = move->add; + hs->taskline = move->taskline; hs->step_count = sc->sdir ? move->count : -move->count; sc->last_position += hs->step_count; list_add_head(&hs->node, &sc->history_list); @@ -401,7 +418,7 @@ queue_flush(struct stepcompress *sc, uint64_t move_clock) static int stepcompress_flush_far(struct stepcompress *sc, uint64_t abs_step_clock) { - struct step_move move = { abs_step_clock - sc->last_step_clock, 1, 0 }; + struct step_move move = { abs_step_clock - sc->last_step_clock, 1, 0, 0 }; add_move(sc, abs_step_clock, &move); calc_last_step_print_time(sc); return 0; diff --git a/klippy/chelper/stepcompress.h b/klippy/chelper/stepcompress.h index c5b40383f..cd87b5dd5 100644 --- a/klippy/chelper/stepcompress.h +++ b/klippy/chelper/stepcompress.h @@ -17,6 +17,8 @@ void stepcompress_fill(struct stepcompress *sc, uint32_t max_error , int32_t set_next_step_dir_msgtag); void stepcompress_set_invert_sdir(struct stepcompress *sc , uint32_t invert_sdir); +void stepcompress_set_taskline(struct stepcompress *sc + , uint32_t taskline); void stepcompress_free(struct stepcompress *sc); uint32_t stepcompress_get_oid(struct stepcompress *sc); int stepcompress_get_step_dir(struct stepcompress *sc); diff --git a/klippy/chelper/trapq.c b/klippy/chelper/trapq.c index b9930e997..0d8f5a7a3 100644 --- a/klippy/chelper/trapq.c +++ b/klippy/chelper/trapq.c @@ -103,6 +103,7 @@ trapq_add_move(struct trapq *tq, struct move *m) // Add a null move to fill time gap struct move *null_move = move_alloc(); null_move->start_pos = m->start_pos; + null_move->taskline = m->taskline; if (!prev->print_time && m->print_time > MAX_NULL_MOVE) // Limit the first null move to improve numerical stability null_move->print_time = m->print_time - MAX_NULL_MOVE; @@ -121,7 +122,7 @@ trapq_append(struct trapq *tq, double print_time , double accel_t, double cruise_t, double decel_t , double start_pos_x, double start_pos_y, double start_pos_z , double axes_r_x, double axes_r_y, double axes_r_z - , double start_v, double cruise_v, double accel) + , double start_v, double cruise_v, double accel, double taskline) { struct coord start_pos = { .x=start_pos_x, .y=start_pos_y, .z=start_pos_z }; struct coord axes_r = { .x=axes_r_x, .y=axes_r_y, .z=axes_r_z }; @@ -133,6 +134,7 @@ trapq_append(struct trapq *tq, double print_time m->half_accel = .5 * accel; m->start_pos = start_pos; m->axes_r = axes_r; + m->taskline = taskline; trapq_add_move(tq, m); print_time += accel_t; @@ -146,6 +148,7 @@ trapq_append(struct trapq *tq, double print_time m->half_accel = 0.; m->start_pos = start_pos; m->axes_r = axes_r; + m->taskline = taskline; trapq_add_move(tq, m); print_time += cruise_t; @@ -159,6 +162,7 @@ trapq_append(struct trapq *tq, double print_time m->half_accel = -.5 * accel; m->start_pos = start_pos; m->axes_r = axes_r; + m->taskline = taskline; trapq_add_move(tq, m); } } diff --git a/klippy/chelper/trapq.h b/klippy/chelper/trapq.h index c463f0c53..262adc371 100644 --- a/klippy/chelper/trapq.h +++ b/klippy/chelper/trapq.h @@ -13,6 +13,7 @@ struct coord { }; struct move { + double taskline; double print_time, move_t; double start_v, half_accel; struct coord start_pos, axes_r; @@ -42,7 +43,7 @@ void trapq_append(struct trapq *tq, double print_time , double accel_t, double cruise_t, double decel_t , double start_pos_x, double start_pos_y, double start_pos_z , double axes_r_x, double axes_r_y, double axes_r_z - , double start_v, double cruise_v, double accel); + , double start_v, double cruise_v, double accel, double taskline); void trapq_finalize_moves(struct trapq *tq, double print_time , double clear_history_time); void trapq_set_position(struct trapq *tq, double print_time diff --git a/klippy/extras/bed_mesh.py b/klippy/extras/bed_mesh.py index 98bb6920a..05c3116f2 100644 --- a/klippy/extras/bed_mesh.py +++ b/klippy/extras/bed_mesh.py @@ -204,7 +204,7 @@ class BedMesh: final_z_adj = factor * z_adj + self.fade_target self.last_position[:] = [x, y, z - final_z_adj, e] return list(self.last_position) - def move(self, newpos, speed): + def move(self, newpos, speed, taskline=0): factor = self.get_z_factor(newpos[2]) if self.z_mesh is None or not factor: # No mesh calibrated, or mesh leveling phased out. @@ -214,13 +214,13 @@ class BedMesh: logging.info( "bed_mesh fade complete: Current Z: %.4f fade_target: %.4f " % (z, self.fade_target)) - self.toolhead.move([x, y, z + self.fade_target, e], speed) + self.toolhead.move([x, y, z + self.fade_target, e], speed, taskline) else: self.splitter.build_move(self.last_position, newpos, factor) while not self.splitter.traverse_complete: split_move = self.splitter.split() if split_move: - self.toolhead.move(split_move, speed) + self.toolhead.move(split_move, speed, taskline) else: raise self.gcode.error( "Mesh Leveling: Error splitting move ") diff --git a/klippy/extras/bed_screws.py b/klippy/extras/bed_screws.py index c34461919..5ede8ccd4 100644 --- a/klippy/extras/bed_screws.py +++ b/klippy/extras/bed_screws.py @@ -41,7 +41,7 @@ class BedScrews: self.state = None self.current_screw = 0 self.accepted_screws = 0 - def move(self, coord, speed): + def move(self, coord, speed, taskline=0): try: self.printer.lookup_object('toolhead').manual_move(coord, speed) except self.printer.command_error as e: diff --git a/klippy/extras/bed_tilt.py b/klippy/extras/bed_tilt.py index cd1ce1774..aa852c716 100644 --- a/klippy/extras/bed_tilt.py +++ b/klippy/extras/bed_tilt.py @@ -26,10 +26,10 @@ class BedTilt: def get_position(self): x, y, z, e = self.toolhead.get_position() return [x, y, z - x*self.x_adjust - y*self.y_adjust - self.z_adjust, e] - def move(self, newpos, speed): + def move(self, newpos, speed, taskline=0): x, y, z, e = newpos self.toolhead.move([x, y, z + x*self.x_adjust + y*self.y_adjust - + self.z_adjust, e], speed) + + self.z_adjust, e], speed, taskline) def update_adjust(self, x_adjust, y_adjust, z_adjust): self.x_adjust = x_adjust self.y_adjust = y_adjust diff --git a/klippy/extras/exclude_object.py b/klippy/extras/exclude_object.py index 194012796..a1a17d007 100644 --- a/klippy/extras/exclude_object.py +++ b/klippy/extras/exclude_object.py @@ -177,7 +177,7 @@ class ExcludeObject: } return status - def move(self, newpos, speed): + def move(self, newpos, speed, taskline=0): move_in_excluded_region = self._test_in_excluded_region() self.last_speed = speed diff --git a/klippy/extras/force_move.py b/klippy/extras/force_move.py index 24783c2c6..6b1549b9b 100644 --- a/klippy/extras/force_move.py +++ b/klippy/extras/force_move.py @@ -83,7 +83,7 @@ class ForceMove: axis_r, accel_t, cruise_t, cruise_v = calc_move_time(dist, speed, accel) print_time = toolhead.get_last_move_time() self.trapq_append(self.trapq, print_time, accel_t, cruise_t, accel_t, - 0., 0., 0., axis_r, 0., 0., 0., cruise_v, accel) + 0., 0., 0., axis_r, 0., 0., 0., cruise_v, accel, 0.) print_time = print_time + accel_t + cruise_t + accel_t stepper.generate_steps(print_time) self.trapq_finalize_moves(self.trapq, print_time + 99999.9, diff --git a/klippy/extras/gcode_move.py b/klippy/extras/gcode_move.py index ecdadc439..098b0b3b6 100644 --- a/klippy/extras/gcode_move.py +++ b/klippy/extras/gcode_move.py @@ -113,6 +113,7 @@ class GCodeMove: def cmd_G1(self, gcmd): # Move params = gcmd.get_command_parameters() + line = gcmd.get_taskline() try: for pos, axis in enumerate('XYZ'): if axis in params: @@ -140,7 +141,7 @@ class GCodeMove: except ValueError as e: raise gcmd.error("Unable to parse move '%s'" % (gcmd.get_commandline(),)) - self.move_with_transform(self.last_position, self.speed) + self.move_with_transform(self.last_position, self.speed, line) # G-Code coordinate manipulation def cmd_G20(self, gcmd): # Set units to inches diff --git a/klippy/extras/manual_stepper.py b/klippy/extras/manual_stepper.py index 9f21cc8d4..2e4337e7c 100644 --- a/klippy/extras/manual_stepper.py +++ b/klippy/extras/manual_stepper.py @@ -64,7 +64,7 @@ class ManualStepper: self.trapq_append(self.trapq, self.next_cmd_time, accel_t, cruise_t, accel_t, cp, 0., 0., axis_r, 0., 0., - 0., cruise_v, accel) + 0., cruise_v, accel, 0.) self.next_cmd_time = self.next_cmd_time + accel_t + cruise_t + accel_t self.rail.generate_steps(self.next_cmd_time) self.trapq_finalize_moves(self.trapq, self.next_cmd_time + 99999.9, diff --git a/klippy/extras/skew_correction.py b/klippy/extras/skew_correction.py index 6a2cbd295..32e665399 100644 --- a/klippy/extras/skew_correction.py +++ b/klippy/extras/skew_correction.py @@ -67,9 +67,9 @@ class PrinterSkew: return [skewed_x, skewed_y, pos[2], pos[3]] def get_position(self): return self.calc_unskew(self.next_transform.get_position()) - def move(self, newpos, speed): + def move(self, newpos, speed, taskline=0): corrected_pos = self.calc_skew(newpos) - self.next_transform.move(corrected_pos, speed) + self.next_transform.move(corrected_pos, speed, taskline) def _update_skew(self, xy_factor, xz_factor, yz_factor): self.xy_factor = xy_factor self.xz_factor = xz_factor diff --git a/klippy/extras/tuning_tower.py b/klippy/extras/tuning_tower.py index 4fec5b1b3..7ef7af4bd 100644 --- a/klippy/extras/tuning_tower.py +++ b/klippy/extras/tuning_tower.py @@ -74,7 +74,7 @@ class TuningTower: if self.band: z = (math.floor(z / self.band) + .5) * self.band return self.start + z * self.factor - def move(self, newpos, speed): + def move(self, newpos, speed, taskline=0): normal_transform = self.normal_transform if (newpos[3] > self.last_position[3] and newpos[2] != self.last_z and newpos[:3] != self.last_position[:3]): @@ -94,7 +94,7 @@ class TuningTower: % (newval,)) # Forward move to actual handler self.last_position[:] = newpos - normal_transform.move(newpos, speed) + normal_transform.move(newpos, speed, taskline) def end_test(self): self.gcode.respond_info("Ending tuning test mode") self.gcode_move.set_move_transform(self.normal_transform, force=True) diff --git a/klippy/extras/virtual_sdcard.py b/klippy/extras/virtual_sdcard.py index 6dc49e2f5..3de1f20db 100644 --- a/klippy/extras/virtual_sdcard.py +++ b/klippy/extras/virtual_sdcard.py @@ -29,6 +29,9 @@ class VirtualSD: self.reactor = self.printer.get_reactor() self.must_pause_work = self.cmd_from_sd = False self.next_file_position = 0 + self.file_line = 0 + self.file_runline = 0 + self.linfo = "" self.work_timer = None # Error handling gcode_macro = self.printer.load_object(config, 'gcode_macro') @@ -46,6 +49,8 @@ class VirtualSD: self.gcode.register_command( "SDCARD_PRINT_FILE", self.cmd_SDCARD_PRINT_FILE, desc=self.cmd_SDCARD_PRINT_FILE_help) + self.gcode.register_command( + 'GET_TASKLINE', self.cmd_GET_TASKLINE, False) def handle_shutdown(self): if self.work_timer is not None: self.must_pause_work = True @@ -95,6 +100,7 @@ class VirtualSD: 'progress': self.progress(), 'is_active': self.is_active(), 'file_position': self.file_position, + 'file_line': self.file_runline, 'file_size': self.file_size, } def file_path(self): @@ -111,6 +117,7 @@ class VirtualSD: def do_pause(self): if self.work_timer is not None: self.must_pause_work = True + self._get_runline() while self.work_timer is not None and not self.cmd_from_sd: self.reactor.pause(self.reactor.monotonic() + .001) def do_resume(self): @@ -126,6 +133,7 @@ class VirtualSD: self.current_file = None self.print_stats.note_cancel() self.file_position = self.file_size = 0 + self.file_line = self.file_runline = 0 # G-Code commands def cmd_error(self, gcmd): raise gcmd.error("SD write not supported") @@ -135,10 +143,28 @@ class VirtualSD: self.current_file.close() self.current_file = None self.file_position = self.file_size = 0 + self.file_line = self.file_runline = 0 self.print_stats.reset() self.printer.send_event("virtual_sdcard:reset_file") cmd_SDCARD_RESET_FILE_help = "Clears a loaded SD File. Stops the print "\ "if necessary" + def _get_runline(self): + toolhead = self.printer.lookup_object('toolhead', None) + if toolhead is None: + raise self.gcode.error("Printer not ready") + kin = toolhead.get_kinematics() + steppers = kin.get_steppers() + linfo = [(s.get_name(), s.get_stepper_taskline()) for s in steppers if s.get_name() != "stepper_z"] + max_position = max(position for _, position in linfo) + self.linfo = linfo + self.file_runline = max_position + + def cmd_GET_TASKLINE(self, gcmd): + if not self.must_pause_work: + self._get_runline() + formatted_pairs = [f"{key}:{value}" for key, value in self.linfo] + formatted_line = " ".join(formatted_pairs) + gcmd.respond_info(f"stepper line: {formatted_line}") def cmd_SDCARD_RESET_FILE(self, gcmd): if self.cmd_from_sd: raise gcmd.error( @@ -217,6 +243,8 @@ class VirtualSD: % (self.file_position, self.file_size)) def get_file_position(self): return self.next_file_position + def get_file_line(self): + return self.file_line def set_file_position(self, pos): self.next_file_position = pos def is_cmd_from_sd(self): @@ -264,6 +292,7 @@ class VirtualSD: # Dispatch command self.cmd_from_sd = True line = lines.pop() + self.file_line += 1 if sys.version_info.major >= 3: next_file_position = self.file_position + len(line.encode()) + 1 else: diff --git a/klippy/extras/z_thermal_adjust.py b/klippy/extras/z_thermal_adjust.py index 0fa0bff0d..90b843aaf 100644 --- a/klippy/extras/z_thermal_adjust.py +++ b/klippy/extras/z_thermal_adjust.py @@ -122,15 +122,15 @@ class ZThermalAdjuster: self.last_position = self.calc_adjust(position) return position - def move(self, newpos, speed): + def move(self, newpos, speed, taskline=0): # don't apply to extrude only moves or when disabled if (newpos[0:2] == self.last_position[0:2]) or not self.adjust_enable: z = newpos[2] + self.last_z_adjust_mm adjusted_pos = [newpos[0], newpos[1], z, newpos[3]] - self.next_transform.move(adjusted_pos, speed) + self.next_transform.move(adjusted_pos, speed, taskline) else: adjusted_pos = self.calc_adjust(newpos) - self.next_transform.move(adjusted_pos, speed) + self.next_transform.move(adjusted_pos, speed, taskline) self.last_position[:] = newpos def temperature_callback(self, read_time, temp): diff --git a/klippy/gcode.py b/klippy/gcode.py index 975da792b..b3065dd9a 100644 --- a/klippy/gcode.py +++ b/klippy/gcode.py @@ -12,14 +12,17 @@ Coord = collections.namedtuple('Coord', ('x', 'y', 'z', 'e')) class GCodeCommand: error = CommandError - def __init__(self, gcode, command, commandline, params, need_ack): + def __init__(self, gcode, command, commandline, params, need_ack, taskline): self._command = command self._commandline = commandline self._params = params self._need_ack = need_ack + self.taskline = taskline # Method wrappers self.respond_info = gcode.respond_info self.respond_raw = gcode.respond_raw + def get_taskline(self): + return self.taskline def get_command(self): return self._command def get_commandline(self): @@ -189,6 +192,11 @@ class GCodeDispatch: # Parse input into commands args_r = re.compile('([A-Z_]+|[A-Z*])') def _process_commands(self, commands, need_ack=True): + sdcard = self.printer.lookup_object('virtual_sdcard', None) + if sdcard is not None: + taskline = sdcard.file_line + else: + taskline = 0 for line in commands: # Ignore comments and leading/trailing spaces line = origline = line.strip() @@ -205,7 +213,7 @@ class GCodeDispatch: # Build gcode "params" dictionary params = { parts[i]: parts[i+1].strip() for i in range(1, len(parts), 2) } - gcmd = GCodeCommand(self, cmd, origline, params, need_ack) + gcmd = GCodeCommand(self, cmd, origline, params, need_ack, taskline) # Invoke handler for command handler = self.gcode_handlers.get(cmd, self.cmd_default) try: @@ -231,7 +239,7 @@ class GCodeDispatch: def get_mutex(self): return self.mutex def create_gcode_command(self, command, commandline, params): - return GCodeCommand(self, command, commandline, params, False) + return GCodeCommand(self, command, commandline, params, False, 0) # Response handling def respond_raw(self, msg): for cb in self.output_callbacks: diff --git a/klippy/kinematics/extruder.py b/klippy/kinematics/extruder.py index 7fb2e7ed5..cfe046b18 100644 --- a/klippy/kinematics/extruder.py +++ b/klippy/kinematics/extruder.py @@ -233,7 +233,7 @@ class PrinterExtruder: if diff_r: return (self.instant_corner_v / abs(diff_r))**2 return move.max_cruise_v2 - def move(self, print_time, move): + def move(self, print_time, move, taskline=0): axis_r = move.axes_r[3] accel = move.accel * axis_r start_v = move.start_v * axis_r @@ -246,7 +246,7 @@ class PrinterExtruder: move.accel_t, move.cruise_t, move.decel_t, move.start_pos[3], 0., 0., 1., can_pressure_advance, 0., - start_v, cruise_v, accel) + start_v, cruise_v, accel, taskline) self.last_position = move.end_pos[3] def find_past_position(self, print_time): if self.extruder_stepper is None: diff --git a/klippy/stepper.py b/klippy/stepper.py index fd44effb6..90ab522a9 100644 --- a/klippy/stepper.py +++ b/klippy/stepper.py @@ -39,6 +39,7 @@ class MCU_stepper: self._invert_dir = self._orig_invert_dir = dir_pin_params['invert'] self._step_both_edge = self._req_step_both_edge = False self._mcu_position_offset = 0. + self.taskline = 0 self._reset_cmd_tag = self._get_position_cmd = None self._active_callbacks = [] ffi_main, ffi_lib = chelper.get_ffi() @@ -90,7 +91,7 @@ class MCU_stepper: self._mcu.add_config_cmd("reset_step_clock oid=%d clock=0" % (self._oid,), on_restart=True) step_cmd_tag = self._mcu.lookup_command( - "queue_step oid=%c interval=%u count=%hu add=%hi").get_command_tag() + "queue_step oid=%c interval=%u count=%hu add=%hi taskline=%u").get_command_tag() dir_cmd_tag = self._mcu.lookup_command( "set_next_step_dir oid=%c dir=%c").get_command_tag() self._reset_cmd_tag = self._mcu.lookup_command( @@ -98,6 +99,9 @@ class MCU_stepper: self._get_position_cmd = self._mcu.lookup_query_command( "stepper_get_position oid=%c", "stepper_position oid=%c pos=%i", oid=self._oid) + self._get_taskline_cmd = self._mcu.lookup_query_command( + "stepper_get_taskline oid=%c", + "stepper_taskline line=%u") max_error = self._mcu.get_max_stepper_error() max_error_ticks = self._mcu.seconds_to_clock(max_error) ffi_main, ffi_lib = chelper.get_ffi() @@ -164,6 +168,11 @@ class MCU_stepper: return (data, count) def get_stepper_kinematics(self): return self._stepper_kinematics + def get_stepper_taskline(self): + if self._mcu.is_fileoutput(): + return 0 + params = self._get_taskline_cmd.send([self._oid]) + return int(params['line']) def set_stepper_kinematics(self, sk): old_sk = self._stepper_kinematics mcu_pos = 0 diff --git a/klippy/toolhead.py b/klippy/toolhead.py index e15f987e5..2783fc420 100644 --- a/klippy/toolhead.py +++ b/klippy/toolhead.py @@ -12,7 +12,7 @@ import mcu, chelper, kinematics.extruder # Class to track each move request class Move: - def __init__(self, toolhead, start_pos, end_pos, speed): + def __init__(self, toolhead, start_pos, end_pos, speed, taskline): self.toolhead = toolhead self.start_pos = tuple(start_pos) self.end_pos = tuple(end_pos) @@ -23,6 +23,7 @@ class Move: self.is_kinematic_move = True self.axes_d = axes_d = [end_pos[i] - start_pos[i] for i in (0, 1, 2, 3)] self.move_d = move_d = math.sqrt(sum([d*d for d in axes_d[:3]])) + self.taskline = taskline if move_d < .000000001: # Extrude only move self.end_pos = (start_pos[0], start_pos[1], start_pos[2], @@ -351,7 +352,7 @@ class ToolHead: move.accel_t, move.cruise_t, move.decel_t, move.start_pos[0], move.start_pos[1], move.start_pos[2], move.axes_r[0], move.axes_r[1], move.axes_r[2], - move.start_v, move.cruise_v, move.accel) + move.start_v, move.cruise_v, move.accel, move.taskline) if move.axes_d[3]: self.extruder.move(next_move_time, move) next_move_time = (next_move_time + move.accel_t @@ -469,8 +470,8 @@ class ToolHead: last_move = self.lookahead.get_last() if last_move is not None: last_move.limit_next_junction_speed(speed) - def move(self, newpos, speed): - move = Move(self, self.commanded_pos, newpos, speed) + def move(self, newpos, speed, taskline=0): + move = Move(self, self.commanded_pos, newpos, speed, taskline) if not move.move_d: return if move.is_kinematic_move: diff --git a/scripts/plr.sh b/scripts/plr.sh index 564245cd0..5225ecf07 100755 --- a/scripts/plr.sh +++ b/scripts/plr.sh @@ -1,34 +1,114 @@ #!/bin/bash -# $1 z_height $2 filename $3 z_offset +PLR_DIR="/home/klipper/printer_data/gcodes/.plr" +CONFIG_FILE="/home/klipper/printer_data/config/config_variables.cfg" +LOG_FILE="/home/klipper/printer_data/logs/moonraker.log" +echo ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> [$(date '+%F %T')] <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" >> "$LOG_FILE" -mkdir -p ~/printer_data/gcodes/.plr -filepath=$(sed -n "s/.*filepath *= *'\([^']*\)'.*/\1/p" /home/klipper/printer_data/config/config_variables.cfg) -filepath=$(printf "$filepath") -echo "$filepath" +z_offset="$1" -last_file=$(sed -n "s/.*last_file *= *'\([^']*\)'.*/\1/p" /home/klipper/printer_data/config/config_variables.cfg) -last_file=$(printf "$last_file") -echo "$last_file" -plr=$last_file -echo "plr=$plr" -PLR_PATH=~/printer_data/gcodes/.plr +mkdir -p "$PLR_DIR" || { + echo "[$(date '+%F %T')] ERROR: Unable to create the directory: $PLR_DIR" >> "$LOG_FILE" + exit 2 +} -file_content=$(cat "${filepath}" | awk '/; thumbnail begin/{flag=1;next}/; thumbnail end/{flag=0} !flag' | grep -v "^;simage:\|^;gimage:") +filepath=$(sed -n "s/.*filepath *= *'\([^']*\)'.*/\1/p" "$CONFIG_FILE") +cp "${filepath}" "/home/klipper/plrtmpA.$$" +sourcefile="/home/klipper/plrtmpA.$$" -echo "$file_content" | sed 's/\r$//' | awk -F"Z" 'BEGIN{OFS="Z"} {if ($2 ~ /^[0-9]+$/) $2=$2".0"} 1' > /home/klipper/plrtmpA.$$ -sed -i 's/Z\./Z0\./g' /home/klipper/plrtmpA.$$ -z_pos=$(echo "${1} + ${3}" | bc) -cat /home/klipper/plrtmpA.$$ | sed -e '1,/Z'${1}'/ d' | sed -ne '/ Z/,$ p' | grep -m 1 ' Z' | sed -ne "s/.* Z\([^ ]*\).*/SET_KINEMATIC_POSITION Z=${z_pos}/p" > ${PLR_PATH}/"${plr}" +raw_value=$(sed -n -E "s/^[[:space:]]*power_loss_paused[[:space:]]*=[[:space:]]*(True|False)[[:space:]]*(;.*)?$/\1/p" "$CONFIG_FILE" | tail -n1) +is_pause=False +[[ "${raw_value,,}" == "true" ]] && is_pause=True -cat /home/klipper/plrtmpA.$$ | sed '/ Z'${1}'/q' | sed -ne '/\(M104\|M140\|M109\|M190\)/p' >> ${PLR_PATH}/"${plr}" +raw_line=$(sed -n -E "s/power_resume_line[[:space:]]*=[[:space:]]*([1-9][0-9]*)['\"]?[[:space:]]*(;.*)?$/\1/p" "$CONFIG_FILE") +run_line=$(tr -cd '0-9' <<< "$raw_line") +if [[ ! "$run_line" =~ ^[1-9][0-9]*$ ]]; then + echo "ERROR: power_resume_line, It must be a valid positive integer" >> "$LOG_FILE" + echo "Current configuration value:'$run_line'" >> "$LOG_FILE" + exit 1 +fi +echo "When power outage, the printer is executing $run_line line of the file." >> "$LOG_FILE" -line=$(cat /home/klipper/plrtmpA.$$ | sed '/ Z'${1}'/q' | sed -n '/START_PRINT/p') +raw_position=$(sed -n -E "s/power_resume_position[[:space:]]*=[[:space:]]*([1-9][0-9]*)['\"]?[[:space:]]*(;.*)?$/\1/p" "$CONFIG_FILE") +target_pos=$(tr -cd '0-9' <<< "$raw_position") +if [[ ! "$target_pos" =~ ^[1-9][0-9]*$ ]]; then + echo "ERROR: power_resume_position, It must be a valid positive integer" >> "$LOG_FILE" + echo "Current configuration value:'$target_pos'" >> "$LOG_FILE" + exit 1 +fi -if [ -n "$line" ]; then - EXTRUDER=$(echo "$line" | sed -n 's/.*EXTRUDER=\([0-9]*\).*/\1/p') - EXTRUDER1=$(echo "$line" | sed -n 's/.*EXTRUDER1=\([0-9]*\).*/\1/p') - BED=$(echo "$line" | sed -n 's/.*BED=\([0-9]*\).*/\1/p') - CHAMBER=$(echo "$line" | sed -n 's/.*CHAMBER=\([0-9]*\).*/\1/p') +last_file="${filepath##*/}" + +echo "Power-off recovery file path: $filepath" >> "$LOG_FILE" +echo "Last printed file name: $last_file" >> "$LOG_FILE" +plr="$last_file" + +cat "${sourcefile}" | awk ' + { + sub(/\r$/, "") + if ($0 ~ /^;/ || $0 ~ /^[[:space:]]*$/) { + print + } else { + exit + } + }' > "${PLR_DIR}/${plr}" + +line=$(awk -v target="$target_pos" ' + BEGIN { current_pos = 0; line_number = 1 } + { + line_length = length($0) + 1 # +1 对应换行符(Linux: \n, Windows: \r\n) + if (current_pos <= target && target < current_pos + line_length) { + print line_number + exit + } + current_pos += line_length + line_number++ + } +' "$sourcefile") +echo "When power outage, it was parsing the $target_pos byte and the $line line" >> "$LOG_FILE" + +line="$run_line" + +z_height=$(awk -v target_line="$line" ' + BEGIN { found = 0 } + NR <= target_line { + if ($0 ~ /^;[[:space:]]*Z:/) { + split($0, parts, /:[[:space:]]*/) + z_val = parts[2] + found = 1 + } + } + NR == target_line { + if (found) { + print z_val + } + exit + } +' "$sourcefile") +echo "When power outage, the printing height: $z_height, the offset value: $z_offset" >> "$LOG_FILE" + +z_pos=$(echo "${z_height} + ${z_offset}" | bc) +echo "Assign the Z height as: $z_pos" >> "$LOG_FILE" + +echo "SET_KINEMATIC_POSITION Z=${z_pos}" >> "${PLR_DIR}/${plr}" +echo ";Z:${z_pos}" >> "${PLR_DIR}/${plr}" + +awk -v end_line="$line" ' + NR > end_line { exit } + /M104|M140|M109|M190/ { print } +' "$sourcefile" >> "${PLR_DIR}/${plr}" + +start_info=$(awk -v max_line="$line" ' + NR > max_line { exit } + $0 ~ /^(START_PRINT|PRINT_START)/ { + print + exit + } +' "$sourcefile") +if [ -n "$start_info" ]; then + EXTRUDER=$(echo "$start_info" | sed -n 's/.*EXTRUDER=\([0-9]*\).*/\1/p') + EXTRUDER1=$(echo "$start_info" | sed -n 's/.*EXTRUDER1=\([0-9]*\).*/\1/p') + BED=$(echo "$start_info" | sed -n 's/.*BED=\([0-9]*\).*/\1/p') + CHAMBER=$(echo "$start_info" | sed -n 's/.*CHAMBER=\([0-9]*\).*/\1/p') EXTRUDER=${EXTRUDER:-0} EXTRUDER1=${EXTRUDER1:-0} BED=${BED:-0} @@ -39,56 +119,112 @@ if [ -n "$line" ]; then for i in "${!temps[@]}"; do if [ "${temps[$i]}" != "0" ]; then - echo "${temp_cmds[$i]} ${temps[$i]}" >> "${PLR_PATH}/${plr}" + echo "${temp_cmds[$i]} ${temps[$i]}" >> "${PLR_DIR}/${plr}" fi done fi -cat /home/klipper/plrtmpA.$$ | sed -ne '/;End of Gcode/,$ p' | tr '\n' ' ' | sed -ne 's/ ;[^ ]* //gp' | sed -ne 's/\\\\n/;/gp' | tr ';' '\n' | grep material_bed_temperature | sed -ne 's/.* = /M140 S/p' | head -1 >> ${PLR_PATH}/"${plr}" -cat /home/klipper/plrtmpA.$$ | sed -ne '/;End of Gcode/,$ p' | tr '\n' ' ' | sed -ne 's/ ;[^ ]* //gp' | sed -ne 's/\\\\n/;/gp' | tr ';' '\n' | grep material_print_temperature | sed -ne 's/.* = /M104 S/p' | head -1 >> ${PLR_PATH}/"${plr}" -cat /home/klipper/plrtmpA.$$ | sed -ne '/;End of Gcode/,$ p' | tr '\n' ' ' | sed -ne 's/ ;[^ ]* //gp' | sed -ne 's/\\\\n/;/gp' | tr ';' '\n' | grep material_bed_temperature | sed -ne 's/.* = /M190 S/p' | head -1 >> ${PLR_PATH}/"${plr}" -cat /home/klipper/plrtmpA.$$ | sed -ne '/;End of Gcode/,$ p' | tr '\n' ' ' | sed -ne 's/ ;[^ ]* //gp' | sed -ne 's/\\\\n/;/gp' | tr ';' '\n' | grep material_print_temperature | sed -ne 's/.* = /M109 S/p' | head -1 >> ${PLR_PATH}/"${plr}" +awk -v plr="${PLR_DIR}/${plr}" ' + BEGIN { + bed_temp = 0 + print_temp = 0 + cmd_generated = 0 + } + $0 ~ /;End of Gcode/,0 { + gsub(/\r?\n/, " ") + gsub(/;/, "\n") + gsub(/[ \t]+/, " ") + if (match($0, /material_bed_temperature[ =]+([0-9]+)/, m)) + bed_temp = m[1] + if (match($0, /material_print_temperature[ =]+([0-9]+)/, m)) + print_temp = m[1] -BG_EX=`tac /home/klipper/plrtmpA.$$ | sed -e '/ Z'${1}'[^0-9]*$/q' | tac | tail -n+2 | sed -e '/ Z[0-9]/ q' | tac | sed -e '/ E[0-9]/ q' | sed -ne 's/.* E\([^ ]*\)/G92 E\1/p'` -# If we failed to match an extrusion command (allowing us to correctly set the E axis) prior to the matched layer height, then simply set the E axis to the first E value present in the resemued gcode. This avoids extruding a huge blod on resume, and/or max extrusion errors. -if [ "${BG_EX}" = "" ]; then - BG_EX=`tac /home/klipper/plrtmpA.$$ | sed -e '/ Z'${1}'[^0-9]*$/q' | tac | tail -n+2 | sed -ne '/ Z/,$ p' | sed -e '/ E[0-9]/ q' | sed -ne 's/.* E\([^ ]*\)/G92 E\1/p'` -fi -M83=$(cat /home/klipper/plrtmpA.$$ | sed '/ Z'${1}'/q' | sed -ne '/\(M83\)/p') -if [ -n "${M83}" ];then - echo 'G92 E0' >> ${PLR_PATH}/"${plr}" - echo ${M83} >> ${PLR_PATH}/"${plr}" -else - echo ${BG_EX} >> ${PLR_PATH}/"${plr}" -fi -echo 'G91' >> ${PLR_PATH}/"${plr}" -echo 'G1 Z10' >> ${PLR_PATH}/"${plr}" -echo 'G90' >> ${PLR_PATH}/"${plr}" -echo 'G28 X Y' >> ${PLR_PATH}/"${plr}" -cat /home/klipper/plrtmpA.$$ | sed '/ Z'${1}'/q' | sed -ne '/\(ACTIVATE_COPY_MODE\|ACTIVATE_MIRROR_MODE\)/p' >> ${PLR_PATH}/"${plr}" -echo 'G1 X5' >> ${PLR_PATH}/"${plr}" -echo 'G1 Y5' >> ${PLR_PATH}/"${plr}" -cat /home/klipper/plrtmpA.$$ | sed -n '1,/Z'"${1}"'/p'| tac | grep -m 1 -o '^[T][01]' >> ${PLR_PATH}/"${plr}" -echo 'G91' >> ${PLR_PATH}/"${plr}" -echo 'G1 Z-5' >> ${PLR_PATH}/"${plr}" -echo 'G90' >> ${PLR_PATH}/"${plr}" -echo 'M106 S204' >> ${PLR_PATH}/"${plr}" + if (bed_temp > 0 || print_temp > 0) { + if (!cmd_generated) { + print "; 温度控制指令" + cmd_generated = 1 + } + if (bed_temp > 0) { + printf "M140 S%d\nM190 S%d\n", bed_temp, bed_temp + } + if (print_temp > 0) { + printf "M104 S%d\nM109 S%d\n", print_temp, print_temp + } + exit + } + } +' "$sourcefile" >> "${PLR_DIR}/${plr}" -first_line=$(cat /home/klipper/plrtmpA.$$ |sed -e '1,/Z'${1}'/ d' | sed -ne '/ Z/,$ p' | grep -m 1 ' Z' | grep -E 'F[0-9]+' | sed -E 's/F[0-9]+/F3000/g') -if [ "${first_line}" = "" ];then - cat /home/klipper/plrtmpA.$$ | sed -e '1,/Z'${1}'/ d' | sed -ne '/ Z/,$ p' >> ${PLR_PATH}/"${plr}" -else - line=$(cat /home/klipper/plrtmpA.$$ | sed -e '1,/Z'${1}'/ d' | sed -ne '/ Z/,$ p' | grep -m 1 ' Z') - z_pos=$(echo "$line" | sed -n 's/.*Z\([0-9.]*\).*/\1/p') - if [[ ${1} != $z_pos ]]; then - first_line=$(cat /home/klipper/plrtmpA.$$ |sed -e '1,/Z'${1}'/ { /Z'${1}'/!d }' | sed -ne '/ Z/,$ p' | grep -m 1 ' Z' | grep -E 'F[0-9]+' | sed -E 's/F[0-9]+/F3000/g') - echo ${first_line} >> ${PLR_PATH}/"${plr}" - cat /home/klipper/plrtmpA.$$ | sed -e '1,/Z'${1}'/ { /Z'${1}'/!d }' | sed -ne '/ Z/,$ p' | tail -n +2 >> ${PLR_PATH}/"${plr}" - else - echo ${first_line} >> ${PLR_PATH}/"${plr}" - cat /home/klipper/plrtmpA.$$ | sed -e '1,/Z'${1}'/ d' | sed -ne '/ Z/,$ p' | tail -n +2 >> ${PLR_PATH}/"${plr}" +awk -v end_line="$line" ' + BEGIN { last_mode = ""; e_value = "" } + # 跳过注释行 + $0 ~ /^;/ { next } + # 只处理到end_line行 + NR > end_line { exit } + # 记录最后出现的模式 + /M83/ { last_mode = "M83" } + /M82/ { last_mode = "M82" } + # 捕获end_line行的E值 + NR == end_line { + if (match($0, /E[0-9.]+/)) { + e_value = substr($0, RSTART+1, RLENGTH-1) + } + } + # 最终决策 + END { + if (last_mode == "M83") { + print "G92 E0" + print "M83" + } + else if (last_mode == "M82") { + print "M82" + print (e_value != "") ? "G92 E" e_value : "G92 E0" + } + } +' "$sourcefile" >> "${PLR_DIR}/${plr}" + +target_position=$(awk -v line_num="$line" 'NR == line_num { gsub(/E[0-9.]+/, ""); print }' "$sourcefile") +{ + echo 'G91' + echo 'G1 Z10' + echo 'G90' + echo 'G28 X Y' + awk -v end_line="$line" ' + NR > end_line { exit } + /ACTIVATE_COPY_MODE|ACTIVATE_MIRROR_MODE/ { print } + ' "$sourcefile" + echo 'G1 X5' + echo 'G1 Y5' + awk -v end_line="$line" ' + NR > end_line { + if (found) { + print last_match + } + exit + } + /^T[01]/ { + last_match = $0 + found = 1 + } + END { + if (found) { + print last_match + } + } + ' "$sourcefile" + + if [ -n "$target_position" ]; then + echo "$target_position" fi -fi + echo 'M106 S204' +} >> "${PLR_DIR}/${plr}" + +echo "G1 Z${z_height} F3000" >> "${PLR_DIR}/${plr}" + +sed -n "${line},$ p" "${sourcefile}" >> "${PLR_DIR}/${plr}" +echo "Append the file from ${line} line to ${PLR_DIR}/${plr}" >> "$LOG_FILE" + rm /home/klipper/plrtmpA.$$ +echo ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> [$(date '+%F %T')] <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" >> "$LOG_FILE" diff --git a/src/stepper.c b/src/stepper.c index 00a8ff012..8b5b3c179 100644 --- a/src/stepper.c +++ b/src/stepper.c @@ -32,6 +32,7 @@ struct stepper_move { struct move_node node; uint32_t interval; + uint32_t taskline; int16_t add; uint16_t count; uint8_t flags; @@ -227,6 +228,7 @@ command_queue_step(uint32_t *args) if (!m->count) shutdown("Invalid count parameter"); m->add = args[3]; + m->taskline = args[4]; m->flags = 0; irq_disable(); @@ -249,7 +251,7 @@ command_queue_step(uint32_t *args) irq_enable(); } DECL_COMMAND(command_queue_step, - "queue_step oid=%c interval=%u count=%hu add=%hi"); + "queue_step oid=%c interval=%u count=%hu add=%hi taskline=%u"); // Set the direction of the next queued step void @@ -307,6 +309,29 @@ command_stepper_get_position(uint32_t *args) } DECL_COMMAND(command_stepper_get_position, "stepper_get_position oid=%c"); +// Report the current line of the stepper +void +command_stepper_get_taskline(uint32_t *args) +{ + uint8_t oid = args[0]; + struct stepper *s = stepper_oid_lookup(oid); + uint32_t max_taskline = 0; + irq_disable(); + struct move_node *mn = s->mq.first; + while (mn) { + struct stepper_move *m = container_of(mn, struct stepper_move, node); + if(m->taskline){ + if (m->taskline > max_taskline) + max_taskline = m->taskline; + break; + } + mn = mn->next; + } + irq_enable(); + sendf("stepper_taskline line=%u", max_taskline); +} +DECL_COMMAND(command_stepper_get_taskline, "stepper_get_taskline oid=%c"); + // Stop all moves for a given stepper (caller must disable IRQs) static void stepper_stop(struct trsync_signal *tss, uint8_t reason)