From 1d05a34cd701e5e282e59da5ef7f0404cbbbc255 Mon Sep 17 00:00:00 2001 From: Kevin O'Connor Date: Fri, 13 Dec 2019 16:51:45 -0500 Subject: [PATCH] docs: Update Kinematics.md document with "smooth pressure advance" Signed-off-by: Kevin O'Connor --- docs/Kinematics.md | 47 +++---- docs/img/pressure-advance.svg | 207 ---------------------------- docs/img/pressure-advance.svg.png | Bin 12986 -> 0 bytes docs/img/pressure-cornering.svg | 180 ------------------------ docs/img/pressure-cornering.svg.png | Bin 9837 -> 0 bytes docs/img/pressure-velocity.png | Bin 0 -> 24301 bytes scripts/graph_extruder.py | 145 +++++++++++++++++++ 7 files changed, 169 insertions(+), 410 deletions(-) delete mode 100644 docs/img/pressure-advance.svg delete mode 100644 docs/img/pressure-advance.svg.png delete mode 100644 docs/img/pressure-cornering.svg delete mode 100644 docs/img/pressure-cornering.svg.png create mode 100644 docs/img/pressure-velocity.png create mode 100755 scripts/graph_extruder.py diff --git a/docs/Kinematics.md b/docs/Kinematics.md index 548076d7..f4b84550 100644 --- a/docs/Kinematics.md +++ b/docs/Kinematics.md @@ -264,35 +264,36 @@ through the nozzle orifice (as in key idea is that the relationship between filament, pressure, and flow rate can be modeled using a linear coefficient: ``` -stepper_position = requested_e_position + pressure_advance_coefficient * nominal_extruder_velocity +pa_position = nominal_position + pressure_advance_coefficient * nominal_velocity ``` See the [pressure advance](Pressure_Advance.md) document for information on how to find this pressure advance coefficient. -Once configured, Klipper will push in an additional amount of filament -during acceleration. The higher the desired filament flow rate, the -more filament must be pushed in during acceleration to account for -pressure. During head deceleration the extra filament is retracted -(the extruder will have a negative velocity). +The basic pressure advance formula can cause the extruder motor to +make sudden velocity changes. Klipper implements "smoothing" of the +extruder movement to avoid this. -![pressure-advance](img/pressure-advance.svg.png) +![pressure-advance](img/pressure-velocity.png) -One may notice that the pressure advance algorithm can cause the -extruder motor to make sudden velocity changes. This is tolerated -based on the idea that the majority of the inertia in the system is in -changing the extruder pressure. As long as the extruder pressure does -not change rapidly the sudden changes in extruder motor velocity are -tolerated. +The above graph shows an example of two extrusion moves with a +non-zero cornering velocity between them. Note that the pressure +advance system causes additional filament to be pushed into the +extruder during acceleration. The higher the desired filament flow +rate, the more filament must be pushed in during acceleration to +account for pressure. During head deceleration the extra filament is +retracted (the extruder will have a negative velocity). -One area where sudden velocity changes become problematic is during -small changes in head speed due to cornering. +The "smoothing" is implemented by averaging the extruder position over +a small time period (as specified by the +`pressure_advance_smooth_time` config parameter). This averaging can +span multiple g-code moves. Note how the extruder motor will start +moving prior to the nominal start of the first extrusion move and will +continue to move after the nominal end of the last extrusion move. -![pressure-cornering](img/pressure-cornering.svg.png) - -To prevent this, the Klipper pressure advance code utilizes the move -look-ahead queue to detect intermittent speed changes. During a -deceleration event the code finds the maximum upcoming head speed -within a configurable time window. The pressure is then only adjusted -to this found maximum. This can greatly reduce (or even completely -eliminate) pressure changes during cornering. +Key formula for "smoothed pressure advance": +``` +smooth_pa_position(t) = + ( definitive_integral(pa_position, from=t-smooth_time/2, to=t+smooth_time/2) + / smooth_time ) +``` diff --git a/docs/img/pressure-advance.svg b/docs/img/pressure-advance.svg deleted file mode 100644 index 79bd4674..00000000 --- a/docs/img/pressure-advance.svg +++ /dev/null @@ -1,207 +0,0 @@ - - - - - - - - - - - - image/svg+xml - - - - - - - - extrudervelocity - - - - head velocity - - - - extrude move - non-extrude move - - extruderpressure - - - time - - diff --git a/docs/img/pressure-advance.svg.png b/docs/img/pressure-advance.svg.png deleted file mode 100644 index fa2c66678f03da2c29eaa0c4651fb3665a365e25..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12986 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 az?O}oO@Ag+?*jib0U78T>(pyOpZ*`PP9q5b diff --git a/docs/img/pressure-cornering.svg b/docs/img/pressure-cornering.svg deleted file mode 100644 index 908d7eb7..00000000 --- a/docs/img/pressure-cornering.svg +++ /dev/null @@ -1,180 +0,0 @@ - - - - - - - - - - - - image/svg+xml - - - - - - - - extrudervelocity - - - - head velocity - - - - first extrude - second extrude - - time - - diff --git a/docs/img/pressure-cornering.svg.png b/docs/img/pressure-cornering.svg.png deleted file mode 100644 index 183411d5bccb1019fef6d55f6c328d77b75f7f84..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9837 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 diff --git a/docs/img/pressure-velocity.png b/docs/img/pressure-velocity.png new file mode 100644 index 0000000000000000000000000000000000000000..89e91ab44d9e5c551077c1ba0b5720b8ab6ff03a GIT binary patch literal 24301 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�yHve&97^Rcb(>cPz!iYWsmZ78~HA=Zu zR@PYtV@~7N_5vPmc3#n0FjOUloi55@OtQ76=7M}z7P^1-w9=hJrE@reqV z+NBSwPxi{2OhtckNM=v^bel)6EL7|kZN=Wn;lD*!L0#8K* zvl)_^$d({3g}9MNX!B>r@3ek^p5J`(9G&iwY*X4NE0lauWE)Qy40#Z23Sv{zcX5#t z5Bufg@w$v{)22-)e0-8~4Z!Mdklh{PG<{h;yr@WvKY5MihVuqxAiEgAi(mob1Cpg{ zXt+F4Tssz=^`-08+&nx{d!)zy*==mBGJht9-neqecOu~$+r*p0Ro<7Y#B+Zt9$nVl z)U;efLnCms@WzIW=KLZ<88{A}fpmKFgLUJw2|r(Q+DMP-zplGt?c|<;HvX(36IbVb z=PN?Kc@>Vf5qv*Lycf0{e0&$rT@`Dq*O~4Q=rxd+-K|ybr~cMAX7i3)^+Evsx(?qy z!fqiacm@LaL4~j%E7nb_80Hw{g&X93KHcBeMk2wTr0?!te7(ZY!*q1Qiemko`}ILP z*9wz5&Ei`M&OAI163D!tTKYA9)a`VaclPw;Eh%}R;5+xcR`bZgN0m~77kTTdy6mgG z#4ynYK7WomcW%jMTb4lUwl6CIex`)nm)W>+srUUKu2sX?p>raT$|P7)`S=VU->wuA z7Zl{3o4Y3}$nMi4oBn0E`9w`1UsY}GzOee8bXveMFR!P-dKmNb!S`y&XI`C%b1$3h zBK1$eTm=`=MCCRa8BSshJUzFdB7QX(5+eH0ywKuiNlDreIk*a@>hZp+)o22v^>UI< z^`$>eFJDrbmSI`4|5mHqGUsR>w!M3KfB$q}P4<^nh-O}2Mp5JyR$F;iaHxyz&ghMt z95y&~E~p+B3ZPG?9kP3f>rT~}OlwnLifQ;tlCCkC<5{cH%?l&U3&$&Ma`p*NaJFam zRc@_J6)Y>MeR2G1uwS?C`Lo{j>{Po>wZmc>nAWQ!KeUu*&yEuBufIw{3eN<>4^&Hj zPY76KHqyevf_XY@%IUHjc4*n|bjtHT!))Ar@(``F>4PYf(+`4g!juLrX(W^&fM+8C zpS?%7V1VY}g)RDUk;{7uJc~@OE|HV3*pFC?X}bt#zF^Pu`4)1wLx1`c(sESlT-@9Z zm~`=gH!jy~rBIXwb#xv)T6*(VPvVhP>yA#w(n()GaL8+Fih>v18X!WWIeRVTAhELt z7~H0BK6_m~L>hmjVQ>H7)&7vNE9J`K6v?;;9C37da6Q}7yNg9#y?rCR7e&aMDU{LQ zwRPdq>p6P+!bgu!C?`53i`;&Q^)=R}w0CDnP0-keCB(0l3t{67Zpqs%sj7Au*VCTN z@<@&5YKnjDz{i(7JNC<;xr&w%TlM82igUaZ*mVh9;g#}4h_hV^ zP~2@?QB^evS`qKhve`m)S!mxOGWYj2VXE!k-sM zp~UD?P`~)Tn?334OT-4rrWvgi-O6QudL}YPPW1}al8{jE z$=W7@5SOGT=fm}9>Xyr=MNxz9l$R6AA&3^AqQ!%` zK!^}0=)w#mEVIn&(a5}3pCj-ZeAD*{?=bfv?)*GsK#^5?(kXr+Z&-fK5rSi;J*~4h zvd`!pKQ0H);K0ZTJ$xzW5kN4~McpS@Lt+5Z8QBwvkvP^6J9}fyt>(<{;FZFPB*0et z3N46kC+JKf`)6?5o_aa^=uGBjGaH-D;E!bxB=H#bnP8j6?=ypX)Qq?nFZP(3n^Tlk zR3hu@>LAO$9wXm#wbXJ2H}~UQ{WzMxe@e4a$Lt4?9dQrJE}vJv%#tdWt? zWB4esQloE{ma6#-vtFr=;Z`5x`Ds2rw`Jw!`H{4-*0sM=l{ah7J$45{^$FAdoo+iwW$2W@eU* z8)TFQA!ez2SOq94GpTv_2(ZR3OBv|!uw zF1zg{B96Md^8;c2Fcr2~qx3u_HODfN_sI9@0V00NJVRO|w7jySBIf(|z?mkQY&xip zua`KCdzhfo5hEsEAiLL>i^FPsbXbqJp-i(Igi#PeCYsJI3)Rbckc?+|9I&gf1p6}>r2+@AHHyO z4d!RqDf`DouORxbqvVytcH-1X(a+r7SuM1HJ1e$c|5;ro$2+J>AxA#JS zR&Fvb-PQ9(h$*LU0)mORl`-AtRh-8jWy zDqCf5|Bl)m8X9T_aCR^R75*u!|G9N5E7AG6i8vrGPN}jYp?A7_dh%eu#%_)wetpkp zBZ?F6ao<(BrrkIn96?UV%E>9~;{jyc;rd0ySu8l>YdF}5oExP4%z#jppimkFT*maX znYg3I*4Ae$6l%|6+Pp^;&F;N>^{uVRc45E$_NSJp?_At2C?N12qA=LY?%Xy?jo)qw zPh2d*Kq+tv>2ckys33w{i26sr$+qmFauQJvS#h;{UX&QKzVOzjX8YHdHOTLAc5@p9 zAc^f|>%pK49je8sX^>;m*4Y_>!EhRAh{Qa2lBwhrZ&NrRzSSN3Bh0>0Sg3(PK^Kd* z8Gin!8k^D@I5oyki>+VJK#C1fy{$hz9d0(3dX8$@*VhLl@cH`R6W(|^F!Vo!zoiUW zj&a^)nj=5I9mCrZ-WI565HIY=?2x=++zpuL2wa53dlU~DS4vGwBVsM#M|P2_-s-x#N)zntN-@pOOcx`) zcTA9J5O#8sK)$S$l9D2r=Pj&<9jfj@K^mRMRpEW>tY+5LiIEW2$>``X2ahaLbyVAM zM#~+?z^?V70-sv5)eVSIEQUr&fSVn6@TnZzNG@t}tQ9nsipO6@DGuH7M9Bm&4u&^h zr*zDa^80Y%WNr`DgbJCRB#hW4uQ&I?L5gqG))w>kFVIqn{p9eu>ES~*Bp(vMf5tG_ zut$(Mz8xf>eO5_!Mn*vE?3T#wmLV#kU$AWn$sc4sfPxBfSMKA=QW9Nm@)1b7NM>P7 zE~zRjuW@U+qKgLl(;#Y+rzpJ5EG(9#8Mzd7_(?zcBp0#6%#06vc7j>1^VcS%b}-7z z%UhyENazYU(WS(Bm69H9?}K^{!Lkm(=bvsiQ=WImgH3kRaIA4n=!Y5(7@J@N*G#~fXIOXJ&S54WbXnV)i)it)Z zcAJ@<9hKPFYo_kYL)QlxMf$(~f5F_F6}zv8i9`4Z+;+LOwKl|M&>L_gpl>F7@z*mO zKJm;_%i^M@r8c!L0UBt1S}0L_PV>ESSza|x3vKw@blKgn~xVfMQ5+iTaZiGR62^ORhm zfTO~Buc_%;h%Ou2+s$x>$D$9s?b)ZMVo|c*Hq33R`?Ba}iBrv*@RqmVvey}S|9%7P zw)*Dg7yg2FM5L&jQJOslF~SokhPHI7Q9iM;qeB+(^z@W2wF+Z>#LN{W(d_K9V&sV` z!rIze-@qUW_%?rHVxnHYd5q5Q&!)Mhr7c4^^A%?^MTj!aZ%_lJA&s`i={ynUBdJ7G zivO37b?H_mXx4V(ytJINx3c1fG;*t&+QKM{n82Wku~Hn*J*PLmLE)IJf1%0wTWBqK zThtE((Fw7GN4n^%SFe(>^{cB_+1my*CP@$}UIcCW=kEd)^eE-KRaI55wj#$U5jc`q zet!PdW+-f6c6ChbAd$Mdy6{?nA+W@=*$J5U5!&o%Fifb=*5ckkszMPvaFB9-FF>O6>Wc!{lJ3?3Rt;8D=HsrI6cG%e7JHZC$!Z~oESVPl|8yOC$rLNkWnwUHV z2S|hk#nfBVoR5vav?cK+cPc9@PY*<|Z}|If5wy#@4GqK13m+pxBMQg#ugQRVA|sOE zW=Ri_&r^mR50Bov%Q1R?o&K(fZJfi~+dE!doAoRd*#^RpG1#W(7Zl{?=d*)5kBW<1 z5gQjbFgn`%!;h1b6Sqs~aD>&puFTwLqdEI~l+hbUi8L}ggTYCv{n}wnKu6D;oB8m3 zq)cTOZk~02orTWrJt&z#5cf&h*$m8G(hf+Ch+dt63=8yaRwV`qw#aZfaNt1ZwjgC# zY&)v2+K={CDWLwcFpFu_Bg)}ol~W^aEuRpWal+q!vSS=+%(>UDkx2V&YzX;`TL~@^~Nk z+Tp4_f|qRDU47=aCRW|5=eua>3^Y1_-$fFLZlOhPQ4u$muC2IS+Gy4k8O|ZR)0!=Z z3N29C@xX>338G)n($doQJ`or8Gcg`Z>%9afEV^#5!^ovWJj>a+Ie#J^5cL8yECg}j z`XaM^@aKh;6eaiW%^+)PPCk#swmBFhleJ@U;kVhLL(#zRkTzQOMf-S#C=nI{uxRgv z1p13;;_hm}>^*q)jMKaRx0;-s+;rQ{)e@STqG7+s?5BQYA)*A;`1{M=_jP@Jl}Yd6 z6(9-_AWjHAh6*c!${*+I=7t(?IifcWT4}V8Pht#W=wI)G{Qfm&zo>^(;#O&K`%xs$ zg+p)KBEK%CG1zBW9DTPbSTqA$TQN~GIc(NnV=dKYM{uy_WqAtuAs<>#G(R(PdVhZY hrwRIh`uKWrsefHgV%gEvG(^*r4E0TDrFstM{tLc1<~slY literal 0 HcmV?d00001 diff --git a/scripts/graph_extruder.py b/scripts/graph_extruder.py new file mode 100755 index 00000000..6223bb11 --- /dev/null +++ b/scripts/graph_extruder.py @@ -0,0 +1,145 @@ +#!/usr/bin/env python2 +# Generate extruder pressure advance motion graphs +# +# Copyright (C) 2019 Kevin O'Connor +# +# This file may be distributed under the terms of the GNU GPLv3 license. +import math, optparse, datetime +import matplotlib + +SEG_TIME = .000100 +INV_SEG_TIME = 1. / SEG_TIME + + +###################################################################### +# Basic trapezoid motion +###################################################################### + +# List of moves: [(start_v, end_v, move_t), ...] +Moves = [ + (0., 0., .200), + (0., 100., None), (100., 100., .200), (100., 60., None), + (60., 100., None), (100., 100., .200), (100., 0., None), + (0., 0., .300) +] +EXTRUDE_R = (.4 * .4 * .75) / (math.pi * (1.75 / 2.)**2) +ACCEL = 3000. * EXTRUDE_R + +def gen_positions(): + out = [] + start_d = start_t = t = 0. + for start_v, end_v, move_t in Moves: + start_v *= EXTRUDE_R + end_v *= EXTRUDE_R + if move_t is None: + move_t = abs(end_v - start_v) / ACCEL + half_accel = 0. + if end_v > start_v: + half_accel = .5 * ACCEL + elif start_v > end_v: + half_accel = -.5 * ACCEL + end_t = start_t + move_t + while t <= end_t: + rel_t = t - start_t + out.append(start_d + (start_v + half_accel * rel_t) * rel_t) + t += SEG_TIME + start_d += (start_v + half_accel * move_t) * move_t + start_t = end_t + return out + +def gen_deriv(data): + return [0.] + [(data[i+1] - data[i]) * INV_SEG_TIME + for i in range(len(data)-1)] + +def time_to_index(t): + return int(t * INV_SEG_TIME + .5) + + +###################################################################### +# Pressure advance +###################################################################### + +PA_HALF_SMOOTH_T = .040 / 2. +PRESSURE_ADVANCE = .045 + +def calc_pa_raw(t, positions): + pa = PRESSURE_ADVANCE * INV_SEG_TIME + i = time_to_index(t) + return positions[i] + pa * (positions[i+1] - positions[i]) + +def calc_pa_smooth(t, positions): + start_index = time_to_index(t - PA_HALF_SMOOTH_T) + 1 + end_index = time_to_index(t + PA_HALF_SMOOTH_T) + pa = PRESSURE_ADVANCE * INV_SEG_TIME + pa_data = [positions[i] + pa * (positions[i+1] - positions[i]) + for i in range(start_index, end_index)] + return sum(pa_data) / (end_index - start_index) + + +###################################################################### +# Plotting and startup +###################################################################### + +MARGIN_TIME = 0.100 + +def plot_motion(): + # Nominal motion + positions = gen_positions() + drop = int(MARGIN_TIME * INV_SEG_TIME) + times = [SEG_TIME * t for t in range(len(positions))][drop:-drop] + velocities = gen_deriv(positions[drop:-drop]) + # Motion with pressure advance + pa_positions = [calc_pa_raw(t, positions) for t in times] + pa_velocities = gen_deriv(pa_positions) + # Smoothed motion + sm_positions = [calc_pa_smooth(t, positions) for t in times] + sm_velocities = gen_deriv(sm_positions) + # Build plot + shift_times = [t - MARGIN_TIME for t in times] + fig, ax1 = matplotlib.pyplot.subplots(nrows=1, sharex=True) + ax1.set_title("Extruder Velocity") + ax1.set_ylabel('Velocity (mm/s)') + pa_plot, = ax1.plot(shift_times, pa_velocities, 'r', + label='Pressure Advance', alpha=0.3) + nom_plot, = ax1.plot(shift_times, velocities, 'black', label='Nominal') + sm_plot, = ax1.plot(shift_times, sm_velocities, 'g', label='Smooth PA', + alpha=0.9) + fontP = matplotlib.font_manager.FontProperties() + fontP.set_size('x-small') + ax1.legend(handles=[nom_plot, pa_plot, sm_plot], loc='best', prop=fontP) + ax1.set_xlabel('Time (s)') + ax1.grid(True) + fig.tight_layout() + return fig + +def setup_matplotlib(output_to_file): + global matplotlib + if output_to_file: + matplotlib.rcParams.update({'figure.autolayout': True}) + matplotlib.use('Agg') + import matplotlib.pyplot, matplotlib.dates, matplotlib.font_manager + import matplotlib.ticker + +def main(): + # Parse command-line arguments + usage = "%prog [options]" + opts = optparse.OptionParser(usage) + opts.add_option("-o", "--output", type="string", dest="output", + default=None, help="filename of output graph") + options, args = opts.parse_args() + if len(args) != 0: + opts.error("Incorrect number of arguments") + + # Draw graph + setup_matplotlib(options.output is not None) + fig = plot_motion() + + # Show graph + if options.output is None: + matplotlib.pyplot.show() + else: + fig.set_size_inches(6, 2.5) + fig.savefig(options.output) + +if __name__ == '__main__': + main()