MAX31865
Jump to navigation
Jump to search
From the datasheet we can read.
The MAX31865 is an easy-to-use resistance-to-digital converter optimized for platinum resistance temperature detectors (RTDs). An external resistor sets the sensitivity for the RTD being used and a precision delta-sigma ADC converts the ratio of the RTD resistance to the reference resistance into digital form. The MAX31865’s inputs are protected against overvoltage faults as large as ±45V. Programmable detection of RTD and cable open and short conditions is included.
Basic software controls
Configuration
There is a single configuration register (0x00). In the C library, that is provided in the max31865_init() function.
Bit 0 Filter, 0=60Hz, 1=50Hz
Bit 1:3 Fault Detection, see datasheet for details.
Bit 4 Mode, 1=3-wire, 0=2- or 4-wire
Bit 5 One-shot, makes a single conversion, and must then be written again.
Bit 6 Auto mode 1=On, 0=Off
Bit 7 VBIAS, 1=On, 0=Off
Register list
0x00 Configuration 0x01 RTD MSB 0x02 RTD LSB 0x03 High Fault Threshold MSB 0x04 High Fault Threshold LSB 0x05 Low Fault Threshold MSB 0x06 Low Fault Threshold LSB 0x07 Fault
SPI Settings
On STM32, the default SPI configuration should work. That is Motorola frame format, 8 bits data size, MSB first, Clock Polarity Low and Clock Phase 1 edge.
Multiple Register Reads
It doesn't seem like the device allows us to read more than one register at a time.
Operation
- Read the RTD MSB (0x01) and RTD LSB (0x02) registers.
- Check whether Bit 0 in RTD LSB register is 1, then handle Faults. Otherwise, continue
- Convert the raw bits from ADC to resistance
- Look up resistance in conversion table (dep on RTD type)
- Linerize between two temperature entrances in the table.
Data Offset
The RTD LSB/MSB registers are left-shifted once, and bit0 indicates that there is a fault.
Conversion Algorithm (Java)
void run()
{
if( ( rtdLsb & 1 ) == 1 )
{
// fault detected
invalidate(input);
} else
{
adc = ( rtdLsb + rtdMsb1 * 256.0 ) / 2.0;
rtd = ( adc * refResistance ) / 32768;
double measuredTemperature = convert( sensorType, rtd1 );
double filtered = input * filter + measuredTemperature * ( 1 - filter );
input = filtered;
}
}
double convert( SensorType type, double resistance )
{
int first = (int) type.first();
double[] lookupTable = type.lookupTable();
if( resistance < lookupTable[ 0 ] || resistance > lookupTable[ lookupTable.length - 1 ] )
{
throw new IllegalArgumentException( "Measured resistance out of range: " + resistance );
}
int step = (int) type.step();
int index = -first / step;
int jumpSize = 5;
double value;
while( true )
{
double lookup1 = lookupTable[ index ];
if( lookup1 <= resistance )
{
double lookup2 = lookupTable[ index + 1 ];
if( lookup2 > resistance )
{
// found value
value = linearize( resistance, ( index + first ) * step, ( index + first + 1 ) * step, lookup1, lookup2 );
break;
} else
{
// jump higher
if( jumpSize > 1 )
{
jumpSize = jumpSize - 1;
}
index = index + jumpSize;
}
} else
{
double lookup3 = lookupTable[ index - 1 ];
if( lookup3 < resistance )
{
// found value
value = linearize( resistance, ( index + first ) * step, ( index + first - 1 ) * step, lookup1, lookup3 );
break;
} else
{
// jump lower
if( jumpSize > 1 )
{
jumpSize = jumpSize - 1;
}
index = index - jumpSize;
}
}
}
return value;
}
double linearize( double input, double y1, double y2, double x1, double x2 )
{
double k = ( y1 - y2 ) / ( x1 - x2 );
double m = y1 - ( k * x1 );
return input * k + m;
}