Skip to content

Commit c84d78f

Browse files
authored
extruder: Allow dynamic adjustment of pressure advance (#6635)
Signed-off-by: Dmitry Butyugin <[email protected]>
1 parent 248d3db commit c84d78f

File tree

6 files changed

+185
-20
lines changed

6 files changed

+185
-20
lines changed

klippy/chelper/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,8 +142,9 @@
142142

143143
defs_kin_extruder = """
144144
struct stepper_kinematics *extruder_stepper_alloc(void);
145+
void extruder_stepper_free(struct stepper_kinematics *sk);
145146
void extruder_set_pressure_advance(struct stepper_kinematics *sk
146-
, double pressure_advance, double smooth_time);
147+
, double print_time, double pressure_advance, double smooth_time);
147148
"""
148149

149150
defs_kin_shaper = """

klippy/chelper/kin_extruder.c

Lines changed: 69 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,15 @@
99
#include <string.h> // memset
1010
#include "compiler.h" // __visible
1111
#include "itersolve.h" // struct stepper_kinematics
12+
#include "list.h" // list_node
1213
#include "pyhelper.h" // errorf
1314
#include "trapq.h" // move_get_distance
1415

16+
struct pa_params {
17+
double pressure_advance, active_print_time;
18+
struct list_node node;
19+
};
20+
1521
// Without pressure advance, the extruder stepper position is:
1622
// extruder_position(t) = nominal_position(t)
1723
// When pressure advance is enabled, additional filament is pushed
@@ -52,17 +58,25 @@ extruder_integrate_time(double base, double start_v, double half_accel
5258

5359
// Calculate the definitive integral of extruder for a given move
5460
static double
55-
pa_move_integrate(struct move *m, double pressure_advance
61+
pa_move_integrate(struct move *m, struct list_head *pa_list
5662
, double base, double start, double end, double time_offset)
5763
{
5864
if (start < 0.)
5965
start = 0.;
6066
if (end > m->move_t)
6167
end = m->move_t;
62-
// Calculate base position and velocity with pressure advance
68+
// Determine pressure_advance value
6369
int can_pressure_advance = m->axes_r.y != 0.;
64-
if (!can_pressure_advance)
65-
pressure_advance = 0.;
70+
double pressure_advance = 0.;
71+
if (can_pressure_advance) {
72+
struct pa_params *pa = list_last_entry(pa_list, struct pa_params, node);
73+
while (unlikely(pa->active_print_time > m->print_time) &&
74+
!list_is_first(&pa->node, pa_list)) {
75+
pa = list_prev_entry(pa, node);
76+
}
77+
pressure_advance = pa->pressure_advance;
78+
}
79+
// Calculate base position and velocity with pressure advance
6680
base += pressure_advance * m->start_v;
6781
double start_v = m->start_v + pressure_advance * 2. * m->half_accel;
6882
// Calculate definitive integral
@@ -75,35 +89,36 @@ pa_move_integrate(struct move *m, double pressure_advance
7589
// Calculate the definitive integral of the extruder over a range of moves
7690
static double
7791
pa_range_integrate(struct move *m, double move_time
78-
, double pressure_advance, double hst)
92+
, struct list_head *pa_list, double hst)
7993
{
8094
// Calculate integral for the current move
8195
double res = 0., start = move_time - hst, end = move_time + hst;
8296
double start_base = m->start_pos.x;
83-
res += pa_move_integrate(m, pressure_advance, 0., start, move_time, start);
84-
res -= pa_move_integrate(m, pressure_advance, 0., move_time, end, end);
97+
res += pa_move_integrate(m, pa_list, 0., start, move_time, start);
98+
res -= pa_move_integrate(m, pa_list, 0., move_time, end, end);
8599
// Integrate over previous moves
86100
struct move *prev = m;
87101
while (unlikely(start < 0.)) {
88102
prev = list_prev_entry(prev, node);
89103
start += prev->move_t;
90104
double base = prev->start_pos.x - start_base;
91-
res += pa_move_integrate(prev, pressure_advance, base, start
105+
res += pa_move_integrate(prev, pa_list, base, start
92106
, prev->move_t, start);
93107
}
94108
// Integrate over future moves
95109
while (unlikely(end > m->move_t)) {
96110
end -= m->move_t;
97111
m = list_next_entry(m, node);
98112
double base = m->start_pos.x - start_base;
99-
res -= pa_move_integrate(m, pressure_advance, base, 0., end, end);
113+
res -= pa_move_integrate(m, pa_list, base, 0., end, end);
100114
}
101115
return res;
102116
}
103117

104118
struct extruder_stepper {
105119
struct stepper_kinematics sk;
106-
double pressure_advance, half_smooth_time, inv_half_smooth_time2;
120+
struct list_head pa_list;
121+
double half_smooth_time, inv_half_smooth_time2;
107122
};
108123

109124
static double
@@ -116,22 +131,45 @@ extruder_calc_position(struct stepper_kinematics *sk, struct move *m
116131
// Pressure advance not enabled
117132
return m->start_pos.x + move_get_distance(m, move_time);
118133
// Apply pressure advance and average over smooth_time
119-
double area = pa_range_integrate(m, move_time, es->pressure_advance, hst);
134+
double area = pa_range_integrate(m, move_time, &es->pa_list, hst);
120135
return m->start_pos.x + area * es->inv_half_smooth_time2;
121136
}
122137

123138
void __visible
124-
extruder_set_pressure_advance(struct stepper_kinematics *sk
139+
extruder_set_pressure_advance(struct stepper_kinematics *sk, double print_time
125140
, double pressure_advance, double smooth_time)
126141
{
127142
struct extruder_stepper *es = container_of(sk, struct extruder_stepper, sk);
128-
double hst = smooth_time * .5;
143+
double hst = smooth_time * .5, old_hst = es->half_smooth_time;
129144
es->half_smooth_time = hst;
130145
es->sk.gen_steps_pre_active = es->sk.gen_steps_post_active = hst;
146+
147+
// Cleanup old pressure advance parameters
148+
double cleanup_time = sk->last_flush_time - (old_hst > hst ? old_hst : hst);
149+
struct pa_params *first_pa = list_first_entry(
150+
&es->pa_list, struct pa_params, node);
151+
while (!list_is_last(&first_pa->node, &es->pa_list)) {
152+
struct pa_params *next_pa = list_next_entry(first_pa, node);
153+
if (next_pa->active_print_time >= cleanup_time) break;
154+
list_del(&first_pa->node);
155+
first_pa = next_pa;
156+
}
157+
131158
if (! hst)
132159
return;
133160
es->inv_half_smooth_time2 = 1. / (hst * hst);
134-
es->pressure_advance = pressure_advance;
161+
162+
if (list_last_entry(&es->pa_list, struct pa_params, node)->pressure_advance
163+
== pressure_advance) {
164+
// Retain old pa_params
165+
return;
166+
}
167+
// Add new pressure advance parameters
168+
struct pa_params *pa = malloc(sizeof(*pa));
169+
memset(pa, 0, sizeof(*pa));
170+
pa->pressure_advance = pressure_advance;
171+
pa->active_print_time = print_time;
172+
list_add_tail(&pa->node, &es->pa_list);
135173
}
136174

137175
struct stepper_kinematics * __visible
@@ -141,5 +179,22 @@ extruder_stepper_alloc(void)
141179
memset(es, 0, sizeof(*es));
142180
es->sk.calc_position_cb = extruder_calc_position;
143181
es->sk.active_flags = AF_X;
182+
list_init(&es->pa_list);
183+
struct pa_params *pa = malloc(sizeof(*pa));
184+
memset(pa, 0, sizeof(*pa));
185+
list_add_tail(&pa->node, &es->pa_list);
144186
return &es->sk;
145187
}
188+
189+
void __visible
190+
extruder_stepper_free(struct stepper_kinematics *sk)
191+
{
192+
struct extruder_stepper *es = container_of(sk, struct extruder_stepper, sk);
193+
while (!list_empty(&es->pa_list)) {
194+
struct pa_params *pa = list_first_entry(
195+
&es->pa_list, struct pa_params, node);
196+
list_del(&pa->node);
197+
free(pa);
198+
}
199+
free(sk);
200+
}

klippy/kinematics/extruder.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ def __init__(self, config):
1818
self.stepper = stepper.PrinterStepper(config)
1919
ffi_main, ffi_lib = chelper.get_ffi()
2020
self.sk_extruder = ffi_main.gc(ffi_lib.extruder_stepper_alloc(),
21-
ffi_lib.free)
21+
ffi_lib.extruder_stepper_free)
2222
self.stepper.set_stepper_kinematics(self.sk_extruder)
2323
self.motion_queue = None
2424
# Register commands
@@ -71,11 +71,14 @@ def _set_pressure_advance(self, pressure_advance, smooth_time):
7171
if not pressure_advance:
7272
new_smooth_time = 0.
7373
toolhead = self.printer.lookup_object("toolhead")
74-
toolhead.note_step_generation_scan_time(new_smooth_time * .5,
75-
old_delay=old_smooth_time * .5)
74+
if new_smooth_time != old_smooth_time:
75+
toolhead.note_step_generation_scan_time(
76+
new_smooth_time * .5, old_delay=old_smooth_time * .5)
7677
ffi_main, ffi_lib = chelper.get_ffi()
7778
espa = ffi_lib.extruder_set_pressure_advance
78-
espa(self.sk_extruder, pressure_advance, new_smooth_time)
79+
toolhead.register_lookahead_callback(
80+
lambda print_time: espa(self.sk_extruder, print_time,
81+
pressure_advance, new_smooth_time))
7982
self.pressure_advance = pressure_advance
8083
self.pressure_advance_smooth_time = smooth_time
8184
cmd_SET_PRESSURE_ADVANCE_help = "Set pressure advance parameters"

test/klippy/commands.test

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ SET_VELOCITY_LIMIT ACCEL=100 VELOCITY=20 SQUARE_CORNER_VELOCITY=1 ACCEL_TO_DECEL
4040
M204 S500
4141

4242
SET_PRESSURE_ADVANCE EXTRUDER=extruder ADVANCE=.001
43-
SET_PRESSURE_ADVANCE ADVANCE=.002 ADVANCE_LOOKAHEAD_TIME=.001
43+
SET_PRESSURE_ADVANCE ADVANCE=.002 SMOOTH_TIME=.001
4444

4545
# Restart command (must be last in test)
4646
RESTART

test/klippy/pressure_advance.cfg

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# Config for extruder testing
2+
[stepper_x]
3+
step_pin: PF0
4+
dir_pin: PF1
5+
enable_pin: !PD7
6+
microsteps: 16
7+
rotation_distance: 40
8+
endstop_pin: ^PE5
9+
position_endstop: 0
10+
position_max: 200
11+
homing_speed: 50
12+
13+
[stepper_y]
14+
step_pin: PF6
15+
dir_pin: !PF7
16+
enable_pin: !PF2
17+
microsteps: 16
18+
rotation_distance: 40
19+
endstop_pin: ^PJ1
20+
position_endstop: 0
21+
position_max: 200
22+
homing_speed: 50
23+
24+
[stepper_z]
25+
step_pin: PL3
26+
dir_pin: PL1
27+
enable_pin: !PK0
28+
microsteps: 16
29+
rotation_distance: 8
30+
endstop_pin: ^PD3
31+
position_endstop: 0.5
32+
position_max: 200
33+
34+
[extruder]
35+
step_pin: PA4
36+
dir_pin: PA6
37+
enable_pin: !PA2
38+
microsteps: 16
39+
rotation_distance: 33.5
40+
nozzle_diameter: 0.500
41+
filament_diameter: 3.500
42+
heater_pin: PB4
43+
sensor_type: EPCOS 100K B57560G104F
44+
sensor_pin: PK5
45+
control: pid
46+
pid_Kp: 22.2
47+
pid_Ki: 1.08
48+
pid_Kd: 114
49+
min_temp: 0
50+
max_temp: 210
51+
52+
[extruder_stepper my_extra_stepper]
53+
extruder: extruder
54+
step_pin: PH5
55+
dir_pin: PH6
56+
enable_pin: !PB5
57+
microsteps: 16
58+
rotation_distance: 28.2
59+
60+
[mcu]
61+
serial: /dev/ttyACM0
62+
63+
[printer]
64+
kinematics: cartesian
65+
max_velocity: 300
66+
max_accel: 3000
67+
max_z_velocity: 5
68+
max_z_accel: 100

test/klippy/pressure_advance.test

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Extruder tests
2+
DICTIONARY atmega2560.dict
3+
CONFIG pressure_advance.cfg
4+
5+
SET_PRESSURE_ADVANCE ADVANCE=0.1
6+
# Home and extrusion moves
7+
G28
8+
G1 X20 Y20 Z1 F6000
9+
G1 E7
10+
G1 X25 Y25 E7.5
11+
12+
# Update pressure advance for my_extra_stepper
13+
SET_PRESSURE_ADVANCE EXTRUDER=my_extra_stepper ADVANCE=0.02
14+
G1 X30 Y30 E8.0
15+
16+
# Unsync my_extra_stepper from extruder
17+
SYNC_EXTRUDER_MOTION EXTRUDER=my_extra_stepper MOTION_QUEUE=
18+
19+
# Update pressure advance for primary extruder
20+
SET_PRESSURE_ADVANCE ADVANCE=0.01
21+
G1 X35 Y35 E8.5
22+
23+
# Update pressure advance both extruders
24+
SET_PRESSURE_ADVANCE EXTRUDER=my_extra_stepper ADVANCE=0.05
25+
SET_PRESSURE_ADVANCE ADVANCE=0.05
26+
# Sync my_extra_stepper to extruder
27+
SYNC_EXTRUDER_MOTION EXTRUDER=my_extra_stepper MOTION_QUEUE=extruder
28+
G1 X40 Y40 E9.0
29+
30+
# Update smooth_time
31+
SET_PRESSURE_ADVANCE SMOOTH_TIME=0.02
32+
SET_PRESSURE_ADVANCE EXTRUDER=my_extra_stepper SMOOTH_TIME=0.02
33+
G1 X45 Y45 E9.5
34+
35+
# Updating both smooth_time and pressure advance
36+
SET_PRESSURE_ADVANCE SMOOTH_TIME=0.03 ADVANCE=0.1
37+
SET_PRESSURE_ADVANCE EXTRUDER=my_extra_stepper SMOOTH_TIME=0.03 ADVANCE=0.1
38+
G1 X50 Y50 E10.0

0 commit comments

Comments
 (0)