CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

MAX31855 thermocouple-to-digital converter Example/Driver

 
Post new topic   Reply to topic    CCS Forum Index -> Code Library
View previous topic :: View next topic  
Author Message
btklister



Joined: 16 Jul 2009
Posts: 14

View user's profile Send private message

MAX31855 thermocouple-to-digital converter Example/Driver
PostPosted: Fri Dec 14, 2012 3:26 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Sun Dec 06, 2015 11:42 am     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Dec 08, 2015 8:47 am     Reply with quote

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

View user's profile Send private message

PostPosted: Thu Dec 10, 2015 6:43 am     Reply with quote

..... 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

View user's profile Send private message

PostPosted: Sat Dec 12, 2015 5:19 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Thu Dec 24, 2015 6:01 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Thu Mar 03, 2016 3:51 pm     Reply with quote

Thanks !!
_________________
MGLSOFT
Gabriel



Joined: 03 Aug 2009
Posts: 1067
Location: Panama

View user's profile Send private message

PostPosted: Wed Oct 05, 2016 11:28 am     Reply with quote

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
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> Code Library All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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