Skip to content

Commit 9e9ee59

Browse files
zelepsthinkyhead
authored andcommitted
🐛 Fix MAX31865 PT1000 normalization (MarlinFirmware#24407)
Co-authored-by: Scott Lahteine <[email protected]>
1 parent 22d51c7 commit 9e9ee59

File tree

2 files changed

+45
-33
lines changed

2 files changed

+45
-33
lines changed

Marlin/src/libs/MAX31865.cpp

+42-23
Original file line numberDiff line numberDiff line change
@@ -133,13 +133,13 @@ SPISettings MAX31865::spiConfig = SPISettings(
133133
/**
134134
* Initialize the SPI interface and set the number of RTD wires used
135135
*
136-
* @param wires The number of wires in enum format. Can be MAX31865_2WIRE, MAX31865_3WIRE, or MAX31865_4WIRE.
137-
* @param zero The resistance of the RTD at 0 degC, in ohms.
138-
* @param ref The resistance of the reference resistor, in ohms.
139-
* @param wire The resistance of the wire connecting the sensor to the RTD, in ohms.
136+
* @param wires The number of wires as an enum: MAX31865_2WIRE, MAX31865_3WIRE, or MAX31865_4WIRE.
137+
* @param zero_res The resistance of the RTD at 0°C, in ohms.
138+
* @param ref_res The resistance of the reference resistor, in ohms.
139+
* @param wire_res The resistance of the wire connecting the sensor to the RTD, in ohms.
140140
*/
141-
void MAX31865::begin(max31865_numwires_t wires, float zero_res, float ref_res, float wire_res) {
142-
zeroRes = zero_res;
141+
void MAX31865::begin(max31865_numwires_t wires, const_float_t zero_res, const_float_t ref_res, const_float_t wire_res) {
142+
resNormalizer = 100.0f / zero_res; // reciprocal of resistance, scaled by 100
143143
refRes = ref_res;
144144
wireRes = wire_res;
145145

@@ -437,42 +437,61 @@ float MAX31865::temperature() {
437437
*
438438
* @return Temperature in C
439439
*/
440-
float MAX31865::temperature(uint16_t adc_val) {
440+
float MAX31865::temperature(const uint16_t adc_val) {
441441
return temperature(((adc_val) * RECIPROCAL(32768.0f)) * refRes - wireRes);
442442
}
443443

444444
/**
445445
* Calculate the temperature in C from the RTD resistance.
446-
* Uses the technique outlined in this PDF:
447-
* http://www.analog.com/media/en/technical-documentation/application-notes/AN709_0.pdf
448446
*
449447
* @param rtd_res the resistance value in ohms
450-
* @return the temperature in degC
448+
* @return the temperature in °C
451449
*/
452450
float MAX31865::temperature(float rtd_res) {
451+
452+
rtd_res *= resNormalizer; // normalize to 100 ohm
453+
454+
// Constants for calculating temperature from the measured RTD resistance.
455+
// http://www.analog.com/media/en/technical-documentation/application-notes/AN709_0.pdf
456+
constexpr float RTD_Z1 = -0.0039083,
457+
RTD_Z2 = +1.758480889e-5,
458+
RTD_Z3 = -2.31e-8,
459+
RTD_Z4 = -1.155e-6;
460+
461+
// Callender-Van Dusen equation
453462
float temp = (RTD_Z1 + sqrt(RTD_Z2 + (RTD_Z3 * rtd_res))) * RECIPROCAL(RTD_Z4);
454463

455-
// From the PDF...
456464
//
457465
// The previous equation is valid only for temperatures of 0°C and above.
458466
// The equation for RRTD(t) that defines negative temperature behavior is a
459467
// fourth-order polynomial (after expanding the third term) and is quite
460468
// impractical to solve for a single expression of temperature as a function
461-
// of resistance.
469+
// of resistance. So here we use a Linear Approximation instead.
462470
//
463471
if (temp < 0) {
464-
rtd_res = (rtd_res / zeroRes) * 100; // normalize to 100 ohm
465-
float rpoly = rtd_res;
472+
#ifndef MAX31865_APPROX
473+
#define MAX31865_APPROX 5
474+
#endif
475+
476+
constexpr float RTD_C[] = {
477+
#if MAX31865_APPROX == 5
478+
-242.02, +2.2228, +2.5859e-3, -4.8260e-6, -2.8183e-8, +1.5243e-10
479+
#elif MAX31865_APPROX == 4
480+
-241.96, +2.2163, +2.8541e-3, -9.9121e-6, -1.7152e-8
481+
#elif MAX31865_APPROX == 3
482+
-242.09, +2.2276, +2.5178e-3, -5.8620e-6
483+
#else
484+
-242.97, +2.2838, +1.4727e-3
485+
#endif
486+
};
466487

467-
temp = -242.02 + (2.2228 * rpoly);
468-
rpoly *= rtd_res; // square
469-
temp += 2.5859e-3 * rpoly;
470-
rpoly *= rtd_res; // ^3
471-
temp -= 4.8260e-6 * rpoly;
472-
rpoly *= rtd_res; // ^4
473-
temp -= 2.8183e-8 * rpoly;
474-
rpoly *= rtd_res; // ^5
475-
temp += 1.5243e-10 * rpoly;
488+
float rpoly = rtd_res;
489+
temp = RTD_C[0];
490+
temp += rpoly * RTD_C[1];
491+
rpoly *= rtd_res; temp += rpoly * RTD_C[2];
492+
if (MAX31865_APPROX >= 3) rpoly *= rtd_res; temp += rpoly * RTD_C[3];
493+
if (MAX31865_APPROX >= 4) rpoly *= rtd_res; temp += rpoly * RTD_C[4];
494+
if (MAX31865_APPROX >= 5) rpoly *= rtd_res; temp += rpoly * RTD_C[5];
476495
}
477496

478497
return temp;

Marlin/src/libs/MAX31865.h

+3-10
Original file line numberDiff line numberDiff line change
@@ -73,13 +73,6 @@
7373
#define MAX31865_FAULT_RTDINLOW 0x08 // D3
7474
#define MAX31865_FAULT_OVUV 0x04 // D2
7575

76-
// http://www.analog.com/media/en/technical-documentation/application-notes/AN709_0.pdf
77-
// constants for calculating temperature from the measured RTD resistance.
78-
#define RTD_Z1 -0.0039083
79-
#define RTD_Z2 0.00001758480889
80-
#define RTD_Z3 -0.0000000231
81-
#define RTD_Z4 -0.000001155
82-
8376
typedef enum max31865_numwires {
8477
MAX31865_2WIRE = 0,
8578
MAX31865_3WIRE = 1,
@@ -103,7 +96,7 @@ class MAX31865 {
10396

10497
uint16_t spiDelay;
10598

106-
float zeroRes, refRes, wireRes;
99+
float resNormalizer, refRes, wireRes;
107100

108101
#if ENABLED(MAX31865_USE_READ_ERROR_DETECTION)
109102
millis_t lastReadStamp = 0;
@@ -160,14 +153,14 @@ class MAX31865 {
160153
int8_t spi_clk);
161154
#endif
162155

163-
void begin(max31865_numwires_t wires, float zero_res, float ref_res, float wire_res);
156+
void begin(max31865_numwires_t wires, const_float_t zero_res, const_float_t ref_res, const_float_t wire_res);
164157

165158
uint8_t readFault();
166159
void clearFault();
167160

168161
uint16_t readRaw();
169162
float readResistance();
170163
float temperature();
171-
float temperature(uint16_t adc_val);
164+
float temperature(const uint16_t adc_val);
172165
float temperature(float rtd_res);
173166
};

0 commit comments

Comments
 (0)