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:
-rw-r--r--src/Heating/Heat.cpp7
-rw-r--r--src/Heating/Heat.h2
-rw-r--r--src/Heating/Heater.cpp95
-rw-r--r--src/Heating/Heater.h48
-rw-r--r--src/Heating/LocalHeater.cpp84
-rw-r--r--src/Heating/LocalHeater.h31
-rw-r--r--src/Heating/RemoteHeater.cpp94
-rw-r--r--src/Heating/RemoteHeater.h33
8 files changed, 257 insertions, 137 deletions
diff --git a/src/Heating/Heat.cpp b/src/Heating/Heat.cpp
index 076f81c0..89875819 100644
--- a/src/Heating/Heat.cpp
+++ b/src/Heating/Heat.cpp
@@ -1092,13 +1092,6 @@ size_t Heat::GetNumSensorsToReport() const noexcept
return s->GetSensorNumber() + 1;
}
-// Get the temperature of a heater
-float Heat::GetHeaterTemperature(size_t heater) const noexcept
-{
- const auto h = FindHeater(heater);
- return (h.IsNull()) ? ABS_ZERO : h->GetTemperature();
-}
-
// Suspend the heaters to conserve power or while doing Z probing
void Heat::SuspendHeaters(bool sus) noexcept
{
diff --git a/src/Heating/Heat.h b/src/Heating/Heat.h
index 3d86ed5e..8b67f807 100644
--- a/src/Heating/Heat.h
+++ b/src/Heating/Heat.h
@@ -104,8 +104,6 @@ public:
float GetAveragePWM(size_t heater) const noexcept // Return the running average PWM to the heater as a fraction in [0, 1].
pre(heater < MaxHeaters);
- float GetHeaterTemperature(size_t heater) const noexcept; // Result is in degrees Celsius
-
const Tool* GetLastStandbyTool(int heater) const noexcept
pre(heater >= 0; heater < MaxHeaters)
{
diff --git a/src/Heating/Heater.cpp b/src/Heating/Heater.cpp
index 952f50ce..d3bd47f5 100644
--- a/src/Heating/Heater.cpp
+++ b/src/Heating/Heater.cpp
@@ -60,8 +60,42 @@ DEFINE_GET_OBJECT_MODEL_TABLE(Heater)
#endif
+// Static members of class Heater
+
+float Heater::tuningPwm; // the PWM to use, 0..1
+float Heater::tuningTargetTemp; // the target temperature
+DeviationAccumulator Heater::tuningStartTemp; // the temperature when we turned on the heater
+uint32_t Heater::tuningBeginTime; // when we started the tuning process
+DeviationAccumulator Heater::dHigh;
+DeviationAccumulator Heater::dLow;
+DeviationAccumulator Heater::tOn;
+DeviationAccumulator Heater::tOff;
+DeviationAccumulator Heater::heatingRate;
+DeviationAccumulator Heater::coolingRate;
+uint32_t Heater::lastOffTime;
+uint32_t Heater::lastOnTime;
+float Heater::peakTemp; // max or min temperature
+uint32_t Heater::peakTime; // the time at which we recorded peakTemp
+float Heater::afterPeakTemp; // temperature after max from which we start timing the cooling rate
+uint32_t Heater::afterPeakTime; // the time at which we recorded afterPeakTemp
+float Heater::lastCoolingRate;
+FansBitmap Heater::tuningFans;
+unsigned int Heater::tuningPhase;
+uint8_t Heater::idleCyclesDone;
+
+// Clear all the counters except tuning voltage and start temperature
+/*static*/ void Heater::ClearCounters() noexcept
+{
+ dHigh.Clear();
+ dLow.Clear();
+ tOn.Clear();
+ tOff.Clear();
+ heatingRate.Clear();
+ coolingRate.Clear();
+}
+
Heater::Heater(unsigned int num) noexcept
- : heaterNumber(num), sensorNumber(-1), activeTemperature(0.0), standbyTemperature(0.0),
+ : tuned(false), heaterNumber(num), sensorNumber(-1), activeTemperature(0.0), standbyTemperature(0.0),
maxTempExcursion(DefaultMaxTempExcursion), maxHeatingFaultTime(DefaultMaxHeatingFaultTime),
active(false), modelSetByUser(false), monitorsSetByUser(false)
{
@@ -170,17 +204,17 @@ GCodeResult Heater::SetOrReportModel(unsigned int heater, GCodeBuffer& gb, const
}
// Set the process model returning true if successful
-GCodeResult Heater::SetModel(float heatingRate, float coolingRateFanOff, float coolingRateFanOn, float td, float maxPwm, float voltage, bool usePid, bool inverted, const StringRef& reply) noexcept
+GCodeResult Heater::SetModel(float hr, float coolingRateFanOff, float coolingRateFanOn, float td, float maxPwm, float voltage, bool usePid, bool inverted, const StringRef& reply) noexcept
{
GCodeResult rslt;
- if (model.SetParameters(heatingRate, coolingRateFanOff, coolingRateFanOn, td, maxPwm, GetHighestTemperatureLimit(), voltage, usePid, inverted))
+ if (model.SetParameters(hr, coolingRateFanOff, coolingRateFanOn, td, maxPwm, GetHighestTemperatureLimit(), voltage, usePid, inverted))
{
if (model.IsEnabled())
{
rslt = UpdateModel(reply);
if (rslt == GCodeResult::ok)
{
- const float predictedMaxTemp = heatingRate/coolingRateFanOff + NormalAmbientTemperature;
+ const float predictedMaxTemp = hr/coolingRateFanOff + NormalAmbientTemperature;
const float noWarnTemp = (GetHighestTemperatureLimit() - NormalAmbientTemperature) * 1.5 + 50.0; // allow 50% extra power plus enough for an extra 50C
if (predictedMaxTemp > noWarnTemp)
{
@@ -192,6 +226,7 @@ GCodeResult Heater::SetModel(float heatingRate, float coolingRateFanOff, float c
else
{
ResetHeater();
+ tuned = false;
rslt = GCodeResult::ok;
}
}
@@ -205,6 +240,58 @@ GCodeResult Heater::SetModel(float heatingRate, float coolingRateFanOff, float c
return rslt;
}
+// Start an auto tune cycle for this heater
+GCodeResult Heater::StartAutoTune(GCodeBuffer& gb, const StringRef& reply, FansBitmap fans) THROWS(GCodeException)
+{
+ // Get the target temperature (required)
+ 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());
+ return GCodeResult::error;
+ }
+
+ const float limit = GetHighestTemperatureLimit();
+ if (targetTemp >= limit)
+ {
+ reply.printf("heater %u target temperature must be below the temperature limit for this heater (%.1fC)", GetHeaterNumber(), (double)limit);
+ return GCodeResult::error;
+ }
+
+ TemperatureError err;
+ const float currentTemp = reprap.GetHeat().GetSensorTemperature(GetSensorNumber(), err);
+ if (err != TemperatureError::success)
+ {
+ reply.printf("heater %u reported error '%s' at start of auto tuning", GetHeaterNumber(), TemperatureErrorString(err));
+ return GCodeResult::error;
+ }
+
+ const bool seenA = gb.Seen('A');
+ const float ambientTemp = (seenA) ? gb.GetFValue() : currentTemp;
+ if (ambientTemp + 20 >= targetTemp)
+ {
+ reply.printf("Target temperature must be at least 20C above ambient temperature");
+ }
+
+ const GCodeResult rslt = StartAutoTune(reply, fans, targetTemp, maxPwm, 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);
+ }
+ return rslt;
+}
+
GCodeResult Heater::SetFaultDetectionParameters(float pMaxTempExcursion, float pMaxFaultTime, const StringRef& reply) noexcept
{
maxTempExcursion = pMaxTempExcursion;
diff --git a/src/Heating/Heater.h b/src/Heating/Heater.h
index eaed5621..4600ab0c 100644
--- a/src/Heating/Heater.h
+++ b/src/Heating/Heater.h
@@ -14,6 +14,7 @@
#include "HeaterMonitor.h"
#include <GCodes/GCodeResult.h>
#include <ObjectModel/ObjectModel.h>
+#include <Math/DeviationAccumulator.h>
#if SUPPORT_CAN_EXPANSION
# include "CanId.h"
@@ -37,12 +38,11 @@ public:
virtual GCodeResult SetPwmFrequency(PwmFrequency freq, const StringRef& reply) = 0;
virtual GCodeResult ReportDetails(const StringRef& reply) const noexcept = 0;
- virtual float GetTemperature() const noexcept = 0; // Get the current temperature
+ virtual float GetTemperature() const noexcept = 0; // Get the current temperature and error status
virtual float GetAveragePWM() const noexcept = 0; // Return the running average PWM to the heater. Answer is a fraction in [0, 1].
virtual GCodeResult ResetFault(const StringRef& reply) noexcept = 0; // Reset a fault condition - only call this if you know what you are doing
virtual void SwitchOff() noexcept = 0;
virtual void Spin() noexcept = 0;
- virtual GCodeResult StartAutoTune(GCodeBuffer& gb, const StringRef& reply, FansBitmap fans) THROWS(GCodeException) = 0; // Start an auto tune cycle for this heater
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
@@ -60,6 +60,7 @@ 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
void GetFaultDetectionParameters(float& pMaxTempExcursion, float& pMaxFaultTime) const noexcept
{ pMaxTempExcursion = maxTempExcursion; pMaxFaultTime = maxHeatingFaultTime; }
@@ -113,15 +114,52 @@ 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;
int GetSensorNumber() const noexcept { return sensorNumber; }
void SetSensorNumber(int sn) noexcept;
float GetMaxTemperatureExcursion() const noexcept { return maxTempExcursion; }
float GetMaxHeatingFaultTime() const noexcept { return maxHeatingFaultTime; }
float GetTargetTemperature() const noexcept { return (active) ? activeTemperature : standbyTemperature; }
- 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
+ GCodeResult SetModel(float hr, 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
+ bool tuned; // true if tuning was successful
+
+ // Constants used during heater tuning
+ static constexpr uint32_t TempSettleTimeout = 20000; // how long we allow the initial temperature to settle
+ static constexpr unsigned int TuningHeaterMinIdleCycles = 3; // minimum number of idle cycles after heating up, including the initial overshoot and cool down
+ 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 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;
+
+ // Variables used during heater tuning
+ static float tuningPwm; // the PWM to use, 0..1
+ static float tuningTargetTemp; // the target temperature
+ static DeviationAccumulator tuningStartTemp; // the temperature when we turned on the heater
+ static uint32_t tuningBeginTime; // when we started the tuning process
+ static DeviationAccumulator dHigh;
+ static DeviationAccumulator dLow;
+ static DeviationAccumulator tOn;
+ static DeviationAccumulator tOff;
+ static DeviationAccumulator heatingRate;
+ static DeviationAccumulator coolingRate;
+ static uint32_t lastOffTime;
+ static uint32_t lastOnTime;
+ static float peakTemp; // max or min temperature
+ static uint32_t peakTime; // the time at which we recorded peakTemp
+ static float afterPeakTemp; // temperature after max from which we start timing the cooling rate
+ static uint32_t afterPeakTime; // the time at which we recorded afterPeakTemp
+ static float lastCoolingRate;
+ static FansBitmap tuningFans;
+ static unsigned int tuningPhase;
+ static uint8_t idleCyclesDone;
+
+ static void ClearCounters() noexcept;
private:
FopDt model;
diff --git a/src/Heating/LocalHeater.cpp b/src/Heating/LocalHeater.cpp
index 949c6096..9a5db5c9 100644
--- a/src/Heating/LocalHeater.cpp
+++ b/src/Heating/LocalHeater.cpp
@@ -16,49 +16,12 @@
#define TUNE_WITH_HALF_FAN 0
-// Private constants
-const uint32_t InitialTuningReadingInterval = 250; // the initial reading interval in milliseconds
-const uint32_t TempSettleTimeout = 20000; // how long we allow the initial temperature to settle
-
-// Variables used during heater tuning
-static float tuningPwm; // the PWM to use, 0..1
-static float tuningTargetTemp; // the target temperature
-static DeviationAccumulator tuningStartTemp; // the temperature when we turned on the heater
-static uint32_t tuningBeginTime; // when we started the tuning process
-static DeviationAccumulator dHigh;
-static DeviationAccumulator dLow;
-static DeviationAccumulator tOn;
-static DeviationAccumulator tOff;
-static DeviationAccumulator heatingRate;
-static DeviationAccumulator coolingRate;
-static uint32_t lastOffTime;
-static uint32_t lastOnTime;
-static float peakTemp; // max or min temperature
-static uint32_t peakTime; // the time at which we recorded peakTemp
-static float afterPeakTemp; // temperature after max from which we start timing the cooling rate
-static uint32_t afterPeakTime; // the time at which we recorded afterPeakTemp
-static float lastCoolingRate;
-static FansBitmap tuningFans;
-static unsigned int tuningPhase;
-static uint8_t idleCyclesDone;
-
static LocalHeater::HeaterParameters fanOffParams, fanOnParams;
#if HAS_VOLTAGE_MONITOR
static DeviationAccumulator tuningVoltage; // sum of the voltage readings we take during the heating phase
#endif
-// Clear all the counters except tuning voltage and start temperature
-static void ClearCounters() noexcept
-{
- dHigh.Clear();
- dLow.Clear();
- tOn.Clear();
- tOff.Clear();
- heatingRate.Clear();
- coolingRate.Clear();
-}
-
// Member functions and constructors
LocalHeater::LocalHeater(unsigned int heaterNum) noexcept : Heater(heaterNum), mode(HeaterMode::off)
@@ -99,7 +62,6 @@ void LocalHeater::ResetHeater() noexcept
previousTemperatureIndex = 0;
iAccumulator = 0.0;
badTemperatureCount = 0;
- tuned = false;
averagePWM = lastPwm = 0.0;
heatingFaultCount = 0;
temperature = BadErrorTemperature;
@@ -478,60 +440,18 @@ float LocalHeater::GetExpectedHeatingRate() const noexcept
}
// Auto tune this heater. The caller has already checked that on other heater is being tuned.
-GCodeResult LocalHeater::StartAutoTune(GCodeBuffer& gb, const StringRef& reply, FansBitmap fans) THROWS(GCodeException)
+GCodeResult LocalHeater::StartAutoTune(const StringRef& reply, FansBitmap fans, float targetTemp, float pwm, bool seenA, float ambientTemp) noexcept
{
- // Get the target temperature (required)
- 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());
- return GCodeResult::error;
- }
-
if (lastPwm > 0.0 || GetAveragePWM() > 0.02)
{
reply.printf("heater %u must be off and cold before auto tuning it", GetHeaterNumber());
return GCodeResult::error;
}
- const float limit = GetHighestTemperatureLimit();
- if (targetTemp >= limit)
- {
- reply.printf("heater %u target temperature must be below the temperature limit for this heater (%.1fC)", GetHeaterNumber(), (double)limit);
- return GCodeResult::error;
- }
-
- const TemperatureError err = ReadTemperature();
- if (err != TemperatureError::success)
- {
- reply.printf("heater %u reported error '%s' at start of auto tuning", GetHeaterNumber(), TemperatureErrorString(err));
- return GCodeResult::error;
- }
-
- const bool seenA = gb.Seen('A');
- const float ambientTemp = (seenA) ? gb.GetFValue() : temperature;
- if (ambientTemp + 20 >= targetTemp)
- {
- reply.printf("Target temperature must be at least 20C above ambient temperature");
- }
-
- 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);
-
tuningFans = fans;
reprap.GetFansManager().SetFansValue(tuningFans, 0.0);
- tuningPwm = maxPwm;
+ tuningPwm = pwm;
tuningTargetTemp = targetTemp;
tuningStartTemp.Clear();
tuningBeginTime = millis();
diff --git a/src/Heating/LocalHeater.h b/src/Heating/LocalHeater.h
index 0486bccf..80afa0ad 100644
--- a/src/Heating/LocalHeater.h
+++ b/src/Heating/LocalHeater.h
@@ -17,7 +17,6 @@
#include "TemperatureError.h"
#include <Hardware/IoPorts.h>
#include <GCodes/GCodeResult.h>
-#include <Math/DeviationAccumulator.h>
class HeaterMonitor;
@@ -41,15 +40,14 @@ public:
GCodeResult SetPwmFrequency(PwmFrequency freq, const StringRef& reply) noexcept override;
GCodeResult ReportDetails(const StringRef& reply) const noexcept override;
- void Spin() noexcept override; // Called in a tight loop to keep things running
- void SwitchOff() noexcept override; // Not even standby - all heater power off
- GCodeResult ResetFault(const StringRef& reply) noexcept override; // Reset a fault condition - only call this if you know what you are doing
- float GetTemperature() const noexcept override; // Get the current temperature
- float GetAveragePWM() const noexcept override; // Return the running average PWM to the heater. Answer is a fraction in [0, 1].
- float GetAccumulator() const noexcept override; // Return the integral accumulator
- GCodeResult StartAutoTune(GCodeBuffer& gb, const StringRef& reply, FansBitmap fans) THROWS(GCodeException) override; // Start an auto tune cycle for this heater
+ void Spin() noexcept override; // Called in a tight loop to keep things running
+ void SwitchOff() noexcept override; // Not even standby - all heater power off
+ GCodeResult ResetFault(const StringRef& reply) noexcept override; // Reset a fault condition - only call this if you know what you are doing
+ float GetTemperature() const noexcept override; // Get the latest temperature
+ float GetAveragePWM() const noexcept override; // Return the running average PWM to the heater. Answer is a fraction in [0, 1].
+ float GetAccumulator() const noexcept override; // Return the integral accumulator
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 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
@@ -59,10 +57,11 @@ public:
protected:
void ResetHeater() noexcept override;
HeaterMode GetMode() const noexcept override { return mode; }
- GCodeResult SwitchOn(const StringRef& reply) noexcept override; // Turn the heater on and set the mode
- GCodeResult UpdateModel(const StringRef& reply) noexcept override; // Called when the heater model has been changed
+ GCodeResult SwitchOn(const StringRef& reply) noexcept override; // Turn the heater on and set the mode
+ 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
private:
void SetHeater(float power) const noexcept; // Power is a fraction in [0,1]
@@ -87,19 +86,9 @@ private:
uint8_t previousTemperaturesGood; // Bitmap indicating which previous temperature were good readings
HeaterMode mode; // Current state of the heater
- bool tuned; // True if tuning was successful
uint8_t badTemperatureCount; // Count of sequential dud readings
static_assert(sizeof(previousTemperaturesGood) * 8 >= NumPreviousTemperatures, "too few bits in previousTemperaturesGood");
-
- static constexpr unsigned int TuningHeaterMinIdleCycles = 3; // minimum number of idle cycles after heating up, including the initial overshoot and cool down
- 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 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;
};
#endif /* SRC_LOCALHEATER_H_ */
diff --git a/src/Heating/RemoteHeater.cpp b/src/Heating/RemoteHeater.cpp
index 4012e387..1620bf1d 100644
--- a/src/Heating/RemoteHeater.cpp
+++ b/src/Heating/RemoteHeater.cpp
@@ -18,7 +18,7 @@
#include <CanMessageBuffer.h>
RemoteHeater::RemoteHeater(unsigned int num, CanAddress board) noexcept
- : Heater(num), boardAddress(board), lastMode(HeaterMode::offline), averagePwm(0), lastTemperature(0.0), whenLastStatusReceived(0)
+ : Heater(num), boardAddress(board), lastMode(HeaterMode::offline), averagePwm(0), tuningState(TuningState::notTuning), lastTemperature(0.0), whenLastStatusReceived(0)
{
}
@@ -33,12 +33,41 @@ RemoteHeater::~RemoteHeater() noexcept
void RemoteHeater::Spin() noexcept
{
- // Nothing needed here unless we want to copy the sensor temperature across. For now we don't store the temperature locally.
+ switch (tuningState)
+ {
+ case TuningState::notTuning:
+ break;
+
+ case TuningState::stabilising:
+ //TODO wait for temp to stabilise
+ {
+ String<StringLength100> reply;
+ if (SendTuningCommand(reply.GetRef(), true) != GCodeResult::ok)
+ {
+ reprap.GetPlatform().MessageF(ErrorMessage, "Heater tuning cancelled: %s\n", reply.c_str());
+ SwitchOff();
+ tuningState = TuningState::notTuning;
+ }
+ }
+ break;
+
+ case TuningState::heatingUp:
+ //TODO
+ break;
+
+ case TuningState::cyclingFanOff:
+ //TODO
+ break;
+
+ case TuningState::cyclingFanOn:
+ //TODO
+ break;
+ }
}
void RemoteHeater::ResetHeater() noexcept
{
- //TODO
+ // This is only called by UpdateModel. Nothing needed here.
}
GCodeResult RemoteHeater::ConfigurePortAndSensor(const char *portName, PwmFrequency freq, unsigned int sn, const StringRef& reply)
@@ -128,10 +157,43 @@ float RemoteHeater::GetAccumulator() const noexcept
return 0.0; // not supported
}
-GCodeResult RemoteHeater::StartAutoTune(GCodeBuffer& gb, const StringRef& reply, FansBitmap fans) THROWS(GCodeException)
+GCodeResult RemoteHeater::StartAutoTune(const StringRef& reply, FansBitmap fans, float targetTemp, float pwm, bool seenA, float ambientTemp) noexcept
{
- reply.copy("remote heater auto tune not implemented");
- return GCodeResult::error;
+ CanMessageBuffer * const buf = CanMessageBuffer::Allocate();
+ if (buf == nullptr)
+ {
+ reply.copy("No CAN buffer");
+ return GCodeResult::error;
+ }
+
+ tuningFans = fans;
+ reprap.GetFansManager().SetFansValue(tuningFans, 0.0);
+
+ tuningPwm = pwm;
+ tuningTargetTemp = targetTemp;
+ tuningStartTemp.Clear();
+ tuningBeginTime = millis();
+ tuningPhase = 0;
+ tuned = false; // assume failure
+
+ if (seenA)
+ {
+ tuningStartTemp.Add(ambientTemp);
+ ClearCounters();
+ timeSetHeating = millis();
+ GCodeResult rslt = SendTuningCommand(reply, true);
+ if (rslt != GCodeResult::ok)
+ {
+ return rslt;
+ }
+ tuningState = TuningState::heatingUp;
+ }
+ else
+ {
+ tuningState = TuningState::stabilising;
+ }
+
+ return GCodeResult::ok;
}
void RemoteHeater::GetAutoTuneStatus(const StringRef& reply) const noexcept
@@ -249,6 +311,26 @@ void RemoteHeater::UpdateRemoteStatus(CanAddress src, const CanHeaterReport& rep
}
}
+GCodeResult RemoteHeater::SendTuningCommand(const StringRef& reply, bool on) noexcept
+{
+ CanMessageBuffer * const buf = CanMessageBuffer::Allocate();
+ if (buf == nullptr)
+ {
+ reply.copy("No CAN buffer");
+ return GCodeResult::error;
+ }
+
+ const CanRequestId rid = CanInterface::AllocateRequestId(boardAddress);
+ auto msg = buf->SetupRequestMessage<CanMessageHeaterTuningCommand>(rid, CanInterface::GetCanAddress(), boardAddress);
+ msg->heaterNumber = GetHeaterNumber();
+ msg->on = on;
+ msg->highTemp = tuningTargetTemp;
+ msg->lowTemp = tuningTargetTemp - TuningHysteresis;
+ msg->pwm = tuningPwm;
+ msg->peakTempDrop = TuningPeakTempDrop;
+ return CanInterface::SendRequestAndGetStandardReply(buf, rid, reply);
+}
+
#endif
// End
diff --git a/src/Heating/RemoteHeater.h b/src/Heating/RemoteHeater.h
index 907908e7..d39558d6 100644
--- a/src/Heating/RemoteHeater.h
+++ b/src/Heating/RemoteHeater.h
@@ -22,34 +22,47 @@ public:
GCodeResult SetPwmFrequency(PwmFrequency freq, const StringRef& reply) override;
GCodeResult ReportDetails(const StringRef& reply) const noexcept override;
- void Spin() noexcept override; // Called in a tight loop to keep things running
- void SwitchOff() noexcept override; // Not even standby - all heater power off
- GCodeResult ResetFault(const StringRef& reply) noexcept override; // Reset a fault condition - only call this if you know what you are doing
- float GetTemperature() const noexcept override; // Get the current temperature
- float GetAveragePWM() const noexcept override; // Return the running average PWM to the heater. Answer is a fraction in [0, 1].
- float GetAccumulator() const noexcept override; // Return the integral accumulator
- GCodeResult StartAutoTune(GCodeBuffer& gb, const StringRef& reply, FansBitmap fans) THROWS(GCodeException) override; // Start an auto tune cycle for this heater
+ void Spin() noexcept override; // Called in a tight loop to keep things running
+ void SwitchOff() noexcept override; // Not even standby - all heater power off
+ GCodeResult ResetFault(const StringRef& reply) noexcept override; // Reset a fault condition - only call this if you know what you are doing
+ float GetTemperature() const noexcept override; // Get the latest temperature
+ float GetAveragePWM() const noexcept override; // Return the running average PWM to the heater. Answer is a fraction in [0, 1].
+ float GetAccumulator() const noexcept override; // Return the integral accumulator
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 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:
void ResetHeater() noexcept override;
HeaterMode GetMode() const noexcept override;
- GCodeResult SwitchOn(const StringRef& reply) noexcept override; // Turn the heater on and set the mode
- GCodeResult UpdateModel(const StringRef& reply) noexcept override; // Called when the heater model has been changed
+ GCodeResult SwitchOn(const StringRef& reply) noexcept override; // Turn the heater on and set the mode
+ 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
private:
+ enum class TuningState : uint8_t
+ {
+ notTuning = 0,
+ stabilising,
+ heatingUp,
+ cyclingFanOff,
+ cyclingFanOn
+ };
+
+ GCodeResult SendTuningCommand(const StringRef& reply, bool on) noexcept;
+
static constexpr uint32_t RemoteStatusTimeout = 2000;
CanAddress boardAddress;
HeaterMode lastMode;
uint8_t averagePwm;
+ TuningState tuningState;
float lastTemperature;
uint32_t whenLastStatusReceived;
+ uint32_t timeSetHeating; // When we turned on the heater at the start of auto tuning
};
#endif