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
path: root/src
diff options
context:
space:
mode:
authorDavid Crocker <dcrocker@eschertech.com>2016-11-12 21:40:20 +0300
committerDavid Crocker <dcrocker@eschertech.com>2016-11-12 21:40:28 +0300
commit35a9a1a7074858f7784c362bc291809a88ea5f4a (patch)
tree162fbbb796a6820d76e4c64aad508b49d9295337 /src
parent500a5df6f117802473b61259725f9e3c413e7d9a (diff)
Version 1.17-dev1
Support R and S parameters in M109 and M190 as Marlin does Added support for M191 Added support for Steinhart-Hart C parameter Thermistor disconnected threshold now depends on thermistor parameters
Diffstat (limited to 'src')
-rw-r--r--src/Configuration.h7
-rw-r--r--src/Duet/Pins_Duet.h8
-rw-r--r--src/DuetNG/Pins_DuetNG.h6
-rw-r--r--src/GCodes/GCodes.cpp176
-rw-r--r--src/GCodes/GCodes.h2
-rw-r--r--src/Heating/Heat.cpp15
-rw-r--r--src/Heating/Heat.h2
-rw-r--r--src/Heating/Thermistor.cpp72
-rw-r--r--src/Heating/Thermistor.h56
-rw-r--r--src/Platform.cpp159
-rw-r--r--src/Platform.h63
-rw-r--r--src/PrintMonitor.cpp2
-rw-r--r--src/Reprap.cpp19
13 files changed, 332 insertions, 255 deletions
diff --git a/src/Configuration.h b/src/Configuration.h
index 42e01f49..4392bdd9 100644
--- a/src/Configuration.h
+++ b/src/Configuration.h
@@ -26,11 +26,11 @@ Licence: GPL
// Firmware name is now defined in the Pins file
#ifndef VERSION
-# define VERSION "1.16"
+# define VERSION "1.17dev1"
#endif
#ifndef DATE
-# define DATE "2016-11-08"
+# define DATE "2016-11-12"
#endif
#define AUTHORS "reprappro, dc42, zpl, t3p3, dnewman"
@@ -103,6 +103,7 @@ const float AllowedTemperatureDerivativeNoise = 0.25; // How much fluctuation in
const float MaxAmbientTemperature = 45.0; // We expect heaters to cool to this temperature or lower when switched off
const float NormalAmbientTemperature = 25.0; // The ambient temperature we assume - allow for the printer heating its surroundings a little
const float DefaultMaxTempExcursion = 10.0; // How much error we tolerate when maintaining temperature before deciding that a heater fault has occurred
+const float MinimumConnectedTemperature = -5.0; // Temperatures below this we treat as a disconnected thermistor
static_assert(DefaultMaxTempExcursion > TEMPERATURE_CLOSE_ENOUGH, "DefaultMaxTempExcursion is too low");
@@ -200,7 +201,7 @@ const float FILAMENT_WIDTH = 1.75; // Millimetres
#define EOF_STRING "<!-- **EoF** -->"
-// Firmware update files are now defined in the Pins file
+// Firmware update file names are now defined in the Pins file
// List defaults
diff --git a/src/Duet/Pins_Duet.h b/src/Duet/Pins_Duet.h
index 6e2a2d91..c097a01a 100644
--- a/src/Duet/Pins_Duet.h
+++ b/src/Duet/Pins_Duet.h
@@ -38,10 +38,8 @@ const size_t NUM_SERIAL_CHANNELS = 3; // The number of serial IO channels (USB
// DRIVES
const Pin ENABLE_PINS[DRIVES] = { 29, 27, X1, X0, 37, X8, 50, 47, X13 };
-const bool ENABLE_VALUES[DRIVES] = { false, false, false, false, false, false, false, false, false }; // What to send to enable a drive
const Pin STEP_PINS[DRIVES] = { 14, 25, 5, X2, 41, 39, X4, 49, X10 };
const Pin DIRECTION_PINS[DRIVES] = { 15, 26, 4, X3, 35, 53, 51, 48, X11 };
-const bool DIRECTIONS[DRIVES] = { BACKWARDS, FORWARDS, FORWARDS, FORWARDS, FORWARDS, FORWARDS, FORWARDS, FORWARDS, FORWARDS }; // What each axis needs to make it go forwards - defaults
// Endstops
// RepRapFirmware only has a single endstop per axis.
@@ -67,11 +65,13 @@ const Pin HEAT_ON_PINS[HEATERS] = { 6, X5, X7, 7, 8, 9, X17 }; // Heater Chann
// Hot end thermistor: http://www.digikey.co.uk/product-search/en?x=20&y=11&KeyWords=480-3137-ND
const float BED_R25 = 10000.0;
const float BED_BETA = 3988.0;
+const float BED_SHC = 0.0;
const float EXT_R25 = 100000.0;
-const float EXT_BETA = 4138.0;
+const float EXT_BETA = 4388.0;
+const float EXT_SHC = 0.0;
// Thermistor series resistor value in Ohms
-const float THERMISTOR_SERIES_RS = 1000.0;
+const float THERMISTOR_SERIES_RS = 4700.0;
// Number of SPI temperature sensors to support
diff --git a/src/DuetNG/Pins_DuetNG.h b/src/DuetNG/Pins_DuetNG.h
index 841aeb47..d5da9a10 100644
--- a/src/DuetNG/Pins_DuetNG.h
+++ b/src/DuetNG/Pins_DuetNG.h
@@ -43,10 +43,8 @@ const Pin ExpansionStart = 200; // Pin numbers at/above this are on the I/O
const Pin GlobalTmcEnablePin = 38; // The pin that drives ENN of all TMC2660 drivers on production boards (on pre-production boards they are grounded)
const Pin ENABLE_PINS[DRIVES] = { 78, 41, 42, 49, 57, 87, 88, 89, 90, 31 };
-const bool ENABLE_VALUES[DRIVES] = { false, false, false, false, false, false, false, false, false, false }; // What to send to enable a drive
const Pin STEP_PINS[DRIVES] = { 70, 71, 72, 69, 68, 66, 65, 64, 67, 91 };
const Pin DIRECTION_PINS[DRIVES] = { 75, 76, 77, 01, 73, 92, 86, 80, 81, 32 };
-const bool DIRECTIONS[DRIVES] = { FORWARDS, FORWARDS, FORWARDS, FORWARDS, FORWARDS, FORWARDS, FORWARDS, FORWARDS, FORWARDS, FORWARDS }; // What each axis needs to make it go forwards - defaults
const Pin DueX_SG = 96; // DueX stallguard detect pin = PE0 (was E2_STOP)
const Pin DueX_INT = 17; // DueX interrupt pin = PA17 (was E6_STOP)
@@ -63,12 +61,12 @@ const Pin TEMP_SENSE_PINS[HEATERS] = { 45, 47, 44, 61, 62, 63, 59, 18 }; // Ther
const Pin HEAT_ON_PINS[HEATERS] = { 19, 20, 16, 35, 37, 40, 43, 15 }; // Heater pin numbers (heater 7 pin TBC)
// Default thermistor parameters
-// Bed thermistor: now assuming 100K
-// Hot end thermistor: http://www.digikey.co.uk/product-search/en?x=20&y=11&KeyWords=480-3137-ND
const float BED_R25 = 100000.0;
const float BED_BETA = 3988.0;
+const float BED_SHC = 0.0;
const float EXT_R25 = 100000.0;
const float EXT_BETA = 4388.0;
+const float EXT_SHC = 0.0;
// Thermistor series resistor value in Ohms
const float THERMISTOR_SERIES_RS = 4700.0;
diff --git a/src/GCodes/GCodes.cpp b/src/GCodes/GCodes.cpp
index 771daa2d..65e67dd8 100644
--- a/src/GCodes/GCodes.cpp
+++ b/src/GCodes/GCodes.cpp
@@ -2479,24 +2479,34 @@ void GCodes::SetHeaterParameters(GCodeBuffer *gb, StringRef& reply)
int heater = gb->GetIValue();
if (heater >= 0 && heater < HEATERS)
{
- PidParameters pp = platform->GetPidParameters(heater);
+ Thermistor& th = platform->GetThermistor(heater);
bool seen = false;
// We must set the 25C resistance and beta together in order to calculate Rinf. Check for these first.
- float r25 = pp.GetThermistorR25();
- float beta = pp.GetBeta();
+ float r25 = th.GetR25();
+ float beta = th.GetBeta();
+ float shC = th.GetShc();
+ float seriesR = th.GetSeriesR();
+
gb->TryGetFValue('T', r25, seen);
gb->TryGetFValue('B', beta, seen);
-
- if (seen) // if seen R25 or Beta or both
+ gb->TryGetFValue('C', shC, seen);
+ gb->TryGetFValue('R', seriesR, seen);
+ if (seen)
{
- pp.SetThermistorR25AndBeta(r25, beta); // recalculate Rinf
+ th.SetParameters(r25, beta, shC, seriesR);
}
- // Now do the other parameters
- gb->TryGetFValue('R', pp.thermistorSeriesR, seen);
- gb->TryGetFValue('L', pp.adcLowOffset, seen);
- gb->TryGetFValue('H', pp.adcHighOffset, seen);
+ if (gb->Seen('L'))
+ {
+ th.SetLowOffset((int8_t)constrain<int>(gb->GetIValue(), -100, 100));
+ seen = true;
+ }
+ if (gb->Seen('H'))
+ {
+ th.SetHighOffset((int8_t)constrain<int>(gb->GetIValue(), -100, 100));
+ seen = true;
+ }
if (gb->Seen('X'))
{
@@ -2515,14 +2525,11 @@ void GCodes::SetHeaterParameters(GCodeBuffer *gb, StringRef& reply)
seen = true;
}
- if (seen)
- {
- platform->SetPidParameters(heater, pp);
- }
- else
+ if (!seen)
{
- reply.printf("T:%.1f B:%.1f R:%.1f L:%.1f H:%.1f X:%d", r25, beta, pp.thermistorSeriesR,
- pp.adcLowOffset, pp.adcHighOffset, platform->GetThermistorNumber(heater));
+ reply.printf("T:%.1f B:%.1f C:%.2e R:%.1f L:%d H:%d X:%d",
+ th.GetR25(), th.GetBeta(), th.GetShc(), th.GetSeriesR(),
+ th.GetLowOffset(), th.GetHighOffset(), platform->GetThermistorNumber(heater));
}
}
else
@@ -3573,13 +3580,29 @@ bool GCodes::HandleMcode(GCodeBuffer* gb, StringRef& reply)
platform->SetFanValue(0, 0.0); //T3P3 as deprecated only applies to fan0
break;
- case 109: // Deprecated
+ case 109: // Deprecated in RRF, but widely generated by slicers
if (!AllMovesAreFinishedAndMoveBufferIsLoaded())
+ {
return false;
-
- if (gb->Seen('S'))
+ }
{
- float temperature = gb->GetFValue();
+ float temperature;
+ bool waitWhenCooling;
+ if (gb->Seen('R'))
+ {
+ waitWhenCooling = true;
+ temperature = gb->GetFValue();
+ }
+ else if (gb->Seen('S'))
+ {
+ waitWhenCooling = false;
+ temperature = gb->GetFValue();
+ }
+ else
+ {
+ break; // no target temperature given
+ }
+
Tool *tool;
if (gb->Seen('T'))
{
@@ -3597,7 +3620,7 @@ bool GCodes::HandleMcode(GCodeBuffer* gb, StringRef& reply)
}
}
SetToolHeaters(tool, temperature);
- result = ToolHeatersAtSetTemperatures(tool);
+ result = ToolHeatersAtSetTemperatures(tool, waitWhenCooling);
}
break;
@@ -3663,7 +3686,7 @@ bool GCodes::HandleMcode(GCodeBuffer* gb, StringRef& reply)
// Wait for the heaters associated with the specified tool to be ready
int toolNumber = gb->GetIValue();
toolNumber += gb->GetToolNumberAdjust();
- if (!ToolHeatersAtSetTemperatures(reprap.GetTool(toolNumber)))
+ if (!ToolHeatersAtSetTemperatures(reprap.GetTool(toolNumber), true))
{
return false;
}
@@ -3678,7 +3701,7 @@ bool GCodes::HandleMcode(GCodeBuffer* gb, StringRef& reply)
gb->GetLongArray(heaters, heaterCount);
for(size_t i=0; i<heaterCount; i++)
{
- if (!reprap.GetHeat()->HeaterAtSetTemperature(heaters[i]))
+ if (!reprap.GetHeat()->HeaterAtSetTemperature(heaters[i], true))
{
return false;
}
@@ -3692,7 +3715,7 @@ bool GCodes::HandleMcode(GCodeBuffer* gb, StringRef& reply)
const int8_t chamberHeater = reprap.GetHeat()->GetChamberHeater();
if (chamberHeater != -1)
{
- if (!reprap.GetHeat()->HeaterAtSetTemperature(chamberHeater))
+ if (!reprap.GetHeat()->HeaterAtSetTemperature(chamberHeater, true))
{
return false;
}
@@ -3925,71 +3948,88 @@ bool GCodes::HandleMcode(GCodeBuffer* gb, StringRef& reply)
break;
case 190: // Set bed temperature and wait
+ case 191: // Set chamber temperature and wait
if (!AllMovesAreFinishedAndMoveBufferIsLoaded()) // tell Move not to wait for more moves
{
return false;
}
- if (gb->Seen('S'))
{
- const int8_t bedHeater = reprap.GetHeat()->GetBedHeater();
- if (bedHeater >= 0)
+ const int8_t heater = (code == 191) ? reprap.GetHeat()->GetChamberHeater() : reprap.GetHeat()->GetBedHeater();
+ if (heater >= 0)
{
- reprap.GetHeat()->SetActiveTemperature(bedHeater, gb->GetFValue());
- reprap.GetHeat()->Activate(bedHeater);
- result = reprap.GetHeat()->HeaterAtSetTemperature(bedHeater);
+ float temperature;
+ bool waitWhenCooling;
+ if (gb->Seen('R'))
+ {
+ waitWhenCooling = true;
+ temperature = gb->GetFValue();
+ }
+ else if (gb->Seen('S'))
+ {
+ waitWhenCooling = false;
+ temperature = gb->GetFValue();
+ }
+ else
+ {
+ break; // no target temperature given
+ }
+
+ reprap.GetHeat()->SetActiveTemperature(heater, temperature);
+ reprap.GetHeat()->Activate(heater);
+ result = reprap.GetHeat()->HeaterAtSetTemperature(heater, waitWhenCooling);
}
}
break;
case 201: // Set/print axis accelerations
- {
- bool seen = false;
- for (size_t axis = 0; axis < numAxes; axis++)
{
- if (gb->Seen(axisLetters[axis]))
+ bool seen = false;
+ for (size_t axis = 0; axis < numAxes; axis++)
{
- platform->SetAcceleration(axis, gb->GetFValue() * distanceScale);
- seen = true;
+ if (gb->Seen(axisLetters[axis]))
+ {
+ platform->SetAcceleration(axis, gb->GetFValue() * distanceScale);
+ seen = true;
+ }
}
- }
- if (gb->Seen(extrudeLetter))
- {
- seen = true;
- float eVals[MaxExtruders];
- size_t eCount = numExtruders;
- gb->GetFloatArray(eVals, eCount, true);
- for (size_t e = 0; e < eCount; e++)
+ if (gb->Seen(extrudeLetter))
{
- platform->SetAcceleration(numAxes + e, eVals[e] * distanceScale);
+ seen = true;
+ float eVals[MaxExtruders];
+ size_t eCount = numExtruders;
+ gb->GetFloatArray(eVals, eCount, true);
+ for (size_t e = 0; e < eCount; e++)
+ {
+ platform->SetAcceleration(numAxes + e, eVals[e] * distanceScale);
+ }
}
- }
- if (gb->Seen('P'))
- {
- // Set max average printing acceleration
- platform->SetMaxAverageAcceleration(gb->GetFValue() * distanceScale);
- seen = true;
- }
-
- if (!seen)
- {
- reply.printf("Accelerations: ");
- for (size_t axis = 0; axis < numAxes; ++axis)
+ if (gb->Seen('P'))
{
- reply.catf("%c: %.1f, ", axisLetters[axis], platform->Acceleration(axis) / distanceScale);
+ // Set max average printing acceleration
+ platform->SetMaxAverageAcceleration(gb->GetFValue() * distanceScale);
+ seen = true;
}
- reply.cat("E:");
- char sep = ' ';
- for (size_t extruder = 0; extruder < numExtruders; extruder++)
+
+ if (!seen)
{
- reply.catf("%c%.1f", sep, platform->Acceleration(extruder + numAxes) / distanceScale);
- sep = ':';
+ reply.printf("Accelerations: ");
+ for (size_t axis = 0; axis < numAxes; ++axis)
+ {
+ reply.catf("%c: %.1f, ", axisLetters[axis], platform->Acceleration(axis) / distanceScale);
+ }
+ reply.cat("E:");
+ char sep = ' ';
+ for (size_t extruder = 0; extruder < numExtruders; extruder++)
+ {
+ reply.catf("%c%.1f", sep, platform->Acceleration(extruder + numAxes) / distanceScale);
+ sep = ':';
+ }
+ reply.catf(", avg. printing: %.1f", platform->GetMaxAverageAcceleration());
}
- reply.catf(", avg. printing: %.1f", platform->GetMaxAverageAcceleration());
}
- }
break;
case 203: // Set/print maximum feedrates
@@ -5948,13 +5988,13 @@ void GCodes::CancelPrint()
}
// Return true if all the heaters for the specified tool are at their set temperatures
-bool GCodes::ToolHeatersAtSetTemperatures(const Tool *tool) const
+bool GCodes::ToolHeatersAtSetTemperatures(const Tool *tool, bool waitWhenCooling) const
{
if (tool != NULL)
{
for (size_t i = 0; i < tool->HeaterCount(); ++i)
{
- if (!reprap.GetHeat()->HeaterAtSetTemperature(tool->Heater(i)))
+ if (!reprap.GetHeat()->HeaterAtSetTemperature(tool->Heater(i), waitWhenCooling))
{
return false;
}
diff --git a/src/GCodes/GCodes.h b/src/GCodes/GCodes.h
index 18dd79a0..4397384e 100644
--- a/src/GCodes/GCodes.h
+++ b/src/GCodes/GCodes.h
@@ -212,7 +212,7 @@ private:
void SetHeaterParameters(GCodeBuffer *gb, StringRef& reply); // Set the thermistor and ADC parameters for a heater
void ManageTool(GCodeBuffer *gb, StringRef& reply); // Create a new tool definition
void SetToolHeaters(Tool *tool, float temperature); // Set all a tool's heaters to the temperature. For M104...
- bool ToolHeatersAtSetTemperatures(const Tool *tool) const; // Wait for the heaters associated with the specified tool to reach their set temperatures
+ bool ToolHeatersAtSetTemperatures(const Tool *tool, bool waitWhenCooling) const; // Wait for the heaters associated with the specified tool to reach their set temperatures
void SetAllAxesNotHomed(); // Flag all axes as not homed
void SetPositions(float positionNow[DRIVES]); // Set the current position to be this
const char *TranslateEndStopResult(EndStopHit es); // Translate end stop result to text
diff --git a/src/Heating/Heat.cpp b/src/Heating/Heat.cpp
index f654ec61..256ad1a2 100644
--- a/src/Heating/Heat.cpp
+++ b/src/Heating/Heat.cpp
@@ -22,7 +22,7 @@ Licence: GPL
#include "Pid.h"
Heat::Heat(Platform* p)
- : platform(p), active(false), coldExtrude(false), bedHeater(BED_HEATER), chamberHeater(-1), heaterBeingTuned(-1), lastHeaterTuned(-1)
+ : platform(p), active(false), coldExtrude(false), bedHeater(DefaultBedHeater), chamberHeater(-1), heaterBeingTuned(-1), lastHeaterTuned(-1)
{
for (size_t heater = 0; heater < HEATERS; heater++)
{
@@ -105,12 +105,9 @@ void Heat::Diagnostics(MessageType mtype)
bool Heat::AllHeatersAtSetTemperatures(bool includingBed) const
{
- size_t firstHeater = (bedHeater == -1) ? E0_HEATER :
- (includingBed) ? min<int8_t>(bedHeater, E0_HEATER) : E0_HEATER;
-
- for(size_t heater = firstHeater; heater < HEATERS; heater++)
+ for(int8_t heater = 0; heater < HEATERS; heater++)
{
- if (!HeaterAtSetTemperature(heater))
+ if (!HeaterAtSetTemperature(heater, true) && (includingBed || heater != bedHeater))
{
return false;
}
@@ -119,7 +116,7 @@ bool Heat::AllHeatersAtSetTemperatures(bool includingBed) const
}
//query an individual heater
-bool Heat::HeaterAtSetTemperature(int8_t heater) const
+bool Heat::HeaterAtSetTemperature(int8_t heater, bool waitWhenCooling) const
{
// If it hasn't anything to do, it must be right wherever it is...
if (heater < 0 || heater >= HEATERS || pids[heater]->SwitchedOff() || pids[heater]->FaultOccurred())
@@ -129,7 +126,9 @@ bool Heat::HeaterAtSetTemperature(int8_t heater) const
const float dt = GetTemperature(heater);
const float target = (pids[heater]->Active()) ? GetActiveTemperature(heater) : GetStandbyTemperature(heater);
- return (target < TEMPERATURE_LOW_SO_DONT_CARE) || (fabsf(dt - target) <= TEMPERATURE_CLOSE_ENOUGH);
+ return (target < TEMPERATURE_LOW_SO_DONT_CARE)
+ || (fabsf(dt - target) <= TEMPERATURE_CLOSE_ENOUGH)
+ || (target < dt && !waitWhenCooling);
}
Heat::HeaterStatus Heat::GetStatus(int8_t heater) const
diff --git a/src/Heating/Heat.h b/src/Heating/Heat.h
index e546ce40..1ec813a7 100644
--- a/src/Heating/Heat.h
+++ b/src/Heating/Heat.h
@@ -66,7 +66,7 @@ public:
void SwitchOffAll(); // Turn all heaters off
void ResetFault(int8_t heater); // Reset a heater fault - only call this if you know what you are doing
bool AllHeatersAtSetTemperatures(bool includingBed) const; // Is everything at temperature within tolerance?
- bool HeaterAtSetTemperature(int8_t heater) const; // Is a specific heater at temperature within tolerance?
+ bool HeaterAtSetTemperature(int8_t heater, bool waitWhenCooling) const; // Is a specific heater at temperature within tolerance?
void Diagnostics(MessageType mtype); // Output useful information
float GetAveragePWM(size_t heater) const // Return the running average PWM to the heater as a fraction in [0, 1].
diff --git a/src/Heating/Thermistor.cpp b/src/Heating/Thermistor.cpp
new file mode 100644
index 00000000..991dc441
--- /dev/null
+++ b/src/Heating/Thermistor.cpp
@@ -0,0 +1,72 @@
+/*
+ * Thermistor.cpp
+ *
+ * Created on: 10 Nov 2016
+ * Author: David
+ */
+
+#include "Thermistor.h"
+#include "Pins.h"
+#include "Configuration.h"
+
+// The Steinhart-Hart equation for thermistor resistance is:
+// 1/T = A + B ln(R) + C [ln(R)]^3
+//
+// The simplified (beta) equation assumes C=0 and is:
+// 1/T = A + (1/Beta) ln(R)
+//
+// The parameters that can be configured in RRF are R25 (the resistance at 25C), Beta, and optionally C.
+
+// Create an instance with default values
+Thermistor::Thermistor() : adcLowOffset(0), adcHighOffset(0)
+{
+ SetParameters(EXT_R25, EXT_BETA, EXT_SHC, THERMISTOR_SERIES_RS);
+}
+
+// Initialise the instance
+void Thermistor::SetParameters(float p_r25, float p_beta, float p_shC, float p_seriesR)
+{
+ r25 = p_r25;
+ beta = p_beta;
+ shC = p_shC;
+ seriesR = p_seriesR;
+ CalcDerivedParameters();
+}
+
+// Calculate temperature from an ADC reading in the range 0..1
+float Thermistor::CalcTemperature(int32_t adcReading) const
+{
+ const float denom = (float)(AdcRange + (int)adcHighOffset - adcReading) - 0.5;
+ if (denom <= 0.0)
+ {
+ return ABS_ZERO;
+ }
+ const float resistance = seriesR * ((float)(adcReading - (int)adcLowOffset) + 0.5)/denom;
+ const float logResistance = log(resistance);
+ const float recipT = shA + shB * logResistance + shC * logResistance * logResistance * logResistance;
+ return (recipT > 0.0) ? (1.0/recipT) + ABS_ZERO : BAD_ERROR_TEMPERATURE;
+}
+
+// Calculate expected ADC reading at a particular temperature, rounded down as the ADC does
+int32_t Thermistor::CalcAdcReading(float temperature) const
+{
+ const double bDFiv3c = shB/(3.0 * shC);
+ const double halfY = (shA - 1.0/(temperature - ABS_ZERO))/(2.0 * shC);
+ const double x = sqrt((bDFiv3c * bDFiv3c * bDFiv3c) + (halfY * halfY));
+ const double oneThird = 1.0/3.0;
+ const float resistance = exp(pow(x - halfY, oneThird) - pow(x + halfY, oneThird));
+ const float fraction = resistance/(resistance + seriesR);
+ const int32_t actualAdcRange = AdcRange + (int)adcHighOffset - (int)adcLowOffset;
+ const int32_t val = (int32_t)(fraction * (float)actualAdcRange) + (int)adcLowOffset;
+ return constrain<int>(val, 0, AdcRange - 1);
+}
+
+// Calculate shA and shB from the other parameters
+void Thermistor::CalcDerivedParameters()
+{
+ shB = 1.0/beta;
+ const double lnR25 = log(r25);
+ shA = 1.0/(25.0 - ABS_ZERO) - shB * lnR25 - shC * lnR25 * lnR25 * lnR25;
+}
+
+// End
diff --git a/src/Heating/Thermistor.h b/src/Heating/Thermistor.h
new file mode 100644
index 00000000..58c504c2
--- /dev/null
+++ b/src/Heating/Thermistor.h
@@ -0,0 +1,56 @@
+/*
+ * Thermistor.h
+ *
+ * Created on: 10 Nov 2016
+ * Author: David
+ */
+
+#ifndef SRC_HEATING_THERMISTOR_H_
+#define SRC_HEATING_THERMISTOR_H_
+
+#include "Core.h"
+
+// The Steinhart-Hart equation for thermistor resistance is:
+// 1/T = A + B ln(R) + C [ln(R)]^3
+//
+// The simplified (beta) equation assumes C=0 and is:
+// 1/T = A + (1/Beta) ln(R)
+//
+// The parameters that can be configured in RRF are R25 (the resistance at 25C), Beta, and optionally C.
+
+class Thermistor
+{
+public:
+ Thermistor(); // create an instance with default values
+ float CalcTemperature(int32_t adcReading) const; // calculate temperature from an ADC reading in the range 0..1
+ int32_t CalcAdcReading(float temperature) const; // calculate expected ADC reading at a particular temperature
+
+ float GetR25() const { return r25; }
+ float GetBeta() const { return beta; }
+ float GetShc() const { return shC; }
+ float GetSeriesR() const { return seriesR; }
+ int8_t GetLowOffset() const { return adcLowOffset; }
+ int8_t GetHighOffset() const { return adcHighOffset; }
+
+ void SetParameters(float p_r25, float p_beta, float p_shC, float p_seriesR); // initialise the main parameters
+ void SetLowOffset(int8_t p_offset) { adcLowOffset = p_offset; }
+ void SetHighOffset(int8_t p_offset) { adcHighOffset = p_offset; }
+
+ // For the theory behind ADC oversampling, see http://www.atmel.com/Images/doc8003.pdf
+ static const unsigned int AdcOversampleBits = 1 ; // we use 1-bit oversampling
+
+private:
+ void CalcDerivedParameters(); // calculate shA and shB
+
+ // The following are configurable parameters
+ float r25, beta, shC, seriesR; // parameters declared in the M305 command
+ int8_t adcLowOffset, adcHighOffset; // ADC low and high end offsets
+
+ // The following are derived from the configurable parameters
+ float shA, shB; // derived parameters
+
+ static const unsigned int AdcBits = 12; // the ADCs in the SAM processors are 12-bit
+ static const int32_t AdcRange = 1 << (AdcBits + AdcOversampleBits); // The readings we pass in should be in range 0..(AdcRange - 1)
+};
+
+#endif /* SRC_HEATING_THERMISTOR_H_ */
diff --git a/src/Platform.cpp b/src/Platform.cpp
index 20409663..b04ac586 100644
--- a/src/Platform.cpp
+++ b/src/Platform.cpp
@@ -120,23 +120,9 @@ bool PidParameters::UsePID() const
return kP >= 0;
}
-float PidParameters::GetThermistorR25() const
-{
- return thermistorInfR * exp(thermistorBeta / (25.0 - ABS_ZERO));
-}
-
-void PidParameters::SetThermistorR25AndBeta(float r25, float beta)
-{
- thermistorInfR = r25 * exp(-beta / (25.0 - ABS_ZERO));
- thermistorBeta = beta;
-}
-
bool PidParameters::operator==(const PidParameters& other) const
{
- return kI == other.kI && kD == other.kD && kP == other.kP && kT == other.kT && kS == other.kS
- && thermistorBeta == other.thermistorBeta && thermistorInfR == other.thermistorInfR
- && thermistorSeriesR == other.thermistorSeriesR && adcLowOffset == other.adcLowOffset
- && adcHighOffset == other.adcHighOffset;
+ return kI == other.kI && kD == other.kD && kP == other.kP && kT == other.kT && kS == other.kS;
}
//*************************************************************************************************
@@ -232,15 +218,14 @@ void Platform::Init()
// DRIVES
- ARRAY_INIT(directions, DIRECTIONS);
- ARRAY_INIT(enableValues, ENABLE_VALUES);
ARRAY_INIT(endStopPins, END_STOP_PINS);
ARRAY_INIT(maxFeedrates, MAX_FEEDRATES);
ARRAY_INIT(accelerations, ACCELERATIONS);
ARRAY_INIT(driveStepsPerUnit, DRIVE_STEPS_PER_UNIT);
ARRAY_INIT(instantDvs, INSTANT_DVS);
-#if !defined(DUET_NG)
+#if !defined(DUET_NG) && !defined(RADDS)
+ // Motor current setting on Duet 0.6 and 0.8.5
ARRAY_INIT(potWipes, POT_WIPES);
senseResistor = SENSE_RESISTOR;
maxStepperDigipotVoltage = MAX_STEPPER_DIGIPOT_VOLTAGE;
@@ -263,21 +248,7 @@ void Platform::Init()
idleCurrentFactor = DEFAULT_IDLE_CURRENT_FACTOR;
- // HEATERS - Bed is assumed to be the first
-
- ARRAY_INIT(tempSensePins, TEMP_SENSE_PINS);
- ARRAY_INIT(heatOnPins, HEAT_ON_PINS);
- ARRAY_INIT(spiTempSenseCsPins, SpiTempSensorCsPins);
-
- configuredHeaters = (BED_HEATER >= 0) ? (1 << BED_HEATER) : 0;
- heatSampleTicks = HEAT_SAMPLE_TIME * SecondsToMillis;
-
- // Enable pullups on all the SPI CS pins. This is required if we are using more than one device on the SPI bus.
- // Otherwise, when we try to initialise the first device, the other devices may respond as well because their CS lines are not high.
- for (size_t i = 0; i < MaxSpiTempSensors; ++i)
- {
- setPullup(SpiTempSensorCsPins[i], true);
- }
+ // SD card interfaces
for (size_t i = 0; i < NumSdCards; ++i)
{
const Pin p = SdCardDetectPins[i];
@@ -296,6 +267,9 @@ void Platform::Init()
for (size_t drive = 0; drive < DRIVES; drive++)
{
+ enableValues[drive] = false; // assume active low enable signal
+ directions[drive] = true; // drive moves forwards by default
+
// Map axes and extruders straight through
if (drive < MAX_AXES)
{
@@ -362,7 +336,20 @@ void Platform::Init()
extrusionAncilliaryPWM = 0.0;
- // HEATERS - Bed is assumed to be index 0
+ ARRAY_INIT(tempSensePins, TEMP_SENSE_PINS);
+ ARRAY_INIT(heatOnPins, HEAT_ON_PINS);
+ ARRAY_INIT(spiTempSenseCsPins, SpiTempSensorCsPins);
+
+ configuredHeaters = (DefaultBedHeater >= 0) ? (1 << DefaultBedHeater) : 0;
+ heatSampleTicks = HEAT_SAMPLE_TIME * SecondsToMillis;
+
+ // Enable pullups on all the SPI CS pins. This is required if we are using more than one device on the SPI bus.
+ // Otherwise, when we try to initialise the first device, the other devices may respond as well because their CS lines are not high.
+ for (size_t i = 0; i < MaxSpiTempSensors; ++i)
+ {
+ setPullup(SpiTempSensorCsPins[i], true);
+ }
+
for (size_t heater = 0; heater < HEATERS; heater++)
{
if (heatOnPins[heater] != NoPin)
@@ -374,11 +361,17 @@ void Platform::Init()
thermistorAdcChannels[heater] = chan;
AnalogInEnableChannel(chan, true);
- SetThermistorNumber(heater, heater); // map the thermistor straight through
+ SetThermistorNumber(heater, heater); // map the thermistor straight through
+ thermistors[heater].SetParameters(
+ (heater == DefaultBedHeater) ? BED_R25 : EXT_R25,
+ (heater == DefaultBedHeater) ? BED_BETA : EXT_BETA,
+ (heater == DefaultBedHeater) ? BED_SHC : EXT_SHC,
+ THERMISTOR_SERIES_RS); // initialise the thermistor parameters
thermistorFilters[heater].Init(0);
}
SetTemperatureLimit(DEFAULT_TEMPERATURE_LIMIT);
+ // Fans
InitFans();
// Hotend configuration
@@ -460,15 +453,6 @@ bool Platform::AnyFileOpen(const FATFS *fs) const
void Platform::SetTemperatureLimit(float t)
{
temperatureLimit = t;
- for (size_t heater = 0; heater < HEATERS; heater++)
- {
- // Calculate and store the ADC average sum that corresponds to an overheat condition, so that we can check it quickly in the tick ISR
- float thermistorOverheatResistance = nvData.pidParams[heater].GetRInf()
- * exp(-nvData.pidParams[heater].GetBeta() / (temperatureLimit - ABS_ZERO));
- float thermistorOverheatAdcValue = (AD_RANGE_REAL + 1) * thermistorOverheatResistance
- / (thermistorOverheatResistance + nvData.pidParams[heater].thermistorSeriesR);
- thermistorOverheatSums[heater] = (uint32_t) (thermistorOverheatAdcValue + 0.9) * THERMISTOR_AVERAGE_READINGS;
- }
}
// Specify which thermistor channel a particular heater uses
@@ -734,14 +718,11 @@ void Platform::ResetNvData()
for (size_t i = 0; i < HEATERS; ++i)
{
PidParameters& pp = nvData.pidParams[i];
- pp.thermistorSeriesR = defaultThermistorSeriesRs[i];
- pp.SetThermistorR25AndBeta(defaultThermistor25RS[i], defaultThermistorBetas[i]);
pp.kI = defaultPidKis[i];
pp.kD = defaultPidKds[i];
pp.kP = defaultPidKps[i];
pp.kT = defaultPidKts[i];
pp.kS = defaultPidKss[i];
- pp.adcLowOffset = pp.adcHighOffset = 0.0;
}
#if FLASH_SAVE_ENABLED
@@ -1579,40 +1560,18 @@ float Platform::GetTemperature(size_t heater, TemperatureError& err)
const volatile ThermistorAveragingFilter& filter = thermistorFilters[heater];
if (filter.IsValid())
{
- int rawTemp = filter.GetSum()/(THERMISTOR_AVERAGE_READINGS >> AD_OVERSAMPLE_BITS);
-
- // If the ADC reading is N then for an ideal ADC, the input voltage is at least N/(AD_RANGE + 1) and less than (N + 1)/(AD_RANGE + 1), times the analog reference.
- // So we add 0.5 to to the reading to get a better estimate of the input.
- float reading = (float) rawTemp + 0.5;
+ const int32_t averagedReading = filter.GetSum()/(ThermistorAverageReadings >> Thermistor::AdcOversampleBits);
+ const float temp = thermistors[heater].CalcTemperature(averagedReading);
- // Recognise the special case of thermistor disconnected.
- // For some ADCs, the high-end offset is negative, meaning that the ADC never returns a high enough value. We need to allow for this here.
- const PidParameters& p = nvData.pidParams[heater];
- if (p.adcHighOffset < 0.0)
- {
- rawTemp -= (int) p.adcHighOffset;
- }
- if (rawTemp >= (int)AD_DISCONNECTED_VIRTUAL)
+ if (temp < MinimumConnectedTemperature)
{
// thermistor is disconnected
err = TemperatureError::openCircuit;
return ABS_ZERO;
}
- // Correct for the low and high ADC offsets
- reading -= p.adcLowOffset;
- reading *= (AD_RANGE_VIRTUAL + 1) / (AD_RANGE_VIRTUAL + 1 + p.adcHighOffset - p.adcLowOffset);
-
- float resistance = reading * p.thermistorSeriesR / ((AD_RANGE_VIRTUAL + 1) - reading);
- if (resistance > p.GetRInf())
- {
- err = TemperatureError::success;
- return ABS_ZERO + p.GetBeta() / log(resistance / p.GetRInf());
- }
-
- // Thermistor short circuit, return a high temperature
- err = TemperatureError::shortCircuit;
- return BAD_ERROR_TEMPERATURE;
+ err = TemperatureError::success;
+ return temp;
}
// Filter is not ready yet
@@ -2196,7 +2155,7 @@ void Platform::InitFans()
{
#ifdef DUET_NG
// Set fan 1 to be thermostatic by default, monitoring all heaters except the default bed heater
- fans[1].SetHeatersMonitored(0xFFFF & ~(1 << BED_HEATER));
+ fans[1].SetHeatersMonitored(0xFFFF & ~(1 << DefaultBedHeater));
fans[1].SetValue(1.0); // set it full on
#else
// Fan 1 on the Duet 0.8.5 shares its control pin with heater 6. Set it full on to make sure the heater (if present) is off.
@@ -2940,41 +2899,25 @@ void Platform::Tick()
{
case 1: // last conversion started was a thermistor
case 3:
+ if (IsThermistorChannel(currentHeater))
{
- if (IsThermistorChannel(currentHeater))
- {
- ThermistorAveragingFilter& currentFilter = const_cast<ThermistorAveragingFilter&>(thermistorFilters[currentHeater]);
- currentFilter.ProcessReading(AnalogInReadChannel(thermistorAdcChannels[heaterTempChannels[currentHeater]]));
- if (currentFilter.IsValid() && (configuredHeaters & (1 << currentHeater)) != 0)
- {
- uint32_t sum = currentFilter.GetSum();
- if (sum < thermistorOverheatSums[currentHeater] || sum >= AD_DISCONNECTED_REAL * THERMISTOR_AVERAGE_READINGS)
- {
- // We have an over-temperature or disconnected reading from this thermistor, so turn off the heater
- SetHeater(currentHeater, 0.0);
- LogError(ErrorCode::BadTemp);
- }
- }
- }
- else
- {
- // Thermocouple case: oversampling is not necessary as the MAX31855 is itself continuously sampling and
- // averaging. As such, the temperature reading is taken directly by Platform::GetTemperature() and
- // periodically called by PID::Spin() where temperature fault handling is taken care of. However, we
- // must guard against overly long delays between successive calls of PID::Spin().
- // Do not call Time() here, it isn't safe. We use millis() instead.
- if ((millis() - reprap.GetHeat()->GetLastSampleTime(currentHeater)) > maxPidSpinDelay)
- {
- SetHeater(currentHeater, 0.0);
- LogError(ErrorCode::BadTemp);
- }
- }
+ // Because we are in the tick ISR and no other ISR reads the averaging filter, we can cast away 'volatile' here
+ ThermistorAveragingFilter& currentFilter = const_cast<ThermistorAveragingFilter&>(thermistorFilters[currentHeater]);
+ currentFilter.ProcessReading(AnalogInReadChannel(thermistorAdcChannels[heaterTempChannels[currentHeater]]));
+ }
- ++currentHeater;
- if (currentHeater == HEATERS)
- {
- currentHeater = 0;
- }
+ // Guard against overly long delays between successive calls of PID::Spin().
+ // Do not call Time() here, it isn't safe. We use millis() instead.
+ if ((configuredHeaters & (1 << currentHeater)) != 0 && (millis() - reprap.GetHeat()->GetLastSampleTime(currentHeater)) > maxPidSpinDelay)
+ {
+ SetHeater(currentHeater, 0.0);
+ LogError(ErrorCode::BadTemp);
+ }
+
+ ++currentHeater;
+ if (currentHeater == HEATERS)
+ {
+ currentHeater = 0;
}
++tickState;
break;
diff --git a/src/Platform.h b/src/Platform.h
index 94ea54bc..7d20dc00 100644
--- a/src/Platform.h
+++ b/src/Platform.h
@@ -47,6 +47,7 @@ Licence: GPL
#include "Core.h"
#include "Heating/TemperatureSensor.h"
+#include "Heating/Thermistor.h"
#include "Heating/TemperatureError.h"
#include "OutputMemory.h"
#include "Libraries/Fatfs/ff.h"
@@ -124,32 +125,10 @@ const uint32_t Z_PROBE_AXES = (1 << X_AXIS) | (1 << Z_AXIS); // Axes for which t
// HEATERS - The bed is assumed to be the at index 0
+// The thermistors used in the R3epRapPro Ormerod are:
// Bed thermistor: http://uk.farnell.com/epcos/b57863s103f040/sensor-miniature-ntc-10k/dp/1299930?Ntt=129-9930
// Hot end thermistor: http://www.digikey.co.uk/product-search/en?x=20&y=11&KeyWords=480-3137-ND
-const float defaultThermistorBetas[HEATERS] = HEATERS_(BED_BETA, EXT_BETA, EXT_BETA, EXT_BETA, EXT_BETA, EXT_BETA, EXT_BETA, EXT_BETA); // Bed thermistor: B57861S104F40; Extruder thermistor: RS 198-961
-const float defaultThermistorSeriesRs[HEATERS] = HEATERS_(THERMISTOR_SERIES_RS, THERMISTOR_SERIES_RS, THERMISTOR_SERIES_RS, THERMISTOR_SERIES_RS,
- THERMISTOR_SERIES_RS, THERMISTOR_SERIES_RS, THERMISTOR_SERIES_RS, THERMISTOR_SERIES_RS);
-const float defaultThermistor25RS[HEATERS] = HEATERS_(BED_R25, EXT_R25, EXT_R25, EXT_R25, EXT_R25, EXT_R25, EXT_R25, EXT_R25); // Thermistor ohms at 25 C = 298.15 K
-
-// Note on hot end PID parameters:
-// The system is highly nonlinear because the heater power is limited to a maximum value and cannot go negative.
-// If we try to run a traditional PID when there are large temperature errors, this causes the I-accumulator to go out of control,
-// which causes a large amount of overshoot at lower temperatures. There are at least two ways of avoiding this:
-//
-// 1. Allow the PID to operate even with very large errors, but choose a very small I-term, just the right amount so that when heating up
-// from cold, the I-accumulator is approximately the value needed to maintain the correct power when the target temperature is reached.
-// This works well most of the time. However if the Duet board is reset when the extruder is hot and is then
-// commanded to heat up again before the extruder has cooled, the I-accumulator doesn't grow large enough, so the
-// temperature undershoots. The small value of the I-term then causes it to take a long time to reach the correct temperature.
-//
-// 2. Only allow the PID to operate when the temperature error is small enough for the PID to operate in the linear region.
-// So we set FULL_PID_BAND to a small value. It needs to be at least 15C because that is how much the temperature overshoots by
-// on an Ormerod when we turn the heater off from full power at about 180C. When we transition to PID, we set the I-term to the
-// value we expect to be needed to maintain the target temperature. We use an additional T parameter to allow this value to be
-// estimated.
-//
-// The default values use method (2).
-//
+
// Note: a negative P, I or D value means do not use PID for this heater, use bang-bang control instead.
// This allows us to switch between PID and bang-bang using the M301 and M304 commands.
@@ -160,28 +139,20 @@ const float defaultPidKps[HEATERS] = HEATERS_(-1.0, 10.0, 10.0, 10.0, 10.0, 10.0
const float defaultPidKts[HEATERS] = HEATERS_(2.7, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4); // approximate PWM value needed to maintain temperature, per degC above room temperature
const float defaultPidKss[HEATERS] = HEATERS_(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0); // PWM scaling factor, to allow for variation in heater power and supply voltage
-// For the theory behind ADC oversampling, see http://www.atmel.com/Images/doc8003.pdf
-const unsigned int AD_OVERSAMPLE_BITS = 1; // Number of bits we oversample when reading temperatures
-
// Define the number of temperature readings we average for each thermistor. This should be a power of 2 and at least 4 ** AD_OVERSAMPLE_BITS.
// Keep THERMISTOR_AVERAGE_READINGS * NUM_HEATERS * 2ms no greater than HEAT_SAMPLE_TIME or the PIDs won't work well.
-const unsigned int THERMISTOR_AVERAGE_READINGS = 32;
-const unsigned int AD_RANGE_REAL = 4095; // The ADC that measures temperatures gives an int this big as its max value
-const unsigned int AD_RANGE_VIRTUAL = ((AD_RANGE_REAL + 1) << AD_OVERSAMPLE_BITS) - 1; // The max value we can get using oversampling
-const unsigned int AD_DISCONNECTED_REAL = AD_RANGE_REAL - 3; // We consider an ADC reading at/above this value to indicate that the thermistor is disconnected
-const unsigned int AD_DISCONNECTED_VIRTUAL = AD_DISCONNECTED_REAL << AD_OVERSAMPLE_BITS;
+const unsigned int ThermistorAverageReadings = 32;
const uint32_t maxPidSpinDelay = 5000; // Maximum elapsed time in milliseconds between successive temp samples by Pid::Spin() permitted for a temp sensor
-const size_t BED_HEATER = 0; // Index of the heated bed
-const size_t E0_HEATER = 1; // Index of the first extruder heater
+const size_t DefaultBedHeater = 0; // Index of the default bed heater
+const size_t DefaultE0Heater = 1; // Index of the default first extruder heater
/****************************************************************************************************/
// File handling
const size_t MAX_FILES = 10; // Must be large enough to handle the max number of simultaneous web requests + files being printed
-
const size_t FILE_BUFFER_SIZE = 256;
/****************************************************************************************************/
@@ -312,21 +283,10 @@ struct ZProbeParameters
class PidParameters
{
// If you add any more variables to this class, don't forget to change the definition of operator== in Platform.cpp!
-private:
- float thermistorBeta, thermistorInfR; // private because these must be changed together
-
public:
float kI, kD, kP, kT, kS;
- float thermistorSeriesR;
- float adcLowOffset, adcHighOffset;
-
- float GetBeta() const { return thermistorBeta; }
- float GetRInf() const { return thermistorInfR; }
bool UsePID() const;
- float GetThermistorR25() const;
- void SetThermistorR25AndBeta(float r25, float beta);
-
bool operator==(const PidParameters& other) const;
bool operator!=(const PidParameters& other) const
{
@@ -393,7 +353,7 @@ private:
//invariant(index < numAveraged)
};
-typedef AveragingFilter<THERMISTOR_AVERAGE_READINGS> ThermistorAveragingFilter;
+typedef AveragingFilter<ThermistorAverageReadings> ThermistorAveragingFilter;
typedef AveragingFilter<Z_PROBE_AVERAGE_READINGS> ZProbeAveragingFilter;
// Enumeration of error condition bits
@@ -613,6 +573,11 @@ public:
float GetHeatSampleTime() const;
void SetPidParameters(size_t heater, const PidParameters& params);
const PidParameters& GetPidParameters(size_t heater) const;
+ Thermistor& GetThermistor(size_t heater)
+ pre (heater < HEATERS)
+ {
+ return thermistors[heater];
+ }
void SetThermistorNumber(size_t heater, size_t thermistor);
int GetThermistorNumber(size_t heater) const;
bool IsThermistorChannel(uint8_t heater) const;
@@ -713,7 +678,7 @@ private:
struct FlashData
{
static const uint16_t magicValue = 0xE6C4; // value we use to recognise that the flash data has been written
- static const uint16_t versionValue = 4; // increment this whenever this struct changes
+ static const uint16_t versionValue = 5; // increment this whenever this struct changes
static const uint32_t nvAddress = (SoftwareResetData::nvAddress + sizeof(SoftwareResetData) + 3) & (~3);
uint16_t magic;
@@ -816,6 +781,7 @@ private:
Pin tempSensePins[HEATERS];
Pin heatOnPins[HEATERS];
+ Thermistor thermistors[HEATERS];
TemperatureSensor SpiTempSensors[MaxSpiTempSensors];
Pin spiTempSenseCsPins[MaxSpiTempSensors];
uint32_t configuredHeaters; // bitmask of all heaters in use
@@ -889,7 +855,6 @@ private:
unsigned int heaterTempChannels[HEATERS];
AnalogChannelNumber thermistorAdcChannels[HEATERS];
AnalogChannelNumber zProbeAdcChannel;
- uint32_t thermistorOverheatSums[HEATERS];
uint8_t tickState;
size_t currentHeater;
int debugCode;
diff --git a/src/PrintMonitor.cpp b/src/PrintMonitor.cpp
index 67dd85a7..6901e555 100644
--- a/src/PrintMonitor.cpp
+++ b/src/PrintMonitor.cpp
@@ -88,7 +88,7 @@ void PrintMonitor::Spin()
// Check if this heater is assigned to a tool and if it has reached its set temperature yet
if (reprap.IsHeaterAssignedToTool(heater))
{
- if (!reprap.GetHeat()->HeaterAtSetTemperature(heater))
+ if (!reprap.GetHeat()->HeaterAtSetTemperature(heater, false))
{
nozzleAtHighTemperature = false;
break;
diff --git a/src/Reprap.cpp b/src/Reprap.cpp
index 6b39b3ff..1a60b022 100644
--- a/src/Reprap.cpp
+++ b/src/Reprap.cpp
@@ -680,7 +680,7 @@ OutputBuffer *RepRap::GetStatusResponse(uint8_t type, ResponseSource source)
// Current temperatures
ch = '[';
- for (size_t heater = E0_HEATER; heater < GetToolHeatersInUse(); heater++)
+ for (size_t heater = DefaultE0Heater; heater < GetToolHeatersInUse(); heater++)
{
response->catf("%c%.1f", ch, heat->GetTemperature(heater));
ch = ',';
@@ -690,7 +690,7 @@ OutputBuffer *RepRap::GetStatusResponse(uint8_t type, ResponseSource source)
// Active temperatures
response->catf(",\"active\":");
ch = '[';
- for (size_t heater = E0_HEATER; heater < GetToolHeatersInUse(); heater++)
+ for (size_t heater = DefaultE0Heater; heater < GetToolHeatersInUse(); heater++)
{
response->catf("%c%.1f", ch, heat->GetActiveTemperature(heater));
ch = ',';
@@ -700,7 +700,7 @@ OutputBuffer *RepRap::GetStatusResponse(uint8_t type, ResponseSource source)
// Standby temperatures
response->catf(",\"standby\":");
ch = '[';
- for (size_t heater = E0_HEATER; heater < GetToolHeatersInUse(); heater++)
+ for (size_t heater = DefaultE0Heater; heater < GetToolHeatersInUse(); heater++)
{
response->catf("%c%.1f", ch, heat->GetStandbyTemperature(heater));
ch = ',';
@@ -710,7 +710,7 @@ OutputBuffer *RepRap::GetStatusResponse(uint8_t type, ResponseSource source)
// Heater statuses (0=off, 1=standby, 2=active, 3=fault)
response->cat(",\"state\":");
ch = '[';
- for (size_t heater = E0_HEATER; heater < GetToolHeatersInUse(); heater++)
+ for (size_t heater = DefaultE0Heater; heater < GetToolHeatersInUse(); heater++)
{
response->catf("%c%d", ch, static_cast<int>(heat->GetStatus(heater)));
ch = ',';
@@ -748,6 +748,9 @@ OutputBuffer *RepRap::GetStatusResponse(uint8_t type, ResponseSource source)
// Delta configuration and number of axes
response->catf(",\"geometry\":\"%s\",\"axes\":%u", move->GetGeometryString(), numAxes);
+ // Firmware name, for PanelDue
+ response->catf(",\"firmwareName\":\"%s\"", NAME);
+
// Total and mounted volumes
size_t mountedCards = 0;
for(size_t i = 0; i < NumSdCards; i++)
@@ -1041,7 +1044,7 @@ OutputBuffer *RepRap::GetLegacyStatusResponse(uint8_t type, int seq)
{
ch = '[';
}
- for (size_t heater = E0_HEATER; heater < GetToolHeatersInUse(); heater++)
+ for (size_t heater = DefaultE0Heater; heater < GetToolHeatersInUse(); heater++)
{
response->catf("%c%.1f", ch, heat->GetTemperature(heater));
ch = ',';
@@ -1059,7 +1062,7 @@ OutputBuffer *RepRap::GetLegacyStatusResponse(uint8_t type, int seq)
{
ch = '[';
}
- for (size_t heater = E0_HEATER; heater < GetToolHeatersInUse(); heater++)
+ for (size_t heater = DefaultE0Heater; heater < GetToolHeatersInUse(); heater++)
{
response->catf("%c%.1f", ch, heat->GetActiveTemperature(heater));
ch = ',';
@@ -1077,7 +1080,7 @@ OutputBuffer *RepRap::GetLegacyStatusResponse(uint8_t type, int seq)
{
ch = '[';
}
- for (size_t heater = E0_HEATER; heater < GetToolHeatersInUse(); heater++)
+ for (size_t heater = DefaultE0Heater; heater < GetToolHeatersInUse(); heater++)
{
response->catf("%c%.1f", ch, heat->GetStandbyTemperature(heater));
ch = ',';
@@ -1095,7 +1098,7 @@ OutputBuffer *RepRap::GetLegacyStatusResponse(uint8_t type, int seq)
{
ch = '[';
}
- for (size_t heater = E0_HEATER; heater < GetToolHeatersInUse(); heater++)
+ for (size_t heater = DefaultE0Heater; heater < GetToolHeatersInUse(); heater++)
{
response->catf("%c%d", ch, static_cast<int>(heat->GetStatus(heater)));
ch = ',';