0

Using github and a tutorial I adapt the given Code to read the temperature on my raspberry using an PT1000 sensor.

I am using the mode "GPIO.BOARD", adapt the "writeRegister(0, 0xB2)" to "writeRegister(0, 0xA2)" and I also changed the programstart.

Here's my current code:

#!/usr/bin/python
# The MIT License (MIT)
#
# Copyright (c) 2015 Stephen P. Smith
#
# 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 THE
# AUTHORS OR COPYRIGHT HOLDERS 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.

import time, math
import RPi.GPIO as GPIO
# import numpy


"""Reading Temperature from the MAX31865 with GPIO using 
   the Raspberry Pi.  Any pins can be used.
   Numpy can be used to completely solve the Callendar-Van Dusen equation 
   but it slows the temp reading down.  I commented it out in the code.  
   Both the quadratic formula using Callendar-Van Dusen equation (ignoring the
   3rd and 4th degree parts of the polynomial) and the straight line approx.
   temperature is calculated with the quadratic formula one being the most accurate.
"""


def setupGPIO():
    GPIO.setwarnings(False)
    GPIO.setmode(GPIO.BOARD)
    GPIO.setup(csPin, GPIO.OUT)
    GPIO.setup(misoPin, GPIO.IN)
    GPIO.setup(mosiPin, GPIO.OUT)
    GPIO.setup(clkPin, GPIO.OUT)

    GPIO.output(csPin, GPIO.HIGH)
    GPIO.output(clkPin, GPIO.LOW)
    GPIO.output(mosiPin, GPIO.LOW)


def readTemp():

    # b10000000 = 0x80
    # 0x8x to specify 'write register value'
    # 0xx0 to specify 'configuration register'
    #
    # 0b10110010 = 0xB2
    # Config Register - https://datasheets.maximintegrated.com/en/ds/MAX31865.pdf
    # ---------------
    # bit 7: Vbias -> 1 (ON)
    # bit 6: Conversion Mode -> 0 (MANUAL)
    # bit 5: 1-shot ->1 (ON)
    # bit 4: 3-wire select -> 1 (3 wire config) (0 for 2-/4-wire)
    # bit 3-2: fault detection cycle -> 0 (none)
    # bit 1: fault status clear -> 1 (clear any fault)
    # bit 0: 50/60 Hz filter select -> 0 (60Hz)
    #
    # 0b11010010 or 0xD2 for continuous auto conversion 
    # at 60Hz (faster conversion)


    # one shot
    writeRegister(0, 0xA2)

    # conversion time is less than 100ms
    time.sleep(.1)  # give it 100ms for conversion

    # read all registers
    out = readRegisters(0, 8)

    conf_reg = out[0]
    print("Config register byte: %x" % conf_reg , " [HEX]")

    [rtd_msb, rtd_lsb] = [out[1], out[2]]
    rtd_ADC_Code = ((rtd_msb << 8) | rtd_lsb) >> 1

    temp_C = calcPT1000Temp(rtd_ADC_Code)

    # High fault threshold
    [hft_msb, hft_lsb] = [out[3], out[4]]
    hft = ((hft_msb << 8) | hft_lsb) >> 1

    # Low fault threshold
    [lft_msb, lft_lsb] = [out[5], out[6]]
    lft = ((lft_msb << 8) | lft_lsb) >> 1
    print ("High fault threshold: ", hft , " --- Low fault threshold: " , lft)

    status = out[7]
    #
    # 10 Mohm resistor is on breakout board to help
    # detect cable faults
    # bit 7: RTD High Threshold / cable fault open 
    # bit 6: RTD Low Threshold / cable fault short
    # bit 5: REFIN- > 0.85 x VBias -> must be requested
    # bit 4: REFIN- < 0.85 x VBias (FORCE- open) -> must be requested
    # bit 3: RTDIN- < 0.85 x VBias (FORCE- open) -> must be requested
    # bit 2: Overvoltage / undervoltage fault
    # bits 1,0 don't care    
    # print "Status byte: %x" % status

    if ((status & 0x80) == 1):
        raise FaultError("High threshold limit (Cable fault/open)")
    if ((status & 0x40) == 1):
        raise FaultError("Low threshold limit (Cable fault/short)")
    if ((status & 0x04) == 1):
        raise FaultError("Overvoltage or Undervoltage Error") 


def writeRegister(regNum, dataByte):
    GPIO.output(csPin, GPIO.LOW)

    # 0x8x to specify 'write register value'
    addressByte = 0x80 | regNum;

    # first byte is address byte
    sendByte(addressByte)
    # the rest are data bytes
    sendByte(dataByte)

    GPIO.output(csPin, GPIO.HIGH)


def readRegisters(regNumStart, numRegisters):
    out = []
    GPIO.output(csPin, GPIO.LOW)

    # 0x to specify 'read register value'
    sendByte(regNumStart)

    for byte in range(numRegisters):    
        data = recvByte()
        out.append(data)

    GPIO.output(csPin, GPIO.HIGH)
    return out


def sendByte(byte):
    for bit in range(8):
        GPIO.output(clkPin, GPIO.HIGH)
        if (byte & 0x80):
            GPIO.output(mosiPin, GPIO.HIGH)
        else:
            GPIO.output(mosiPin, GPIO.LOW)
        byte <<= 1
        GPIO.output(clkPin, GPIO.LOW)


def recvByte():
    byte = 0x00
    for bit in range(8):
        GPIO.output(clkPin, GPIO.HIGH)
        byte <<= 1
        if GPIO.input(misoPin):
            byte |= 0x1
        GPIO.output(clkPin, GPIO.LOW)
    return byte    


def calcPT1000Temp(RTD_ADC_Code):

    ############# PT1000 #############
    R_REF = 400.0  # Reference Resistor
    Res0 = 1000.0;  # Resistance at 0 degC for 400ohm R_Ref
    a = .00381
    b = -.000000602
    # c = -4.18301e-12 # for -200 <= T <= 0 (degC)
    c = -0.000000000006
    # c = 0 # for 0 <= T <= 850 (degC)
    # c = 0 # for 0 <= T <= 850 (degC)

    """
    ############# PT100 #############
    R_REF = 400.0  # Reference Resistor
    Res0 = 100.0;  # Resistance at 0 degC for 400ohm R_Ref
    a = .00390830
    b = -.000000577500
    # c = -4.18301e-12 # for -200 <= T <= 0 (degC)
    c = -0.00000000000418301
    # c = 0 # for 0 <= T <= 850 (degC)
    """

    Res_RTD = (RTD_ADC_Code * R_REF) / 32768.0  # PT1000 Resistance
    Res_RTD = round(Res_RTD, 3)
    print("RTD ADC Code: ", RTD_ADC_Code , " --- PT1000 Resistance: ",  Res_RTD , " Ohms")


    # Callendar-Van Dusen equation
    # Res_RTD = Res0 * (1 + a*T + b*T**2 + c*(T-100)*T**3)
    # Res_RTD = Res0 + a*Res0*T + b*Res0*T**2 # c = 0
    # (c*Res0)T**4 - (c*Res0)*100*T**3  
    # + (b*Res0)*T**2 + (a*Res0)*T + (Res0 - Res_RTD) = 0
    #
    # quadratic formula:
    # for 0 <= T <= 850 (degC)
    temp_C = -(a * Res0) + math.sqrt(a * a * Res0 * Res0 - 4 * (b * Res0) * (Res0 - Res_RTD))
    temp_C = temp_C / (2 * (b * Res0))
    temp_C_line = (RTD_ADC_Code / 32.0) - 256.0
    # removing numpy.roots will greatly speed things up
    # temp_C_numpy = numpy.roots([c*Res0, -c*Res0*100, b*Res0, a*Res0, (Res0 - Res_RTD)])
    # temp_C_numpy = abs(temp_C_numpy[-1])

    print ("Straight Line Approx. Temp: ", temp_C_line , " --- Callendar-Van Dusen Temp (degC > 0): " , temp_C)
    # print "Solving Full Callendar-Van Dusen using numpy: %f" %  temp_C_numpy
    if (temp_C < 0):  # use straight line approximation if less than 0
        # Can also use python lib numpy to solve cubic
        # Should never get here in this application
        temp_C = (RTD_ADC_Code / 32) - 256
    return temp_C


###############################################################################################################################
#                                                         Programstart                                                        #
###############################################################################################################################
# Pin-Setup: (BCM: 8, 9, 10, 11)
csPin = 24
misoPin = 21
mosiPin = 19
clkPin = 23

setupGPIO()

while True:
    tempC = readTemp()
    time.sleep(1)

GPIO.cleanup()

class FaultError(Exception):
    pass

The output is the following:

Config register byte: 80  [HEX]
RTD ADC Code:  1299  --- PT1000 Resistance:  15.857  Ohms
Straight Line Approx. Temp:  -215.40625  --- Callendar-Van Dusen Temp (degC > 0):  -248.54456939832218

The values of the "RTD ADC Code" and the "PT1000 Resistance" increase continuously.

I dont know whats the reason for this wrong behavior. I also tried different wiring-settings - Currently is use this one.

Narendra Jadhav
  • 10,052
  • 15
  • 33
  • 44
Lukas
  • 1
  • 5
  • Can you verify the resistance reading? You are getting 15.857 ohms which is pretty unusual for PT1000, do you have any resistors at home you could attach to the MAX31865 to verify whether it is working? If you do not, take two wires and put then into glass of water and observe if the value of RTD_ADC_Code changes while you put the wires closer – gabonator Apr 21 '18 at 09:21
  • And you forgot to short the `2/3 wire` and `2 wire` jumpers on adafruit MAX module – gabonator Apr 21 '18 at 09:32
  • After shorting the the both wires I get the following output: "RTD ADC Code: 8396 --- PT1000 Resistance: 102.49 Ohms Straight Line Approx. Temp: 6.375 --- Callendar-Van Dusen Temp (degC > 0): -227.39660180168164" Using a lighter the values increase until I stop using it. Then the values decrease. – Lukas Apr 21 '18 at 10:20
  • Using a 100 Ohm resistor (incl. shorting) i get the following output: "Config register byte: ff [HEX] RTD ADC Code: 32767 --- PT1000 Resistance: 399.988 Ohms Straight Line Approx. Temp: 767.96875 --- Callendar-Van Dusen Temp (degC > 0): -153.74844419335676" I also get this output if nothing is connected to the Max31865. I also get this result using another Max31865 modul. – Lukas Apr 21 '18 at 10:20
  • RTD_ADC_Code 32767 means that you reched the upper limit of ADC range, are you sure you have 100ohm resistor? What you will get if you short all 4 terminals? – gabonator Apr 21 '18 at 10:28
  • If nothing is connected I get the following outputs: "RTD ADC Code: 32767 --- PT1000 Resistance: 399.988 Ohms" or "RTD ADC Code: 0 --- PT1000 Resistance: 0.0 Ohms" – Lukas Apr 21 '18 at 17:57
  • And when you short all four terminals? – gabonator Apr 21 '18 at 18:06
  • "RTD ADC Code: 32767 --- PT1000 Resistance: 399.988 Ohms" with following https://preview.ibb.co/f6h0tc/IMG_20180421_201309.jpg – Lukas Apr 21 '18 at 18:16
  • you need to short all the wires together :) this is still not enough – gabonator Apr 21 '18 at 18:18
  • Sry for all my mistakes.. I am a bloody beginner.. Now I have connected the middle terminals with each other - yellow wire: https://preview.ibb.co/fY1wzH/IMG_20180421_202436.jpg I am still getting the same result as before.. – Lukas Apr 21 '18 at 18:31
  • Doesn't give any sense... Only thing that comes to my mind is cold joint on the terminal. Do you have multimeter and can you measure the voltage across the capacitor connected to RTD- and RTD+ signals? – gabonator Apr 21 '18 at 18:38
  • And you still have forgotten to short the switch "24 / 3", here is a detail of [the module](https://learn.adafruit.com/assets/37305), see how they soldered this jumper for use with three terminal thermometer, you need to solder the upper two copper squares together – gabonator Apr 21 '18 at 18:44
  • Now I have soldered it like you told me. With this setup (https://image.ibb.co/gd9Ywx/IMG_20180421_214913.jpg) I get the following output "RTD ADC Code: 0 --- PT1000 Resistance: 0.0 Ohms" - I think thats ok. When I replace the yellow wire with an 100 Ohm resistor (brown-black-black-black-brown) I get the following output "RTD ADC Code: 766 --- PT1000 Resistance: 9.351 Ohms" I also tested the resistor with a multimeter.. – Lukas Apr 21 '18 at 19:55
  • Can you put there any resistor of different value? Or two 100ohm resistors in series so we can verify whether there is only scaling problem? – gabonator Apr 21 '18 at 20:38
  • With a 220Ohm-resistor I get the following output: "RTD ADC Code: 1685 --- PT1000 Resistance: 20.569 Ohms" Using the PT1000 I get "RTD ADC Code: 8372 --- PT1000 Resistance: 102.197 Ohms Straight Line Approx. Temp: 5.625 --- Callendar-Van Dusen Temp (degC > 0): -227.4683481998611" (I have about 25 degrees in my room and the sensor has a measuring range from -80°C to 250°C) - so I think it is now a scaling problem / error at the code.. – Lukas Apr 21 '18 at 20:51
  • According to https://stackoverflow.com/a/44935228/8900456 I changed "R_REF = 400" to "R_REF = 4300" - not it's working *-* – Lukas Apr 21 '18 at 21:59
  • how do you power the module? Vin should be connected to 3.3V source. Refer to the [MAX31865 manual](https://datasheets.maximintegrated.com/en/ds/MAX31865.pdf) regarding the resistance/output code relationship on page 20. So far we have 0ohm -> 0, 100ohm -> 766 (should be 8192), 220ohm -> 1685 (should be 18000). Try measuring the resistance of both resisors in series, and then try `temp_C = calcPT1000Temp(rtd_ADC_Code*10)` just for fun – gabonator Apr 22 '18 at 06:48
  • I power it with 3.3V source. I think my result is correct. Adding "rtd_ADC_Code*10" at 220ohm i get "RTD ADC Code: 16860 --- PT1000 Resistance: 221.25 Ohms". The MAX31865-Modul is use is special for the PT1000 (not the PT100 to which the table on page 20 refers). On https://www.adafruit.com/product/3328 it is mentioned "If you have a PT1000 RTD, please visit this page to purchase a version of this board with the reference resistor for 1000-ohm RTDs" Changing the adc-value also manipulates the value of "Straight Line Approx. Temp" – Lukas Apr 23 '18 at 04:46
  • Does anybody know if it is possible to use two PT1000-sensors on my raspberry? – Lukas Apr 23 '18 at 04:47
  • Keep in mind that by multiplying the ADC value by 10 you are losing accuracy. You should replace the 100ohm reference resistor with 1000ohm. For switching between multiple sensors you can use relay (I do not recommend it), or use multiple MAX modules and switch between them using the CS (chip select) signal – gabonator Apr 23 '18 at 06:53
  • After I changed my setup for a 3wire-PT100 (https://preview.ibb.co/i6pewx/IMG_20180427_213403.jpg) I only get the adc values 32767 and 0 alternately. I changed my code above: "writeRegister(0, 0xB2)" and the values at the beginning of the function "calcPT1000Temp". Any idea whats wrong? – Lukas Apr 27 '18 at 19:40

0 Answers0