diff options
-rw-r--r-- | src/Heating/Heater.cpp | 29 | ||||
-rw-r--r-- | src/Heating/Heater.h | 10 | ||||
-rw-r--r-- | src/Heating/LocalHeater.cpp | 21 | ||||
-rw-r--r-- | src/Heating/LocalHeater.h | 4 | ||||
-rw-r--r-- | src/Heating/RemoteHeater.cpp | 16 | ||||
-rw-r--r-- | src/Heating/RemoteHeater.h | 4 |
6 files changed, 43 insertions, 41 deletions
diff --git a/src/Heating/Heater.cpp b/src/Heating/Heater.cpp index 2d943e8f..53184f85 100644 --- a/src/Heating/Heater.cpp +++ b/src/Heating/Heater.cpp @@ -65,6 +65,8 @@ DEFINE_GET_OBJECT_MODEL_TABLE(Heater) float Heater::tuningPwm; // the PWM to use, 0..1 float Heater::tuningTargetTemp; // the target temperature +float Heater::tuningHysteresis; +float Heater::tuningFanPwm; DeviationAccumulator Heater::tuningStartTemp; // the temperature when we turned on the heater DeviationAccumulator Heater::dHigh; @@ -253,14 +255,6 @@ GCodeResult Heater::StartAutoTune(GCodeBuffer& gb, const StringRef& reply, FansB gb.MustSee('S'); const float targetTemp = gb.GetFValue(); - // Get the optional PWM - const float maxPwm = (gb.Seen('P')) ? gb.GetFValue() : GetModel().GetMaxPwm(); - if (maxPwm < 0.1 || maxPwm > 1.0) - { - reply.copy("Invalid PWM value"); - return GCodeResult::error; - } - if (!GetModel().IsEnabled()) { reply.printf("heater %u cannot be auto tuned while it is disabled", GetHeaterNumber()); @@ -289,11 +283,18 @@ GCodeResult Heater::StartAutoTune(GCodeBuffer& gb, const StringRef& reply, FansB reply.printf("Target temperature must be at least 20C above ambient temperature"); } - const GCodeResult rslt = StartAutoTune(reply, fans, targetTemp, maxPwm, seenA, ambientTemp); + // Get abd store the optional parameters + tuningTargetTemp = targetTemp; + tuningFans = fans; + tuningPwm = (gb.Seen('P')) ? gb.GetLimitedFValue('P', 0.1, 1.0) : GetModel().GetMaxPwm(); + tuningHysteresis = (gb.Seen('Y')) ? gb.GetLimitedFValue('Y', 1.0, 20.0) : DefaultTuningHysteresis; + tuningFanPwm = (gb.Seen('F')) ? gb.GetLimitedFValue('F', 0.1, 1.0) : 1.0; + + const GCodeResult rslt = StartAutoTune(reply, seenA, ambientTemp); if (rslt == GCodeResult::ok) { reply.printf("Auto tuning heater %u using target temperature %.1f" DEGREE_SYMBOL "C and PWM %.2f - do not leave printer unattended", - GetHeaterNumber(), (double)targetTemp, (double)maxPwm); + GetHeaterNumber(), (double)targetTemp, (double)tuningPwm); } return rslt; } @@ -365,8 +366,8 @@ void Heater::CalculateModel(HeaterParameters& params) noexcept } const float cycleTime = tOn.GetMean() + tOff.GetMean(); // in milliseconds - const float averageTemperatureRiseHeating = tuningTargetTemp - 0.5 * (TuningHysteresis - TuningPeakTempDrop) - tuningStartTemp.GetMean(); - const float averageTemperatureRiseCooling = tuningTargetTemp - TuningPeakTempDrop - 0.5 * TuningHysteresis - tuningStartTemp.GetMean(); + const float averageTemperatureRiseHeating = tuningTargetTemp - 0.5 * (tuningHysteresis - TuningPeakTempDrop) - tuningStartTemp.GetMean(); + const float averageTemperatureRiseCooling = tuningTargetTemp - TuningPeakTempDrop - 0.5 * tuningHysteresis - tuningStartTemp.GetMean(); params.deadTime = (((dHigh.GetMean() * tOff.GetMean()) + (dLow.GetMean() * tOn.GetMean())) * MillisToSeconds)/cycleTime; // in seconds params.coolingRate = coolingRate.GetMean()/averageTemperatureRiseCooling; // in seconds params.heatingRate = (heatingRate.GetMean() + (coolingRate.GetMean() * averageTemperatureRiseHeating/averageTemperatureRiseCooling)) / tuningPwm; @@ -377,7 +378,9 @@ void Heater::SetAndReportModel(bool usingFans) noexcept { const float hRate = (usingFans) ? (fanOffParams.heatingRate + fanOnParams.heatingRate) * 0.5 : fanOffParams.heatingRate; const float deadTime = (usingFans) ? (fanOffParams.deadTime + fanOnParams.deadTime) * 0.5 : fanOffParams.deadTime; - const float fanOnCoolingRate = (usingFans) ? fanOnParams.coolingRate : fanOffParams.coolingRate; + const float fanOnCoolingRate = (usingFans) + ? fanOffParams.coolingRate + (fanOnParams.coolingRate - fanOffParams.coolingRate)/tuningFanPwm + : fanOffParams.coolingRate; String<StringLength256> str; const GCodeResult rslt = SetModel( hRate, fanOffParams.coolingRate, fanOnCoolingRate, diff --git a/src/Heating/Heater.h b/src/Heating/Heater.h index 7a08444c..c5b088b7 100644 --- a/src/Heating/Heater.h +++ b/src/Heating/Heater.h @@ -62,7 +62,8 @@ public: float GetStandbyTemperature() const noexcept { return standbyTemperature; } GCodeResult Activate(const StringRef& reply) noexcept; // Switch from idle to active void Standby() noexcept; // Switch from active to idle - GCodeResult StartAutoTune(GCodeBuffer& gb, const StringRef& reply, FansBitmap fans) THROWS(GCodeException); // Start an auto tune cycle for this heater + GCodeResult StartAutoTune(GCodeBuffer& gb, const StringRef& reply, FansBitmap fans) THROWS(GCodeException); + // Start an auto tune cycle for this heater void GetAutoTuneStatus(const StringRef& reply) const noexcept; // Get the auto tune status or last result void GetFaultDetectionParameters(float& pMaxTempExcursion, float& pMaxFaultTime) const noexcept @@ -124,7 +125,7 @@ protected: virtual GCodeResult UpdateModel(const StringRef& reply) noexcept = 0; virtual GCodeResult UpdateFaultDetectionParameters(const StringRef& reply) noexcept = 0; virtual GCodeResult UpdateHeaterMonitors(const StringRef& reply) noexcept = 0; - virtual GCodeResult StartAutoTune(const StringRef& reply, FansBitmap fans, float targetTemp, float pwm, bool seenA, float ambientTemp) noexcept = 0; + virtual GCodeResult StartAutoTune(const StringRef& reply, bool seenA, float ambientTemp) noexcept = 0; int GetSensorNumber() const noexcept { return sensorNumber; } void SetSensorNumber(int sn) noexcept; @@ -146,7 +147,7 @@ protected: static constexpr unsigned int TuningHeaterMaxIdleCycles = 10; static constexpr unsigned int MinTuningHeaterCycles = 5; static constexpr unsigned int MaxTuningHeaterCycles = 25; - static constexpr float TuningHysteresis = 5.0; + static constexpr float DefaultTuningHysteresis = 5.0; static constexpr float TuningPeakTempDrop = 2.0; // must be well below TuningHysteresis static constexpr float FeedForwardMultiplier = 1.3; // how much we over-compensate feedforward to allow for heat reservoirs during tuning static constexpr float HeaterSettledCoolingTimeRatio = 0.93; @@ -154,6 +155,9 @@ protected: // Variables used during heater tuning static float tuningPwm; // the PWM to use, 0..1 static float tuningTargetTemp; // the target temperature + static float tuningHysteresis; + static float tuningFanPwm; + static DeviationAccumulator tuningStartTemp; // the temperature when we turned on the heater static uint32_t tuningBeginTime; // when we started the tuning process static DeviationAccumulator dHigh; diff --git a/src/Heating/LocalHeater.cpp b/src/Heating/LocalHeater.cpp index f9de4a96..2b866bea 100644 --- a/src/Heating/LocalHeater.cpp +++ b/src/Heating/LocalHeater.cpp @@ -431,8 +431,8 @@ float LocalHeater::GetExpectedHeatingRate() const noexcept : 0.0; } -// Auto tune this heater. The caller has already checked that on other heater is being tuned. -GCodeResult LocalHeater::StartAutoTune(const StringRef& reply, FansBitmap fans, float targetTemp, float pwm, bool seenA, float ambientTemp) noexcept +// Auto tune this heater. The caller has already checked that no other heater is being tuned and has set up tuningTargetTemp, tuningPwm, tuningFans, tuningHysteresis and tuningFanPwm. +GCodeResult LocalHeater::StartAutoTune(const StringRef& reply, bool seenA, float ambientTemp) noexcept { if (lastPwm > 0.0 || GetAveragePWM() > 0.02) { @@ -440,11 +440,8 @@ GCodeResult LocalHeater::StartAutoTune(const StringRef& reply, FansBitmap fans, return GCodeResult::error; } - tuningFans = fans; reprap.GetFansManager().SetFansValue(tuningFans, 0.0); - tuningPwm = pwm; - tuningTargetTemp = targetTemp; tuningStartTemp.Clear(); tuningBeginTime = millis(); tuned = false; // assume failure @@ -595,7 +592,7 @@ void LocalHeater::DoTuningStep() noexcept peakTemp = afterPeakTemp = temperature; peakTime = afterPeakTime = now; } - else if (temperature < tuningTargetTemp - TuningHysteresis) + else if (temperature < tuningTargetTemp - tuningHysteresis) { // Temperature has dropped below the low limit. // If we have been doing idle cycles, see whether we can switch to collecting data, and turn the heater on. @@ -649,9 +646,9 @@ void LocalHeater::DoTuningStep() noexcept tuningPhase = 4; ClearCounters(); #if TUNE_WITH_HALF_FAN - reprap.GetFansManager().SetFansValue(tuningFans, 0.5); // turn fans on at half PWM + reprap.GetFansManager().SetFansValue(tuningFans, tuningFanPwm * 0.5); // turn fans on at half PWM #else - reprap.GetFansManager().SetFansValue(tuningFans, 1.0); // turn fans on at full PWM + reprap.GetFansManager().SetFansValue(tuningFans, tuningFanPwm); // turn fans on at full PWM #endif ReportTuningUpdate(); } @@ -662,13 +659,13 @@ void LocalHeater::DoTuningStep() noexcept CalculateModel(fanOnParams); tuningPhase = 5; ClearCounters(); - reprap.GetFansManager().SetFansValue(tuningFans, 1.0); // turn fans fully on + reprap.GetFansManager().SetFansValue(tuningFans, tuningFanPwm); // turn fans fully on ReportTuningUpdate(); } #endif else { - reprap.GetFansManager().SetFansValue(tuningFans, 0.0); // turn fans off + reprap.GetFansManager().SetFansValue(tuningFans, 0.0); // turn fans off CalculateModel(fanOnParams); SetAndReportModel(true); break; @@ -707,7 +704,7 @@ void LocalHeater::DoTuningStep() noexcept lastPwm = 0.0; // turn heater off mode = HeaterMode::tuning2; } - else if (afterPeakTime == peakTime && temperature - tuningTargetTemp >= TuningPeakTempDrop - TuningHysteresis) + else if (afterPeakTime == peakTime && temperature - tuningTargetTemp >= TuningPeakTempDrop - tuningHysteresis) { afterPeakTime = now; afterPeakTemp = temperature; @@ -720,7 +717,7 @@ void LocalHeater::DoTuningStep() noexcept } // If we get here, we have finished - SwitchOff(); // sets mode and lastPWM, also deletes tuningTempReadings + SwitchOff(); // sets mode and lastPWM, also deletes tuningTempReadings } // Calculate the heater model from the accumulated heater parameters diff --git a/src/Heating/LocalHeater.h b/src/Heating/LocalHeater.h index 040b6ba6..d6ef0c99 100644 --- a/src/Heating/LocalHeater.h +++ b/src/Heating/LocalHeater.h @@ -52,8 +52,8 @@ protected: GCodeResult UpdateModel(const StringRef& reply) noexcept override; // Called when the heater model has been changed GCodeResult UpdateFaultDetectionParameters(const StringRef& reply) noexcept override { return GCodeResult::ok; } GCodeResult UpdateHeaterMonitors(const StringRef& reply) noexcept override { return GCodeResult::ok; } - GCodeResult StartAutoTune(const StringRef& reply, FansBitmap fans, float targetTemp, float pwm, bool seenA, float ambientTemp) noexcept override; // Start an auto tune cycle for this heater - + GCodeResult StartAutoTune(const StringRef& reply, bool seenA, float ambientTemp) noexcept override; + // Start an auto tune cycle for this heater private: void SetHeater(float power) const noexcept; // Power is a fraction in [0,1] TemperatureError ReadTemperature() noexcept; // Read and store the temperature of this heater diff --git a/src/Heating/RemoteHeater.cpp b/src/Heating/RemoteHeater.cpp index bf98ab99..e4cf368d 100644 --- a/src/Heating/RemoteHeater.cpp +++ b/src/Heating/RemoteHeater.cpp @@ -160,9 +160,9 @@ void RemoteHeater::Spin() noexcept tuningPhase = 4; ClearCounters(); #if TUNE_WITH_HALF_FAN - reprap.GetFansManager().SetFansValue(tuningFans, 0.5); // turn fans on at half PWM + reprap.GetFansManager().SetFansValue(tuningFans,tuningFanPwm * 0.5); // turn fans on at half PWM #else - reprap.GetFansManager().SetFansValue(tuningFans, 1.0); // turn fans on at full PWM + reprap.GetFansManager().SetFansValue(tuningFans, tuningFanPwm); // turn fans on at full PWM #endif ReportTuningUpdate(); } @@ -173,13 +173,13 @@ void RemoteHeater::Spin() noexcept CalculateModel(fanOnParams); tuningPhase = 5; ClearCounters(); - reprap.GetFansManager().SetFansValue(tuningFans, 1.0); // turn fans fully on + reprap.GetFansManager().SetFansValue(tuningFans, tuningFanPwm); // turn fans fully on ReportTuningUpdate(); } #endif else { - reprap.GetFansManager().SetFansValue(tuningFans, 0.0); // turn fans off + reprap.GetFansManager().SetFansValue(tuningFans, 0.0); // turn fans off CalculateModel(fanOnParams); SetAndReportModel(true); StopTuning(); @@ -286,7 +286,8 @@ float RemoteHeater::GetAccumulator() const noexcept return 0.0; // not supported } -GCodeResult RemoteHeater::StartAutoTune(const StringRef& reply, FansBitmap fans, float targetTemp, float pwm, bool seenA, float ambientTemp) noexcept +// Auto tune this heater. The caller has already checked that no other heater is being tuned and has set up tuningTargetTemp, tuningPwm, tuningFans, tuningHysteresis and tuningFanPwm. +GCodeResult RemoteHeater::StartAutoTune(const StringRef& reply, bool seenA, float ambientTemp) noexcept { CanMessageBuffer * const buf = CanMessageBuffer::Allocate(); if (buf == nullptr) @@ -295,11 +296,8 @@ GCodeResult RemoteHeater::StartAutoTune(const StringRef& reply, FansBitmap fans, return GCodeResult::error; } - tuningFans = fans; reprap.GetFansManager().SetFansValue(tuningFans, 0.0); - tuningPwm = pwm; - tuningTargetTemp = targetTemp; tuningStartTemp.Clear(); tuningBeginTime = millis(); tuned = false; @@ -490,7 +488,7 @@ GCodeResult RemoteHeater::SendTuningCommand(const StringRef& reply, bool on) noe msg->heaterNumber = GetHeaterNumber(); msg->on = on; msg->highTemp = tuningTargetTemp; - msg->lowTemp = tuningTargetTemp - TuningHysteresis; + msg->lowTemp = tuningTargetTemp - tuningHysteresis; msg->pwm = tuningPwm; msg->peakTempDrop = TuningPeakTempDrop; return CanInterface::SendRequestAndGetStandardReply(buf, rid, reply); diff --git a/src/Heating/RemoteHeater.h b/src/Heating/RemoteHeater.h index 548abe9e..0391426b 100644 --- a/src/Heating/RemoteHeater.h +++ b/src/Heating/RemoteHeater.h @@ -40,8 +40,8 @@ protected: GCodeResult UpdateModel(const StringRef& reply) noexcept override; // Called when the heater model has been changed GCodeResult UpdateFaultDetectionParameters(const StringRef& reply) noexcept override; GCodeResult UpdateHeaterMonitors(const StringRef& reply) noexcept override; - GCodeResult StartAutoTune(const StringRef& reply, FansBitmap fans, float targetTemp, float pwm, bool seenA, float ambientTemp) noexcept override; // Start an auto tune cycle for this heater - + GCodeResult StartAutoTune(const StringRef& reply, bool seenA, float ambientTemp) noexcept override; + // Start an auto tune cycle for this heater private: enum class TuningState : uint8_t { |