|
|
View previous topic :: View next topic |
Author |
Message |
btklister
Joined: 16 Jul 2009 Posts: 14
|
MAX31855 thermocouple-to-digital converter Example/Driver |
Posted: Fri Dec 14, 2012 3:26 pm |
|
|
Hi,
This is an example how to interface MAX31855 thermocouple-to-digital converter. Feel free to use it and/or optimize it!
Slave Select: pin_b0
data in: pin_b1
clock: pin_b4
Code: |
#include <16F88.h>
#device adc=16
#FUSES NOWDT //No Watch Dog Timer
#FUSES PUT //Power Up Timer
#FUSES INTRC_IO //Internal RC Osc, no CLKOUT
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#use delay(int=8000000)
//#USE SPI (MASTER, SPI1, CLOCK_HIGH=100, CLOCK_LOW=100, MODE=0, LOAD_ACTIVE=1, ENABLE_ACTIVE=0, STREAM=SPI_1, MSB_FIRST,FORCE_HW)
#use rs232(baud=9600,parity=N,xmit=PIN_b7,rcv=PIN_b6,bits=8,errors)
#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_L_TO_H)
#define SS PIN_B0
int8 spival[4];
/*******************************************************************************
//Read SPI data
*******************************************************************************/
void readMAX()
{
output_low(SS);
delay_us(10);
spival[3]=spi_read(0);
spival[2]=spi_read(0);
spival[1]=spi_read(0);
spival[0]=spi_read(0);
delay_us(10);
output_high(SS);
}
/*******************************************************************************
//Fault detection.
//Returns >0 if FAULT. If necessary do a bitwise analisys to check fault source
*******************************************************************************/
int tempFault()
{
int1 Fvdd=0,Fgnd=0,Fopen=0,fault=0;
fault=spival[2]&0x01; // pelos menos uma falha
Fvdd=(spival[0]>>2)&0x01;
Fgnd=(spival[0]>>1)&0x01;
Fopen=spival[0]&0x01;
return (fault*1+Fvdd*2,Fgnd*4,Fopen*8);
}
/*******************************************************************************
//Read thermocouple temperature
//Returns returns signed temperature in ºC approximately
*******************************************************************************/
int16 readExtTemp()
{
int8 aux;
int16 temp1;
aux=spival[2]>>2;
temp1=spival[3];
temp1<<=6;
temp1+=aux;
return temp1/=4;
}
/*******************************************************************************
//Read internal temperature
//Returns returns signed temperature in ºC approximately
*******************************************************************************/
int16 readIntTemp()
{
int8 aux;
int16 temp2;
temp2=spival[1];
temp2<<=4;
aux=spival[0]>>4;
temp2=spival[1]<<4;
temp2+=aux;
return temp2/=16;
}
void main()
{
setup_oscillator(OSC_8MHZ|OSC_INTRC);
setup_spi(SPI_MASTER | SPI_MODE_1 | SPI_CLK_DIV_64);
while(TRUE)
{
do{
readMAX();
}while(tempFault()!=0);
printf("\n\n Thermocouple: %Ld, Ambient: %Ld\n\r",readExtTemp(),readIntTemp());
delay_ms(500);
}
} |
|
|
|
Gabriel
Joined: 03 Aug 2009 Posts: 1067 Location: Panama
|
|
Posted: Sun Dec 06, 2015 11:42 am |
|
|
After much hair pulling i will share this:
with a PIC18F87J50 i had to change
Code: | void readMAX()
{
output_low(CS);
delay_us(10);
spival[3]=spi_read(0);
delay_us(10);
spival[2]=spi_read(0);
delay_us(10);
spival[1]=spi_read(0);
delay_us(10);
spival[0]=spi_read(0);
delay_us(10);
output_high(CS);
} |
Seems like the speed of the reads is too fast. _________________ CCS PCM 5.078 & CCS PCH 5.093 |
|
|
Gabriel
Joined: 03 Aug 2009 Posts: 1067 Location: Panama
|
|
Posted: Tue Dec 08, 2015 8:47 am |
|
|
Another contribution to the driver.
The original does not handle Negative temperatures properly.
I've corrected this and made it return a Float - Because i want to - but it is easily made into a signed int...
Code: | float readExtTemp()
{
int16 temp1;
float aux;
temp1=make16(spival[3],spival[2]);
if(!bit_test(temp1,15))
{
temp1>>=2;
aux=(temp1/4);
return aux;
}
else
{
temp1=~temp1;
temp1>>=2;
temp1+=1;
aux=((temp1/4)*-1.00);
return aux;
}
} |
G. _________________ CCS PCM 5.078 & CCS PCH 5.093 |
|
|
Gabriel
Joined: 03 Aug 2009 Posts: 1067 Location: Panama
|
|
Posted: Thu Dec 10, 2015 6:43 am |
|
|
..... while i develop a proper(read: to the best of my abilities) NIST based cold junction compensation code, i would advise anyone here to only use this code/chip with + temperatures...
At -80c this chip reads -40c.
The chip uses a CONSTANT linearization which QUICKLY goes to hell at negative temperatures.... i suspect the same for positive temps.
G. _________________ CCS PCM 5.078 & CCS PCH 5.093 |
|
|
Gabriel
Joined: 03 Aug 2009 Posts: 1067 Location: Panama
|
|
Posted: Sat Dec 12, 2015 5:19 pm |
|
|
MAX31855 users be advised: there are at least 5 bad batches of IC's.
I just found out ALL of mine are from said bad batches....
I just wasted 3 days calculating nth order polynomials.... but on the bright side when i get replacements, i will post NIST compensated code for 0 to -200C
This sucks... i missed a deadline due to poor quality control.
16/04/2018 - I should update this and mention that the guys at MAXIM where SPLENDID with their customer service related to the bad batch of IC's. I apologize for not doing it sooner. They helped me get refund, new chips and some pretty cool App notes.
G. _________________ CCS PCM 5.078 & CCS PCH 5.093
Last edited by Gabriel on Mon Apr 16, 2018 1:13 pm; edited 1 time in total |
|
|
Gabriel
Joined: 03 Aug 2009 Posts: 1067 Location: Panama
|
|
Posted: Thu Dec 24, 2015 6:01 pm |
|
|
Hi All,
Merry Christmas.
This is my modified Driver for the MAX31855 based on the OP's original driver.
Mine is Optimized for Negative Temperatures.
It does NOTHING For positive temperatures... it literally just spits the data straight from the MAX31855.
I have tested this driver down to -85C, and I am currently monitoring 3 medical freezers with it, and its working pretty good.
I have externally linearized the results (NEGATIVE ONLY) based on the MAXIM guidelines, but Ive eliminated complex calculations in favor of Lookup Tables.
I am using Floats as a result... i didn't have the time to optimize this for Integer math.
you can tell the driver is a bit RUSHED but it WORKS and its ACCURATE.
THIS FUNCTION UPDATES A GLOBAL VARIABLE CALLED "TEMPERATURE"
This goes in my Main Program.c
Code: | void Read_Sensor()
{
float Filter[10]={0,0,0,0,0,0,0,0,0,0};
int index=0;
float local_high=-1000;
float local_low=1000;
Temperature=0;
while(index<10)
{
fprintf(lcd_putc,"%u ",index);
//***********************************************
//while(1){fprintf(lcd_putc,"Pre-Filtered:%3.2f\r\n\r\n",Linearized_TC());delay_ms(500);}
Filter[index]=Linearized_TC();
//**********************************************************
delay_ms(100); //Delay because then the Main loop time is too fast
index++;
}
fprintf(lcd_putc,"\r\n");
index=0;
while(index<10)
{
if(Filter[index]<local_low)local_low=Filter[index];
if(Filter[index]>local_high)local_high=Filter[index];
index++;
}
index=0;
while(index<10)
{
Temperature+=Filter[index];
index++;
}
Temperature-=local_low;
Temperature-=local_high;
Temperature/=8;
if(Temperature<t_low)t_low=Temperature;
if(Temperature>t_high)t_high=Temperature;
fprintf(lcd_putc,"___Temp int:%3.2f\r\n",readIntTemp());
fprintf(lcd_putc,"___Temp ext:%3.2f - TRIG:%u - HYS:%u - VT:%u\r\n",Temperature,ALARM_TRIGGERED,ALARM_HYSTERESIS,VALID_TIME);
fprintf(lcd_putc,"Discarded LOW: %3.2f - Discarded HIGH: %3.2f\r\n",local_low,local_high);
} |
The DRIVER: Thermocuple.c
Code: |
#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_L_TO_H)
#define CS PIN_D1
const int16 NegativeK[150]={ 0, 39, 79, 118, 157, 197, 236, 275, 314, 353,
392, 431, 470, 508, 547, 586, 624, 663, 701, 739,
778, 816, 854, 892, 930, 968,1006,1043,1081,1119,
1156,1194,1231,1268,1305,1343,1380,1417,1453,1490,
1527,1564,1600,1637,1673,1709,1745,1782,1818,1854,
1889,1925,1961,1996,2032,2067,2103,2138,2173,2208,
2243,2278,2312,2347,2382,2416,2450,2485,2519,2553,
2587,2620,2654,2688,2721,2755,2788,2821,2854,2887,
2920,2953,2986,3018,3050,3083,3115,3147,3179,3211,
3243,3274,3306,3337,3368,3400,3431,3462,3492,3523,
3554,3584,3614,3645,3675,3705,3734,3764,3794,3823,
3852,3882,3911,3939,3968,3997,4025,4054,4082,4110,
4138,4166,4194,4221,4249,4276,4303,4330,4357,4384,
4411,4437,4463,4490,4516,4542,4567,4593,4618,4644,
4669,4694,4719,4744,4768,4793,4817,4841,4865,4889};
const int16 PositiveK[150]={ 0, 39, 79, 119, 158, 198, 238, 277, 317, 357,
397, 437, 477, 517, 557, 597, 637, 677, 718, 758,
798, 838, 879, 919, 960,1000,1041,1081,1122,1163,
1203,1244,1285,1326,1366,1407,1448,1489,1530,1571,
1612,1653,1694,1735,1776,1817,1858,1899,1941,1982,
2023,2064,2106,2147,2188,2230,2271,2312,2354,2395,
2436,2478,2519,2561,2602,2644,2685,2727,2768,2810,
2851,2893,2934,2976,3017,3059,3100,3142,3184,3225,
3267,3308,3350,3391,3433,3474,3516,3557,3599,3640,
3682,3723,3765,3806,3848,3889,3931,3972,4013,4055,
4096,4138,4179,4220,4262,4303,4344,4385,4427,4468,
4509,4550,4591,4633,4674,4715,4756,4797,4838,4879,
4920,4961,5002,5043,5084,5124,5165,5206,5247,5288,
5328,5369,5410,5450,5491,5532,5572,5613,5653,5694,
5735,5775,5815,5856,5896,5937,5977,6017,6058,6098};
int spival[4];
int16 Count=0;
/*******************************************************************************
//Read SPI data
*******************************************************************************/
void readMAX()
{
output_low(CS);
delay_us(1);
spival[3]=spi_read(0);
spival[2]=spi_read(0);
spival[1]=spi_read(0);
spival[0]=spi_read(0);
delay_us(1);
output_high(CS);
}
/*******************************************************************************
//Fault detection.
//Returns >0 if FAULT. If necessary do a bitwise analisys to check fault source
*******************************************************************************/
int tempFault()
{
int1 Fvdd=0,Fgnd=0,Fopen=0,fault=0;
fault=spival[2]&0x01; // pelos menos uma falha
Fvdd=(spival[0]>>2)&0x01;
Fgnd=(spival[0]>>1)&0x01;
Fopen=spival[0]&0x01;
return (fault*1+Fvdd*2,Fgnd*4,Fopen*8);
}
/*******************************************************************************
//Read thermocouple temperature
//Returns returns signed temperature in ºC approximately
*******************************************************************************/
float readExtTemp()
{
int16 temp1=0;
float aux=0;
//spival[3]=0x01;
//spival[2]=0x90;
//Count++;
temp1=make16(spival[3],spival[2]);
//temp1-=Count;
//fprintf(lcd_putc,"REXT:%LX , ",Temp1);
if(!bit_test(temp1,15))
{
temp1>>=2;
//fprintf(lcd_putc,"SR+EXT:%LX , ",Temp1);
aux=(temp1/4.00);
//fprintf(lcd_putc,"Ext+C:%3.2f, ",aux);
return aux;
}
else
{
temp1=~temp1;
temp1>>=2;
temp1+=1;
//fprintf(lcd_putc,"SR-EXT:%LX , ",Temp1);
aux=((temp1/4.00)*-1.00);
//fprintf(lcd_putc,"RAW Ext-C:%3.2f, ",aux);
return aux;
}
}
/*******************************************************************************
//Read internal temperature
//Returns returns signed temperature in ºC approximately
*******************************************************************************/
float readIntTemp()
{
int16 temp2=0;
float aux=0;
temp2=make16(spival[1],spival[0]);
//fprintf(lcd_putc,"RINT:%LX , ",Temp2);
if(!bit_test(temp2,15))
{
temp2>>=4;
//fprintf(lcd_putc,"SR+INT:%LX , ",Temp2);
aux=(temp2/16.00);
//fprintf(lcd_putc,"Int+C:%3.2f\r\n",aux);
return aux;
}
else
{
temp2=~temp2;
temp2>>=4;
temp2+=1;
//fprintf(lcd_putc,"SR-INT:%LX , ",Temp2);
aux=((temp2/16.00)*-1.00);
//fprintf(lcd_putc,"RAW Int-C:%3.2f\r\n",aux);
return aux;
}
}
float PreFilter()
{
float Raw_TC_Temp[3]={0.00,0.00,0.00};
int Raw_Temp_Index=0;
int1 Temp_Stable=0;
while(Temp_Stable==0)
{
Raw_TC_Temp[0]=0.00;
Raw_TC_Temp[1]=0.00;
Raw_TC_Temp[2]=0.00;
Raw_Temp_Index=0;
while(Raw_Temp_Index<3)
{
do{readMAX();}while(tempFault()!=0);
Raw_TC_Temp[Raw_Temp_Index]=readExtTemp();
//Raw_TC_Temp[Raw_Temp_Index]=-70.00; // DEBUG
Raw_Temp_Index++;
delay_ms(100);
}
if((abs(Raw_TC_Temp[0]-Raw_TC_Temp[1])<1.25)&&(abs(Raw_TC_Temp[1]-Raw_TC_Temp[2])<1.25)&&(abs(Raw_TC_Temp[0]-Raw_TC_Temp[2])<1.25))
Temp_Stable=1;
}
//fprintf(lcd_putc,"RAW1:%3.2f - RAW2:%3.2f - RAW3:%3.2f \r\n",Raw_TC_Temp[0],Raw_TC_Temp[1],Raw_TC_Temp[2]);
return((Raw_TC_Temp[0]+Raw_TC_Temp[1]+Raw_TC_Temp[2])/3.00);
}
float Linearized_TC()
{
const float Curve_Value=0.041276;
float EXT_Minus_INT=0.00;
float TC_Voltage=0.00;
float INT_Temp=0.00;
float EXT_Temp=0.00;
int NIST_Index=0;
EXT_Temp=PreFilter();
INT_Temp=readIntTemp();
if(EXT_Temp<0.00)
{
EXT_Minus_INT=(EXT_Temp-INT_Temp);
TC_Voltage=EXT_Minus_INT*Curve_Value;
//fprintf(lcd_putc,"TC_Voltage:%3.2f\r\n",TC_Voltage); //MATH OK
//fprintf(lcd_putc,"DEC_INT:%3.2f\r\n",INT_Temp);
while(NIST_Index<INT_Temp)NIST_Index++;
NIST_Index--;
//fprintf(lcd_putc,"NIST:%d\r\n",NIST_Index);
//fprintf(lcd_putc,"NIST MV:%ld\r\n",PositiveK[NIST_Index]);
TC_Voltage+=(PositiveK[NIST_Index]/1000.00);
TC_Voltage*=-1000.00;
//fprintf(lcd_putc,"TC_Voltage2:%3.2f\r\n",TC_Voltage);
NIST_Index=0;
while(TC_Voltage>NegativeK[NIST_Index])
{
NIST_Index++;
}
NIST_Index--;
//fprintf(lcd_putc,"EXT NIST:%d\r\n",NIST_Index);
return(NIST_Index*-1.00);
}
else
return(EXT_Temp);
}
|
_________________ CCS PCM 5.078 & CCS PCH 5.093 |
|
|
mglsoft
Joined: 18 Feb 2008 Posts: 48
|
|
Posted: Thu Mar 03, 2016 3:51 pm |
|
|
Thanks !! _________________ MGLSOFT |
|
|
Gabriel
Joined: 03 Aug 2009 Posts: 1067 Location: Panama
|
|
Posted: Wed Oct 05, 2016 11:28 am |
|
|
Hi All,
I made a comparison of a DS18B20 with the Linearized thermocouple driver i uploaded - Ive made some further adjustments - and i got the following results.
Might not be the best test ever, but hey, its a good starting reference.
Code: |
TC_K-type DS18B20 Error
29.00 28.46 0.53
29.00 28.48 0.51
29.00 28.50 0.50
29.00 28.51 0.48
28.44 27.05 1.39
23.50 20.99 2.50
16.09 13.64 2.45
9.25 7.12 2.12
3.81 1.94 1.87
-1.07 -1.93 0.86
-4.69 -4.76 0.06
-7.05 -6.83 0.22
-8.56 -8.28 0.27
-9.75 -9.36 0.38
-10.77 -10.15 0.62
-11.16 -10.76 0.40
-11.96 -11.21 0.74
-12.08 -11.58 0.49
-12.68 -11.88 0.80
Average Absolute Error: 0.90
|
Most of the error is due to the differences in time response due to the mass or rubber shielding of the DS18B20 - or lack of on the TC
G _________________ CCS PCM 5.078 & CCS PCH 5.093 |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|