Skip to content

Commit

Permalink
More changes to heater feedforward, version 3.6.0-beta.2
Browse files Browse the repository at this point in the history
  • Loading branch information
dc42 committed Nov 12, 2024
1 parent 52f05eb commit 6559c8d
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 58 deletions.
82 changes: 41 additions & 41 deletions src/Heating/LocalHeater.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -287,64 +287,64 @@ void LocalHeater::Spin() noexcept
{
// Get the target temperature and the error
const float targetTemperature = min<float>(GetTargetTemperature() + extrusionTemperatureBoost, GetHighestTemperatureLimit());
const float error = targetTemperature - temperature;

if (extrusionTemperatureBoost != 0.0 || lastExtrusionTemperatureBoost != extrusionTemperatureBoost)
if (IsPidMode(mode) && extrusionTemperatureBoost != lastExtrusionTemperatureBoost)
{
// Calculate new heater mode to prevent heater fault due to exceededAllowedExcursion
String<1> dummy;
(void)SwitchOn(dummy.GetRef());
mode = (temperature + TemperatureCloseEnough < targetTemperature) ? HeaterMode::heating
: (temperature > targetTemperature + TemperatureCloseEnough) ? HeaterMode::cooling
: HeaterMode::stable;
lastExtrusionTemperatureBoost = extrusionTemperatureBoost;
}
lastExtrusionTemperatureBoost = extrusionTemperatureBoost;

const float error = targetTemperature - temperature;

// Do the heating checks
switch(mode)
switch (mode)
{
case HeaterMode::heating:
if (error <= TemperatureCloseEnough)
{
if (error <= TemperatureCloseEnough)
mode = HeaterMode::stable;
heatingFaultCount = 0;
}
else
{
const uint32_t now = millis();
if ((float)(now - timeSetHeating) < GetModel().GetDeadTime() * SecondsToMillis * 2) // wait for twice the dead time before we start looking at the temperature rise
{
mode = HeaterMode::stable;
heatingFaultCount = 0;
// Record the temperature for when we are past the dead time
lastTemperatureValue = temperature;
lastTemperatureMillis = now;
}
else
else if (gotDerivative) // this is a check in case we just had a temperature spike
{
const uint32_t now = millis();
if ((float)(now - timeSetHeating) < GetModel().GetDeadTime() * SecondsToMillis * 2) // wait for twice the dead time before we start looking at the temperature rise
{
// Record the temperature for when we are past the dead time
lastTemperatureValue = temperature;
lastTemperatureMillis = now;
}
else if (gotDerivative) // this is a check in case we just had a temperature spike
const float expectedRate = GetExpectedHeatingRate();
const float minSamplingInterval = 3.0/expectedRate; // only check the temperature when we expect at least 3C rise since last time
const float actualInterval = (float)(now - lastTemperatureMillis) * MillisToSeconds;
if (actualInterval >= minSamplingInterval)
{
const float expectedRate = GetExpectedHeatingRate();
const float minSamplingInterval = 3.0/expectedRate; // only check the temperature when we expect at least 3C rise since last time
const float actualInterval = (float)(now - lastTemperatureMillis) * MillisToSeconds;
if (actualInterval >= minSamplingInterval)
// Check that we are heating fast enough, and if so, take another sample
const float expectedTemperatureRise = expectedRate * actualInterval;
const float actualTemperatureRise = temperature - lastTemperatureValue;
// Bed heaters sometimes have much slower long term heating rates than their short term heating rates, so allow them a lower measured heating rate
if (actualTemperatureRise < expectedTemperatureRise * ((IsBedOrChamber()) ? MinBedTemperatureRiseFactor : MinToolTemperatureRiseFactor))
{
// Check that we are heating fast enough, and if so, take another sample
const float expectedTemperatureRise = expectedRate * actualInterval;
const float actualTemperatureRise = temperature - lastTemperatureValue;
// Bed heaters sometimes have much slower long term heating rates than their short term heating rates, so allow them a lower measured heating rate
if (actualTemperatureRise < expectedTemperatureRise * ((IsBedOrChamber()) ? MinBedTemperatureRiseFactor : MinToolTemperatureRiseFactor))
++heatingFaultCount;
if (heatingFaultCount * HeatSampleIntervalMillis > GetMaxHeatingFaultTime() * SecondsToMillis)
{
++heatingFaultCount;
if (heatingFaultCount * HeatSampleIntervalMillis > GetMaxHeatingFaultTime() * SecondsToMillis)
{
RaiseHeaterFault(HeaterFaultType::temperatureRisingTooSlowly,
"expected %.2f" DEGREE_SYMBOL "C/sec measured %.2f" DEGREE_SYMBOL "C/sec",
(double)expectedRate, (double)(actualTemperatureRise/actualInterval));
}
RaiseHeaterFault(HeaterFaultType::temperatureRisingTooSlowly,
"expected %.2f" DEGREE_SYMBOL "C/sec measured %.2f" DEGREE_SYMBOL "C/sec",
(double)expectedRate, (double)(actualTemperatureRise/actualInterval));
}
else
}
else
{
lastTemperatureValue = temperature;
lastTemperatureMillis = now;
if (heatingFaultCount != 0)
{
lastTemperatureValue = temperature;
lastTemperatureMillis = now;
if (heatingFaultCount != 0)
{
--heatingFaultCount;
}
--heatingFaultCount;
}
}
}
Expand Down
44 changes: 28 additions & 16 deletions src/Movement/DDARing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ void DDARing::Init1(unsigned int numDdas) noexcept

getPointer = addPointer;
lastFeedForwardTool = nullptr;
lastAverageExtrusionSpeed = 0.0;
}

// This must be called from Move::Init, not from the Move constructor, because it indirectly refers to the GCodes module which must therefore be initialised first
Expand Down Expand Up @@ -731,6 +732,8 @@ uint32_t DDARing::ManageIOBitsAndFeedForward() noexcept
SetBasePriority(NvicPriorityStep);
DDA *cdda = getPointer;
const uint32_t now = StepTimer::GetMovementTimerTicks();
const Tool *_ecv_null feedForwardTool;
float feedForwardAverageExtrusionSpeed = 0.0;

while (cdda->IsCommitted())
{
Expand All @@ -752,22 +755,25 @@ uint32_t DDARing::ManageIOBitsAndFeedForward() noexcept
}
}

const Tool *_ecv_null t;
if (!doneFeedForward && (t = cdda->GetTool()) != nullptr && timeToMoveStart < (int32_t)t->GetFeedForwardAdvanceClocks() && timeToMoveEnd > (int32_t)t->GetFeedForwardAdvanceClocks())
if (!doneFeedForward)
{
// This move is current from the perspective of feedforward
if (!cdda->HaveDoneFeedForward())
feedForwardTool = cdda->GetTool();
if (feedForwardTool != nullptr && timeToMoveStart < (int32_t)feedForwardTool->GetFeedForwardAdvanceClocks() && timeToMoveEnd > (int32_t)feedForwardTool->GetFeedForwardAdvanceClocks())
{
// Don't set feedforward here because we have set a very high base priority and we may need to send CAN messages. Just record that we need to set it.
setFeedForward = true;
lastFeedForwardTool = t;
cdda->SetDoneFeedForward();
}
nextWakeupDelay = min<uint32_t>(nextWakeupDelay, (uint32_t)timeToMoveEnd > t->GetFeedForwardAdvanceClocks());
doneFeedForward = true;
if (doneIoBits)
{
break;
// This move is current from the perspective of feedforward
if (!cdda->HaveDoneFeedForward())
{
// Don't set feedforward here because we have set a very high base priority and we may need to send CAN messages. Just record that we need to set it.
cdda->SetDoneFeedForward();
feedForwardAverageExtrusionSpeed = cdda->GetAverageExtrusionSpeed();
setFeedForward = true;
}
nextWakeupDelay = min<uint32_t>(nextWakeupDelay, (uint32_t)timeToMoveEnd > feedForwardTool->GetFeedForwardAdvanceClocks());
doneFeedForward = true;
if (doneIoBits)
{
break;
}
}
}
cdda = cdda->GetNext();
Expand All @@ -782,12 +788,18 @@ uint32_t DDARing::ManageIOBitsAndFeedForward() noexcept

if (setFeedForward)
{
lastFeedForwardTool->ApplyExtrusionFeedForward(cdda->GetAverageExtrusionSpeed());
if (feedForwardTool != lastFeedForwardTool || fabsf(feedForwardAverageExtrusionSpeed - lastAverageExtrusionSpeed) > lastAverageExtrusionSpeed * 0.05)
{
feedForwardTool->ApplyExtrusionFeedForward(feedForwardAverageExtrusionSpeed);
lastFeedForwardTool = feedForwardTool;
lastAverageExtrusionSpeed = feedForwardAverageExtrusionSpeed;
}
}
else if (!doneFeedForward && lastFeedForwardTool != nullptr)
else if (!doneFeedForward && lastFeedForwardTool != nullptr && lastAverageExtrusionSpeed != 0.0)
{
lastFeedForwardTool->StopExtrusionFeedForward(); // no move with a tool active so cancel the last feedforward we commanded
lastFeedForwardTool = nullptr;
lastAverageExtrusionSpeed = 0.0;
}

return (nextWakeupDelay + StepClockRate/1000 - 1)/(StepClockRate/1000); // convert step clocks to milliseconds, rounding up
Expand Down
1 change: 1 addition & 0 deletions src/Movement/DDARing.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ class DDARing INHERIT_OBJECT_MODEL
uint32_t gracePeriod; // The minimum idle time in milliseconds, before we should start a move. Better to have a few moves in the queue so that we can do lookahead

const Tool *_ecv_null lastFeedForwardTool; // the tool we last applied heater feedforward to
float lastAverageExtrusionSpeed; // the extrusion speed we last set heater feedforward for

uint32_t scheduledMoves; // Number of moves scheduled in this ring
uint32_t completedMoves; // Number of moves completed in this ring
Expand Down
2 changes: 1 addition & 1 deletion src/Version.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

#ifndef VERSION
// Note: the complete VERSION string must be in standard version number format and must not contain spaces! This is so that DWC can parse it.
# define MAIN_VERSION "3.6.0-beta.1+3"
# define MAIN_VERSION "3.6.0-beta.2"
# ifdef USE_CAN0
# define VERSION_SUFFIX "(CAN0)"
# else
Expand Down

0 comments on commit 6559c8d

Please sign in to comment.