Correct Way To Use A Wheatstone Bridge

Hi there.
It's me again with my PT100 problem XD
In my last version, I used a voltage divider to calculate the resistance of the PT100 sensor, which worked just "OK" but, I'm not satisfied with it, I think that it still has room to upgrade a bit.
So I decided to use a Wheatstone Bridge instead of a voltage divider and this is my circuit:

As you can see, I'm using an ADS1015 (it's ADS1115 in the circuit but I have ADS1015) to measure the voltage in differential mode. In A0 and A1 I connect the output voltage of the Wheatstone bridge and to the A2 and A3, I connect the GND and VCC so I can measure the very exact VCC of the circuit for future calculations.

The resistors in the circuit are 100 Ohms but in the actual circuit on a breadboard, I measured each resistor's actual value and used that in the sketch, not just 100 Ohms.

Heres my sketch:

#include <Wire.h>
#include <Adafruit_ADS1015.h>

Adafruit_ADS1015 ads;     //Initialize ADS1015 12-bit ADC module

float WBVoltage = 0.0;  //Voltage measured from wheatstone bridge
float R1 = 96.7;  //resistance of 1st known resistors in wheatstone bridge
float R2 = 97.5;  //resistance of 2nd known resistors in wheatstone bridge
float R3 = 97;  //resistance of 3rd known resistors in wheatstone bridge
float Resistance = 0;  //resistance of unknown resistor AKA PT100 sensor
float Vin = 5;  //VCC Voltage of the circuit / wheatstone bridge
float Temperature; //The calculated temperature


void setup() {

  // initialize serial:
  Serial.begin(9600);

  //                                                                ADS1015  ADS1115
  //                                                                -------  -------
  ads.setGain(GAIN_TWOTHIRDS);     // 2/3x gain +/- 6.144V  1 bit = 3mV      0.1875mV (default)
  // ads.setGain(GAIN_ONE);        // 1x gain   +/- 4.096V  1 bit = 2mV      0.125mV
  // ads.setGain(GAIN_TWO);        // 2x gain   +/- 2.048V  1 bit = 1mV      0.0625mV
  // ads.setGain(GAIN_FOUR);       // 4x gain   +/- 1.024V  1 bit = 0.5mV    0.03125mV
  // ads.setGain(GAIN_EIGHT);      // 8x gain   +/- 0.512V  1 bit = 0.25mV   0.015625mV
  // ads.setGain(GAIN_SIXTEEN);    // 16x gain  +/- 0.256V  1 bit = 0.125mV  0.0078125mV

  ads.begin();
}

void loop() {

  int16_t WB; //This will contain the diffrential value of Wheatstone Bridge output

  /* Be sure to update this value based on the IC and the gain settings! */
  float   multiplier = 3.0F;    /* ADS1015 @ +/- 6.144V gain (12-bit results) */
  //float multiplier = 0.1875F; /* ADS1115  @ +/- 6.144V gain (16-bit results) */

  WB = ads.readADC_Differential_0_1();
  WBVoltage = WB * multiplier / 1000;

  int16_t VCC; //This will contain the diffrential value of VCC voltage

  // Be sure to update this value based on the IC and the gain settings!
  float   multiplier2 = 3.0F;    // ADS1015 @ +/- 6.144V gain (12-bit results)
  //float multiplier = 0.1875F; // ADS1115  @ +/- 6.144V gain (16-bit results)

  VCC = ads.readADC_Differential_2_3();
  Vin = VCC * multiplier2 / 1000;
  Resistance = ((R2 * R3) + (R3 * (R1 + R2) * WBVoltage / Vin)) / (R1 - (R1 + R2) * WBVoltage / Vin);  //WB equation for calculating the unknown resistor AKA PT100
  Temperature = (Resistance * 2.6) - 260;  //Calculate the temperture


  Serial.println("--------------------");
  Serial.println(" ");
  Serial.print("Voltage: ");
  Serial.println(WBVoltage, 5);  //Print the measured voltage from WB
  Serial.println(" ");
  Serial.print("VCC: ");
  Serial.println(Vin);  //Print the VCC voltage
  Serial.println(" ");
  Serial.print("Resistance: "); 
  Serial.println(Resistance, 5);  //Print the calculated resistance of unknown resistor AKA PT100
  Serial.println(" ");
  Serial.println("--------------------");
  Serial.println(" ");
  Serial.print("Temp: ");
  Serial.println(Temperature);
  Serial.println(" ");
  Serial.println("--------------------");
  Serial.println(" ");

  delay(750);
 
}

Now let's get to my problem,
In action, everything works fine, calculations are correct the measured value is correct and relatively stable, the only thing that makes everything useless is that the calculated resistance I get is wrong.
For example, when the serial shows the resistance of 123 Ohms, the actual resistance is about 111 or so.

The equation I'm using for converting the measured voltage into resistance is this:

  Resistance = ((R2 * R3) + (R3 * (R1 + R2) * WBVoltage / Vin)) / (R1 - (R1 + R2) * WBVoltage / Vin);

I got this equation from this website. you can see it at the very end of this page.
And if I insert my measured voltage in the website, It gives the same value that I already calculated.

I thought that it may be because of the current that is going through the PT100, I measured the current, and its 20mA.
It's relatively small, but even if this is the problem, the resistance of the PT100 should stay high after I disconnected it from the circuit to measure the resistance with my multi-meter, and then drop slowly in few seconds. but it's not like that, it's just that same 111 Ohms or something near that which means 25°C.

So I don't know what else can be the problem, I'd appreciate any help and advice.

In this case, use of the Wheatstone bridge does not help you at all, and in fact it introduces additional errors due to the two extra resistors.

Your basic approach in using the absolute ADC to measure Vcc is correct, and will work fine with just one resistor and one PT100. But using the ADS1015 will give very poor temperature resolution.

Here is the code I use for a similar setup with the ADS1115 and two voltage dividers, consisting of 1K resistors and PT1000 sensors. I calibrated each probe against a professional thermometer, and the results are accurate to about +/- 0.1 Celsius. I average 100 readings per sample.

#include <Wire.h>
#include <Adafruit_ADS1015.h>

Adafruit_ADS1115 ads;

unsigned long currentM, lastM;
void setup(void)
{
  Serial.begin(9600);
  Serial.println("ADS1115 ADC");

  Serial.println("Single-ended readings from AIN0..3");
  Serial.println("ADC Range: +/- 6.144V (1 bit = 0.1875mV/ADS1115)");

  // The ADC input range (or gain) can be changed via the following
  // functions, but be careful never to exceed VDD +0.3V max, or to
  // exceed the upper and lower limits if you adjust the input range!
  // Setting these values incorrectly may destroy your ADC!
  //                                                                ADS1015  ADS1115
  //                                                                -------  -------
  // ads.setGain(GAIN_TWOTHIRDS);  // 2/3x gain +/- 6.144V  1 bit = 3mV      0.1875mV (default)
  // ads.setGain(GAIN_ONE);        // 1x gain   +/- 4.096V  1 bit = 2mV      0.125mV
  // ads.setGain(GAIN_TWO);        // 2x gain   +/- 2.048V  1 bit = 1mV      0.0625mV
  // ads.setGain(GAIN_FOUR);       // 4x gain   +/- 1.024V  1 bit = 0.5mV    0.03125mV
  // ads.setGain(GAIN_EIGHT);      // 8x gain   +/- 0.512V  1 bit = 0.25mV   0.015625mV
  // ads.setGain(GAIN_SIXTEEN);    // 16x gain  +/- 0.256V  1 bit = 0.125mV  0.0078125mV

  ads.begin();
}

long adc_long, adc_short, adc_vcc, adc_gnd;
float avg_dif=0;
float alpha = 0.5;

void loop(void)
{

  adc_long = 0;
  adc_short = 0;
  adc_vcc = 0;
  adc_gnd = 0;

  for (int i = 0; i < 100; i++) {
    adc_long += (signed long) ads.readADC_SingleEnded(0);
    adc_short += (signed long) ads.readADC_SingleEnded(1);
    adc_vcc += (signed long) ads.readADC_SingleEnded(2);
  }
  adc_long /= 100;
  adc_short /= 100;
  adc_vcc /= 100;
/*  
  Serial.print (adc_long);
  Serial.print( ", ");
  Serial.print (adc_short);
  Serial.print( ", ");
  Serial.print (adc_vcc);
  Serial.println();
*/
  float R_long = 1000.*adc_long / (adc_vcc - adc_long);
  float R_short = 1000.*adc_short / (adc_vcc - adc_short);
 // Serial.print(R_long);
//  Serial.print(", ");
//  Serial.print(R_short);
//  Serial.print(", ");
 float Tc_long = (R_long -1000.8)/3.808 - 0.054; //empirical offset to ice at 0
 float Tc_short = (R_short - 1005.8) / 3.776;
// avg_dif = (1.0-alpha)*avg_dif + alpha*(Tc_long-Tc_short);
  Serial.print(Tc_long);
  Serial.print(",");
  Serial.println(Tc_short);
//  Serial.print(", ");
//  Serial.println(avg_dif);
 }

jremington:
Your basic approach in using the absolute ADC to measure Vcc is correct, and will work fine with just one resistor and one PT100. But using the ADS1015 will give very poor temperature resolution.

If I understand you correctly, you mean the 12bit ADC won't help me right? That's right, I ordered an ADS1115 module online and got an ADS1115, but after the first use, I realized that I got scammed!! The IC on the board was actually an ADS1015, so now I have to stick with it anyway until I buy another one, I cant order directly from Adafriut or Amazon or eBay and I have to buy my electronic devices from local shops, hopefully, next time it won't be like that...

jremington:
Here is the code I use for a similar setup with the ADS1115 and two voltage dividers, consisting of 1K resistors and PT1000 sensors. I calibrated each probe against a professional thermometer, and the results are accurate to about +/- 0.2 Celsius. I average 100 readings per sample.

Thank you for the code, but can you please give me a schematic too? or maybe better if you add some comments in your code.

jremington:
Your basic approach in using the absolute ADC to measure Vcc is correct, and will work fine with just one resistor and one PT100. But using the ADS1015 will give very poor temperature resolution.

Also about the ADS1015, it's not giving me a good resolution but it's also not giving me a wrong measurement, the measured voltage is very accurate according to my multi-meter as reference. so I think the ADC is not my actual problem, I think it should be something with the equation or the hardware.

Schematic for my setup below, with two independent temperature sensors.

The 12 bit ADC is certainly better than the Arduino 10 bit ADC. You can work out what temperature resolution to expect, knowing that the PT100 sensor resistance changes by about 0.38 Ohms per degree C. By oversampling and averaging you could extend the ADC resolution to 13 or 14 bits.

PT1000.png

PT1000.png

jremington:
Schematic for my setup below, with two independent temperature sensors.

The 12 bit ADC is certainly better than the Arduino 10 bit ADC. You can work out what temperature resolution to expect, knowing that the PT100 sensor resistance changes by about 0.38 Ohms per degree C. By oversampling and averaging you could extend the ADC resolution to 13 or 14 bits.

What's the point of having 2 sensors? I need my circuit to work with only 1. do you mean I should use the voltage divider solution for 1 sensor? I had some research about PT100 in industrial applications and they all use Wheatstone bridge.

For my project, two sensors are used to measure two temperatures.

Compared to a professional grade recording thermometer, with this setup my measurements are accurate to +/- 0.1 degree C, between 0 and 80 C. The noise level is similar.

What about a MAX31865 - this is an A/D designed for use the with pt100. Adafruit make a board with it on .

There is a good guide with it to using prt sensors , lead compensation etc . You should only pass a small current through the prt ( say 1mA)....

Or as said before , throw away and use a ds18b20

Or as said before , throw away and use a ds18b20

That would be my move.

hammy:
What about a MAX31865 - this is an A/D designed for use the with pt100. Adafruit make a board with it on .

https://www.amazon.co.uk/Adafruit-PT100-Temperature-Sensor-Amplifier/dp/B01N4LEVZN

As I said, I can't order anything from Adafriut, Amazon, eBay, etc :frowning: for some reasons that if say them here it would distract the topic.
And I couldn't find the MAX31865 in local shops. I did a bit of research and the IC is just basically a 16Bit ADC and some other stuff that I can build by myself, and so I'm trying to do so

Or as said before , throw away and use a ds18b20

My application is an Industrial application, this device should show the temperature of an industrial oven which heats up to about 150°C, so I have to do some standards. I couldn't find any device that takes PT100 input and gives me an output for a big seven-segment, so I just designed a big seven-segment and now I'm trying to improve the old temperature unit

guys please just tell me how to fix my circuit, I know all the alternatives that I have, but I just need to do it this way :slight_smile:
All I need to do is to measure resistance with a Wheatstone bridge! that's it!

The HX711 is another chip that's designed for use with Wheatstone bridges. It's commonly used with load cells, which are also read in Wheatstone bridge configuration. A quick Google search shows it should be possible to use that with a PT100, so maybe it's worth checking out.

In order to solve the equation, I need to know the voltage across Vout+ and Vout - for a given measured
resistance of PT100.
Your statement here:

In action, everything works fine, calculations are correct the measured value is correct and relatively stable, the only thing that makes everything useless is that the calculated resistance I get is wrong.
For example, when the serial shows the resistance of 123 Ohms, the actual resistance is about 111 or so.

does NOT supply that information.
MEASURE the voltage from Vout+ to Vout-
THEN measure the voltage ACROSS the R3, R1, & R2
WHY ?
Think about it.
If the equation for current is I=V/R and R3 is 100 ohms, then at 0 degree C, the PT100 resistance
is 100 ohms and the current through the PT100 is Vout+/100 ohms =[5V*R3/(100+100)] /0.025A (25mA)
The resistance of R1, R2 & R3 is 100 ohms.
R1 and R2 are in parallel. 5V/(100+100) = 5/200=0.025A (25mA)
If you measure the voltage ACROSS R3, that tells you the CURRENT through R3.
If you measure 2.369V across R3, then 0.02369A is going through R3 AND the PT100, and thus the voltage across
the PT100 = 5V-2.369V= 2.361V.
2.361V/0.02369A = 111.48 ohms = PT100 resistance.
From the table you can see the PT100 resistance is 107.7928 at 20 degrees and 111.6718 at 30 degree so it changes 0.3879 ohms per degree.
R1 & R2 are /2 voltage divider so the voltage at Vout- should be 5V/2=2.5V.
If you measure 2.361 volts at Vout+ and 2.5V at Vout- then the voltage across Vo+ and Vo- is 2.361-2.5=-0.139V.
I would just measure the voltage at Vout+ and subtract it from 5V to get the voltage across R3 and then divide
that by 100 ohms to get the current through R3 and then divide the voltage at Vout+ by the current calculated
through R3 to get the resistance of the PT100.

All I need to do is to measure resistance with a Wheatstone bridge!

There is absolutely no reason to use a Wheatstone bridge in this particular application.

But do have fun!

As it’s an industrial type application why not just buy a pT100 display module or a transmitter with a 4-20mA output. - both pretty cheap

hammy:
As it’s an industrial type application why not just buy a pT100 display module or a transmitter with a 4-20mA output. - both pretty cheap

There is no such device that can give me an output for a large display, by large I mean like 17*35cm display, what I designed and ordered right now.
I can use a PT100 transmitter, but those are EXTREMELY expensive where I live.
Sometimes I really feel pathetic when I ask questions here in this forum because I know the correct answer to my problem which is like this time just buying a 0-5V or 0-10V transmitter, but because I live in a country which is sanctioned by half of the world and has the weakest currency in the whole world, I just need to go with the cheapest value possible.
A normal Chinese non-brand transmitter is about 7000000 Rial here, which is very expensive and very worthless at the same time, and know that I get 70$ per month as an Electrical AND Electronic technician in a factory, just saying so can understand why I say that's expensive.
I mean I'm not tryna complain here, I'm just telling you why I'm not doing what you say.

wvmarle:
The HX711 is another chip that's designed for use with Wheatstone bridges. It's commonly used with load cells, which are also read in Wheatstone bridge configuration. A quick Google search shows it should be possible to use that with a PT100, so maybe it's worth checking out.

Sounds like a great module with 24bit ADC!
I'll try that out for sure! thank you for suggestion

jremington:
There is absolutely no reason to use a Wheatstone bridge in this particular application.

But do have fun!

Sir, I really asked you this question about 2 or 3 times and you just repeated your sentence.
Can you please tell me why there's no reason to use a Wheatstone bridge to calculate the resistance?!

raschemmel:
I would just measure the voltage at Vout+ and subtract it from 5V to get the voltage across R3 and then divide
that by 100 ohms to get the current through R3 and then divide the voltage at Vout+ by the current calculated
through R3 to get the resistance of the PT100.

This is the equation I understood from what you said:
( VCC - Vout+ ) / R3 = IR3 (R3 Current)
then after that:
Vout+ / IR3 = PT100
Am I correct?