| 
	
	|  |  |  
	
		| 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: 1074
 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: 1074
 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: 1074
 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: 1074
 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: 1074
 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: 1074
 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
 
 |