Browse Source

🐛 Fix MAX31865 PT1000 normalization (#24407)

Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
John Lagonikas 3 years ago
parent
commit
31d286750c
No account linked to committer's email address
2 changed files with 45 additions and 33 deletions
  1. 42
    23
      Marlin/src/libs/MAX31865.cpp
  2. 3
    10
      Marlin/src/libs/MAX31865.h

+ 42
- 23
Marlin/src/libs/MAX31865.cpp View File

133
 /**
133
 /**
134
  * Initialize the SPI interface and set the number of RTD wires used
134
  * Initialize the SPI interface and set the number of RTD wires used
135
  *
135
  *
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.
140
  */
140
  */
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
143
   refRes = ref_res;
143
   refRes = ref_res;
144
   wireRes = wire_res;
144
   wireRes = wire_res;
145
 
145
 
437
  *
437
  *
438
  * @return  Temperature in C
438
  * @return  Temperature in C
439
  */
439
  */
440
-float MAX31865::temperature(uint16_t adc_val) {
440
+float MAX31865::temperature(const uint16_t adc_val) {
441
   return temperature(((adc_val) * RECIPROCAL(32768.0f)) * refRes - wireRes);
441
   return temperature(((adc_val) * RECIPROCAL(32768.0f)) * refRes - wireRes);
442
 }
442
 }
443
 
443
 
444
 /**
444
 /**
445
  * Calculate the temperature in C from the RTD resistance.
445
  * 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
448
  *
446
  *
449
  * @param    rtd_res  the resistance value in ohms
447
  * @param    rtd_res  the resistance value in ohms
450
- * @return            the temperature in degC
448
+ * @return            the temperature in °C
451
  */
449
  */
452
 float MAX31865::temperature(float rtd_res) {
450
 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
453
   float temp = (RTD_Z1 + sqrt(RTD_Z2 + (RTD_Z3 * rtd_res))) * RECIPROCAL(RTD_Z4);
462
   float temp = (RTD_Z1 + sqrt(RTD_Z2 + (RTD_Z3 * rtd_res))) * RECIPROCAL(RTD_Z4);
454
 
463
 
455
-  // From the PDF...
456
   //
464
   //
457
   // The previous equation is valid only for temperatures of 0°C and above.
465
   // The previous equation is valid only for temperatures of 0°C and above.
458
   // The equation for RRTD(t) that defines negative temperature behavior is a
466
   // The equation for RRTD(t) that defines negative temperature behavior is a
459
   // fourth-order polynomial (after expanding the third term) and is quite
467
   // fourth-order polynomial (after expanding the third term) and is quite
460
   // impractical to solve for a single expression of temperature as a function
468
   // 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.
462
   //
470
   //
463
   if (temp < 0) {
471
   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
+    };
466
 
487
 
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];
476
   }
495
   }
477
 
496
 
478
   return temp;
497
   return temp;

+ 3
- 10
Marlin/src/libs/MAX31865.h View File

73
 #define MAX31865_FAULT_RTDINLOW 0x08    // D3
73
 #define MAX31865_FAULT_RTDINLOW 0x08    // D3
74
 #define MAX31865_FAULT_OVUV 0x04        // D2
74
 #define MAX31865_FAULT_OVUV 0x04        // D2
75
 
75
 
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
-
83
 typedef enum max31865_numwires {
76
 typedef enum max31865_numwires {
84
   MAX31865_2WIRE = 0,
77
   MAX31865_2WIRE = 0,
85
   MAX31865_3WIRE = 1,
78
   MAX31865_3WIRE = 1,
103
 
96
 
104
   uint16_t spiDelay;
97
   uint16_t spiDelay;
105
 
98
 
106
-  float zeroRes, refRes, wireRes;
99
+  float resNormalizer, refRes, wireRes;
107
 
100
 
108
   #if ENABLED(MAX31865_USE_READ_ERROR_DETECTION)
101
   #if ENABLED(MAX31865_USE_READ_ERROR_DETECTION)
109
     millis_t lastReadStamp = 0;
102
     millis_t lastReadStamp = 0;
160
              int8_t spi_clk);
153
              int8_t spi_clk);
161
   #endif
154
   #endif
162
 
155
 
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);
164
 
157
 
165
   uint8_t readFault();
158
   uint8_t readFault();
166
   void clearFault();
159
   void clearFault();
168
   uint16_t readRaw();
161
   uint16_t readRaw();
169
   float readResistance();
162
   float readResistance();
170
   float temperature();
163
   float temperature();
171
-  float temperature(uint16_t adc_val);
164
+  float temperature(const uint16_t adc_val);
172
   float temperature(float rtd_res);
165
   float temperature(float rtd_res);
173
 };
166
 };

Loading…
Cancel
Save