@droftarts
I have updated the description so that it hopefully becomes clearer how much material has to be extruded and why you should aim for a 20% plus error margin and that you should use the temp_base for slicing.
Posts made by timschneider
-
RE: [feature] Adaptive / Feedforward Temperature setpoint
-
RE: [feature] Adaptive / Feedforward Temperature setpoint
@droftarts
Hi @droftarts
I use the following tuning method:- determine the lowest possible temperatur
Temp_base
for the filament, e.g. extrude with F30 (0.5 mm/secSpeed_base
) so that the filament is melting and will bond to each other - define your desired extrusion rate, e.g. 35 mm³/sec -> calculate the required extrusion speed -> around 5.5 mm/sec (
Speed_desired
) for 2.85mm filament -> F330 - Extrude the filament with the desired speed + 20% and increase the temperature of the hotend till you are able to extrude at the desired speed. Note the needed temperature for that speed
Temp_required
. The extrusion length should be at least two times your hotend length. The 20% increase is some kind of error margin for non linear extrusion and when the fan is on. - calculate the needed temperature boost with
Temp_boost = (Temp_required - Temp_base) / (Speed_desired - Speed_base)
For Example PLA
Temp_base = 190 Temp_required = 230 Speed_base = 0.5 mm/s Speed_desired = 5.5 mm/s Temp_boost = 40 / 5 => 8 => T8
Edit:
Temp_base
will be the temperature you set in your slicer for that material. - determine the lowest possible temperatur
-
RE: [3.5.3-SBC] Closed loop position recovery / rehoming
I came up with the following solution:
content of driver-warning.g
; driver-warning.g ; driver warning - 51.0 : 1024 ,Driver 51.0 warning: position tolerance exceeded if param.B > 0 && param.D == 0 && param.P == 1024 && move.axes[0].homed == false && move.axes[1].homed == false M99 ; ignore warning when drives are not homed echo "driver warning - "^{param.B}^"."^{param.D}^" : "^{param.P}^" ,"^{param.S} if state.status == "paused" || state.status == "pausing" || state.status == "resuming" M99 ; ignore this event - it is already handled if !exists(global.event_driver_stall) global event_driver_stall = true ; check if a printjob is running ; if it is a can connected driver in closed loop mode with error position tolerance exceeded (param.B > 0 && param.D == 0 && param.P == 1024) if job.file.fileName != null if param.B > 0 && param.D == 0 && param.P == 1024 set global.event_driver_stall = true M25 ; pause print and rehome X and Y M207 Z{tools[0].retraction.zHop+0.2} ; raise z-hop 0.2mm to prevent further crashes set global.resume_deferred = state.upTime + 5 ; resume print after 5 seconds else set global.event_driver_stall = false ; do not rehome while pausing G91 ; relative positioning G1 H2 Z0.5 F600 ; lift Z relative to current position M568 P0 R0 S0 A0 ; disable hotend M25 ; pause print
content of driver-error.g
; driver-error.g ; called to home x and y after stall detection ; driver error - 51.0 : 3072 ,Driver 51.0 error: failed to maintain position if param.B > 0 && param.D == 0 && param.P == 3072 && move.axes[0].homed == false && move.axes[1].homed == false M99 ; ignore warning when drives are not homed echo "driver error - "^{param.B}^"."^{param.D}^" : "^{param.P}^" ,"^{param.S} if !exists(global.event_driver_stall) global event_driver_stall = true if state.status == "paused" || state.status == "pausing" || state.status == "resuming" set global.resume_deferred = 0 ; reset resume_deferred M99 ; ignore this event - it is already handled ; check if a printjob is running ; if it is a can connected driver in closed loop mode with failed to maintain position (param.B > 0 && param.D == 0 && param.P == 3072) if job.file.fileName != null if param.B > 0 && param.D == 0 && param.P == 3072 set global.event_driver_stall = true M207 Z{tools[0].retraction.zHop+0.2} ; raise z-hop 0.2mm to prevent further crashes else set global.event_driver_stall = false ; do not rehome while pausing G91 ; relative positioning G1 H2 Z0.5 F600 ; lift Z relative to current position M568 P0 R0 S0 A0 ; disable hotend M25 ; pause print
content of daemon.g
if exists(global.resume_deferred) && global.resume_deferred > 0 && global.resume_deferred < state.upTime if state.status == "paused" set global.resume_deferred = 0 M24 ; resume print
The magic is done by the
global.resume_deferred
. It is set tostate.upTime + 5
which means 5 second delay.
The flow looks like the followingdriver-warning event -> check if it is already paused if so, exit else set resume_deferred driver-error event -> check if it is already paused, if so, reset resume_deferred to 0 to disable it and exit daemon.g -> Check whether the delay for resume_deferred has already passed, if so resume the print.
-
[3.5.3-SBC] Closed loop position recovery / rehoming
Hello, I am having the following issue with my closed-loop printer in an SBC configuration using CoreXY when a ‘position error’ occurs. I get a motor driver-warning event for each motor, 2 in total, and 1 driver-error event for each motor, again 2 in total, for a total of 4 events for a full crash.
content of driver-warning.g
; driver warning - 51.0 : 1024 ,Driver 51.0 warning: position tolerance exceeded if param.B > 0 && param.D == 0 && param.P == 1024 && move.axes[0].homed == false && move.axes[1].homed == false M99 ; ignore warning when drives are not homed echo "driver warning - "^{param.B}^"."^{param.D}^" : "^{param.P}^" ,"^{param.S} if !exists(global.event_driver_stall) global event_driver_stall = true ; check if a printjob is running ; if it is a can connected driver in closed loop mode with error position tolerance exceeded (param.B > 0 && param.D == 0 && param.P == 1024) if job.file.fileName != null if param.B > 0 && param.D == 0 && param.P == 1024 set global.event_driver_stall = true M25 ; pause print and rehome X and Y M207 Z{tools[0].retraction.zHop+0.2} ; raise z-hop 0.2mm to prevent further crashes M24 ; resume print else set global.event_driver_stall = false ; do not rehome while pausing G91 ; relative positioning G1 H2 Z0.5 F600 ; lift Z relative to current position M568 P0 R0 S0 A0 ; disable hotend M25 ; pause print
content of driver-error.g
; driver-stall.g ; called to home x and y after stall detection ; driver error - 51.0 : 3072 ,Driver 51.0 error: failed to maintain position if param.B > 0 && param.D == 0 && param.P == 3072 && move.axes[0].homed == false && move.axes[1].homed == false M99 ; ignore warning when drives are not homed echo "driver error - "^{param.B}^"."^{param.D}^" : "^{param.P}^" ,"^{param.S} if !exists(global.event_driver_stall) global event_driver_stall = true ; check if a printjob is running ; if it is a can connected driver in closed loop mode with failed to maintain position (param.B > 0 && param.D == 0 && param.P == 3072) if job.file.fileName != null if param.B > 0 && param.D == 0 && param.P == 3072 set global.event_driver_stall = true M207 Z{tools[0].retraction.zHop+0.2} ; raise z-hop 0.2mm to prevent further crashes else set global.event_driver_stall = false ; do not rehome while pausing G91 ; relative positioning G1 H2 Z0.5 F600 ; lift Z relative to current position M568 P0 R0 S0 A0 ; disable hotend M25 ; pause print
I have already tried to check if the printer is in the ‘pausing’ or ‘paused’ state to prevent further pauses, but the events are deferred and the first event is processed completely, including the resume print, before the second is processed.
if state.status == "paused" || state.status == "pausing" || state.status == "resuming" M99 ; ignore this event - it is already handled
How can I cancle pending events? or what else should I do?
-
RE: Laser perfilometer
@Marcossf these sensors are around 1k€?
e.g. if you use the Baumer OXM with Modbus RTU you can look in the forum on how to communicate with an RS485 modbus inverter. You will find some examples.I'm in contact with baumer to get my hands on one of these OXP sensors with an SBC setup. The P sensor will give you a point cloud over TCP, so I need to do the curve fitting and so on. The OXM is doing the fitting internally and can give you the results.
-
3.5.2 Closed loop SBC Setup Duet3 6HC 2x1HCL+Magnetic Encoder
@dc42 @chrishamm @T3P3Tony and the whole Duet3D Team! Thank you!
3.5.2 Closed loop SBC Setup Duet3 6HC 2x 1HCL with Magnetic Encoder on NEMA 17 1.8° LDO Motor
I have the Closed Loop System running for a week now and have been printing continuously 24/7 on a job that I had to abort six times before. Without the Closed Loop System, I would not be able to print the job!
Thanks a lot for this! After initial difficulties in tuning the system, because the instructions were written for quadrature shaft encoders, I was able to achieve a high-performance tuning. The Closed Loop System even has a better print quality e.g. because the backlash is compensated. I can run the steppers at full current, higher accelerations, higher speeds and the steppers are even cooler.
Btw. the printer is loosing the position about every 15 minutes on that print, due to the material. It's our PA6 CF HT which is very stiff and strong, so even the smallest amount of residues will stop/crash the print head. The print takes around 5.5 kg, where the material is around 89€/kg.
Please find attached a picture in which you can hardly see the misalignments.
Chris, after the hard work you put in the SBC setup it runs pretty stable now not rock solid, as I can still crash it - but mostly solid
Keep up the great work!
-
RE: Machine not returning to the correct Z position after resuming
@curieos do you use firmware retraction?
-
RE: [feature] Adaptive / Feedforward Temperature setpoint
@Tinchus, it's the extrusion speed. So I use 2.85 mm filament and if I use an extrusion speed of 1 mm/s, for example, it is about 6.38 mm³/s, regardless of the nozzle size. The only difference between extrusion speed and volume speed is the area of the filament, e.g. for 2.85 mm filament 6.38 mm² and thus only a factor.
-
RE: [feature] Adaptive / Feedforward Temperature setpoint
@Tinchus it is extruder speed e.g. movement of filament per sec, not travel speed so it is accounting for that. I print with 0.8mm to 1.2mm nozzles.
-
RE: [feature] Adaptive / Feedforward Temperature setpoint
@Tinchus said in [feature] Adaptive / Feedforward Temperature setpoint:
And regarding where: I think the oposite. It should be the formware the one in charge of that because the slicer never knows the real speed of a path. Final real speed is decided by firmware, the slciewr never knows the real printing speed (and that is the reason why the time calculation on slicer are allways really off)
Thats a good point!
I made a PR for this https://github.com/Duet3D/RepRapFirmware/pull/1036
But due to memory contrains, it will not fit in the ROM of a regular Duet2 combined firmware. You need to disable other not important features to make it work e.g. Telnet and FTP.
-
RE: Firmware update bricked printer - SPI connection has been reset
@p8blr was the extended delay able to get rid of the unknown driver messages?
the M122 looks normal to me.
-
RE: Firmware update bricked printer - SPI connection has been reset
@p8blr hi sorry to here that it is not working!
I've looked at the config and maybe you can increase the wait delay for the startup of the can connected boards.; Wait a moment for the CAN expansion boards to start G4 S2
just increase it for test purpose e.g. to 10 sec. as you can query the boards after startup without an issue but the drive setup fails. I use 5 seconds for one connected expansion board.
Can you also post the content of the daemon.g
, as it appears, that there is a problem in line 8.Edit: only different output e.g.bedStripTempMax
, isn't it supposed to beglobal.bedStripTempMax
?set global.unknownVar
orecho {global.unknownVar}
Do you run your printer mainboard and expansion boards at 24V or more than that?
If so, there is a feature in the FW that reduces the voltage via PWM for the breaks and that may create EMV problems.EDIT: it is only activated when M569.7 V is provided, which is not the case.Maybe you can show the output of
M122
btw.
thanks for sharing!
sudo rpi-eeprom-config --edit PSU_MAX_CURRENT=5000
EDIT
from this screenshot https://forum.duet3d.com/assets/uploads/files/1725041834892-m115.jpg
it is not clear which version runs on the 6XD can you please show the whole line ofM115 B0
-
RE: Pulse Input to Control a Spindle
@Kittifix you are maybe able to use it, but RRF is able to create a spindle with an PWM output for the speed control.
If you use a PWM to Freqency Converter PCB you will maybe able to use the pulse input.
-
RE: 3.5.0-rc.1 Brakes not engaging
@p8blr thank you for the files, but can you just make a screenshot of the output when you send the command
M98 P"config.g"
in the console. -
RE: Pulse Input to Control a Spindle
@Kittifix
I think that the encoder input/pulse input from an encoder should be used as a feedback loop and not as a control input.If you are referring to the following datasheet https://assets.danfoss.com/documents/latest/271209/AQ276736419659en-000101.pdf
you may have a look into https://files.danfoss.com/download/Drives/MG02K402.pdf
And you could either use RS485 or use the 0-10V Interface with an PWM to Voltage Converter PCB. -
RE: 3.5.0-rc.1 Brakes not engaging
@p8blr
can you send us the output of
M98 P"config.g"
maybe there is a bug in the config, as it appears to me, that was created for an older version of RRF. As stated in the config, it was created for
Firmware Version 3.5.0 Release Candidate 1
, since then there have been a few incompatible changes. -
RE: 3.5.0-rc.1 Brakes not engaging
@p8blr
hi maybe you try the 3.5.3 rc-1 the fix is includedhttps://github.com/Duet3D/RepRapFirmware/releases/tag/3.5.3-rc.1
M17 did not energise the motor brake solenoid (issue 1023)
-
RE: Babystep Accumulates between prints !?
@fotomas do you use firmware retraction with Z-Hob?
e.g.M207 P0 Z0.075
If so make sure your pause.g contains aG10
and your stop.g/cancle.g/resume.g contains aG11
https://github.com/Duet3D/RepRapFirmware/issues/967#issuecomment-2100868942
Otherwise the z-hob will add up -
RE: [feature] Adaptive / Feedforward Temperature setpoint
@dc42
do you mean something like the following:From 83be8a6fac88110fc62f6e105f522ef601164b69 Mon Sep 17 00:00:00 2001 From: Tim Schneider <tim@schneider.engineering> Date: Wed, 21 Aug 2024 14:22:41 +0200 Subject: [PATCH] - M309: added T parameter to specify the temperature increase(s) per unit of extrusion speed --- src/Heating/Heat.cpp | 4 ++-- src/Heating/Heat.h | 2 +- src/Heating/Heater.h | 2 +- src/Heating/LocalHeater.cpp | 17 +++++++++++++---- src/Heating/LocalHeater.h | 4 +++- src/Heating/RemoteHeater.h | 2 +- src/Tools/Tool.cpp | 15 +++++++++++++-- src/Tools/Tool.h | 1 + 8 files changed, 35 insertions(+), 12 deletions(-) diff --git a/src/Heating/Heat.cpp b/src/Heating/Heat.cpp index 397c25bd..cd4cb7d0 100644 --- a/src/Heating/Heat.cpp +++ b/src/Heating/Heat.cpp @@ -876,14 +876,14 @@ void Heat::FeedForwardAdjustment(unsigned int heater, float fanPwmChange, float } // This one is called from an ISR so we must not get a lock -void Heat::SetExtrusionFeedForward(unsigned int heater, float pwm) const noexcept +void Heat::SetExtrusionFeedForward(unsigned int heater, float pwm, float degree) const noexcept { if (heater < MaxHeaters) { Heater * const h = heaters[heater]; if (h != nullptr) { - h->SetExtrusionFeedForward(pwm); + h->SetExtrusionFeedForward(pwm, degree); } } } diff --git a/src/Heating/Heat.h b/src/Heating/Heat.h index 7ca1e5e4..5e49680b 100644 --- a/src/Heating/Heat.h +++ b/src/Heating/Heat.h @@ -128,7 +128,7 @@ public: GCodeResult SetActiveOrStandby(int heater, const Tool *tool, bool active, const StringRef& reply) noexcept; // Turn a heater on void SwitchOff(int heater) noexcept; // Turn off a specific heater void FeedForwardAdjustment(unsigned int heater, float fanPwmChange, float extrusionChange) const noexcept; - void SetExtrusionFeedForward(unsigned int heater, float pwm) const noexcept; + void SetExtrusionFeedForward(unsigned int heater, float pwm, float degree) const noexcept; #if HAS_MASS_STORAGE || HAS_SBC_INTERFACE bool WriteModelParameters(FileStore *f) const noexcept; // Write heater model parameters to file returning true if no error diff --git a/src/Heating/Heater.h b/src/Heating/Heater.h index 64f61666..b71f3405 100644 --- a/src/Heating/Heater.h +++ b/src/Heating/Heater.h @@ -57,7 +57,7 @@ public: virtual void Suspend(bool sus) noexcept = 0; // Suspend the heater to conserve power or while doing Z probing virtual float GetAccumulator() const noexcept = 0; // Get the inertial term accumulator virtual void FeedForwardAdjustment(float fanPwmChange, float extrusionChange) noexcept = 0; - virtual void SetExtrusionFeedForward(float pwm) noexcept = 0; + virtual void SetExtrusionFeedForward(float pwm, float degree) noexcept = 0; #if SUPPORT_CAN_EXPANSION virtual bool IsLocal() const noexcept = 0; diff --git a/src/Heating/LocalHeater.cpp b/src/Heating/LocalHeater.cpp index 9059d7f2..eaff1314 100644 --- a/src/Heating/LocalHeater.cpp +++ b/src/Heating/LocalHeater.cpp @@ -86,7 +86,7 @@ void LocalHeater::ResetHeater() noexcept mode = HeaterMode::off; previousTemperaturesGood = 0; previousTemperatureIndex = 0; - iAccumulator = extrusionBoost = 0.0; + iAccumulator = extrusionBoost = extrusionTemperatureBoost = lastExtrusionTemperatureBoost = 0.0; badTemperatureCount = 0; averagePWM = lastPwm = 0.0; heatingFaultCount = 0; @@ -189,7 +189,7 @@ GCodeResult LocalHeater::SwitchOn(const StringRef& reply) noexcept return GCodeResult::error; } - const float target = GetTargetTemperature(); + const float target = min<float>(GetTargetTemperature() + extrusionTemperatureBoost, GetHighestTemperatureLimit()); const HeaterMode newMode = (temperature + TemperatureCloseEnough < target) ? HeaterMode::heating : (temperature > target + TemperatureCloseEnough) ? HeaterMode::cooling : HeaterMode::stable; @@ -282,9 +282,17 @@ void LocalHeater::Spin() noexcept if (GetModel().IsEnabled()) { // Get the target temperature and the error - const float targetTemperature = GetTargetTemperature(); + const float targetTemperature = min<float>(GetTargetTemperature() + extrusionTemperatureBoost, GetHighestTemperatureLimit()); const float error = targetTemperature - temperature; + if (extrusionTemperatureBoost != 0.0 || lastExtrusionTemperatureBoost != extrusionTemperatureBoost) + { + // calculate new heater mode to prevent heater fault due to exceededAllowedExcursion + String<1> dummy; + (void)SwitchOn(dummy.GetRef()); + } + lastExtrusionTemperatureBoost = extrusionTemperatureBoost; + // Do the heating checks switch(mode) { @@ -570,9 +578,10 @@ void LocalHeater::FeedForwardAdjustment(float fanPwmChange, float extrusionChang } // Set extrusion feedforward. This is called from an ISR. -void LocalHeater::SetExtrusionFeedForward(float pwm) noexcept +void LocalHeater::SetExtrusionFeedForward(float pwm, float degree) noexcept { extrusionBoost = pwm; + extrusionTemperatureBoost = degree; } /* Notes on the auto tune algorithm diff --git a/src/Heating/LocalHeater.h b/src/Heating/LocalHeater.h index cf0840c5..d5a18221 100644 --- a/src/Heating/LocalHeater.h +++ b/src/Heating/LocalHeater.h @@ -39,7 +39,7 @@ public: float GetAccumulator() const noexcept override; // Return the integral accumulator void Suspend(bool sus) noexcept override; // Suspend the heater to conserve power or while doing Z probing void FeedForwardAdjustment(float fanPwmChange, float extrusionChange) noexcept override; - void SetExtrusionFeedForward(float pwm) noexcept override; // Set extrusion feedforward + void SetExtrusionFeedForward(float pwm, float degree) noexcept override; // Set extrusion feedforward #if SUPPORT_CAN_EXPANSION bool IsLocal() const noexcept override { return true; } void UpdateRemoteStatus(CanAddress src, const CanHeaterReport& report) noexcept override { } @@ -76,6 +76,8 @@ private: float lastPwm; // The last PWM value set for this heater float averagePWM; // The running average of the PWM, after scaling. volatile float extrusionBoost; // The amount of extrusion feedforward to apply + volatile float extrusionTemperatureBoost; // The amount of extrusion feedforward to apply + float lastExtrusionTemperatureBoost; // The amount of extrusion feedforward to apply float lastTemperatureValue; // the last temperature we recorded while heating up uint32_t lastTemperatureMillis; // when we recorded the last temperature uint32_t timeSetHeating; // When we turned on the heater diff --git a/src/Heating/RemoteHeater.h b/src/Heating/RemoteHeater.h index a6c09029..a30872d7 100644 --- a/src/Heating/RemoteHeater.h +++ b/src/Heating/RemoteHeater.h @@ -30,7 +30,7 @@ public: float GetAccumulator() const noexcept override; // Return the integral accumulator void Suspend(bool sus) noexcept override; // Suspend the heater to conserve power or while doing Z probing void FeedForwardAdjustment(float fanPwmChange, float extrusionChange) noexcept override; - void SetExtrusionFeedForward(float pwm) noexcept override { } // We can't yet set feedforward on remote heaters because this is called from an ISR + void SetExtrusionFeedForward(float pwm, float degree) noexcept override { } // We can't yet set feedforward on remote heaters because this is called from an ISR bool IsLocal() const noexcept override { return false; } void UpdateRemoteStatus(CanAddress src, const CanHeaterReport& report) noexcept override; void UpdateHeaterTuning(CanAddress src, const CanMessageHeaterTuningReport& msg) noexcept override; diff --git a/src/Tools/Tool.cpp b/src/Tools/Tool.cpp index c0676b8f..b41174c9 100644 --- a/src/Tools/Tool.cpp +++ b/src/Tools/Tool.cpp @@ -946,6 +946,12 @@ GCodeResult Tool::GetSetFeedForward(GCodeBuffer& gb, const StringRef& reply) THR gb.GetFloatArray(heaterFeedForward, numValues, false); ToolUpdated(); } + else if (gb.Seen('T')) + { + size_t numValues = heaterCount; + gb.GetFloatArray(temperatureFeedForward, numValues, false); + ToolUpdated(); + } else { reply.printf("Tool %u heater feedforward:", myNumber); @@ -953,6 +959,11 @@ GCodeResult Tool::GetSetFeedForward(GCodeBuffer& gb, const StringRef& reply) THR { reply.catf(" %.3f", (double)heaterFeedForward[i]); } + reply.printf("Tool %u temperature feedforward:", myNumber); + for (size_t i = 0; i < heaterCount; ++i) + { + reply.catf(" %.3f", (double)temperatureFeedForward[i]); + } } return GCodeResult::ok; @@ -964,7 +975,7 @@ void Tool::ApplyFeedForward(float extrusionSpeed) const noexcept Heat& heat = reprap.GetHeat(); for (size_t i = 0; i < heaterCount; ++i) { - heat.SetExtrusionFeedForward(heaters[i], extrusionSpeed * heaterFeedForward[i]); + heat.SetExtrusionFeedForward(heaters[i], extrusionSpeed * heaterFeedForward[i], extrusionSpeed * temperatureFeedForward[i]); } } @@ -974,7 +985,7 @@ void Tool::StopFeedForward() const noexcept Heat& heat = reprap.GetHeat(); for (size_t i = 0; i < heaterCount; ++i) { - heat.SetExtrusionFeedForward(heaters[i], 0.0); + heat.SetExtrusionFeedForward(heaters[i], 0.0, 0.0); } } diff --git a/src/Tools/Tool.h b/src/Tools/Tool.h index 2c2e5afb..e071000b 100644 --- a/src/Tools/Tool.h +++ b/src/Tools/Tool.h @@ -188,6 +188,7 @@ private: float activeTemperatures[MaxHeatersPerTool]; float standbyTemperatures[MaxHeatersPerTool]; float heaterFeedForward[MaxHeatersPerTool]; + float temperatureFeedForward[MaxHeatersPerTool]; // Firmware retraction settings float retractLength, retractExtra; // retraction length and extra length to un-retract -- 2.39.2.windows.1
I'm not sure about the change of the method interface and so on but if it is heading in the right direction I can prepare a merge request.
Update
The implementation will not fit into Duet2 due to too less rom.
It will fit if the wifi is compiled without W5500 and the ethernet without WIFI
or both without FTP and Telnet support -
RE: [feature] Adaptive / Feedforward Temperature setpoint
@droftarts said in [feature] Adaptive / Feedforward Temperature setpoint:
@timschneider Interesting! There is a discussion in the OrcaSlicer community about this, see https://github.com/SoftFever/OrcaSlicer/discussions/5057, and an implementation as a post-slicing app here https://github.com/sb53systems/G-Code-Flow-Temperature-Controller
I think while it could be firmware controlled, a slicer implementation might be more desirable.
Ian
hey cool - yes i though that a slicer implementaion is even better, but the problem is the calibration of it, it takes ages to calibrate the PA and NLE for every setpoint and since we can automatically calculate the NLE in the printer as a macro, we can also tune the adaptive temp control with it, automatically.