RFC: Marlin mod: extruder pid feed forward and lag June 03, 2014 05:12PM |
Registered: 10 years ago Posts: 27 |
diff -u Z:\Hack\RepRap\Marlin-Marlin_v1_Mendel90\Marlin/Configuration_adv.h ./Configuration_adv.h --- Z:\Hack\RepRap\Marlin-Marlin_v1_Mendel90\Marlin/Configuration_adv.h 2014-03-27 10:56:54 +0100 +++ ./Configuration_adv.h 2014-06-03 02:47:35 +0200 @@ -23,7 +23,8 @@ // if Kc is chosen well, the additional required power due to increased melting should be compensated. #define PID_ADD_EXTRUSION_RATE #ifdef PID_ADD_EXTRUSION_RATE - #define DEFAULT_Kc (1) //heating power=Kc*(e_speed) + #define DEFAULT_Kc (100) //heating power=Kc*(e_speed) + #define LPQ_MAX_LEN 50 #endif #endif diff -u Z:\Hack\RepRap\Marlin-Marlin_v1_Mendel90\Marlin/Marlin_main.cpp ./Marlin_main.cpp --- Z:\Hack\RepRap\Marlin-Marlin_v1_Mendel90\Marlin/Marlin_main.cpp 2014-03-27 10:56:54 +0100 +++ ./Marlin_main.cpp 2014-06-03 02:54:55 +0200 @@ -2576,6 +2584,8 @@ #ifdef PID_ADD_EXTRUSION_RATE if(code_seen('C')) Kc = code_value(); + if(code_seen('L')) lpq_len = code_value(); + if(lpq_len > LPQ_MAX_LEN) lpq_len = LPQ_MAX_LEN; #endif updatePID(); diff -u Z:\Hack\RepRap\Marlin-Marlin_v1_Mendel90\Marlin/temperature.cpp ./temperature.cpp --- Z:\Hack\RepRap\Marlin-Marlin_v1_Mendel90\Marlin/temperature.cpp 2014-03-27 10:56:54 +0100 +++ ./temperature.cpp 2014-06-03 03:33:37 +0200 @@ -71,7 +71,12 @@ #ifdef BABYSTEPPING volatile int babystepsTodo[3]={0,0,0}; #endif - + +#ifdef PID_ADD_EXTRUSION_RATE +//TODO: M301 printout +int lpq_len = 20; +#endif + //=========================================================================== //=============================private variables============================ //=========================================================================== @@ -84,6 +89,12 @@ static float pTerm[EXTRUDERS]; static float iTerm[EXTRUDERS]; static float dTerm[EXTRUDERS]; +#ifdef PID_ADD_EXTRUSION_RATE + static long last_position[EXTRUDERS]; + static float cTerm[EXTRUDERS]; + static long lpq[LPQ_MAX_LEN]; + static int lpq_ptr = 0; +#endif //int output; static float pid_error[EXTRUDERS]; static float temp_iState_min[EXTRUDERS]; @@ -407,6 +418,7 @@ { float pid_input; float pid_output; + long e_position; if(temp_meas_ready != true) //better readability return; @@ -442,7 +454,24 @@ //K1 defined in Configuration.h in the PID settings #define K2 (1.0-K1) dTerm[e] = (Kd * (pid_input - temp_dState[e]))*K2 + (K1 * dTerm[e]); +#ifdef PID_ADD_EXTRUSION_RATE + cTerm[e] = 0; + if(e == active_extruder) { + e_position = st_get_position(E_AXIS); + if(e_position > last_position[e]) { + lpq[lpq_ptr++] = e_position - last_position[e]; + last_position[e] = e_position; + } else { + lpq[lpq_ptr++] = 0; + } + if(lpq_ptr >= lpq_len) lpq_ptr = 0; + cTerm[e] = (lpq[lpq_ptr] / axis_steps_per_unit[E_AXIS]) * Kc; + } + + pid_output = constrain(pTerm[e] + iTerm[e] - dTerm[e] + cTerm[e], 0, PID_MAX); +#else pid_output = constrain(pTerm[e] + iTerm[e] - dTerm[e], 0, PID_MAX); +#endif } temp_dState[e] = pid_input; #else @@ -461,7 +490,13 @@ SERIAL_ECHO(" iTerm "); SERIAL_ECHO(iTerm[e]); SERIAL_ECHO(" dTerm "); +#ifndef PID_ADD_EXTRUSION_RATE SERIAL_ECHOLN(dTerm[e]); +#else + SERIAL_ECHO(dTerm[e]); + SERIAL_ECHO(" cTerm "); + SERIAL_ECHOLN(cTerm[e]); +#endif #endif //PID_DEBUG #else /* PID off */ pid_output = 0; @@ -708,6 +743,9 @@ #ifdef PIDTEMP temp_iState_min[e] = 0.0; temp_iState_max[e] = PID_INTEGRAL_DRIVE_MAX / Ki; +#ifdef PID_ADD_EXTRUSION_RATE + last_position[e] = 0; +#endif #endif //PIDTEMP #ifdef PIDTEMPBED temp_iState_min_bed = 0.0; diff -u Z:\Hack\RepRap\Marlin-Marlin_v1_Mendel90\Marlin/temperature.h ./temperature.h --- Z:\Hack\RepRap\Marlin-Marlin_v1_Mendel90\Marlin/temperature.h 2014-03-27 10:56:54 +0100 +++ ./temperature.h 2014-06-03 02:54:55 +0200 @@ -65,6 +65,10 @@ #ifdef BABYSTEPPING extern volatile int babystepsTodo[3]; #endif + +#ifdef PID_ADD_EXTRUSION_RATE +extern int lpq_len; +#endif //high level conversion routines, for use outside of temperature.cpp //inline so that there is no performance decrease.
Re: RFC: Marlin mod: extruder pid feed forward and lag June 04, 2014 05:33AM |
Registered: 14 years ago Posts: 7,616 |
Quote
svanteg
The method is to calculate the amount of "new" plastic fed into the extruder per PID tick and adding the corresponding heat via feed forward with adjustable lag. I've found that about 110 * e_steps / steps_per_mm applied with a 2 second lag works well with my j-head and ABS - i.e. doing a free air extraction at 150 mm/min shows a flat temperature line and a nice extruder power "mesa" plateau in Repetier host. Existing PID C-term (FF factor) and a new L-term (lag in PID ticks) has been added to enable tuning.
Quote
svanteg
I kindly request the Marlin gods to descend with benevolence [...]
Generation 7 Electronics | Teacup Firmware | RepRap DIY |
Re: RFC: Marlin mod: extruder pid feed forward and lag June 04, 2014 09:53PM |
Registered: 10 years ago Posts: 27 |
Re: RFC: Marlin mod: extruder pid feed forward and lag June 05, 2014 12:59PM |
Registered: 12 years ago Posts: 258 |
Re: RFC: Marlin mod: extruder pid feed forward and lag June 06, 2014 01:35AM |
Registered: 10 years ago Posts: 27 |
Quote
DaveX
In Marlin there's an AUTOTEMP feature in the planner that increases the temperature SP proportionally to the highest E speed in the move buffer.
Quote
DaveX
It does seem like a feed-forward term should lead the process rather than lag it, anticipating the heat-load required by the expected disturbance, leaving the PID to clean up any discrepancies.
Quote
DaveX
The windup-free isn't particular to type C-PIDs...
Quote
DaveX
if the resolution of temperature and temperature slope measurement limits the effectiveness of the Kp and Kd terms, then the only thing that can un-windup the CO integration is the kI term when it overshoots the setpoint.
Quote
DaveX
The differential forms depend on differencing measurements of PV(k), which might be a problem with higher sampling rates and any noise. ... Also, be careful to maintain the CO integral in something in high enough resolution to actually accumulate the Ki*dPV/dt terms.
Re: RFC: Marlin mod: extruder pid feed forward and lag June 07, 2014 02:06PM |
Registered: 12 years ago Posts: 258 |
Quote
svanteg
Interesting, informative and I think we agree on most aspects.
Quote
DaveX
In Marlin there's an AUTOTEMP feature in the planner that increases the temperature SP proportionally to the highest E speed in the move buffer.
I have not tried this yet so I might have misunderstood. However my understanding of it is not to regulate a desired set temperature but rather change the temperature based on flow of plastic (which follows speed) to generally enable higher speeds by temporarily reducing the viscosity of plastic. So in my mind this is not internal to regulation, rather it depends on some useful level of regulation to achieve higher extrusion speed.
Quote
svanteg
Quote
DaveX
It does seem like a feed-forward term should lead the process rather than lag it, anticipating the heat-load required by the expected disturbance, leaving the PID to clean up any discrepancies.
I agree - but we have to separate the ideal physics from the detectable reality from the artifacts of the PID algorithm to keep the discussion straight.
The practical physics gives that heat flux happens "immediately" at the point it is applied - as draw away by filament from the extruder whereever it contacts or as added heat at the element. This sets up a temperature gradient that propagates out at some speed. Ideally we want to modulate the filament-extruder interface area temperature to make the plastic leaving the tip to have a controlled and homogenous enough temperature. The faster we melt plastic, the higher the surface-to-core temperature gradient we need to set up in the incoming filament to balance the heat propagation speed and conduction in the plastic. At some point the filament surface will phase-change into vapour and the heat conduction will drop drastically. That's one limit. Another that might happen sooner is that we cannot melt it through fast enough so we get too much solid plastic casuing blockage - even if the average temperature would indicate melted plastic.
In practice we see this all happening through the sensor which is some distance away from both the filament-extruder interface as well as the the element. On top of that we have the PID regulation delay.
Our current best norm in regulation uses PID to control the temperature at the sensor - accepting that PID will start to regulate when it sees a change and taking some time to null that out depending on the measured physical process cycle time.
A first order improvement is to keep the strategy to regulate at the sensor, hitting it with a heat pulse from the element timed to coincide with the cooling pulse drawn away by the filament. This way the PID sees no change and does not try to regulate - and we've removed the PID regulation delay (still having the element to filament propagation delay). Depending on the sensor-element-barrel topology, the filament either gets more or less than the ideal for a brief moment. The benefits are that the PID is now free to regulate external disturbances - and if they are slower than the dTemp caused by a filament extrusion pulse we can have more aggressive regulation at the same risk of overshoot / ringing. Also we don't need to mess with the PID implementation. This is what I am currently going for.
The ideal improvement strategy is to regulate at the extruder-filament interface - which implies generating a heat pulse before moving filament. Since we're now not regulating at the sensor we will get some waveform there as the heat and cooling pulses pass. If the PID sees this it will start to regulate - essentially generating noise - so we want to hide this in some way by adding the perfectly timed inverse wave form to the sensor reading. Perhaps this is achievable but I don't think very practical since it will be much harder to calibrate and need more assets to implement.
(Thought: if one would arrange the element, the sensor and the barrel so that a heat pulse would arrive at the barrel wall at the same time as the sensor outputs it and same for a cooling pulse, one would get the ideal performance from the "first order" solution above. I am guessing that the ideal geometry places the sensor between the element and the barrel. I think this is a more practical direction to investigate than the software route.)
The sanity check is that the current scope of speeds we can practically use is primarily limited by blobbing caused by us not having a descent "Advance" solution yet. So the real world improvements by better extrudate temperature control is minor until "everyone" can practically run at ~500mm/s with excellent quality rather than the current ~50mm/s. When we're there I might consider looking at the ideal solution if my thought above does not pan out.
Also, in comparison to motion control where FF is key for optimal performance it usually involves sensing the exact positions over time so it is practical to implement the ideal. In our terms it would be similar to having a temp sensor right at the exit measuring the actual cross section average temperature with zero time lag.
Quote
svanteg
Quote
DaveX
The windup-free isn't particular to type C-PIDs...
Yes, thanks for pointing that out.
Quote
DaveX
if the resolution of temperature and temperature slope measurement limits the effectiveness of the Kp and Kd terms, then the only thing that can un-windup the CO integration is the kI term when it overshoots the setpoint.
Yes, but only relevant if you have very aggressive regulation and PV step events. And I think I want to object a little to the use of "wind-up" here since it seems you're talking about events where CO doesn't hit a limit - i.e. a normal unconstrained regulation event. My understanding of "wind-up" is when CO is sitting at max or min and the integrator keeps on adding in the compensation - when the disturbance is removed the integrator has to "un-wind" all the accumulated compensation. Usually this means that the PID stays at the limit for some while before it resumes regulation. Keeping it in the CO means regulation starts immediately when the disturbance is removed regardless of how long that event was.
With sane parameters CO will come down from e.g. max before PV crosses SP so there should be no or a chosen and controlled overshoot.
Quote
svanteg
Quote
DaveX
The differential forms depend on differencing measurements of PV(k), which might be a problem with higher sampling rates and any noise. ... Also, be careful to maintain the CO integral in something in high enough resolution to actually accumulate the Ki*dPV/dt terms.
A practical strategy when you have lower than desired sensor resolution and noise is to oversample and average. This increases resolution and reduces noise at the cost of higher system load - as long as faster sampling does not mean more noise... Even so you're still bound by how often you need to update CO to maintain stable regulation. The rule of thumb is that CO update rate is ten times the measured physical process cycle time. Any oversampling of the sensor is based off of that.
In your case with an 8s = 0.125Hz cycle time (i.e. fastest possible oscillation period) you would want _at least_ an 1.25Hz CO update rate. if you get 7 bits from the sensor but need 8 you must read the sensor at 2.5Hz. If this leaves you with too much noise you have to up the rate even more - I would aim for 8-16x, so 20-40 Hz sensor sample rate with a 1.25Hz CO update rate. More - up to about 12.5Hz CO with 400Hz sensor sample rate - will improve PID stability.
All internal variables must of course be stored at least at the precision of the input, internal calculations and accumulated data to provide the best possible results from the data at hand. Floats are convenient especially with a generalized PID module, otherwise fixed point or scaled integers if necessary. I.e. I would prefer keeping PID CO in a float and convert to actual CO for output.
Re: RFC: Marlin mod: extruder pid feed forward and lag June 08, 2014 06:06PM |
Registered: 10 years ago Posts: 27 |
Quote
DaveX
For 500mm/s, a 20W heater wouldn't be able to keep up, since you'd have a heating load of about 21W in the extrusion. A 40W heater would need to vary its CO about 50% full scale to handle the difference between 0mm/s and 500mm/s extrusion speeds. ...
Quote
DaveX
At extrudate speeds of 500mm/s, I'd expect the transition cycles to be even shorter. I guess I think that if you lag the heater behind the measured/computed/actual position of the filament already extruded, in the case of sensors on the far side of the hole, the heat pulse is doomed to lag the cooling pulse. So to get the lags right, you'd need to drive the feed forward process with the planned disturbances in the motion planning queue.
Quote
DaveX
See the overshoot and oscillations in the second graph of [numbersixreprap.blogspot.com] -- The PID started from 10C below SP, cooled because of non-bumpless transition, overshot because of windup.
Quote
DaveX
With Kp or Kd values in the 20-100 COcounts/(C/s) range, a small bit of noise can produce 90% FS swings in the CO, see [forums.reprap.org] for an example.
Quote
DaveX
I'm more concerned with the noise-free behavior of the discretized PV signal and the relatively fast sampling rates producing mostly zeros for the velocity form's (PV(k) - PV(k)) and (PV(k)-2(PV(k-1)+PV(k-2)) terms. Without noise, those terms will be zero most of the time due to discretisation in the ADC and not affect the process.
Re: RFC: Marlin mod: extruder pid feed forward and lag June 09, 2014 03:35PM |
Registered: 12 years ago Posts: 258 |
bias: 114 d: 114 min: 177.32 max: 182.57 Ku: 55.32 Tu: 44.83 Classic PID Kp: 33.19 Ki: 1.48 Kd: 186.00
Re: RFC: Marlin mod: extruder pid feed forward and lag June 09, 2014 09:23PM |
Registered: 12 years ago Posts: 258 |
Re: RFC: Marlin mod: extruder pid feed forward and lag July 17, 2014 06:27PM |
Registered: 10 years ago Posts: 1 |
Adding PID_ADD_EXTRUSION_RATE to MarlinDev/master August 30, 2015 10:37PM |
Registered: 11 years ago Posts: 126 |
Re: Adding PID_ADD_EXTRUSION_RATE to MarlinDev/master August 31, 2015 04:05PM |
Registered: 10 years ago Posts: 27 |
Quote
Thinkyhead
Please check out [github.com] for my implementation of PID_ADD_EXTRUSION_RATE based on the example code above. It probably needs some revision, so please give your feedback on the PR, and I will try to make it as solid as possible!
M301 P20.72 I1.78 D60.42 C110 L20 ; Set extruder PID 245 degrees
Re: Adding PID_ADD_EXTRUSION_RATE to MarlinDev/master September 04, 2015 05:35PM |
Registered: 11 years ago Posts: 126 |
Quote
svanteg
One thing I haven't fixed yet is the missing reset for last_position[e] when/if e_position is reset. I think there is one somewhere in the code...
Re: Adding PID_ADD_EXTRUSION_RATE to MarlinDev/master September 06, 2015 04:07AM |
Registered: 10 years ago Posts: 27 |
Quote
Thinkyhead
Quote
svanteg
One thing I haven't fixed yet is the missing reset for last_position[e] when/if e_position is reset. I think there is one somewhere in the code...
I've done a global search for (last|e)_position to see where this might be, but I couldn't find anyplace where this should go. Maybe you can point out the line in pid_with_kc/Marlin/temperature.cpp — or maybe everything is as it should be already.
Re: RFC: Marlin mod: extruder pid feed forward and lag March 15, 2017 01:51PM |
Registered: 9 years ago Posts: 294 |