断行续打功能优化
This commit is contained in:
parent
46e033ccc5
commit
567d7ee7e8
@ -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
|
||||
@ -841,7 +841,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."
|
||||
@ -974,9 +974,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
|
||||
|
||||
@ -992,9 +992,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 %}
|
||||
@ -1004,7 +1004,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
|
||||
|
||||
|
@ -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
|
||||
@ -887,9 +887,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
|
||||
|
||||
@ -905,9 +905,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 %}
|
||||
@ -917,7 +917,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
|
||||
|
||||
|
@ -843,7 +843,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."
|
||||
@ -976,9 +976,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
|
||||
|
||||
@ -994,9 +994,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 %}
|
||||
@ -1006,7 +1006,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
|
||||
|
||||
|
@ -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
|
||||
@ -882,9 +882,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
|
||||
|
||||
@ -900,9 +900,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 %}
|
||||
@ -912,7 +912,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
|
||||
|
||||
|
@ -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 %}
|
||||
@ -1157,9 +1157,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
|
||||
|
||||
@ -1175,9 +1175,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 %}
|
||||
@ -1187,7 +1187,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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 (;;) {
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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 ")
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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:
|
||||
|
@ -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):
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
268
scripts/plr.sh
268
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"
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user