jal
Posts: 28
Joined: Mon Oct 01, 2012 10:47 am
Location: Estonia

MAX31865 PT1000 temperature measurement over long distance

Sun Feb 16, 2014 11:42 am

Hi all,

I have a plan to read PT1000 sensor with help MAX31865. MAX31865 is needed because I need long distance (~200 meters), this chip uses 4-wire connection which should give me long distance.

But at the moment I don't have any idea where to start :) I have used different I2C devices, but as I understand reading SPI is totally different.

MAX31865 has 7 wires:
1. VIN - 3v3 in
2. GND - GND
3. DRDY - Active-Low Push-Pull Data-Ready Output. DRDY goes low when a new conversion result is available in
the data register. When a read-operation of an RTD resistance data register occurs, DRDY returns high.
4. SDI - Serial-Data Input
5. SCLK - Serial-Data Clock Input
6. CS - Active-Low Chip Select. Set CS low to enable the serial interface
7. SDO - Serial-Data Output

To connect with raspberry:

1 -> pin1
2 -> pin6
3 -> ????pin26????
4 -> pin19
5 -> pin23
6 -> pin24
7 -> pin21

Can I read it or at least test connection it with bash script?

Thanks for any help!

User avatar
FLYFISH TECHNOLOGIES
Posts: 1750
Joined: Thu Oct 03, 2013 7:48 am
Location: Ljubljana, Slovenia
Contact: Website

Re: MAX31865 PT1000 temperature measurement over long distan

Sun Feb 16, 2014 2:34 pm

Hi,
jal wrote:I need long distance (~200 meters), this chip uses 4-wire connection which should give me long distance.
??? This conclusion seems a bit odd to me.
This is a SPI bus chip. I avoid usage of this bus for distances exceeding even less than one meter.

For distance of 200m you need to consider RS-422/485, digital 20mA loop or something wireless (ISM band modules). Most likely, you need to add a microcontroller in this equation.


Best wishes, Ivan Zilic.
Running out of GPIO pins and/or need to read analog values?
Solution: http://www.flyfish-tech.com/FF32

jal
Posts: 28
Joined: Mon Oct 01, 2012 10:47 am
Location: Estonia

Re: MAX31865 PT1000 temperature measurement over long distan

Sun Feb 16, 2014 2:44 pm

By 4 wire connection I mean, that PT1000 can be far away from MAX, MAX itself and Raspberry will be close.

Image

User avatar
FLYFISH TECHNOLOGIES
Posts: 1750
Joined: Thu Oct 03, 2013 7:48 am
Location: Ljubljana, Slovenia
Contact: Website

Re: MAX31865 PT1000 temperature measurement over long distan

Sun Feb 16, 2014 2:58 pm

Hi,
jal wrote:By 4 wire connection I mean, that PT1000 can be far away from MAX, MAX itself and Raspberry will be close.
Ok, I see. Sorry, I misunderstood planned location of the MAX chip.


Best wishes, Ivan Zilic.
Running out of GPIO pins and/or need to read analog values?
Solution: http://www.flyfish-tech.com/FF32

jal
Posts: 28
Joined: Mon Oct 01, 2012 10:47 am
Location: Estonia

Re: MAX31865 PT1000 temperature measurement over long distan

Sun Feb 16, 2014 10:53 pm

So I have tested with this:

Code: Select all

import spidev
import time
spi = spidev.SpiDev()
spi.open(0,1)
while True:
    resp = spi.xfer2([0x30])
    print resp[0]
    time.sleep(1)
If powered up and CS is low it always reads 255 otherwise 0. Also I can disconnect clock and data out from Raspberry it still reads 255, but if i disconnect data in from Raspberry reading will be 0.
Any ideas where to go next?

As I undestand to read info from MAX I have to write first what I want to know?

stanswi
Posts: 1
Joined: Fri Feb 21, 2014 5:41 am

Re: MAX31865 PT1000 temperature measurement over long distan

Fri Feb 21, 2014 5:43 am

I too am looking to use the MAX31865 with the Raspberry Pi but have had no luck even using it with an Arduino. I am using the PT100 breakout board from Playing with Fusion (http://playingwithfusion.com/productvie ... catid=1001). Unfortunately I am not a programmer by trade and which I could contribute to this post haha. Have you had any luck with your project by chance?

PBytes
Posts: 1
Joined: Thu Apr 30, 2015 4:31 pm

Re: MAX31865 PT1000 temperature measurement over long distan

Thu Apr 30, 2015 4:34 pm

Over a year from the last post, but I am going to ask anyway. Have either of you figured out how to make the MAX31865 work with the Raspberry Pi?
I am having no luck and there is no documentation I can find anywhere. Hope you can help myself and others.

pjr_pdco
Posts: 17
Joined: Thu Jan 08, 2015 6:08 pm

Re: MAX31865 PT1000 temperature measurement over long distan

Sat May 02, 2015 3:49 am

The component datasheet is a great place to start. I have not worked directly with the MAX31865 so what follows is just from reading the datasheet.

In the original post it looks to me the chip was actually working correctly.

Communication with the chip is through a register set with addresses of 0x00 through 0x07. A register read request is made with a logical OR of a register address and 0x00. A register write request is made with a logical OR of a register address and 0x80.

The datasheet states specifying an invalid address will result in a returned value of 255 ( 0xFF ).

Looks to me the original posters code writes 0x30 to the chip ( which is an invalid address ). The returned result is 255 ( 0xFF ) which seems correct.

So it looks like the chip was actually working as specified in the datasheet and just the code needs to be corrected to interface with the chip correctly.

Have your efforts gotten to the same results as the original poster?

Pat

a.texer
Posts: 8
Joined: Thu Dec 03, 2015 6:18 pm

Re: MAX31865 PT1000 temperature measurement over long distan

Thu Dec 03, 2015 6:20 pm

Any progress on the issue?

a.texer
Posts: 8
Joined: Thu Dec 03, 2015 6:18 pm

Re: MAX31865 PT1000 temperature measurement over long distan

Tue Jan 05, 2016 9:47 pm

Pretty raw so far but may be helpful for someone...

Code: Select all

#!/usr/bin/python -tt

'''
    Python driver for [MAX38865PMB1 RTD-to-digital converter] (https://datasheets.maximintegrated.com/en/ds/MAX31865PMB1.pdf)
	
    Requires:
	  - The [GPIO Library](https://code.google.com/p/raspberry-gpio-python/) (Already on most Raspberry Pi OS builds)
	  - A [Raspberry Pi](http://www.raspberrypi.org/)
	
    Author:
    Alexey B. Tikhomirov 

    Version:
    1.0, 05-Jan-2016
    Comments: Adopted from https://github.com/Tuckie/max31855
'''

__author__ = 'Alexey Tikhomirov'
__copyright__ = 'Copyright 2016, Alexey Tikhomirov'
__credits__ = ['']
__license__ = 'GPL'
__version__ = '1.0'
__date__  = '05-Jan-2016'
__maintainer__ = 'Alexey Tikhomirov'
__status__ = 'Production'

import RPi.GPIO as GPIO
import time

class MAX31865(object):
    
    def __init__(self, cs_pin, clock_pin, data_in_pin, data_out_pin, address, data, units = "c", board = GPIO.BCM):

        '''Initialize Soft (Bitbang) SPI bus
        Parameters:
        - cs_pin:    Chip Select (CS) / Slave Select (SS) pin (Any GPIO)  
        - clock_pin: Clock (SCLK / SCK) pin (Any GPIO)
        - data_in_pin:  Data input (SO / MOSI) pin (Any GPIO)
	      - data_out_pin: Data output (MISO) pin (Any GPIO)
        - units:     (optional) unit of measurement to return. ("c" (default) | "k" | "f")
        - board:     (optional) pin numbering method as per RPi.GPIO library (GPIO.BCM (default) | GPIO.BOARD)
        '''

        self.cs_pin = cs_pin
        self.clock_pin = clock_pin
        self.data_in_pin = data_in_pin
        self.data_out_pin = data_out_pin
        self.address = address           # address of the register to write/read
        #self.data = data                # data to write/read
        self.units = units
        self.data = data
        self.board = board

        # Initialize needed GPIO
        GPIO.setmode(self.board)
        GPIO.setup(self.cs_pin, GPIO.OUT)
        GPIO.setup(self.clock_pin, GPIO.OUT)
        GPIO.setup(self.data_in_pin, GPIO.IN)
        GPIO.setup(self.data_out_pin, GPIO.OUT)

        # Pull chip select high to make chip inactive
        GPIO.output(self.cs_pin, GPIO.HIGH)
        
    def get_data(self):
        '''Acqures raw RDT data.'''
        self.address = int(0x01)    #RTD MSBs
        MSB = self.read()
        self.address = int(0x02)    #RTD LSBs
        LSB = self.read()
        #print MSB
        #print LSB
        MSB = MSB<<8 
        raw = MSB+LSB
        #print raw
        #fault = raw & 1
        #print fault
        raw = raw>>1
        #print raw      
        #print self
        #self.checkErrors()        
        return raw

    def write(self):
        '''Writes 8 bit of data to the 8 bit address'''
        GPIO.output(self.cs_pin, GPIO.LOW)
        GPIO.output(self.clock_pin, GPIO.LOW)
	      
        # Write to address 
        for i in range(8):        
            #print address, data
            bit  = self.address>>(7 - i)
            bit = bit & 1 
            #GPIO.output(self.clock_pin, GPIO.LOW)
            GPIO.output(self.data_out_pin, bit)
            #if bit:
            #    GPIO.output(self.data_out_pin, GPIO.HIGH)
            #else:
            #    GPIO.output(self.data_out_pin, GPIO.LOW)
            GPIO.output(self.clock_pin, GPIO.HIGH)            
            GPIO.output(self.clock_pin, GPIO.LOW)
                
        for i in range(8):        
            bit  = self.data>>(7 - i)
            bit = bit & 1 
            #GPIO.output(self.clock_pin, GPIO.LOW)
            GPIO.output(self.data_out_pin, bit)
            #if bit:
            #    GPIO.output(self.data_out_pin, GPIO.HIGH)
            #else:
            #    GPIO.output(self.data_out_pin, GPIO.LOW)
            GPIO.output(self.clock_pin, GPIO.HIGH)
            GPIO.output(self.clock_pin, GPIO.LOW)
            #GPIO.output(self.data_out_pin, GPIO.LOW)
        
        GPIO.output(self.clock_pin, GPIO.HIGH)                      
        # Unselect the chip
        GPIO.output(self.cs_pin, GPIO.HIGH)
        

    def read(self):
        '''Reads 16 bits of the SPI bus from a self.address register & stores as an integer in self.data.'''
        bytesin = 0                
        
        # Select the chip
        GPIO.output(self.cs_pin, GPIO.LOW)
        # Assert clock bit
        GPIO.output(self.clock_pin, GPIO.LOW)
	      
        # Write to address 
        for i in range(8):        
            #print address, data
            bit  = self.address>>(7 - i)
            bit = bit & 1 
            #GPIO.output(self.clock_pin, GPIO.LOW)
            GPIO.output(self.data_out_pin, bit)
            #if bit:
            #    GPIO.output(self.data_out_pin, GPIO.HIGH)
            #else:
            #    GPIO.output(self.data_out_pin, GPIO.LOW)
            GPIO.output(self.clock_pin, GPIO.HIGH)
            GPIO.output(self.clock_pin, GPIO.LOW)
            #GPIO.output(self.data_out_pin, GPIO.LOW)
        
        # Read in 8 bits        
        for i in range(8):
            GPIO.output(self.clock_pin, GPIO.HIGH)
            bytesin = bytesin << 1
            if (GPIO.input(self.data_in_pin)):
                bytesin = bytesin | 1
            GPIO.output(self.clock_pin, GPIO.LOW)
        
        # Dsable clock                
        GPIO.output(self.clock_pin, GPIO.HIGH)
        # Unselect the chip
        GPIO.output(self.cs_pin, GPIO.HIGH)
        
        # Save data
        self.data = bytesin
        #print bytesin
        return self.data

    def checkErrors(self, data_32 = None):
    # Not finished yet
        '''Checks error bits to see if there are any SCV, SCG, or OC faults'''
        if data_32 is None:
            data_32 = self.data
        anyErrors = (data_32 & 0x10000) != 0    # Fault bit, D16
        noConnection = (data_32 & 1) != 0       # OC bit, D0
        shortToGround = (data_32 & 2) != 0      # SCG bit, D1
        shortToVCC = (data_32 & 4) != 0         # SCV bit, D2
        if anyErrors:
            if noConnection:
                raise MAX31865Error("No Connection")
            elif shortToGround:
                raise MAX31865Error("Thermocouple short to ground")
            elif shortToVCC:
                raise MAX31865Error("Thermocouple short to VCC")
            else:
                # Perhaps another SPI device is trying to send data?
                # Did you remember to initialize all other SPI devices?
                raise MAX31865Error("Unknown Error")

    def convert(self, raw):
        #Takes raw RTD data and returns RTD temperature in celsius as well as RTD resistance.
        RefR = 400.0 #RefR/2        
        R0 = raw * RefR / 32768
        if R0==0:
            temperature_data = ['', '', '']       
        else:         
            t = -247.29 + 2.3992*R0 + 0.00063962*R0*R0 + 1.0241E-6*R0*R0*R0
            temperature_data = ['{:.0f}'.format(raw), '{:.4f}'.format(R0), '{:.4f}'.format(t)]
        #if R0==0:
        #    return -1,0        
        #print temperature_data
        temperature_data = tuple('-' if x == '' else x for x in temperature_data)
        temperature_data = '\t'.join(temperature_data)                   
        #return raw, R0, t
        return temperature_data
    
    def to_c(self, celsius):
        '''Celsius passthrough for generic to_* method.'''
        return celsius

    def to_k(self, celsius):
        '''Convert celsius to kelvin.'''
        return celsius + 273.15

    def to_f(self, celsius):
        '''Convert celsius to fahrenheit.'''
        return celsius * 9.0/5.0 + 32

    def cleanup(self):
        '''Selective GPIO cleanup'''
        GPIO.setup(self.cs_pin, GPIO.IN)
        GPIO.setup(self.clock_pin, GPIO.IN)

class MAX31865Error(Exception):
     def __init__(self, value):
         self.value = value
     def __str__(self):
         return repr(self.value)

if __name__ == "__main__":

    # Multi-chip example   
    # Configure GPIO pins    
    cs_pins = [8, 25, 24]
    clock_pin = 11
    data_in_pin = 9
    data_out_pin = 10
    #units = "k"
    
    # Configure RTDs
    rtds = []
    address = int(0x80)    # RTD control register, see datasheet for details
    data =  int(0xC2)      # RTD control register data, see datasheet for details
    for cs_pin in cs_pins:
        rtds.append(MAX31865(cs_pin, clock_pin, data_in_pin, data_out_pin, address, data))  
    for rtd in rtds:        
        rtd.write()
    
    # Run main program    
    running = True
    while(running):
        try:
            for rtd in rtds:
                code = rtd.get_data()
                data = rtd.convert(code)
                print data                
            time.sleep(1)
        except KeyboardInterrupt:
            running = False
    GPIO.cleanup()

yaleman
Posts: 1
Joined: Sun Feb 07, 2016 1:15 pm

Re: MAX31865 PT1000 temperature measurement over long distan

Sun Feb 07, 2016 1:22 pm

Just wondering in the example above if the DRDY pin has to be connected to anything? I can't get it to work, but I'm not sure if it's me mis-wiring something or another problem. :(

a.texer
Posts: 8
Joined: Thu Dec 03, 2015 6:18 pm

Re: MAX31865 PT1000 temperature measurement over long distan

Tue Feb 09, 2016 6:00 am

Here is my pinout:
MAX 31865 dev board<--> RPi2
1 SS 24 or 18 or 22
2 MOSI 19
3 MISO 21
4 SCLK 23
5 GND 06
6 Vcc 01
7 DRDY nc
8 nc
9 nc
10 nc
11 GND nc
12 Vcc +3.3 nc
The code works fine for me. I have three MAX boards on the same SPI bus on PRi2.
In my case DRDY is not connected, but in general it can be used to sense whether new data is available.
I am in the process of updating the code in order to get rid of the for loops in the write and read procedures.
Will post it here as soon as it is ready.
Also have similar code for Adafruit BMP280 pressure sensor which is actually the forth board on my RPi2 SPI bus.

Bobstin
Posts: 1
Joined: Mon Sep 05, 2016 3:00 am

Re: MAX31865 PT1000 temperature measurement over long distan

Mon Sep 05, 2016 3:09 am

The code above worked for me, but I wanted to document my pinout (it matches a.texer's, but the pins on my board were labeled differently):

1: GND -> GND
2: Vin -> 3.3v
3: DDRY -> not connected
4: SDO -> Pin 21
5: CS1 -> Either pin 24 or 18 or 22 (connect each CS to one of those pins for up to three sensors)
6: SCLK -> Pin 23
7: SDI -> Pin 19
8: DDRY2 -> Not connected
9: CS2 - > Either pin 24 or 18 or 22 (connect each CS to one of those pins for up to three sensors)

ciucci
Posts: 3
Joined: Fri Dec 30, 2016 9:38 am

Re: MAX31865 PT1000 temperature measurement over long distan

Fri Dec 30, 2016 9:45 am

Hello,

I am pretty new with this. I tried to connect a PT100 to the MAX31865 and used the code form a.texer but i get a value for raw of 32767.

Any idea what is going wrong?

ciucci
Posts: 3
Joined: Fri Dec 30, 2016 9:38 am

Re: MAX31865 PT1000 temperature measurement over long distan

Fri Jan 06, 2017 3:26 pm

So I am now getting some data in.
I have two max31865 from adafruit with 2 pt100 connected and I am getting the same low temperatures from both, around 1 degree instead of 19-20. (measured with a ds18b20 also connected to the same raspberry).
I boiled some water and brought my water to the sensors and got 90 degrees from the ds18b20 and 70 from both the pt100. I am still using the code from a.texer. So it seems a linear thing.

If I measure the resistance of the pt100 with a multimeter I get a resistance of +/- 111 and +/- 3,5 between the other two wires. So 107,5 should be measured but from the code I get R0 just above 100.

Am i doing something wrong with the 3rd wire configurations?

ciucci
Posts: 3
Joined: Fri Dec 30, 2016 9:38 am

Re: MAX31865 PT1000 temperature measurement over long distan

Sat Jan 07, 2017 8:29 pm

I solved my problem. The adafruit board has a 430 reference resistor. So changing it in the code from 400 to 430 solved it and now everything is working.

ChrisPolin
Posts: 1
Joined: Wed Feb 08, 2017 11:55 pm

Re: MAX31865 PT1000 temperature measurement over long distan

Wed Feb 08, 2017 11:58 pm

@ciucci, I'm at the point you were at on dec 30th, with the consistent reading of 32767. I presume this is due to an incorrect read/write address, how did you solve the issue?

Also kudos to a.texer for the code!

Passecoul
Posts: 1
Joined: Sat May 20, 2017 6:53 am

Re: MAX31865 PT1000 temperature measurement over long distan

Sat May 20, 2017 7:10 am

Hi all,

Could you please "a.texer" send your new codes please.
I'll try to connect 4 x MAX31865.

One question please ; to use the code above, to use MAX31865 on any GPIO is it necessary to activate the SPI mode on setup of the RPi ? or it s finally not needed?

Thanks all

User avatar
DougieLawson
Posts: 35025
Joined: Sun Jun 16, 2013 11:19 pm
Location: Basingstoke, UK
Contact: Website Twitter

Re: MAX31865 PT1000 temperature measurement over long distan

Sat May 20, 2017 3:46 pm

Passecoul wrote:Hi all,

Could you please "a.texer" send your new codes please.
Don't wait too long he has a massive total of three posts on the forum and hasn't visited since Tue 09 Feb 2016 @ 14:34.
Note: Having anything remotely humorous in your signature is completely banned on this forum.

Any DMs sent on Twitter will be answered next month.

This is a hippy & doctor free zone.

a.texer
Posts: 8
Joined: Thu Dec 03, 2015 6:18 pm

Re: MAX31865 PT1000 temperature measurement over long distance

Mon Aug 28, 2017 9:35 pm

Please, find an archive with scripts using a link below.
Sorry, not enough time for this project anymore.

https://drive.google.com/file/d/0B4esHv ... WVfc0JFVGs

mackowiakp
Posts: 16
Joined: Mon Oct 30, 2017 9:21 am

Re: MAX31865 PT1000 temperature measurement over long distance

Mon Oct 30, 2017 9:43 am

The Python code from a.texer looks pretty promising. I an noob in Python programming so I look for help.. I use Pi ver 3 mod B and Adafruit MAX31865 module for PT100 sensor. Below part of program:

Code: Select all

 def __init__(self, cs_pin, clock_pin, data_in_pin, data_out_pin, address, data, units = "c", board = GPIO.BCM):

        '''Initialize Soft (Bitbang) SPI bus
        Parameters:
        - cs_pin:    Chip Select (CS) / Slave Select (SS) pin (Any GPIO)  
        - clock_pin: Clock (SCLK / SCK) pin (Any GPIO)
        - data_in_pin:  Data input (SO / MOSI) pin (Any GPIO)
	      - data_out_pin: Data output (MISO) pin (Any GPIO)
        - units:     (optional) unit of measurement to return. ("c" (default) | "k" | "f")
        - board:     (optional) pin numbering method as per RPi.GPIO library (GPIO.BCM (default) | GPIO.BOARD)
        '''

        self.cs_pin = cs_pin
        self.clock_pin = clock_pin
        self.data_in_pin = data_in_pin
        self.data_out_pin = data_out_pin
        self.address = address           # address of the register to write/read
        #self.data = data                # data to write/read
        self.units = units
        self.data = data
        self.board = board
So as I understand in first line I have to pace value of GPIO pin numbers (not socket pin number but GPIO numbers) and it could be any free pins. But what should I place as value of "self" "data" and "board".
Be so kind to explain me, please !

rmiller107
Posts: 5
Joined: Thu Jul 21, 2016 2:06 pm

Re: MAX31865 PT1000 temperature measurement over long distance

Tue Dec 05, 2017 2:48 am

Anyone's help on this would be very much appreciated. I'm trying to get two PT100s (2-wire version) working with the MAX31865s to use as the temp for two PID controllers. I'm using the the code from a.texer's link above. I've included a fritzing diagram of my wiring setup.
Attachments
Schematic_bb.jpg
Schematic_bb.jpg (122.52 KiB) Viewed 5722 times

a.texer
Posts: 8
Joined: Thu Dec 03, 2015 6:18 pm

Re: MAX31865 PT1000 temperature measurement over long distance

Fri Jan 12, 2018 5:10 pm

Updated version of the archive with pinouts for RPi2 as it was done in my case can be found here:
https://drive.google.com/open?id=1kliwD ... raJGvohiLb

a.texer
Posts: 8
Joined: Thu Dec 03, 2015 6:18 pm

Re: MAX31865 PT1000 temperature measurement over long distance

Fri Jan 12, 2018 5:20 pm

rmiller107
Not sure why you have a short between F+ and F-.
In two wire RTD configuration you need to short F+ to RTD+ and F- to RTD-.
F+ should be connected to F2 as well.
RTD sensor is connected between RTD+ and RTD-.
https://learn.adafruit.com/adafruit-max ... /downloads
Good luck.

rmiller107
Posts: 5
Joined: Thu Jul 21, 2016 2:06 pm

Re: MAX31865 PT1000 temperature measurement over long distance

Tue Jan 16, 2018 5:17 pm

a.texer wrote: rmiller107
Not sure why you have a short between F+ and F-.
In two wire RTD configuration you need to short F+ to RTD+ and F- to RTD-.
F+ should be connected to F2 as well.
RTD sensor is connected between RTD+ and RTD-.
https://learn.adafruit.com/adafruit-max ... /downloads
Good luck.
Alright, I must be missing something still because my data file doesn't make sense to me. I have a DS18B20 reading temps right next to the PT100 and it is reading 21 Celsius/70 Fahrenheit.
  • I have the most recent code but modified for 1 MAX31865 (I will add a second once I get this one working properly)
    I have shorted together components (F+ and F2 illustrated as the pink wire connecting the "2 4" pads next to the adafruit logo)
Schematic-1.png
Schematic-1.png (120.67 KiB) Viewed 5048 times

Return to “Automation, sensing and robotics”