Browse Source

🐛 Fix and improve MAX31865 (#23215)

Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
John Lagonikas 2 years ago
parent
commit
9e6ded3cdf
No account linked to committer's email address

+ 9
- 0
Marlin/Configuration_adv.h View File

142
  *   FORCE_HW_SPI:   Ignore SCK/MOSI/MISO pins and just use the CS pin & default SPI bus.
142
  *   FORCE_HW_SPI:   Ignore SCK/MOSI/MISO pins and just use the CS pin & default SPI bus.
143
  *   MAX31865_WIRES: Set the number of wires for the probe connected to a MAX31865 board, 2-4. Default: 2
143
  *   MAX31865_WIRES: Set the number of wires for the probe connected to a MAX31865 board, 2-4. Default: 2
144
  *   MAX31865_50HZ:  Enable 50Hz filter instead of the default 60Hz.
144
  *   MAX31865_50HZ:  Enable 50Hz filter instead of the default 60Hz.
145
+ *   MAX31865_USE_READ_ERROR_DETECTION: Detects random read errors from value spikes (a 20°C difference in less than 1sec)
146
+ *   MAX31865_USE_AUTO_MODE: Faster and more frequent reads than 1-shot, but bias voltage always on, slightly affecting RTD temperature.
147
+ *   MAX31865_MIN_SAMPLING_TIME_MSEC: in 1-shot mode, the minimum time between subsequent reads. This reduces the effect of bias voltage by leaving the sensor unpowered for longer intervals.
148
+ *   MAX31865_WIRE_OHMS: In 2-wire configurations, manually set the wire resistance for more accurate readings
145
  */
149
  */
146
 //#define TEMP_SENSOR_FORCE_HW_SPI
150
 //#define TEMP_SENSOR_FORCE_HW_SPI
147
 //#define MAX31865_SENSOR_WIRES_0 2
151
 //#define MAX31865_SENSOR_WIRES_0 2
148
 //#define MAX31865_SENSOR_WIRES_1 2
152
 //#define MAX31865_SENSOR_WIRES_1 2
149
 //#define MAX31865_50HZ_FILTER
153
 //#define MAX31865_50HZ_FILTER
154
+//#define MAX31865_USE_READ_ERROR_DETECTION
155
+//#define MAX31865_USE_AUTO_MODE
156
+//#define MAX31865_MIN_SAMPLING_TIME_MSEC 100
157
+//#define MAX31865_WIRE_OHMS_0 0.0f
158
+//#define MAX31865_WIRE_OHMS_1 0.0f
150
 
159
 
151
 /**
160
 /**
152
  * Hephestos 2 24V heated bed upgrade kit.
161
  * Hephestos 2 24V heated bed upgrade kit.

+ 6
- 0
Marlin/src/inc/Conditionals_adv.h View File

159
     #ifndef MAX31865_SENSOR_WIRES_0
159
     #ifndef MAX31865_SENSOR_WIRES_0
160
       #define MAX31865_SENSOR_WIRES_0 2
160
       #define MAX31865_SENSOR_WIRES_0 2
161
     #endif
161
     #endif
162
+    #ifndef MAX31865_WIRE_OHMS_0
163
+      #define MAX31865_WIRE_OHMS_0 0.0f
164
+    #endif
162
   #elif TEMP_SENSOR_0 == -3
165
   #elif TEMP_SENSOR_0 == -3
163
     #define TEMP_SENSOR_0_IS_MAX31855 1
166
     #define TEMP_SENSOR_0_IS_MAX31855 1
164
     #define TEMP_SENSOR_0_MAX_TC_TMIN -270
167
     #define TEMP_SENSOR_0_MAX_TC_TMIN -270
193
     #ifndef MAX31865_SENSOR_WIRES_1
196
     #ifndef MAX31865_SENSOR_WIRES_1
194
       #define MAX31865_SENSOR_WIRES_1 2
197
       #define MAX31865_SENSOR_WIRES_1 2
195
     #endif
198
     #endif
199
+    #ifndef MAX31865_WIRE_OHMS_1
200
+      #define MAX31865_WIRE_OHMS_1 0.0f
201
+    #endif
196
   #elif TEMP_SENSOR_1 == -3
202
   #elif TEMP_SENSOR_1 == -3
197
     #define TEMP_SENSOR_1_IS_MAX31855 1
203
     #define TEMP_SENSOR_1_IS_MAX31855 1
198
     #define TEMP_SENSOR_1_MAX_TC_TMIN -270
204
     #define TEMP_SENSOR_1_MAX_TC_TMIN -270

+ 188
- 125
Marlin/src/libs/MAX31865.cpp View File

40
  * All rights reserved.
40
  * All rights reserved.
41
  */
41
  */
42
 
42
 
43
-// Useful for RTD debugging.
44
-//#define MAX31865_DEBUG
45
-//#define MAX31865_DEBUG_SPI
46
-
47
 #include "../inc/MarlinConfig.h"
43
 #include "../inc/MarlinConfig.h"
48
 
44
 
49
 #if HAS_MAX31865 && !USE_ADAFRUIT_MAX31865
45
 #if HAS_MAX31865 && !USE_ADAFRUIT_MAX31865
50
 
46
 
51
 #include "MAX31865.h"
47
 #include "MAX31865.h"
52
 
48
 
49
+#ifndef MAX31865_MIN_SAMPLING_TIME_MSEC
50
+  #define MAX31865_MIN_SAMPLING_TIME_MSEC 0
51
+#endif
52
+
53
 #ifdef TARGET_LPC1768
53
 #ifdef TARGET_LPC1768
54
   #include <SoftwareSPI.h>
54
   #include <SoftwareSPI.h>
55
 #endif
55
 #endif
56
 
56
 
57
+#define DEBUG_OUT ENABLED(DEBUG_MAX31865)
58
+#include "../core/debug_out.h"
59
+
57
 // The maximum speed the MAX31865 can do is 5 MHz
60
 // The maximum speed the MAX31865 can do is 5 MHz
58
 SPISettings MAX31865::spiConfig = SPISettings(
61
 SPISettings MAX31865::spiConfig = SPISettings(
59
   TERN(TARGET_LPC1768, SPI_QUARTER_SPEED, TERN(ARDUINO_ARCH_STM32, SPI_CLOCK_DIV4, 500000)),
62
   TERN(TARGET_LPC1768, SPI_QUARTER_SPEED, TERN(ARDUINO_ARCH_STM32, SPI_CLOCK_DIV4, 500000)),
61
   SPI_MODE1 // CPOL0 CPHA1
64
   SPI_MODE1 // CPOL0 CPHA1
62
 );
65
 );
63
 
66
 
64
-#ifndef LARGE_PINMAP
67
+#if DISABLED(LARGE_PINMAP)
65
 
68
 
66
   /**
69
   /**
67
    * Create the interface object using software (bitbang) SPI for PIN values
70
    * Create the interface object using software (bitbang) SPI for PIN values
137
  * @param wires  The number of wires in enum format. Can be MAX31865_2WIRE, MAX31865_3WIRE, or MAX31865_4WIRE.
140
  * @param wires  The number of wires in enum format. Can be MAX31865_2WIRE, MAX31865_3WIRE, or MAX31865_4WIRE.
138
  * @param zero   The resistance of the RTD at 0 degC, in ohms.
141
  * @param zero   The resistance of the RTD at 0 degC, in ohms.
139
  * @param ref    The resistance of the reference resistor, in ohms.
142
  * @param ref    The resistance of the reference resistor, in ohms.
143
+ * @param wire   The resistance of the wire connecting the sensor to the RTD, in ohms.
140
  */
144
  */
141
-void MAX31865::begin(max31865_numwires_t wires, float zero, float ref) {
142
-  zeroRes = zero;
143
-  refRes = ref;
145
+void MAX31865::begin(max31865_numwires_t wires, float zero_res, float ref_res, float wire_res) {
146
+  zeroRes = zero_res;
147
+  refRes = ref_res;
148
+  wireRes = wire_res;
144
 
149
 
145
-  OUT_WRITE(cselPin, HIGH);
150
+  pinMode(cselPin, OUTPUT);
151
+  digitalWrite(cselPin, HIGH);
146
 
152
 
147
-  if (sclkPin != TERN(LARGE_PINMAP, -1UL, -1)) {
153
+  if (sclkPin != TERN(LARGE_PINMAP, -1UL, 255))
148
     softSpiBegin(SPI_QUARTER_SPEED); // Define pin modes for Software SPI
154
     softSpiBegin(SPI_QUARTER_SPEED); // Define pin modes for Software SPI
149
-  }
150
   else {
155
   else {
151
-    #ifdef MAX31865_DEBUG
152
-      SERIAL_ECHOLNPGM("Initializing MAX31865 Hardware SPI");
153
-    #endif
156
+    DEBUG_ECHOLNPGM("Initializing MAX31865 Hardware SPI");
154
     SPI.begin();    // Start and configure hardware SPI
157
     SPI.begin();    // Start and configure hardware SPI
155
   }
158
   }
156
 
159
 
157
-  setWires(wires);
158
-  enableBias(false);
159
-  autoConvert(false);
160
-  clearFault();
161
-
162
-  #ifdef MAX31865_DEBUG_SPI
163
-    SERIAL_ECHOLNPGM(
164
-      TERN(LARGE_PINMAP, "LARGE_PINMAP", "Regular")
165
-      " begin call with cselPin: ", cselPin,
166
-      " misoPin: ", misoPin,
167
-      " sclkPin: ", sclkPin,
168
-      " mosiPin: ", mosiPin,
169
-      " config: ", readRegister8(MAX31865_CONFIG_REG)
170
-    );
171
-  #endif
160
+  initFixedFlags(wires);
161
+
162
+  clearFault(); // also initializes flags
163
+
164
+  #if DISABLED(MAX31865_USE_AUTO_MODE) // make a proper first 1 shot read to initialize _lastRead
165
+
166
+    enableBias();
167
+    DELAY_US(11500);
168
+    oneShot();
169
+    DELAY_US(65000);
170
+    uint16_t rtd = readRegister16(MAX31865_RTDMSB_REG);
171
+
172
+    if (rtd & 1) {
173
+      lastRead = 0xFFFF; // some invalid value
174
+      lastFault = readRegister8(MAX31865_FAULTSTAT_REG);
175
+      clearFault(); // also clears the bias voltage flag, so no further action is required
176
+
177
+      DEBUG_ECHOLNPGM("MAX31865 read fault: ", rtd);
178
+    }
179
+    else {
180
+      DEBUG_ECHOLNPGM("RTD MSB:", (rtd >> 8), "  RTD LSB:", (rtd & 0x00FF));
181
+
182
+      resetFlags();
183
+
184
+      lastRead = rtd;
185
+      nextEvent = SETUP_BIAS_VOLTAGE;
186
+      millis_t now = millis();
187
+      nextEventStamp = now + MAX31865_MIN_SAMPLING_TIME_MSEC;
188
+
189
+      TERN_(MAX31865_USE_READ_ERROR_DETECTION, lastReadStamp = now);
190
+    }
191
+
192
+  #endif // !MAX31865_USE_AUTO_MODE
193
+
194
+  DEBUG_ECHOLNPGM(
195
+    TERN(LARGE_PINMAP, "LARGE_PINMAP", "Regular")
196
+    " begin call with cselPin: ", cselPin,
197
+    " misoPin: ", misoPin,
198
+    " sclkPin: ", sclkPin,
199
+    " mosiPin: ", mosiPin,
200
+    " config: ", readRegister8(MAX31865_CONFIG_REG)
201
+  );
172
 }
202
 }
173
 
203
 
174
 /**
204
 /**
175
- * Read the raw 8-bit FAULTSTAT register
205
+ * Return and clear the last fault value
176
  *
206
  *
177
- * @return The raw unsigned 8-bit FAULT status register
207
+ * @return The raw unsigned 8-bit FAULT status register or spike fault
178
  */
208
  */
179
 uint8_t MAX31865::readFault() {
209
 uint8_t MAX31865::readFault() {
180
-  return readRegister8(MAX31865_FAULTSTAT_REG);
210
+  uint8_t r = lastFault;
211
+  lastFault = 0;
212
+  return r;
181
 }
213
 }
182
 
214
 
183
 /**
215
 /**
184
- * Clear all faults in FAULTSTAT.
216
+ * Clear last fault
185
  */
217
  */
186
 void MAX31865::clearFault() {
218
 void MAX31865::clearFault() {
187
   setConfig(MAX31865_CONFIG_FAULTSTAT, 1);
219
   setConfig(MAX31865_CONFIG_FAULTSTAT, 1);
188
 }
220
 }
189
 
221
 
190
 /**
222
 /**
191
- * Whether we want to have continuous conversions (50/60 Hz)
192
- *
193
- * @param b  If true, auto conversion is enabled
194
- */
195
-void MAX31865::autoConvert(bool b) {
196
-  setConfig(MAX31865_CONFIG_MODEAUTO, b);
197
-}
198
-
199
-/**
200
- * Whether we want filter out 50Hz noise or 60Hz noise
201
- *
202
- * @param b  If true, 50Hz noise is filtered, else 60Hz(default)
223
+ * Reset flags
203
  */
224
  */
204
-void MAX31865::enable50HzFilter(bool b) {
205
-  setConfig(MAX31865_CONFIG_FILT50HZ, b);
225
+void MAX31865::resetFlags() {
226
+  writeRegister8(MAX31865_CONFIG_REG, stdFlags);
206
 }
227
 }
207
 
228
 
208
 /**
229
 /**
209
  * Enable the bias voltage on the RTD sensor
230
  * Enable the bias voltage on the RTD sensor
210
- *
211
- * @param b  If true bias is enabled, else disabled
212
  */
231
  */
213
-void MAX31865::enableBias(bool b) {
214
-  setConfig(MAX31865_CONFIG_BIAS, b);
215
-
216
-  // From the datasheet:
217
-  // Note that if VBIAS is off (to reduce supply current between conversions), any filter
218
-  // capacitors at the RTDIN inputs need to charge before an accurate conversion can be
219
-  // performed. Therefore, enable VBIAS and wait at least 10.5 time constants of the input
220
-  // RC network plus an additional 1ms before initiating the conversion.
221
-  if (b)
222
-    DELAY_US(11500); //11.5ms
232
+void MAX31865::enableBias() {
233
+  setConfig(MAX31865_CONFIG_BIAS, 1);
223
 }
234
 }
224
 
235
 
225
 /**
236
 /**
226
  * Start a one-shot temperature reading.
237
  * Start a one-shot temperature reading.
227
  */
238
  */
228
 void MAX31865::oneShot() {
239
 void MAX31865::oneShot() {
229
-  setConfig(MAX31865_CONFIG_1SHOT, 1);
230
-
231
-  // From the datasheet:
232
-  // Note that a single conversion requires approximately 52ms in 60Hz filter
233
-  // mode or 62.5ms in 50Hz filter mode to complete. 1-Shot is a self-clearing bit.
234
-  // TODO: switch this out depending on the filter mode.
235
-  DELAY_US(65000); // 65ms
240
+  setConfig(MAX31865_CONFIG_1SHOT | MAX31865_CONFIG_BIAS, 1);
236
 }
241
 }
237
 
242
 
238
 /**
243
 /**
239
- * How many wires we have in our RTD setup, can be MAX31865_2WIRE,
240
- * MAX31865_3WIRE, or MAX31865_4WIRE
244
+ * Initialize standard flags with flags that will not change during operation (Hz, polling mode and no. of wires)
241
  *
245
  *
242
  * @param wires The number of wires in enum format
246
  * @param wires The number of wires in enum format
243
  */
247
  */
244
-void MAX31865::setWires(max31865_numwires_t wires) {
245
-  uint8_t t = readRegister8(MAX31865_CONFIG_REG);
248
+void MAX31865::initFixedFlags(max31865_numwires_t wires) {
249
+
250
+  // set config-defined flags (same for all sensors)
251
+  stdFlags = TERN(MAX31865_50HZ_FILTER, MAX31865_CONFIG_FILT50HZ, MAX31865_CONFIG_FILT60HZ) |
252
+              TERN(MAX31865_USE_AUTO_MODE, MAX31865_CONFIG_MODEAUTO | MAX31865_CONFIG_BIAS, MAX31865_CONFIG_MODEOFF);
253
+
246
   if (wires == MAX31865_3WIRE)
254
   if (wires == MAX31865_3WIRE)
247
-    t |= MAX31865_CONFIG_3WIRE;
248
-  else // 2 or 4 wire
249
-    t &= ~MAX31865_CONFIG_3WIRE;
250
-  writeRegister8(MAX31865_CONFIG_REG, t);
255
+    stdFlags |= MAX31865_CONFIG_3WIRE;
256
+  else  // 2 or 4 wire
257
+    stdFlags &= ~MAX31865_CONFIG_3WIRE;
251
 }
258
 }
252
 
259
 
253
 /**
260
 /**
257
  * @return The raw unsigned 16-bit register value with ERROR bit attached, NOT temperature!
264
  * @return The raw unsigned 16-bit register value with ERROR bit attached, NOT temperature!
258
  */
265
  */
259
 uint16_t MAX31865::readRaw() {
266
 uint16_t MAX31865::readRaw() {
260
-  clearFault();
261
-  enableBias(true);
262
 
267
 
263
-  oneShot();
264
-  uint16_t rtd = readRegister16(MAX31865_RTDMSB_REG);
268
+  #if ENABLED(MAX31865_USE_AUTO_MODE)
265
 
269
 
266
-  #ifdef MAX31865_DEBUG
267
-    SERIAL_ECHOLNPGM("RTD MSB:", (rtd >> 8), "  RTD LSB:", (rtd & 0x00FF));
268
-  #endif
270
+    const uint16_t rtd = readRegister16(MAX31865_RTDMSB_REG);
271
+    DEBUG_ECHOLNPGM("MAX31865 RTD MSB:", (rtd >> 8), " LSB:", (rtd & 0x00FF));
272
+
273
+    if (rtd & 1) {
274
+      lastFault = readRegister8(MAX31865_FAULTSTAT_REG);
275
+      lastRead |= 1;
276
+      clearFault(); // also clears the bias voltage flag, so no further action is required
277
+      DEBUG_ECHOLNPGM("MAX31865 read fault: ", rtd);
278
+    }
279
+    #if ENABLED(MAX31865_USE_READ_ERROR_DETECTION)
280
+      else if (ABS(lastRead - rtd) > 500 && PENDING(millis(), lastReadStamp + 1000)) { // if two readings within a second differ too much (~20°C), consider it a read error.
281
+        lastFault = 0x01;
282
+        lastRead |= 1;
283
+        DEBUG_ECHOLNPGM("MAX31865 read error: ", rtd);
284
+      }
285
+    #endif
286
+    else {
287
+      lastRead = rtd;
288
+      TERN_(MAX31865_USE_READ_ERROR_DETECTION, lastReadStamp = millis());
289
+    }
269
 
290
 
270
-  // Disable the bias to lower power dissipation between reads.
271
-  // If the ref resistor heats up, the temperature reading will be skewed.
272
-  enableBias(false);
291
+  #else
292
+
293
+    if (PENDING(millis(), nextEventStamp)) {
294
+      DEBUG_ECHOLNPGM("MAX31865 waiting for event ", nextEvent);
295
+      return lastRead;
296
+    }
297
+
298
+    switch (nextEvent) {
299
+      case SETUP_BIAS_VOLTAGE:
300
+        enableBias();
301
+        nextEventStamp = millis() + 11; // wait at least 11msec before enabling 1shot
302
+        nextEvent = SETUP_1_SHOT_MODE;
303
+        DEBUG_ECHOLN("MAX31865 bias voltage enabled");
304
+        break;
305
+
306
+      case SETUP_1_SHOT_MODE:
307
+        oneShot();
308
+        nextEventStamp = millis() + 65; // wait at least 65msec before reading RTD register
309
+        nextEvent = READ_RTD_REG;
310
+        DEBUG_ECHOLN("MAX31865 1 shot mode enabled");
311
+        break;
312
+
313
+      case READ_RTD_REG: {
314
+        const uint16_t rtd = readRegister16(MAX31865_RTDMSB_REG);
315
+        DEBUG_ECHOLNPGM("MAX31865 RTD MSB:", (rtd >> 8), " LSB:", (rtd & 0x00FF));
316
+
317
+        if (rtd & 1) {
318
+          lastFault = readRegister8(MAX31865_FAULTSTAT_REG);
319
+          lastRead |= 1;
320
+          clearFault(); // also clears the bias voltage flag, so no further action is required
321
+          DEBUG_ECHOLNPGM("MAX31865 read fault: ", rtd);
322
+        }
323
+        #if ENABLED(MAX31865_USE_READ_ERROR_DETECTION)
324
+          else if (ABS(lastRead - rtd) > 500 && PENDING(millis(), lastReadStamp + 1000)) { // if two readings within a second differ too much (~20°C), consider it a read error.
325
+            lastFault = 0x01;
326
+            lastRead |= 1;
327
+            DEBUG_ECHOLNPGM("MAX31865 read error: ", rtd);
328
+          }
329
+        #endif
330
+        else {
331
+          lastRead = rtd;
332
+          TERN_(MAX31865_USE_READ_ERROR_DETECTION, lastReadStamp = millis());
333
+        }
334
+
335
+        if (!(rtd & 1))   // if clearFault() was not invoked, need to clear the bias voltage and 1-shot flags
336
+          resetFlags();
337
+
338
+        nextEvent = SETUP_BIAS_VOLTAGE;
339
+        nextEventStamp = millis() + MAX31865_MIN_SAMPLING_TIME_MSEC; // next step should not occur within less than MAX31865_MIN_SAMPLING_TIME_MSEC from the last one
340
+      } break;
341
+    }
342
+
343
+  #endif
273
 
344
 
274
-  return rtd;
345
+  return lastRead;
275
 }
346
 }
276
 
347
 
277
 /**
348
 /**
278
  * Calculate and return the resistance value of the connected RTD.
349
  * Calculate and return the resistance value of the connected RTD.
279
  *
350
  *
280
- * @param  refResistor The value of the matching reference resistor, usually 430 or 4300
281
  * @return             The raw RTD resistance value, NOT temperature!
351
  * @return             The raw RTD resistance value, NOT temperature!
282
  */
352
  */
283
 float MAX31865::readResistance() {
353
 float MAX31865::readResistance() {
284
   // Strip the error bit (D0) and convert to a float ratio.
354
   // Strip the error bit (D0) and convert to a float ratio.
285
   // less precise method: (readRaw() * refRes) >> 16
355
   // less precise method: (readRaw() * refRes) >> 16
286
-  return (((readRaw() >> 1) / 32768.0f) * refRes);
356
+  return ((readRaw() * RECIPROCAL(65536.0f)) * refRes - wireRes);
287
 }
357
 }
288
 
358
 
289
 /**
359
 /**
301
  * @return  Temperature in C
371
  * @return  Temperature in C
302
  */
372
  */
303
 float MAX31865::temperature(uint16_t adc_val) {
373
 float MAX31865::temperature(uint16_t adc_val) {
304
-  return temperature(((adc_val) / 32768.0f) * refRes);
374
+  return temperature(((adc_val) * RECIPROCAL(32768.0f)) * refRes - wireRes);
305
 }
375
 }
306
 
376
 
307
 /**
377
 /**
352
  * @param enable  whether to enable or disable the value
422
  * @param enable  whether to enable or disable the value
353
  */
423
  */
354
 void MAX31865::setConfig(uint8_t config, bool enable) {
424
 void MAX31865::setConfig(uint8_t config, bool enable) {
355
-  uint8_t t = readRegister8(MAX31865_CONFIG_REG);
356
-  if (enable)
357
-    t |= config;
358
-  else
359
-    t &= ~config; // disable
425
+  uint8_t t = stdFlags;
426
+  if (enable) t |= config; else t &= ~config;
360
   writeRegister8(MAX31865_CONFIG_REG, t);
427
   writeRegister8(MAX31865_CONFIG_REG, t);
361
 }
428
 }
362
 
429
 
369
 uint8_t MAX31865::readRegister8(uint8_t addr) {
436
 uint8_t MAX31865::readRegister8(uint8_t addr) {
370
   uint8_t ret = 0;
437
   uint8_t ret = 0;
371
   readRegisterN(addr, &ret, 1);
438
   readRegisterN(addr, &ret, 1);
372
-
373
   return ret;
439
   return ret;
374
 }
440
 }
375
 
441
 
380
  * @return       both register contents as a single 16-bit int
446
  * @return       both register contents as a single 16-bit int
381
  */
447
  */
382
 uint16_t MAX31865::readRegister16(uint8_t addr) {
448
 uint16_t MAX31865::readRegister16(uint8_t addr) {
383
-  uint8_t buffer[2] = {0, 0};
449
+  uint8_t buffer[2] = { 0 };
384
   readRegisterN(addr, buffer, 2);
450
   readRegisterN(addr, buffer, 2);
385
-
386
-  uint16_t ret = buffer[0];
387
-  ret <<= 8;
388
-  ret |= buffer[1];
389
-
390
-  return ret;
451
+  return uint16_t(buffer[0]) << 8 | buffer[1];
391
 }
452
 }
392
 
453
 
393
 /**
454
 /**
399
  */
460
  */
400
 void MAX31865::readRegisterN(uint8_t addr, uint8_t buffer[], uint8_t n) {
461
 void MAX31865::readRegisterN(uint8_t addr, uint8_t buffer[], uint8_t n) {
401
   addr &= 0x7F; // make sure top bit is not set
462
   addr &= 0x7F; // make sure top bit is not set
402
-  if (sclkPin == TERN(LARGE_PINMAP, -1UL, -1))
463
+  if (sclkPin == TERN(LARGE_PINMAP, -1UL, 255))
403
     SPI.beginTransaction(spiConfig);
464
     SPI.beginTransaction(spiConfig);
404
   else
465
   else
405
-    WRITE(sclkPin, LOW);
466
+    digitalWrite(sclkPin, LOW);
406
 
467
 
407
-  WRITE(cselPin, LOW);
468
+  digitalWrite(cselPin, LOW);
408
 
469
 
409
   #ifdef TARGET_LPC1768
470
   #ifdef TARGET_LPC1768
410
     DELAY_CYCLES(spiSpeed);
471
     DELAY_CYCLES(spiSpeed);
414
 
475
 
415
   while (n--) {
476
   while (n--) {
416
     buffer[0] = spiTransfer(0xFF);
477
     buffer[0] = spiTransfer(0xFF);
417
-    #ifdef MAX31865_DEBUG_SPI
418
-      SERIAL_ECHOLNPGM("buffer read ", n, " data: ", buffer[0]);
419
-    #endif
420
     buffer++;
478
     buffer++;
421
   }
479
   }
422
 
480
 
423
-  if (sclkPin == TERN(LARGE_PINMAP, -1UL, -1))
481
+  if (sclkPin == TERN(LARGE_PINMAP, -1UL, 255))
424
     SPI.endTransaction();
482
     SPI.endTransaction();
425
 
483
 
426
-  WRITE(cselPin, HIGH);
484
+  digitalWrite(cselPin, HIGH);
427
 }
485
 }
428
 
486
 
429
 /**
487
 /**
433
  * @param data  the data to write
491
  * @param data  the data to write
434
  */
492
  */
435
 void MAX31865::writeRegister8(uint8_t addr, uint8_t data) {
493
 void MAX31865::writeRegister8(uint8_t addr, uint8_t data) {
436
-  if (sclkPin == TERN(LARGE_PINMAP, -1UL, -1))
494
+  if (sclkPin == TERN(LARGE_PINMAP, -1UL, 255))
437
     SPI.beginTransaction(spiConfig);
495
     SPI.beginTransaction(spiConfig);
438
   else
496
   else
439
-    WRITE(sclkPin, LOW);
497
+    digitalWrite(sclkPin, LOW);
440
 
498
 
441
-  WRITE(cselPin, LOW);
499
+  digitalWrite(cselPin, LOW);
442
 
500
 
443
   #ifdef TARGET_LPC1768
501
   #ifdef TARGET_LPC1768
444
     DELAY_CYCLES(spiSpeed);
502
     DELAY_CYCLES(spiSpeed);
447
   spiTransfer(addr | 0x80); // make sure top bit is set
505
   spiTransfer(addr | 0x80); // make sure top bit is set
448
   spiTransfer(data);
506
   spiTransfer(data);
449
 
507
 
450
-  if (sclkPin == TERN(LARGE_PINMAP, -1UL, -1))
508
+  if (sclkPin == TERN(LARGE_PINMAP, -1UL, 255))
451
     SPI.endTransaction();
509
     SPI.endTransaction();
452
 
510
 
453
-  WRITE(cselPin, HIGH);
511
+  digitalWrite(cselPin, HIGH);
454
 }
512
 }
455
 
513
 
456
 /**
514
 /**
463
  * @return    the 8-bit response
521
  * @return    the 8-bit response
464
  */
522
  */
465
 uint8_t MAX31865::spiTransfer(uint8_t x) {
523
 uint8_t MAX31865::spiTransfer(uint8_t x) {
466
-  if (sclkPin == TERN(LARGE_PINMAP, -1UL, -1))
524
+
525
+  if (sclkPin == TERN(LARGE_PINMAP, -1UL, 255))
467
     return SPI.transfer(x);
526
     return SPI.transfer(x);
468
 
527
 
469
   #ifdef TARGET_LPC1768
528
   #ifdef TARGET_LPC1768
529
+
470
     return swSpiTransfer(x, spiSpeed, sclkPin, misoPin, mosiPin);
530
     return swSpiTransfer(x, spiSpeed, sclkPin, misoPin, mosiPin);
531
+
471
   #else
532
   #else
533
+
472
     uint8_t reply = 0;
534
     uint8_t reply = 0;
473
     for (int i = 7; i >= 0; i--) {
535
     for (int i = 7; i >= 0; i--) {
474
-      WRITE(sclkPin, HIGH);         DELAY_NS_VAR(spiDelay);
536
+      digitalWrite(sclkPin, HIGH);       DELAY_NS_VAR(spiDelay);
475
       reply <<= 1;
537
       reply <<= 1;
476
-      WRITE(mosiPin, x & _BV(i));   DELAY_NS_VAR(spiDelay);
477
-      if (READ(misoPin)) reply |= 1;
478
-      WRITE(sclkPin, LOW);          DELAY_NS_VAR(spiDelay);
538
+      digitalWrite(mosiPin, x & _BV(i)); DELAY_NS_VAR(spiDelay);
539
+      if (digitalRead(misoPin)) reply |= 1;
540
+      digitalWrite(sclkPin, LOW);        DELAY_NS_VAR(spiDelay);
479
     }
541
     }
480
     return reply;
542
     return reply;
543
+
481
   #endif
544
   #endif
482
 }
545
 }
483
 
546
 
484
 void MAX31865::softSpiBegin(const uint8_t spi_speed) {
547
 void MAX31865::softSpiBegin(const uint8_t spi_speed) {
485
-  #ifdef MAX31865_DEBUG
486
-    SERIAL_ECHOLNPGM("Initializing MAX31865 Software SPI");
487
-  #endif
548
+  DEBUG_ECHOLNPGM("Initializing MAX31865 Software SPI");
549
+
488
   #ifdef TARGET_LPC1768
550
   #ifdef TARGET_LPC1768
489
     swSpiBegin(sclkPin, misoPin, mosiPin);
551
     swSpiBegin(sclkPin, misoPin, mosiPin);
490
     spiSpeed = swSpiInit(spi_speed, sclkPin, mosiPin);
552
     spiSpeed = swSpiInit(spi_speed, sclkPin, mosiPin);
491
   #else
553
   #else
492
     spiDelay = (100UL << spi_speed) / 3; // Calculate delay in ns. Top speed is ~10MHz, or 100ns delay between bits.
554
     spiDelay = (100UL << spi_speed) / 3; // Calculate delay in ns. Top speed is ~10MHz, or 100ns delay between bits.
493
-    OUT_WRITE(sclkPin, LOW);
494
-    SET_OUTPUT(mosiPin);
495
-    SET_INPUT(misoPin);
555
+    pinMode(sclkPin, OUTPUT);
556
+    digitalWrite(sclkPin, LOW);
557
+    pinMode(mosiPin, OUTPUT);
558
+    pinMode(misoPin, INPUT);
496
   #endif
559
   #endif
497
 }
560
 }
498
 
561
 

+ 34
- 9
Marlin/src/libs/MAX31865.h View File

41
  */
41
  */
42
 #pragma once
42
 #pragma once
43
 
43
 
44
+//#define DEBUG_MAX31865
45
+
44
 #include "../inc/MarlinConfig.h"
46
 #include "../inc/MarlinConfig.h"
45
 #include "../HAL/shared/Delay.h"
47
 #include "../HAL/shared/Delay.h"
46
 #include HAL_PATH(../HAL, MarlinSPI.h)
48
 #include HAL_PATH(../HAL, MarlinSPI.h)
84
   MAX31865_4WIRE = 0
86
   MAX31865_4WIRE = 0
85
 } max31865_numwires_t;
87
 } max31865_numwires_t;
86
 
88
 
89
+#if DISABLED(MAX31865_USE_AUTO_MODE)
90
+  typedef enum one_shot_event : uint8_t {
91
+    SETUP_BIAS_VOLTAGE,
92
+    SETUP_1_SHOT_MODE,
93
+    READ_RTD_REG
94
+  } one_shot_event_t;
95
+#endif
96
+
87
 /* Interface class for the MAX31865 RTD Sensor reader */
97
 /* Interface class for the MAX31865 RTD Sensor reader */
88
 class MAX31865 {
98
 class MAX31865 {
89
 private:
99
 private:
97
     uint16_t spiDelay;
107
     uint16_t spiDelay;
98
   #endif
108
   #endif
99
 
109
 
100
-  float zeroRes, refRes;
110
+  float zeroRes, refRes, wireRes;
111
+
112
+  #if ENABLED(MAX31865_USE_READ_ERROR_DETECTION)
113
+    millis_t lastReadStamp = 0;
114
+  #endif
115
+
116
+  uint16_t lastRead = 0;
117
+  uint8_t lastFault = 0;
118
+
119
+  #if DISABLED(MAX31865_USE_AUTO_MODE)
120
+    millis_t nextEventStamp;
121
+    one_shot_event_t nextEvent;
122
+  #endif
123
+
124
+  uint8_t stdFlags = 0;
101
 
125
 
102
   void setConfig(uint8_t config, bool enable);
126
   void setConfig(uint8_t config, bool enable);
103
 
127
 
110
 
134
 
111
   void softSpiBegin(const uint8_t spi_speed);
135
   void softSpiBegin(const uint8_t spi_speed);
112
 
136
 
137
+  void initFixedFlags(max31865_numwires_t wires);
138
+
139
+  void enable50HzFilter(bool b);
140
+  void enableBias();
141
+  void oneShot();
142
+  void resetFlags();
143
+
113
 public:
144
 public:
114
-  #ifdef LARGE_PINMAP
145
+  #if ENABLED(LARGE_PINMAP)
115
     MAX31865(uint32_t spi_cs, uint8_t pin_mapping);
146
     MAX31865(uint32_t spi_cs, uint8_t pin_mapping);
116
     MAX31865(uint32_t spi_cs, uint32_t spi_mosi, uint32_t spi_miso,
147
     MAX31865(uint32_t spi_cs, uint32_t spi_mosi, uint32_t spi_miso,
117
              uint32_t spi_clk, uint8_t pin_mapping);
148
              uint32_t spi_clk, uint8_t pin_mapping);
121
              int8_t spi_clk);
152
              int8_t spi_clk);
122
   #endif
153
   #endif
123
 
154
 
124
-  void begin(max31865_numwires_t wires, float zero, float ref);
155
+  void begin(max31865_numwires_t wires, float zero_res, float ref_res, float wire_res);
125
 
156
 
126
   uint8_t readFault();
157
   uint8_t readFault();
127
   void clearFault();
158
   void clearFault();
128
 
159
 
129
-  void setWires(max31865_numwires_t wires);
130
-  void autoConvert(bool b);
131
-  void enable50HzFilter(bool b);
132
-  void enableBias(bool b);
133
-  void oneShot();
134
-
135
   uint16_t readRaw();
160
   uint16_t readRaw();
136
   float readResistance();
161
   float readResistance();
137
   float temperature();
162
   float temperature();

+ 2
- 8
Marlin/src/module/temperature.cpp View File

2202
     #elif TEMP_SENSOR_IS_MAX(0, 31865)
2202
     #elif TEMP_SENSOR_IS_MAX(0, 31865)
2203
       max31865_0.begin(
2203
       max31865_0.begin(
2204
         MAX31865_WIRES(MAX31865_SENSOR_WIRES_0) // MAX31865_2WIRE, MAX31865_3WIRE, MAX31865_4WIRE
2204
         MAX31865_WIRES(MAX31865_SENSOR_WIRES_0) // MAX31865_2WIRE, MAX31865_3WIRE, MAX31865_4WIRE
2205
-        OPTARG(LIB_INTERNAL_MAX31865, MAX31865_SENSOR_OHMS_0, MAX31865_CALIBRATION_OHMS_0)
2205
+        OPTARG(LIB_INTERNAL_MAX31865, MAX31865_SENSOR_OHMS_0, MAX31865_CALIBRATION_OHMS_0, MAX31865_WIRE_OHMS_0)
2206
       );
2206
       );
2207
-      #if defined(LIB_INTERNAL_MAX31865) && ENABLED(MAX31865_50HZ_FILTER)
2208
-        max31865_0.enable50HzFilter(1);
2209
-      #endif
2210
     #endif
2207
     #endif
2211
 
2208
 
2212
     #if TEMP_SENSOR_IS_MAX(1, 6675) && HAS_MAX6675_LIBRARY
2209
     #if TEMP_SENSOR_IS_MAX(1, 6675) && HAS_MAX6675_LIBRARY
2216
     #elif TEMP_SENSOR_IS_MAX(1, 31865)
2213
     #elif TEMP_SENSOR_IS_MAX(1, 31865)
2217
       max31865_1.begin(
2214
       max31865_1.begin(
2218
         MAX31865_WIRES(MAX31865_SENSOR_WIRES_1) // MAX31865_2WIRE, MAX31865_3WIRE, MAX31865_4WIRE
2215
         MAX31865_WIRES(MAX31865_SENSOR_WIRES_1) // MAX31865_2WIRE, MAX31865_3WIRE, MAX31865_4WIRE
2219
-        OPTARG(LIB_INTERNAL_MAX31865, MAX31865_SENSOR_OHMS_1, MAX31865_CALIBRATION_OHMS_1)
2216
+        OPTARG(LIB_INTERNAL_MAX31865, MAX31865_SENSOR_OHMS_1, MAX31865_CALIBRATION_OHMS_1, MAX31865_WIRE_OHMS_1)
2220
       );
2217
       );
2221
-      #if defined(LIB_INTERNAL_MAX31865) && ENABLED(MAX31865_50HZ_FILTER)
2222
-        max31865_1.enable50HzFilter(1);
2223
-      #endif
2224
     #endif
2218
     #endif
2225
     #undef MAX31865_WIRES
2219
     #undef MAX31865_WIRES
2226
     #undef _MAX31865_WIRES
2220
     #undef _MAX31865_WIRES

Loading…
Cancel
Save