Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MAX31865 PT1000 normalization issue #24407

Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 42 additions & 23 deletions Marlin/src/libs/MAX31865.cpp
Original file line number Diff line number Diff line change
@@ -133,13 +133,13 @@ SPISettings MAX31865::spiConfig = SPISettings(
/**
* Initialize the SPI interface and set the number of RTD wires used
*
* @param wires The number of wires in enum format. Can be MAX31865_2WIRE, MAX31865_3WIRE, or MAX31865_4WIRE.
* @param zero The resistance of the RTD at 0 degC, in ohms.
* @param ref The resistance of the reference resistor, in ohms.
* @param wire The resistance of the wire connecting the sensor to the RTD, in ohms.
* @param wires The number of wires as an enum: MAX31865_2WIRE, MAX31865_3WIRE, or MAX31865_4WIRE.
* @param zero_res The resistance of the RTD at 0°C, in ohms.
* @param ref_res The resistance of the reference resistor, in ohms.
* @param wire_res The resistance of the wire connecting the sensor to the RTD, in ohms.
*/
void MAX31865::begin(max31865_numwires_t wires, float zero_res, float ref_res, float wire_res) {
zeroRes = zero_res;
void MAX31865::begin(max31865_numwires_t wires, const_float_t zero_res, const_float_t ref_res, const_float_t wire_res) {
resNormalizer = 100.0f / zero_res; // reciprocal of resistance, scaled by 100
refRes = ref_res;
wireRes = wire_res;

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

/**
* Calculate the temperature in C from the RTD resistance.
* Uses the technique outlined in this PDF:
* http://www.analog.com/media/en/technical-documentation/application-notes/AN709_0.pdf
*
* @param rtd_res the resistance value in ohms
* @return the temperature in degC
* @return the temperature in °C
*/
float MAX31865::temperature(float rtd_res) {

rtd_res *= resNormalizer; // normalize to 100 ohm

// Constants for calculating temperature from the measured RTD resistance.
// http://www.analog.com/media/en/technical-documentation/application-notes/AN709_0.pdf
constexpr float RTD_Z1 = -0.0039083,
RTD_Z2 = +1.758480889e-5,
RTD_Z3 = -2.31e-8,
RTD_Z4 = -1.155e-6;

// Callender-Van Dusen equation
float temp = (RTD_Z1 + sqrt(RTD_Z2 + (RTD_Z3 * rtd_res))) * RECIPROCAL(RTD_Z4);

// From the PDF...
//
// The previous equation is valid only for temperatures of 0°C and above.
// The equation for RRTD(t) that defines negative temperature behavior is a
// fourth-order polynomial (after expanding the third term) and is quite
// impractical to solve for a single expression of temperature as a function
// of resistance.
// of resistance. So here we use a Linear Approximation instead.
//
if (temp < 0) {
rtd_res = (rtd_res / zeroRes) * 100; // normalize to 100 ohm
float rpoly = rtd_res;
#ifndef MAX31865_APPROX
#define MAX31865_APPROX 5
#endif

constexpr float RTD_C[] = {
#if MAX31865_APPROX == 5
-242.02, +2.2228, +2.5859e-3, -4.8260e-6, -2.8183e-8, +1.5243e-10
#elif MAX31865_APPROX == 4
-241.96, +2.2163, +2.8541e-3, -9.9121e-6, -1.7152e-8
#elif MAX31865_APPROX == 3
-242.09, +2.2276, +2.5178e-3, -5.8620e-6
#else
-242.97, +2.2838, +1.4727e-3
#endif
};

temp = -242.02 + (2.2228 * rpoly);
rpoly *= rtd_res; // square
temp += 2.5859e-3 * rpoly;
rpoly *= rtd_res; // ^3
temp -= 4.8260e-6 * rpoly;
rpoly *= rtd_res; // ^4
temp -= 2.8183e-8 * rpoly;
rpoly *= rtd_res; // ^5
temp += 1.5243e-10 * rpoly;
float rpoly = rtd_res;
temp = RTD_C[0];
temp += rpoly * RTD_C[1];
rpoly *= rtd_res; temp += rpoly * RTD_C[2];
if (MAX31865_APPROX >= 3) rpoly *= rtd_res; temp += rpoly * RTD_C[3];
if (MAX31865_APPROX >= 4) rpoly *= rtd_res; temp += rpoly * RTD_C[4];
if (MAX31865_APPROX >= 5) rpoly *= rtd_res; temp += rpoly * RTD_C[5];
}

return temp;
13 changes: 3 additions & 10 deletions Marlin/src/libs/MAX31865.h
Original file line number Diff line number Diff line change
@@ -73,13 +73,6 @@
#define MAX31865_FAULT_RTDINLOW 0x08 // D3
#define MAX31865_FAULT_OVUV 0x04 // D2

// http://www.analog.com/media/en/technical-documentation/application-notes/AN709_0.pdf
// constants for calculating temperature from the measured RTD resistance.
#define RTD_Z1 -0.0039083
#define RTD_Z2 0.00001758480889
#define RTD_Z3 -0.0000000231
#define RTD_Z4 -0.000001155

typedef enum max31865_numwires {
MAX31865_2WIRE = 0,
MAX31865_3WIRE = 1,
@@ -103,7 +96,7 @@ class MAX31865 {

uint16_t spiDelay;

float zeroRes, refRes, wireRes;
float resNormalizer, refRes, wireRes;

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

void begin(max31865_numwires_t wires, float zero_res, float ref_res, float wire_res);
void begin(max31865_numwires_t wires, const_float_t zero_res, const_float_t ref_res, const_float_t wire_res);

uint8_t readFault();
void clearFault();

uint16_t readRaw();
float readResistance();
float temperature();
float temperature(uint16_t adc_val);
float temperature(const uint16_t adc_val);
float temperature(float rtd_res);
};