Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/Duet3D/RepRapFirmware.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Crocker <dcrocker@eschertech.com>2020-11-11 15:42:20 +0300
committerDavid Crocker <dcrocker@eschertech.com>2020-11-11 15:42:20 +0300
commit56cc6e24532e74919c29f42cc9ae4e7c564cdb0f (patch)
tree847b9b7f419ec65d49efc5598470bdc90a6dd2b8 /src/Heating
parentd2e3056950eef02a5614ef8f0e3d34c06140bdb3 (diff)
Implemented heater feedforward for fan RPM changes
Diffstat (limited to 'src/Heating')
-rw-r--r--src/Heating/FOPDT.cpp19
-rw-r--r--src/Heating/FOPDT.h11
-rw-r--r--src/Heating/Heat.cpp9
-rw-r--r--src/Heating/Heat.h1
-rw-r--r--src/Heating/Heater.cpp6
-rw-r--r--src/Heating/Heater.h5
-rw-r--r--src/Heating/LocalHeater.cpp10
-rw-r--r--src/Heating/LocalHeater.h1
-rw-r--r--src/Heating/RemoteHeater.cpp13
-rw-r--r--src/Heating/RemoteHeater.h1
10 files changed, 54 insertions, 22 deletions
diff --git a/src/Heating/FOPDT.cpp b/src/Heating/FOPDT.cpp
index bb62bb9a..4c5e81fd 100644
--- a/src/Heating/FOPDT.cpp
+++ b/src/Heating/FOPDT.cpp
@@ -38,7 +38,7 @@ constexpr ObjectModelTableEntry FopDt::objectModelTable[] =
{ "pid", OBJECT_MODEL_FUNC(self, 1), ObjectModelEntryFlags::none },
{ "standardVoltage", OBJECT_MODEL_FUNC(self->standardVoltage, 1), ObjectModelEntryFlags::none },
{ "timeConstant", OBJECT_MODEL_FUNC(self->GetTimeConstantFanOff(), 1), ObjectModelEntryFlags::none },
- { "timeConstantFanOn", OBJECT_MODEL_FUNC(self->GetTimeConstantFanOn(), 1), ObjectModelEntryFlags::none },
+ { "timeConstantFansOn", OBJECT_MODEL_FUNC(self->GetTimeConstantFanOn(), 1), ObjectModelEntryFlags::none },
// 1. PID members
{ "d", OBJECT_MODEL_FUNC(self->loadChangeParams.tD * self->loadChangeParams.kP, 1), ObjectModelEntryFlags::none },
@@ -58,7 +58,7 @@ DEFINE_GET_OBJECT_MODEL_TABLE(FopDt)
// Set up sensible defaults here in case the user enables the heater without specifying values for all the parameters.
FopDt::FopDt() noexcept
: heatingRate(DefaultHotEndHeaterHeatingRate),
- coolingRateFanOff(DefaultHotEndHeaterCoolingRate), coolingRateFanOn(DefaultHotEndHeaterCoolingRate),
+ coolingRateFanOff(DefaultHotEndHeaterCoolingRate), coolingRateChangeFanOn(0.0),
deadTime(DefaultHotEndHeaterDeadTime), maxPwm(1.0), standardVoltage(0.0),
enabled(false), usePid(true), inverted(false), pidParametersOverridden(false)
{
@@ -80,7 +80,7 @@ bool FopDt::SetParameters(float phr, float pcrFanOff, float pcrFanOn, float pdt,
{
heatingRate = phr;
coolingRateFanOff = pcrFanOff;
- coolingRateFanOn = pcrFanOn;
+ coolingRateChangeFanOn = pcrFanOn - pcrFanOff;
deadTime = pdt;
maxPwm = pMaxPwm;
standardVoltage = pVoltage;
@@ -121,7 +121,7 @@ bool FopDt::WriteParameters(FileStore *f, size_t heater) const noexcept
{
String<StringLength256> scratchString;
scratchString.printf("M307 H%u R%.3f C%.3f:%.3f D%.2f S%.2f V%.1f B%d\n",
- heater, (double)heatingRate, (double)coolingRateFanOff, (double)coolingRateFanOn, (double)deadTime, (double)maxPwm, (double)standardVoltage, (usePid) ? 0 : 1);
+ heater, (double)heatingRate, (double)GetTimeConstantFanOff(), (double)GetTimeConstantFanOn(), (double)deadTime, (double)maxPwm, (double)standardVoltage, (usePid) ? 0 : 1);
bool ok = f->Write(scratchString.c_str());
if (ok && pidParametersOverridden)
{
@@ -166,7 +166,7 @@ bool FopDt::WriteParameters(FileStore *f, size_t heater) const noexcept
void FopDt::CalcPidConstants() noexcept
{
- const float averageCoolingRate = (coolingRateFanOff + coolingRateFanOn) * 0.5;
+ const float averageCoolingRate = coolingRateFanOff + 0.5 * coolingRateChangeFanOn;
loadChangeParams.kP = 0.7/(heatingRate * deadTime);
loadChangeParams.recipTi = powf(averageCoolingRate, 0.25)/(1.14 * powf(deadTime, 0.75)); // Ti = 1.14 * timeConstant^0.25 * deadTime^0.75 (Ho et al)
loadChangeParams.tD = deadTime * 0.7;
@@ -180,11 +180,14 @@ void FopDt::CalcPidConstants() noexcept
#if SUPPORT_CAN_EXPANSION
-void FopDt::SetupCanMessage(unsigned int heater, CanMessageUpdateHeaterModel& msg) const noexcept
+void FopDt::SetupCanMessage(unsigned int heater, CanMessageUpdateHeaterModelNew& msg) const noexcept
{
msg.heater = heater;
- msg.gain = gain;
- msg.timeConstant = timeConstant;
+ msg.heatingRate = heatingRate;
+ msg.coolingRate = coolingRateFanOff;
+ msg.coolingRateChangeFanOn = coolingRateChangeFanOn;
+ msg.coolingRateChangeExtruding = 0.0;
+ msg.zero2 = 0.0;
msg.deadTime = deadTime;
msg.maxPwm = maxPwm;
msg.standardVoltage = standardVoltage;
diff --git a/src/Heating/FOPDT.h b/src/Heating/FOPDT.h
index 728b3c78..eab8d1fb 100644
--- a/src/Heating/FOPDT.h
+++ b/src/Heating/FOPDT.h
@@ -34,7 +34,7 @@ class FileStore;
#endif
#if SUPPORT_CAN_EXPANSION
-struct CanMessageUpdateHeaterModel;
+struct CanMessageUpdateHeaterModelNew;
#endif
class FopDt INHERIT_OBJECT_MODEL
@@ -47,7 +47,8 @@ public:
// Stored parameters
float GetHeatingRate() const noexcept { return heatingRate; }
float GetCoolingRateFanOff() const noexcept { return coolingRateFanOff; }
- float GetCoolingRateFanOn() const noexcept { return coolingRateFanOn; }
+ float GetCoolingRateFanOn() const noexcept { return coolingRateFanOff + coolingRateChangeFanOn; }
+ float GetCoolingRateChangeFanOn() const noexcept { return coolingRateChangeFanOn; }
float GetDeadTime() const noexcept { return deadTime; }
float GetMaxPwm() const noexcept { return maxPwm; }
float GetVoltage() const noexcept { return standardVoltage; }
@@ -58,7 +59,7 @@ public:
// Derived parameters
float GetGainFanOff() const noexcept { return heatingRate/coolingRateFanOff; }
float GetTimeConstantFanOff() const noexcept { return 1.0/coolingRateFanOff; }
- float GetTimeConstantFanOn() const noexcept { return 1.0/coolingRateFanOn; }
+ float GetTimeConstantFanOn() const noexcept { return 1.0/GetCoolingRateFanOn(); }
bool ArePidParametersOverridden() const noexcept { return pidParametersOverridden; }
M301PidParameters GetM301PidParameters(bool forLoadChange) const noexcept;
void SetM301PidParameters(const M301PidParameters& params) noexcept;
@@ -73,7 +74,7 @@ public:
#endif
#if SUPPORT_CAN_EXPANSION
- void SetupCanMessage(unsigned int heater, CanMessageUpdateHeaterModel& msg) const noexcept;
+ void SetupCanMessage(unsigned int heater, CanMessageUpdateHeaterModelNew& msg) const noexcept;
#endif
protected:
@@ -84,7 +85,7 @@ private:
float heatingRate;
float coolingRateFanOff;
- float coolingRateFanOn;
+ float coolingRateChangeFanOn;
float deadTime;
float maxPwm;
float standardVoltage; // power voltage reading at which tuning was done, or 0 if unknown
diff --git a/src/Heating/Heat.cpp b/src/Heating/Heat.cpp
index bdd8bf1a..2a3d8e94 100644
--- a/src/Heating/Heat.cpp
+++ b/src/Heating/Heat.cpp
@@ -727,6 +727,15 @@ void Heat::Standby(int heater, const Tool *tool) noexcept
}
}
+void Heat::PrintCoolingFanPwmChanged(unsigned int heater, float pwmChange) const noexcept
+{
+ const auto h = FindHeater(heater);
+ if (h.IsNotNull())
+ {
+ h->PrintCoolingFanPwmChanged(pwmChange);
+ }
+}
+
GCodeResult Heat::ResetFault(int heater, const StringRef& reply) noexcept
{
// This gets called for all heater numbers when clearing all temperature faults, so don't report an error if the heater was not found
diff --git a/src/Heating/Heat.h b/src/Heating/Heat.h
index bbe9bff9..74bccc26 100644
--- a/src/Heating/Heat.h
+++ b/src/Heating/Heat.h
@@ -131,6 +131,7 @@ public:
GCodeResult Activate(int heater, const StringRef& reply) noexcept; // Turn on a heater
void Standby(int heater, const Tool* tool) noexcept; // Set a heater to standby
void SwitchOff(int heater) noexcept; // Turn off a specific heater
+ void PrintCoolingFanPwmChanged(unsigned int heater, float pwmChange) const noexcept;
#if HAS_MASS_STORAGE
bool WriteModelParameters(FileStore *f) const noexcept; // Write heater model parameters to file returning true if no error
diff --git a/src/Heating/Heater.cpp b/src/Heating/Heater.cpp
index 4d7133bf..9a862383 100644
--- a/src/Heating/Heater.cpp
+++ b/src/Heating/Heater.cpp
@@ -179,17 +179,17 @@ GCodeResult Heater::SetOrReportModel(unsigned int heater, GCodeBuffer& gb, const
}
// Set the process model returning true if successful
-GCodeResult Heater::SetModel(float gain, float tcOff, float tcOn, float td, float maxPwm, float voltage, bool usePid, bool inverted, const StringRef& reply) noexcept
+GCodeResult Heater::SetModel(float heatingRate, float coolingRateFanOff, float coolingRateFanOn, float td, float maxPwm, float voltage, bool usePid, bool inverted, const StringRef& reply) noexcept
{
GCodeResult rslt;
- if (model.SetParameters(gain, tcOff, tcOn, td, maxPwm, GetHighestTemperatureLimit(), voltage, usePid, inverted))
+ if (model.SetParameters(heatingRate, coolingRateFanOff, coolingRateFanOn, td, maxPwm, GetHighestTemperatureLimit(), voltage, usePid, inverted))
{
if (model.IsEnabled())
{
rslt = UpdateModel(reply);
if (rslt == GCodeResult::ok)
{
- const float predictedMaxTemp = gain + NormalAmbientTemperature;
+ const float predictedMaxTemp = heatingRate/coolingRateFanOff + NormalAmbientTemperature;
const float noWarnTemp = (GetHighestTemperatureLimit() - NormalAmbientTemperature) * 1.5 + 50.0; // allow 50% extra power plus enough for an extra 50C
if (predictedMaxTemp > noWarnTemp)
{
diff --git a/src/Heating/Heater.h b/src/Heating/Heater.h
index 502e2e74..8c8231e0 100644
--- a/src/Heating/Heater.h
+++ b/src/Heating/Heater.h
@@ -43,9 +43,10 @@ public:
virtual void SwitchOff() noexcept = 0;
virtual void Spin() noexcept = 0;
virtual GCodeResult StartAutoTune(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeException) = 0; // Start an auto tune cycle for this heater
- virtual void GetAutoTuneStatus(const StringRef& reply) const = 0; // Get the auto tune status or last result
+ virtual void GetAutoTuneStatus(const StringRef& reply) const noexcept = 0; // Get the auto tune status or last result
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 PrintCoolingFanPwmChanged(float pwmChange) noexcept = 0;
#if SUPPORT_CAN_EXPANSION
virtual void UpdateRemoteStatus(CanAddress src, const CanHeaterReport& report) noexcept = 0;
@@ -117,7 +118,7 @@ protected:
float GetMaxTemperatureExcursion() const noexcept { return maxTempExcursion; }
float GetMaxHeatingFaultTime() const noexcept { return maxHeatingFaultTime; }
float GetTargetTemperature() const noexcept { return (active) ? activeTemperature : standbyTemperature; }
- GCodeResult SetModel(float gain, float tcOff, float tcOn, float td, float maxPwm, float voltage, bool usePid, bool inverted, const StringRef& reply) noexcept; // Set the process model
+ GCodeResult SetModel(float heatingRate, float coolingRateFanOff, float coolingRateFanOn, float td, float maxPwm, float voltage, bool usePid, bool inverted, const StringRef& reply) noexcept; // Set the process model
HeaterMonitor monitors[MaxMonitorsPerHeater]; // embedding them in the Heater uses less memory than dynamic allocation
diff --git a/src/Heating/LocalHeater.cpp b/src/Heating/LocalHeater.cpp
index d5764c04..1d0af3f3 100644
--- a/src/Heating/LocalHeater.cpp
+++ b/src/Heating/LocalHeater.cpp
@@ -596,6 +596,16 @@ void LocalHeater::GetAutoTuneStatus(const StringRef& reply) const noexcept
}
}
+// Call this when the PWM of a cooling fan has changed. If there are multiple fans, caller must divide pwmChange by the number of fans.
+void LocalHeater::PrintCoolingFanPwmChanged(float pwmChange) noexcept
+{
+ if (mode == HeaterMode::stable)
+ {
+ const float coolingRateIncrease = GetModel().GetCoolingRateChangeFanOn() * pwmChange;
+ iAccumulator += (coolingRateIncrease * (GetTargetTemperature() - NormalAmbientTemperature))/GetModel().GetHeatingRate();
+ }
+}
+
/* Notes on the auto tune algorithm
*
* Most 3D printer firmwares use the �str�m-H�gglund relay tuning method (sometimes called Ziegler-Nichols + relay).
diff --git a/src/Heating/LocalHeater.h b/src/Heating/LocalHeater.h
index 8c32dc39..5cad973b 100644
--- a/src/Heating/LocalHeater.h
+++ b/src/Heating/LocalHeater.h
@@ -50,6 +50,7 @@ public:
GCodeResult StartAutoTune(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeException) override; // Start an auto tune cycle for this heater
void GetAutoTuneStatus(const StringRef& reply) const noexcept override; // Get the auto tune status or last result
void Suspend(bool sus) noexcept override; // Suspend the heater to conserve power or while doing Z probing
+ void PrintCoolingFanPwmChanged(float pwmChange) noexcept override;
#if SUPPORT_CAN_EXPANSION
void UpdateRemoteStatus(CanAddress src, const CanHeaterReport& report) noexcept override { }
diff --git a/src/Heating/RemoteHeater.cpp b/src/Heating/RemoteHeater.cpp
index 70dfe8bb..94e6f377 100644
--- a/src/Heating/RemoteHeater.cpp
+++ b/src/Heating/RemoteHeater.cpp
@@ -41,13 +41,13 @@ void RemoteHeater::ResetHeater() noexcept
//TODO
}
-GCodeResult RemoteHeater::ConfigurePortAndSensor(const char *portName, PwmFrequency freq, unsigned int sensorNumber, const StringRef& reply)
+GCodeResult RemoteHeater::ConfigurePortAndSensor(const char *portName, PwmFrequency freq, unsigned int sn, const StringRef& reply)
{
- SetSensorNumber(sensorNumber);
+ SetSensorNumber(sn);
CanMessageGenericConstructor cons(M950HeaterParams);
cons.AddUParam('H', GetHeaterNumber());
cons.AddUParam('Q', freq);
- cons.AddUParam('T', sensorNumber);
+ cons.AddUParam('T', sn);
cons.AddStringParam('C', portName);
return cons.SendAndGetResponse(CanMessageType::m950Heater, boardAddress, reply);
}
@@ -139,6 +139,11 @@ void RemoteHeater::GetAutoTuneStatus(const StringRef& reply) const noexcept
reply.copy("remote heater auto tune not implemented");
}
+void RemoteHeater::PrintCoolingFanPwmChanged(float pwmChange) noexcept
+{
+ //TODO send a CAN message to remote
+}
+
void RemoteHeater::Suspend(bool sus) noexcept
{
CanMessageBuffer * const buf = CanMessageBuffer::Allocate();
@@ -189,7 +194,7 @@ GCodeResult RemoteHeater::UpdateModel(const StringRef& reply) noexcept
if (buf != nullptr)
{
const CanRequestId rid = CanInterface::AllocateRequestId(boardAddress);
- CanMessageUpdateHeaterModel * const msg = buf->SetupRequestMessage<CanMessageUpdateHeaterModel>(rid, CanInterface::GetCanAddress(), boardAddress);
+ CanMessageUpdateHeaterModelNew * const msg = buf->SetupRequestMessage<CanMessageUpdateHeaterModelNew>(rid, CanInterface::GetCanAddress(), boardAddress);
GetModel().SetupCanMessage(GetHeaterNumber(), *msg);
return CanInterface::SendRequestAndGetStandardReply(buf, rid, reply);
}
diff --git a/src/Heating/RemoteHeater.h b/src/Heating/RemoteHeater.h
index 676dfdfa..558b49b4 100644
--- a/src/Heating/RemoteHeater.h
+++ b/src/Heating/RemoteHeater.h
@@ -31,6 +31,7 @@ public:
GCodeResult StartAutoTune(GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeException) override; // Start an auto tune cycle for this heater
void GetAutoTuneStatus(const StringRef& reply) const noexcept override; // Get the auto tune status or last result
void Suspend(bool sus) noexcept override; // Suspend the heater to conserve power or while doing Z probing
+ void PrintCoolingFanPwmChanged(float pwmChange) noexcept override;
void UpdateRemoteStatus(CanAddress src, const CanHeaterReport& report) noexcept override;
protected: