RTD / PT100 1000 measurement: Library for MCP 3551 22bit ADC.

Also I'm not sure how the 16 bit operations are handled on the 8 bit AVR. So there is a good change for whatever reason to have a division by zero.

it is not 16 bit problem, it is a float (32bit IEEE754) problem.

The only thing I can remember right now was that direct multiplication between calRAdevice and byteCode will always result in an overflow.

what are typical values for bytecode?

robtillaart:
ovf stands for OVERFLOW, so the value exceeds the limits of print.cpp A fix to be able to print the whole value exists here - Proposed update for the printFloat code of print.cpp - Libraries - Arduino Forum -

Can you give the source of the math?

I checked byteCode in serial and have seen that it is alternating between 0 and 2097151-2097140).

2097152.0 has so many digits the float precision might be corrupted: 2097152.0 - 2097151 ==> might be 0 ==> causing a divide by zero

can you change these lines to check?

...

if (rtdReady)
  {
    // calculate RTD acc. MCP AN1154:
    float divider = 2097152.0 - float(myRTD.byteCode;
    Serial.print("divider: ");
    Serial.println(divider, 4);
   
    RTD = calRAdevice1 * float(myRTDbyteCode) / divider;   
...

I changed the lines as you suggested, please find the code and serial data below..
CODE:

#include <LiquidCrystal.h>
#include <MCP3551.h>
#include <SPI.h>
LiquidCrystal lcd(7, 6, 5, 4, 3, 2);

const int pushButton = 8;
const int MCPPin = 53;
float calRAdevice1 = 13340;
float RTD;
const int RZero = 100;
MCP3551 myRTD(MCPPin);
void setup() {
  Serial.begin(9600);
  lcd.begin(16, 2);  
  lcd.setCursor(0, 0);                                           
  lcd.print("MCP3551& PT100");   
  delay (1000);
  pinMode(pushButton, INPUT);
}
void loop() {  
  int buttonState = digitalRead(pushButton);
  bool rtdReady = myRTD.getCode();
  if(rtdReady)
  { // Serial.println(getRTD1.byteCode);    
    //calculate RTD acc. MCP AN1154:    
    float divider = 2097152.0 - float(myRTD.byteCode);
    Serial.print("divider: ");
    Serial.println(divider, 4);    
    RTD = calRAdevice1 * float(myRTD.byteCode) / divider; 
    //This is part of a calculation for T(RTD)
    RTD = (RTD / RZero) - 1;
    float temperature = (RTD * (255.8723 + RTD * (9.6 + RTD * 0.878)));    
    Serial.println("Temperature: "); 
    Serial.println(temperature);
    Serial.println("code "); 
    Serial.println((float(myRTD.byteCode)));
    Serial.println("RTD "); 
    Serial.println(RTD);    
    lcd.setCursor(0, 0);                                          
    lcd.print("TEMPERATURE ");                                   
    lcd.setCursor(0, 1);                                          
    lcd.print(temperature);
    delay (1000);
    // A simple method for calibration at 0°C with iced water:
    if (buttonState){
      char n=0;
      float temp=0;
      do 
      {
        if (myRTD.getCode());
        {
          temp+= float(myRTD.byteCode);
          n++;
        } 			
      }
      while (n<10); 
      temp /= 10;	
      calRAdevice1 = RZero;
      calRAdevice1 /= ( temp /( 2097152.0 - temp)); 
      delay(2000);
      Serial.print("Ra: "); 
      Serial.println(calRAdevice1);
    }
  }
}

SERIAL DATA:

divider: 2097151.0000
Temperature: 
-247.14
code 
1.00
RTD 
-1.00
divider: 2097152.0000
Temperature: 
-247.15
code 
0.00
RTD 
-1.00
divider: 2097152.0000
Temperature: 
-247.15
code 
0.00
RTD 
-1.00
divider: 2097152.0000
Temperature: 
-247.15
code 
0.00
RTD 
-1.00
divider: 2097152.0000
Temperature: 
-247.15
code 
0.00
RTD 
-1.00
divider: 2097152.0000
Temperature: 
-247.15
code 
0.00
RTD 
-1.00
divider: 2097152.0000

k4ktus:

RTD = calRAdevice1 * (float(myRTD.byteCode) / ( 2097152.0 - float(myRTD.byteCode)));

this is now also strange to me :smiley:
The only thing I can remember right now was that direct multiplication between calRAdevice and byteCode will always result in an overflow.

As in my previous post, I checked the setup in UNO over a month satisfactorily. I was about to check the setup in a nearby calibration lab for accuracy (I cross checked with ice and a mercury thermometer[lab grade, calibrated, upto 110C) and thought that it will be nice to change to MEGA(my bad). I made lot of testing and calculations throughout the month, One of them was to check with a trim pot as input and observe the relation between byte code, temperature and RTD. I checked with different resistor values, please see it below

Trim pot as PT100 >    0        10      25       50       100        150      200      250      300       350      500      800
CODE               >   25      2045    3610      7492     15280      22911     30386     37670     44985     52130    73078   112270
TEMP             >   -246    -215   -191     -130     -5.4      123.4   255.5    390.9    534.2   681.8   1165      2332
RTD                >  -1          -0.87  -0.77    -0.52    -0.02    0.47    0.96       1.44     1.92    2.40    3.82      6.55

I put the values in excel and got a straight line stating that the setup is liner. So I wonder what caused suddenly the working setup just moved to MEGA caused it to stop working :frowning:

Have you measured you resistors? Are they both 6.8 kOhm?
How you have connected the RTD? Two, three, or four conductor?
Looks to me like the values of Ra not correct, because the hardware seems to work well. Or you just measuring the wrong pair of conductors.

Yes. I measured and tried with different resistors for RA and Rb(6.8k). Also checked PT100( shows 112 ohm) . I even connected 100 ohm resistor in place of PT100. Also changed Another MCP3551. Code is either 0 or 2^21. Is ADC working in that case?

weird...
do you have a voltmeter/scope to check the voltage level that enters the ADC, does it shows 'normal' behavior ?

Yes. Really weird. And it seems I am the only person testing this circuit and sketch.
I checked all the voltages. VREF and VDD getting +5V. Pin 2 & 3(where PT100 connected) showing +5V. Pin 5(SCK) showing 1-1.4 mV. Pin 6(MISO) showing 9-18 mV. Pin 7(CS) showing +5V. Is everuthing Ok?. I am not sure about these values since I didn't checked it when the time its worked :frowning:

robtillaart,
You saved my life. As you can see in my previous post, I checked all the voltages and posted it. Then suddenly it sparked me that if both the PT100 pins feeding +5V, then how it can convert the temp to voltages. Then I connected a ground pin to Pin number 3 which was there in the original diagram, but the jumper in between confused me. Also last time when I connected this circuit to UNO, I didn't connect this pin to ground. Now I wonder how I was getting correct reading before :P. I think sometimes the Pin4(Ground) is accidentally touching the pin 3. Anyway, robtillaart, thank you for your advice's and valuable help. k4ktus, many many thanks for your wonderful effort and kind help...

welcome

Yeah this jumpers are really weird! But the use of them is for connecting 3 and 4 wires to compensate cable length.

Hi there,

Am I missng something? What schematic are you guys talking about? The AN1154 does not cover 4 wire PT100´s. So is there any schematic for this circuit to use with wire lenght compensation? Or do you just refer to the MCP3551 Datasheet?

THX,
J.

You have just to change the wiring to add the compensate wires in row to the Ra resistor.

for example:

what I've done, was to put two jumpers to switch between 2 and 3,4 wire configuration. And this may be a little bit weird.

You can see the shematic somewhere on my blog.

Hi Everybody,
Now I am happy that past two months my temperature measurement setup working great( thanks again k4ktus :). Now I want make it as a 8 channel setup. I have seen a very nice article with CD4052 multiplexer in " http://openenergymonitor.org/emon/buildingblocks/rtd-temperature-sensing " but it is an analog circuit and I am not sure how to implement the same here. Any ideas??

Hi, I'm wondering if someone can help a novice. Without a firm schematic for an Arduino, I'm a little unsure I've connected everything correctly.

From the MCP3551 to the Arduino Uno I have:

MCP3551 pin 6 (SDO/RDY) to Arduino 11 (MOSI)
MCP3551 pin 5 (SCK) to Arduino 13 (SCK)

Another point of confusion: I have a PT100 with two red wires and a white wire. I am connecting them as follows.. is this correct?

red wire to MCP3551 pin 2 (VIN+)
red wire to MCP3551 pin3 (VIN-)
white wire to 6.8k resistor to 3.3v rail (and 1uf capacitor to GND).

I also have:
MCP3551 pin 1 (VREF) to 3.3v rail
MCP3551 pin 4 (VSS) to GND
MCP3551 pin 7 (CS) to GND
MCP3551 pin 8 (VDD) to 3.3v rail (and 1uf capacitor to GND).

Arduino pin 2 to Arduino GND, to avoid the buttonState calibration logic.

When I run the Arduino sketch I get a constant temperature of -247.15 (myRTD.byteCode is 0).

Not sure where to start debugging, so any help would be appreciated.

scott459,
I am also newbie..
My connection looks like below and its working!!

  1. CHANGE MCP3551 pin 6 (SDO/RDY) to Arduino MISO
  2. CHANGE MCP3551 pin 7 (CS) to Dig pin10(SS)

Another point of confusion: I have a PT100 with two red wires and a white wire. I am connecting them as follows.. is this correct?

Findout common wire using multimeter( you have two red, so it must be common. To findout connect a multimeter and check which wires giving around 110 ohms(ambient temp) and connect those wires to MCP3551 pin 2 (VIN+) and MCP3551 pin3 (VIN-). Connect common wire to ground.

I also have: (You need to study schematics :slight_smile: so study well the same. Tip: you need some corrections to the below..rest are fine :slight_smile:
MCP3551 pin 1 (VREF) to through 3.3v rail
MCP3551 pin 4 (VSS) to GND
MCP3551 pin 7 (CS) to GND
MCP3551 pin 8 (VDD) to 3.3v rail (and 1uf capacitor to GND).

Ah, thank you, I finally got it working.

I had previously caught my MOSI pin error, but still had a few things backwards.

And just to clarify, the two red wires have no measurable resistance between them, but when I connect either to the white wire, it's about 110 ohms. Given that, I connected the white wire to MCP3551 pin 2 (VIN+) and one of the red wires to MCP3551 pin 3 (VIN-). And the other red wire to GND. Does that seem right to you?

Thanks again,
scott

Congratulations!
The purpose of the third wire is for the cancallation of line resistance. The way we connected this 3 wire RTD will help to eliminate the error due to the connector length resistonce(I believe!). So you are absolutely right. :slight_smile:

Hi,
I wanted to make it to a 4 channel thermometer. I tried to interface with a CD4051 multiplexer but not succeeded. So now I had setup two MCP3551 circuits and attached the SS pins from each circuit to different digital pins. Now two channel are working fine. But I wanted to make sure the software modifications I made are correct or if any better way to do it. Any help is appreciated.. Please find my sketech below..

#include <MCP3551.h>
#include <SPI.h>
// Slave select pin:
const int MCPPin1 = 46;
const int MCPPin2 = 47;
const int MCPPin3 = 48;
const int MCPPin4 = 53;
float calRAdevice1 = 13340; //stores the series resistor value 
float RTD; //resistor of RTD
const int RZero = 100; //resistance at 0°C
//create a instance with IC connect to SCK, MOSI and SS (MCPPin):
MCP3551 myRTD1(MCPPin1);
MCP3551 myRTD2(MCPPin2);
MCP3551 myRTD3(MCPPin3);
MCP3551 myRTD4(MCPPin4);

// the setup routine runs once when you press reset:
void setup() {  
  Serial.begin(9600);  
}
void loop()
{
  bool rtdReady = myRTD1.getCode();
  if(rtdReady)  {
    RTD = calRAdevice1 * (float(myRTD1.byteCode) / ( 2097152.0 - float(myRTD1.byteCode))); 
    RTD = (RTD / RZero) - 1;
    float temperature1 = (RTD * (255.8723 + RTD * (9.6 + RTD * 0.878)));    
    Serial.print("Temperature1: "); 
    Serial.println(temperature1);
  }   
  delay(100);
  {   
    bool rtdReady = myRTD2.getCode();
    if(rtdReady)
    { 
      RTD = calRAdevice1 * (float(myRTD2.byteCode) / ( 2097152.0 - float(myRTD2.byteCode))); 
      RTD = (RTD / RZero) - 1;
      float temperature2 = (RTD * (255.8723 + RTD * (9.6 + RTD * 0.878)));    
      Serial.print("Temperature2: "); 
      Serial.println(temperature2);
    }   
    delay(1000);
  }
}

Hi,
I am interested in the hardware part of this setup.
I was not able to get the schematic, the links in the first post are now connecting to some other language pages.
Please give a link to schematics.

Hi there,

i have same problem like arduinofankerala.
The wiring is done like equation 1, i use also the arduino uno. 2x 6,8k resistors with 0,1% precision.

Temperature in serial monitor is shown like this: Temperature: -247.15

An these are the voltages on the mcp 3551
Pin 1 2,5 V
The voltage between pin 2 & 3 is 40mV
Pin 5 1,1 mV
Pin 6 5 V
Pin 7 5V

Did you have any ideas?

Thanks a lot
Bjoern