View previous topic :: View next topic |
Author |
Message |
Jody
Joined: 08 Sep 2006 Posts: 182
|
MAX31865 what am I doing wrong?? |
Posted: Wed Aug 25, 2021 5:38 am |
|
|
What I have:
MAX31865 connected as on page 24 from the datasheet.. the 2-wire sensor connection.
What I get is that the rtd value I read from the MAX31865 is alway 0x8087.
What ever I do with the PT100 I have connected.. when I freeze him I get this and when I heat him I also get this..
It seems like the communication is going good but what have I done wrong to get the same value always???
Thanks for all your help!!!!
Best regards,
Jody
I use this code MAX31865_test.c:
Code: |
#include <MAX31865_test.h>
#include <math.h>
#include "MAX31865_SPI.c"
void main()
{
double Rref = 470;
int16 result = 0;
float Temperature_vriezer;
int16 vriezer;
double Resistance;
MAX31865_init(); //Iniatilize the MAX31865 RTD temperature sensors...
while(1)
{
result = MAX31865_read_data();
if(result == 0x7fff) result = 0;
Resistance = ((double)result*Rref)/32768;
Temperature_vriezer = CallendarVanDusen(Resistance);
vriezer = (int16) Temperature_vriezer;
delay_us(1);
}
}
|
and this MAX31865_SPI.c:
Code: |
//---------------------------------------
// Call this function to read the 16-bit A/D result
// from the MAX31865.
int16 MAX31865_read_data(void)
{
int16 rtd;
int8 msb,lsb;
output_low(MAX31865_CS);
delay_us(10);
spi_write(MAX31856_RTDMSB_REG);
msb = spi_read(0); // Data comes out MSB first
spi_write(MAX31856_RTDLSB_REG);
lsb = spi_read(0);
delay_us(10);
output_high(MAX31865_CS);
// Convert the data bytes into a 16-bit value.
rtd = make16(msb,lsb);
rtd >>= 1;//remove fault
return(rtd);
}
//---------------------------------------
// Call this function to write a 8-bit value
// to the MAX31865 register.
void MAX31865_write_register(int8 address,int8 config)
{
output_low(MAX31865_CS);
delay_us(10);
spi_write(address);
delay_us(10);
spi_write(config);
delay_us(10);
output_high(MAX31865_CS);
}
//Resistance to degrees celcius
double CallendarVanDusen(double r)
{
double a = 3.9083E-03;
double b = -5.7750E-07;
double R0 = 100;//bij 0C
double deel1 = -R0*a;
double deel2 = ((R0*a)*(R0*a));
double deel3 = 4*(R0*b*(R0-r));
double deel4 = 2*R0*b;
double deel5 = sqrt(deel2 - deel3);
double temp = (deel1+deel5)/deel4;
if(r == 0) temp =0;
delay_us(1);
return (temp);
}
//---------------------------------------
// Setup the hardware SPI module in the PIC.
// The MAX31865 uses SPI mode 3. The maximum SPI clock
// rate is 5 MHz. For a 10 MHz PIC, the closest
// clock divisor that will work is 4, giving 147kHz.
// Initialize the chip select pin to the inactive state.
void MAX31865_init(void)
{
setup_spi(SPI_MASTER | SPI_MODE_3 | SPI_CLK_DIV_16);
MAX31865_write_register(MAX31856_CONFIG_REG_WRITE,0xC3);//BIAS, AUTO, 50Hz
}
|
and the MAX31865_test.h:
Code: |
#include <18F87J50.h>
//#device adc=16
#FUSES NOWDT //No Watch Dog Timer
//#FUSES WDT128 //Watch Dog Timer uses 1:128 Postscale
#FUSES HS
#FUSES NOXINST //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES NOIESO
#use delay(crystal=8MHz)
/***************************************************************************************/
// SPI chip select pin
#define MAX31865_CS PIN_D1
// SPI mode definitions (for 16F and 18F PICs).
#define SPI_MODE_0 (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_1 (SPI_L_TO_H)
#define SPI_MODE_2 (SPI_H_TO_L)
#define SPI_MODE_3 (SPI_H_TO_L | SPI_XMIT_H_TO_L)
#define MAX31856_CONFIG_REG_READ 0x00
#define MAX31856_CONFIG_REG_WRITE 0x80
#define MAX31856_CONFIG_BIAS 0x80
#define MAX31856_CONFIG_MODEAUTO 0x40
#define MAX31856_CONFIG_MODEOFF 0x00
#define MAX31856_CONFIG_1SHOT 0x20
#define MAX31856_CONFIG_3WIRE 0x10
#define MAX31856_CONFIG_24WIRE 0x00
#define MAX31856_CONFIG_FAULTSTAT 0x02
#define MAX31856_CONFIG_FILT50HZ 0x01
#define MAX31856_CONFIG_FILT60HZ 0x00
#define MAX31856_RTDMSB_REG 0x01
#define MAX31856_RTDLSB_REG 0x02
#define MAX31856_HFAULTMSB_REG 0x03
#define MAX31856_HFAULTLSB_REG 0x04
#define MAX31856_LFAULTMSB_REG 0x05
#define MAX31856_LFAULTLSB_REG 0x06
#define MAX31856_FAULTSTAT_REG 0x07
#define MAX31865_FAULT_HIGHTHRESH 0x80
#define MAX31865_FAULT_LOWTHRESH 0x40
#define MAX31865_FAULT_REFINLOW 0x20
#define MAX31865_FAULT_REFINHIGH 0x10
#define MAX31865_FAULT_RTDINLOW 0x08
#define MAX31865_FAULT_OVUV 0x04
/***************************************************************************************/
|
|
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9244 Location: Greensville,Ontario
|
|
Posted: Wed Aug 25, 2021 6:28 am |
|
|
I'd edit main() and use KNOWN values for the 'result', to test the 'math'.
The datasheet will have a table of temps vs bits. I'd use 3 or 5 values and see how the 'math' works.
If it is correct, then either the 'driver' or hardware would be at fault.
BTW if the device a 3V and the PIC is 5V, you'll have 'problems'... |
|
|
Jody
Joined: 08 Sep 2006 Posts: 182
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19545
|
|
Posted: Wed Aug 25, 2021 7:33 am |
|
|
One little thing. You need:
output_high(MAX31865_CS);
at the start of your main. Currently the CS line will be floating, and then
pulled low at the start of the register access. Means the very first access
probably won't actually work, since the line was not high.
Means the first write may well not correctly happen.... |
|
|
Jody
Joined: 08 Sep 2006 Posts: 182
|
|
Posted: Wed Aug 25, 2021 8:50 am |
|
|
Hello,
Ttelmah,
I changed that.... if it starts working then it will working from the start...
But the value I get is still the same..
0x807F
Any ideas???
Best regards,
Jody |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
Re: MAX31865 what am I doing wrong?? |
Posted: Wed Aug 25, 2021 1:11 pm |
|
|
Jody wrote: | What I have:
MAX31865 connected as on page 24 from the datasheet.. the 2-wire sensor connection.
What I get is that the rtd value I read from the MAX31865 is alway 0x8087. |
1. What values are you using for the Rref resistor and C1 ?
2. Post a list of connections between your PIC pins and the MAX31865 pins.
3. Post the raw value that you get when you call MAX31865_read_data(void).
Post it in hex. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9244 Location: Greensville,Ontario
|
|
Posted: Wed Aug 25, 2021 2:57 pm |
|
|
0x8000 is about 250-260*C (from the datasheet) so I suspect either a bad TC or wrong components for the RTD device. |
|
|
Jody
Joined: 08 Sep 2006 Posts: 182
|
|
Posted: Wed Aug 25, 2021 3:22 pm |
|
|
Hello,
Rref=470 ohm
C1 = 100nF
CS -> PIN_D1
SCK -> PIN_C3
MISO -> PIN_C4
MOSI -> PIN_C5
after:
spi_write(MAX31856_RTDMSB_REG);
msb = spi_read(0); // Data comes out MSB first
msb = 0x80
and after:
spi_write(MAX31856_RTDLSB_REG);
lsb = spi_read(0);
lsb = 0x7F
after:
// Convert the data bytes into a 16-bit value.
rtd = make16(msb,lsb);
rtd = 0x807F |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Aug 25, 2021 11:01 pm |
|
|
On the MAX31865 board, what pins do you have the jumper installed on ?
For the 2-wire sensor connection, the jumper should be on pins 2-3. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19545
|
|
Posted: Thu Aug 26, 2021 12:14 am |
|
|
OK.
I'd suggest first of all you add a test to see if the fault bit is set. This
might help tell what is wrong.
If this is set, read the error register and look at table 10. This gives the
fault codes that are returned when this bit is 1.
So you really need to read the fault registers and see what it is saying is
wrong. The fault threshold registers are meant to be set to 0xFFFF, and
0x0000 at reset, so the limit errors should not apply.
However looking at the code, your read is wrong. The address byte can
only be written as the first byte after CS drops. It does not anywhere
show sending a subsequent address byte, You read the two registers
by doing a multi byte read, not by sending a second address, the address
automatically increments after each read. The data sheet specifically says:
Quote: |
The address byte is always the first byte transferred after CS is driven low.
|
So you need:
Code: |
int16 MAX31865_read_data(void)
{
int16 rtd;
int8 msb,lsb;
output_low(MAX31865_CS);
delay_us(1); //400nSec is all that is needed
spi_write(MAX31856_RTDMSB_REG);
msb = spi_read(0); // Data comes out MSB first
lsb = spi_read(0);
delay_us(1); //400nSec is all that is needed
output_high(MAX31865_CS);
// Convert the data bytes into a 16-bit value.
rtd = make16(msb,lsb);
rtd >>= 1;//remove fault
return(rtd);
}
|
You also need to delay 62.5mSec after starting the chip, before the first
reading is available.
I must admit, I cannot see anywhere in the data where it actually
describes how it handles continuous reads in the automatic mode. I'd
have expected you to need to wait for the DRDY bit to drop before a
reading can be made. I would be much happier putting it into single
conversion mode, then triggering a conversion, waiting for this to
complete, and then reading this. Perhaps worth trying.
However I'd suspect that trying to send two addresses is the big problem. |
|
|
Jody
Joined: 08 Sep 2006 Posts: 182
|
|
Posted: Thu Aug 26, 2021 3:11 am |
|
|
Hello Ttelmah,
I check the fault register now after every read-data of the MAX
The fault register data returns always with 0x00..
Checked the PT100 and this one is working fine (right now it is 108ohm).
I seems that everything is working but the data is still not right..... |
|
|
Jody
Joined: 08 Sep 2006 Posts: 182
|
|
Posted: Thu Aug 26, 2021 3:26 am |
|
|
It is working!!!!!!!!!!!!!!!!!!!!!!
What I changed, in the MAX31865_test.h :
was: #define SPI_MODE_3 (SPI_H_TO_L | SPI_XMIT_H_TO_L)
now: #define SPI_MODE_3 (SPI_H_TO_L | SPI_XMIT_L_TO_H)
and now it starts giving me the temperature it should be here........ |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19545
|
|
Posted: Thu Aug 26, 2021 3:53 am |
|
|
OK.
I meanwhile, took your code and rewrote it to use spi_xfer, and add the
delays that are really needed.
If your code is working without the change to the read routine, it implies
the chip is ignoring the second address write.
Note there is no such thing as 'double' in your chip. This is always just a
standard float32.
Code: |
//main31865.c
#include <18F87J50.h>
#device ADC=10
#FUSES NOWDT //No Watch Dog Timer
#FUSES NOXINST
#FUSES NOIESO
#use delay(crystal=8000000)
#use SPI(SPI1, baud=4000000, MODE=1, bits=32, STREAM=MAX)
#include "math.h"
#include "stdint.h"
#include "MAX31865.h"
void main()
{
float Rref = 470.0;
uint16_t result = 0;
float Temperature_vriezer;
uint16_t vriezer;
float Resistance;
output_high(MAX31865_CS);
delay_ms(100); //ensure chip has time to wake up
MAX31865_init(); //wake up chip
while(1)
{
result = MAX31865_read_data();
if (result & 1)
{
//error bit is set, read the error status
result=MAX31865_read8(MAX31856_FAULTSTAT_REG);
//here add fault diagmostics
}
else
{
result>>=1; //remove low bit
if(result == 0x7fff) result = 0;
Resistance = ((double)result*Rref)/32768;
Temperature_vriezer = CallendarVanDusen(Resistance);
vriezer = (int16) Temperature_vriezer;
delay_ms(17); //minimum 16.5mSec between readings;
}
}
}
|
Code: |
//max31865.h
/***************************************************************************************/
// SPI chip select pin
#define MAX31865_CS PIN_D1
#define MAX31856_CONFIG_REG_READ 0x00
#define MAX31856_CONFIG_REG_WRITE 0x80
#define MAX31856_CONFIG_BIAS 0x80
#define MAX31856_CONFIG_MODEAUTO 0x40
#define MAX31856_CONFIG_MODEOFF 0x00
#define MAX31856_CONFIG_1SHOT 0x20
#define MAX31856_CONFIG_3WIRE 0x10
#define MAX31856_CONFIG_24WIRE 0x00
#define MAX31856_CONFIG_FAULTSTAT 0x02
#define MAX31856_CONFIG_FILT50HZ 0x01
#define MAX31856_CONFIG_FILT60HZ 0x00
#define MAX31856_RTDMSB_REG 0x01
#define MAX31856_RTDLSB_REG 0x02
#define MAX31856_HFAULTMSB_REG 0x03
#define MAX31856_HFAULTLSB_REG 0x04
#define MAX31856_LFAULTMSB_REG 0x05
#define MAX31856_LFAULTLSB_REG 0x06
#define MAX31856_FAULTSTAT_REG 0x07
#define MAX31865_FAULT_HIGHTHRESH 0x80
#define MAX31865_FAULT_LOWTHRESH 0x40
#define MAX31865_FAULT_REFINLOW 0x20
#define MAX31865_FAULT_REFINHIGH 0x10
#define MAX31865_FAULT_RTDINLOW 0x08
#define MAX31865_FAULT_OVUV 0x04
/***************************************************************************************/
//---------------------------------------
// Call this function to read a 16bit value from a register pair
uint16_t MAX31865_read16(int regno)
{
uint16_t rtd;
output_low(MAX31865_CS);
delay_us(1);
spi_xfer(MAX,regno,8); //send the register number
rtd = spi_xfer(MAX,0L,16); // clock out 16 dummy bits and read the reply
delay_us(1);
output_high(MAX31865_CS);
return(rtd);
}
// Call this function to read an 8bit value from a register
uint8_t MAX31865_read8(int regno)
{
uint8_t rtd;
output_low(MAX31865_CS);
delay_us(1);
spi_xfer(MAX,regno,8); //send the register number
rtd = spi_xfer(MAX,0,8); // clock out 8 dummy bits and read the reply
delay_us(1);
output_high(MAX31865_CS);
return(rtd);
}
//specific version for data register
#define MAX31865_read_data() MAX31865_read16(MAX31856_RTDMSB_REG)
//---------------------------------------
// Call this function to write a 8-bit value
// to a MAX31865 register.
void MAX31865_write_register(uint8_t reg_address,uint8_t value)
{
output_low(MAX31865_CS);
delay_us(1);
spi_xfer(MAX,reg_address,8);
spi_xfer(MAX,value,8);
delay_us(1);
output_high(MAX31865_CS);
}
//Resistance to degrees celcius - your PIC does not support a double type
float CallendarVanDusen(float r)
{
float a = 3.9083E-03;
float b = -5.7750E-07;
float R0 = 100;//bij 0C
float deel1 = -R0*a;
float deel2 = ((R0*a)*(R0*a));
float deel3 = 4*(R0*b*(R0-r));
float deel4 = 2*R0*b;
float deel5 = sqrt(deel2 - deel3);
float temp = (deel1+deel5)/deel4;
if(r == 0) temp =0;
delay_us(1);
return (temp);
}
void MAX31865_init(void)
{
MAX31865_write_register(MAX31856_CONFIG_REG_WRITE,0xC3);//BIAS, AUTO, 50Hz
delay_ms(63); //minimum 62.5mSec before a result can be read
}
|
|
|
|
Jody
Joined: 08 Sep 2006 Posts: 182
|
|
Posted: Thu Aug 26, 2021 4:23 am |
|
|
O I changed it to what you sayed.. only used one write..
but I will check the code you wrote!!!
Do you want to know if it works?? |
|
|
Jody
Joined: 08 Sep 2006 Posts: 182
|
|
Posted: Thu Aug 26, 2021 4:33 am |
|
|
Hi Ttelmah,
Checked your code and it is working like a charm!!!!!!!!!!!!!
thanks for all your help!!! |
|
|
|