Platinum Rtd resolution

how do I use the pt100 or other rtd to get accurate and precise results around the boiling temperature of water. I would like resolution down to a tenth of a degree F. Do I sue a linear amplifier like an opamp and take the output into an analog input on the arduino? I am very open to suggestions, but keep it somewhat simple. Thanks... Jobie

jobierossell:
how do I use the pt100 or other rtd to get accurate and precise results around the boiling temperature of water. I would like resolution down to a tenth of a degree F. Do I sue a linear amplifier like an opamp and take the output into an analog input on the arduino? I am very open to suggestions, but keep it somewhat simple. Thanks... Jobie

I know some people are litigious but sueing an amplifier is taking things too far.

Your problem is the arduino o ly has a 10 bit A/D converter so that means low resoloution an a wide range or high resoloution and a narrow range.
There is no simple answer. It will involve making a complex circuit with an operational amplifier that has a 0 to 5 volt output when your resistance changes over a very small range. Also to maintain accuracy the other components in the circuit have to have a very stable temprature charastic.

You'll certainly want some precision resistors with low tempco, perhaps a precision
voltage reference driving an opamp current source, and a nice high resolution
ADC to read the resultant voltage?

Or you'll probably find someone sells a one-chip solution to the problem...

This might help

http://openenergymonitor.org/emon/buildingblocks/rtd-temperature-sensing

Or use a chip designed to work with PT100 or PT1000: MAX31865
And code I received from Atmel to read temperatures, in 2 parts:

MAX31865.pdf (1.53 MB)

/*******************************************************************************
* Copyright (C) 2013 Maxim Integrated Products, Inc., All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Except as contained in this notice, the name of Maxim Integrated 
* Products, Inc. shall not be used except as stated in the Maxim Integrated 
* Products, Inc. Branding Policy.
*
* The mere transfer of this software does not imply any licenses                                      
* of trade secrets, proprietary technology, copyrights, patents,
* trademarks, maskwork rights, or any other form of intellectual
* property whatsoever. Maxim Integrated Products, Inc. retains all 
* ownership rights.
*******************************************************************************
*/
#include <SPI.h>

//Registers defined in Table 1 on page 12 of the data sheet
static byte Configuration = 0b10000000; //0x80H                          
static byte read_Configuration = 0b00000000; //0x00H
static byte Write_High_Fault_Threshold_MSB = 0b10000011; //0x83H
static byte Write_High_Fault_Threshold_LSB = 0b10000100; //0x84H
static byte Read_High_Fault_Threshold_MSB =  0b00000011; //0x03H
static byte Read_High_Fault_Threshold_LSB =  0b00000100; //0x04H
static byte Write_Low_Fault_Threshold_MSB =  0b10000101; //0x85H
static byte Write_Low_Fault_Threshold_LSB =  0b10000110; //0x86H
static byte Read_Low_Fault_Threshold_MSB =   0b00000101; //0x05H
static byte Read_Low_Fault_Threshold_LSB =   0b00000110; //0x06H
static byte Fault_Status = 0b00000111; //0x07H

//Callendar-Van Dusen equation is used for temperature linearization. Coeffeicant of equations are as follows:
//R(T) = R0(1 + aT + bT^2 + c(T - 100)T^3)
//Equation from : http://www.honeywell-sensor.com.cn/prodinfo/sensor_temperature/technical/c15_136.pdf
static float a = 0.00390830;
static float b = -0.0000005775;
static float c = -0.00000000000418301;
float Reference_Resistor;                     //Reference Resistor installed on the board.
float RTD_Resistance;                         //RTD Resistance at 0 Degrees. Please refer to your RTD data sheet.

//local variables
double Temperature = 0;                        //Variable defined to read data from getTemp() and display on serial console.
byte Fault_Error = 0;                          //Variable to read Fault register and compute faults
byte value = 0;                                // defined a variable to display the contents on the serial output
const int slaveSelectPin = 52;                 //using Digital Pin 52 for Chip Select
int DRDY = 50;

/* Write(byte, byte) function requires the register address and the data to be written to the register provided when called in the respective sequence. 
Write function does require that slaveSelectPin is properly defined in the setup. Changing the variable name of slaveSelectPin would require a change in Write function "slaveSelectPin" name as well
*/
void Write(byte w_addr, byte data)
{ digitalWrite(slaveSelectPin,LOW);   
  SPI.transfer(w_addr);                 
  SPI.transfer(data);                
  digitalWrite(slaveSelectPin,HIGH);}

//Read function(byte ) accepts the register address to be read and returns the contents of the register to the loop function
  byte Read(byte r_addr)
  { digitalWrite(slaveSelectPin,LOW);
    SPI.transfer(r_addr);                 // read from configuration register
    value = SPI.transfer(0xFF);         // dummy write to provide SPI clock signals to read                                                                      
    digitalWrite(slaveSelectPin,HIGH); 
    return value;}


/* get_Temp() function checks if the fault bit (D0)of LSB RTD regiset is set. If so, the conversion is aborted. If the fault
bit is not set, the conversion is initiated. The Digital Code is then computed to a temperature value and printed on the serial console.

For linearization, Callendar-Van Dusen equation is used. 
R(T) = R0(1 + aT + bT^2 + c(T - 100)T^3)
*/
void get_Temp()
{  byte lsb_rtd = Read(0x02);  
   byte fault_test = lsb_rtd&0x01;
   while(fault_test == 0)
     { 
       if(digitalRead(DRDY) == 0)
         { byte msb_rtd = Read(0x01);                                             
           float RTD = ((msb_rtd << 7)+((lsb_rtd & 0xFE) >> 1));                 //Combining RTD_MSB and RTD_LSB to protray decimal value. Removing MSB and LSB during   shifting/Anding
           float R = (RTD*Reference_Resistor)/32768; //Conversion of ADC RTD code to resistance 
           float Temp = -RTD_Resistance*a + sqrt(RTD_Resistance*RTD_Resistance*a*a - 4*RTD_Resistance*b*(RTD_Resistance-R));                         //Conversion of RTD resistance to Temperature
           Temp = Temp/(2*RTD_Resistance*b);
           Serial.print("Temperature measured from RTD is: "); Serial.println(Temp, 4 );       //Printing Temperature on console
           delay(100);
           lsb_rtd = Read(0x02); 
           fault_test = lsb_rtd&0x01;
         }
      }
   Serial.println("Error was detected. The RTD resistance measured is not within the range specified in the Threshold Registers.");   
}
         
//Fault(byte) function requires the contents of the fault bit to be provided. It checks for the bits that are set and provides the faulty bit information on the serial console.
void Fault(byte fault)
    {Serial.println(fault, BIN);
      byte temp = 0;            //temporary variable created: Purpose is to find out which error bit is set in the fault register
      temp = fault & 0x80;      //Logic Anding fault register contents with 0b10000000 to detect for D7 error bit
      if(temp>0) {Serial.println("Bit D7 is Set. It's Possible your RTD device is disconnected from RTD+ or RTD-. Please verify your connection and High Fault Threshold Value");}
      temp = fault & 0x40;
      if(temp>0) {Serial.println("Bit D6 is Set. It's Possible your RTD+ and RTD- is shorted. Please verify your connection and your Low Fault Threshold Value."); }
      temp = fault & 0x20;
      if(temp>0){Serial.println("Bit D5 is Set. Vref- is greater than 0.85 * Vbias");}
      temp = fault & 0x10;
      if(temp>0){Serial.println("Bit D4 is Set. Please refer to data sheet for more information");}
      temp = fault &0x08;
      if(temp>0){Serial.println("Bit D3 is Set. Please refer to data sheet for more information");}
      temp = fault &0x04;
      if(temp>0){Serial.println("Bit D2 is Set. Please refer to data sheet for more information");}
    }

void setup() {  
  Serial.begin(9600);                            // Serial Communication Baud Rate
  pinMode (slaveSelectPin, OUTPUT);              // Defining CS terminal as Output
  pinMode (DRDY, INPUT);                         // DRDY termianl as Input
  SPI.begin();    
  SPI.setClockDivider(128);                      // Setting SPI clock to 625 MHz. Please note it is important to initialize SPI bus prior to making any changes.
  Serial.println("This is sample code of MAX31865 - RTD to Digital Converter:");
  Write(Configuration, 0b10000000);              //Enabling Vbias of max31865
  value = Read(read_Configuration);             //Reading contents of Configuration register to verify communication with max31865 is done properly
        if (value == 128)
            {   Write(Write_High_Fault_Threshold_MSB, 0xFF);   //Writing High Fault Threshold MSB
                Write(Write_High_Fault_Threshold_LSB, 0xFF);   //Writing High Fault Threshold LSB
                Write(Write_Low_Fault_Threshold_MSB,  0x00);   //Writing Low Fault Threshold MSB
                Write(Write_Low_Fault_Threshold_MSB,  0x00);   //Writing Low Fault Threshold LSB  
                Reference_Resistor = 4000;                     //Reference Resistor installed on EVM
                RTD_Resistance = 1000;                         //RTD Resistance at 0 Degrees
                Serial.println("Communication successful with max31865");} 
        else
            { Serial.println(" Unable to communicate with the device. Please check your connections and try again");}
  }


void loop() 
{     //Prior to getting started with RTD to Digital Conversion, Users can do a preliminary test to detect if their is a fault in RTD connection with max31865
      Fault_Error = Read(Fault_Status);         
      
      //If their is no fault detected, the get_Temp() is called and it initiates the conversion. The results are displayed on the serial console     
      if(Fault_Error == 0)
       {  Write(Configuration, 0b11000000);
          get_Temp();           //Calling get_Temp() to read RTD registers and convert to Temperature reading
        }
      else{
      //If a fault is detected, Fault register is called and list of faults are displayed in the Serial console. Users are expected to troubleshoot the faults prior to proceeding      
        Serial.println("Fault Detected. Please refer to fault bits below: ");
        Serial.println(" ");
        Fault(Fault_Error);
        Write(Configuration, 0b10000010);delay(700); //Fault register isn't cleared automatically. Users are expected to clear it after every fault.
        Write(Configuration, 0b11000000);delay(700); }    //Setting the device in autoconfiguration again.    
}
const int slaveSelectPin = 52;                 //using Digital Pin 52 for Chip Select
int DRDY = 50;

Written for a Mega, adjust as needed.

Nice...

jobierossell, you said resolution to a tenth of a degree. What about accuracy? Although that Maxim chip says it is 0.5C accuracy, that is over its entire operating range, so within a limited range, much better accuracy should be achievable.

Coincidentally, I just had someone ask me if I could build a platinum RTD temperature sensor with 0.1C resolution. Slightly easier to do that 0.1F.

@ cross roads,
have you got wiring sketch of the max31865 in circuit?

http://datasheets.maximintegrated.com/en/ds/MAX31865.pdf

2-wire connection on page 23.

I had 15 wired up like this on board.
'1284P and three 5V to 3.3V buffer chips.
SPI, MISO, MOSI in common, each chip with its own CS.

@ cross roads, for the Max31865, can you/I get more accuracy than 0.5C, I just want to measure the room temperature of water, 15-30C, I just checked the range of max is about -50~125C, so possible to get 0.05c if the range is narrow?

Or any suggestion to get 0.01-0.05C accuray with PT-RTD?

15-Bit ADC Resolution; Nominal Temperature Resolution 0.03125 degree C (Varies Due to RTD Nonlinearity)

So I'd say yes.