After researching over the past several days, I've implemented the following circuit:
Using Ohm's Law, we can choose resistors to use to limit the amperage crossing the PT100. In my case, I determined a 3.9k ohm resistor in front of my two 100 ohm resistors (the second being the PT100) would limit the amps to where I need them.
PT100 is 100 ohms
A0 sees .16v -> (3.3v / (3900ohm + 100ohm + 100ohm)) * (100ohm + 100ohm)
A1 sees .08v -> (3.3v / (3900ohm + 100ohm + 100ohm)) * 100ohm
PT100 sees .805mA -> 3.3v / (3900ohm + 100ohm + 100ohm)
PT100 is 175.84 ohms
A0 sees .218v -> (3.3v / (3900ohm + 100ohm + 175.84ohm)) * (100ohm + 175.84ohm)
A1 sees .139v -> (3.3v / (3900ohm + 100ohm + 175.84ohm)) * 175.84ohm
PT100 sees .79mA -> 3.3v / (3900ohm + 100ohm + 175.84ohm)
At most, the PT100 will see .805mA which is in the required .3mA to 1mA range, meaning we reduce the accuracy lost due to the PT100 self-heating. I read the voltages at pins
A1, then compute the resistance of the PT100 using the equation in the link to the other SO question I posted in my question.
R2 = R1 * 1 / ( Vin / Vout - 1)
Adjusted for the labels in my diagram:
R3 = R2 * (1 / ((A0 / A1) - 1))
In my code, I check to make sure
A1 is not 0, and that the quantity
(A0 / A1) - 1 is also not 0, otherwise we'll be attempting to divide by 0!
Also since the highest voltage I care about is .218v, I can set the gain on the ADS1115 to 16x which puts full scale from 0 to .256v. Since the typical values we see will be on the range .08v to .218v we're losing out on some of the scale, but it's still pretty good as is!
.256v full scale range at 16x gain, with 15 bits useable on the ADS1115
.256 / 2**15 = 0.0000078125v resolution
usable scale = .218v - .08v
usable scale / 0.0000078125v = 17,664 possible values
(0°c - 200°c) / 17664 = 0.011°c resolution
I had originally planned to use the PT100 with 3 wires, but one limitation of the ADS1115 is that it has a single result register, meaning I can only read 1 pin at a time! This means, at a data rate of 64, it takes roughly 1/64 of a second or 16ms to read a single pin! Given I have to read them serially since it can only store one result at a time, it takes 32ms to read both
A1. I wanted to keep my loop as quick as possible, so I dropped the third wire.
Going forward, improvements would be to:
- Find an ADC that can store multiple results at once.
- Use a constant current source.
- This would make the voltages read at pins
A1 increase and decrease in a linear fashion, unlike what they do now.
- This would also mean I don't need the 3.9k ohm resistor, since I'm able to limit the current via the current source.
- On top of this, I wouldn't need to read the value at pin
A0! (Since the current could be fixed to 1mA, and we know the value of the reference resistor is 100ohm, we have all the information we need except for the change in resistance of the PT100 which is determined by the voltage at
- Pick up an LMP90080, since it has it's own built in constant current source, plus more bells and whistles to accurately sample from a PT100. The drawback is that there's no python library for interfacing with it, so I'd have to walk through the datasheet and figure out how to read and write to it :(
If anyone sees any issues with my logic above or has their own recommendations, please do let me know!