Type K thermocouple conversion module

Coding and general discussion relating to user created compiler modules

Moderators: David Barker, Jerry Messina

Post Reply
matherp
Registered User
Registered User
Posts: 31
Joined: Tue May 31, 2011 2:59 pm
Location: Cambridge

Type K thermocouple conversion module

Post by matherp » Sun Jun 12, 2011 1:25 pm

Routines to do conversions for Type K thermocouples mathematically with no lookup tables:

Hope this may be of use to someone:

Test program

Code: Select all

{
*****************************************************************************
*  Name    : ThermocoupleTest.BAS                                           *
*  Author  : Peter Mather                                                   *
*  Notice  : Copyright (c) 2011 Peter Mather                                *
*          : All Rights Reserved                                            *
*  Date    : 11/06/2011                                                     *
*  Version : 1.0                                                            *
*  Notes   :                                                                *
*          :                                                                *
*****************************************************************************
}
Device = 18F26K22
Clock = 64
Include "usart.bas"
Include "convert.bas"
Include "thermocouplek.bas"
SetBaudrate(br19200)
DelayMS (500)
USART.Write(FloatToStr(TypeKTemptoMv(-270.0),3),13,10)
USART.Write(FloatToStr(TypeKTemptoMv(-200.0),3),13,10)
USART.Write(FloatToStr(TypeKTemptoMv(-100.0),3),13,10)
USART.Write(FloatToStr(TypeKTemptoMv(-1.0),3),13,10)
USART.Write(FloatToStr(TypeKTemptoMv(0.0),3),13,10)
USART.Write(FloatToStr(TypeKTemptoMv(1.0),3),13,10)
USART.Write(FloatToStr(TypeKTemptoMv(20.0),3),13,10)
USART.Write(FloatToStr(TypeKTemptoMv(100.0),3),13,10)
USART.Write(FloatToStr(TypeKTemptoMv(200.0),3),13,10)
USART.Write(FloatToStr(TypeKTemptoMv(300.0),3),13,10)
USART.Write(FloatToStr(TypeKTemptoMv(400.0),3),13,10)
USART.Write(FloatToStr(TypeKTemptoMv(500.0),3),13,10)
USART.Write(FloatToStr(TypeKTemptoMv(600.0),3),13,10)
USART.Write(FloatToStr(TypeKTemptoMv(700.0),3),13,10)
USART.Write(FloatToStr(TypeKTemptoMv(800.0),3),13,10)
USART.Write(FloatToStr(TypeKTemptoMv(900.0),3),13,10)
USART.Write(FloatToStr(TypeKTemptoMv(1000.0),3),13,10)
USART.Write(FloatToStr(TypeKTemptoMv(1100.0),3),13,10)
USART.Write(FloatToStr(TypeKTemptoMv(1200.0),3),13,10)
USART.Write(FloatToStr(TypeKTemptoMv(1300.0),3),13,10)
USART.Write(FloatToStr(TypeKTemptoMv(1372.0),3),13,10)
USART.Write(FloatToStr(TypeKMvtoTemp(54.886),3),13,10)
USART.Write(FloatToStr(TypeKMvtoTemp(52.41),3),13,10)
USART.Write(FloatToStr(TypeKMvtoTemp(48.838),3),13,10)
USART.Write(FloatToStr(TypeKMvtoTemp(45.119),3),13,10)
USART.Write(FloatToStr(TypeKMvtoTemp(37.326),3),13,10)
USART.Write(FloatToStr(TypeKMvtoTemp(33.275),3),13,10)
USART.Write(FloatToStr(TypeKMvtoTemp(29.129),3),13,10)
USART.Write(FloatToStr(TypeKMvtoTemp(24.905),3),13,10)
USART.Write(FloatToStr(TypeKMvtoTemp(20.644),3),13,10)
USART.Write(FloatToStr(TypeKMvtoTemp(16.397),3),13,10)
USART.Write(FloatToStr(TypeKMvtoTemp(12.209),3),13,10)
USART.Write(FloatToStr(TypeKMvtoTemp(8.138),3),13,10)
USART.Write(FloatToStr(TypeKMvtoTemp(4.096),3),13,10)
USART.Write(FloatToStr(TypeKMvtoTemp(0.798),3),13,10)
USART.Write(FloatToStr(TypeKMvtoTemp(0.039),3),13,10)
USART.Write(FloatToStr(TypeKMvtoTemp(0.0),3),13,10)
USART.Write(FloatToStr(TypeKMvtoTemp(-0.039),3),13,10)
USART.Write(FloatToStr(TypeKMvtoTemp(-3.554),3),13,10)
USART.Write(FloatToStr(TypeKMvtoTemp(-5.891),3),13,10)
USART.Write(FloatToStr(Kconvert(20,20.644),3),13,10)


USART.Write(13,10)
End

Module

Code: Select all

Module ThermocoupleK 
{ 
***************************************************************************** 
*  Name    : ThermocoupleK.BAS                                              * 
*  Author  : Peter Mather                                                   * 
*  Notice  : Copyright (c) Peter Mather                                     * 
*          : All Rights Reserved                                            * 
*  Date    : 11/06/2011                                                     * 
*  Version : 1.0                                                            * 
*  Notes   :                                                                * 
*          :                                                                * 
***************************************************************************** 
} 
Include "math.bas" 
Const comp0 = -1.7600413686E1 
Const comp1 = 3.8921204975E1 
Const comp2 = 1.8558770032E-2 
Const comp3 = -9.9457592874E-5 
Const comp4 = 3.1840945719E-7 
Const comp5 = -5.6072844889E-9  //scaled by E1 to workround parsing bug
Const comp6 = 5.6075059059E-9  //scaled by E4 to workround parsing bug
Const comp7 = -3.2020720003E-9 //scaled by E7 to workround parsing bug 
Const comp8 = 9.7151147152E-9  //scaled by E11 to workround parsing bug 
Const comp9 = -1.2104721275E-9 //scaled by E14 to workround parsing bug 

Const lcomp1 = 3.9450128025E1 
Const lcomp2 = 2.3622373598E-2 
Const lcomp3 = -3.2858906784E-4 
Const lcomp4 = -4.9904828777E-6 
Const lcomp5 = -6.7509059137E-8 
Const lcomp6 = -5.7410327428E-9 //scaled by E1 to workround parsing bug
Const lcomp7 = -3.1088872894E-9 //scaled by E3 to workround parsing bug
Const lcomp8 = -1.0451609365E-9 //scaled by E5 to workround parsing bug 
Const lcomp9 = -1.9889266878E-9 //scaled by E8 to workround parsing bug 
Const lcomp10 = -1.63226974865E-9 //scaled by E11 to workround parsing bug 

Const C0L = 0.0 
Const C1L = 2.5173462E1 
Const C2L = -1.1662878 
Const C3L = -1.0833638 
Const C4L = -8.9773540E-1 
Const C5L = -3.7342377E-1 
Const C6L = -8.6632643E-2 
Const C7L = -1.0450598E-2 
Const C8L = -5.1920577E-4 
Const C9L = 0.0 

Const C0 = 0.0 
Const C1 = 2.508355E1 
Const C2 = 7.860106E-2 
Const C3 = -2.503131E-1 
Const C4 = 8.315270E-2 
Const C5 = -1.228034E-2 
Const C6 = 9.804036E-4 
Const C7 = -4.413030E-5 
Const C8 = 1.057734E-6 
Const C9 = -1.052755E-8 
  
Const C0H = -1.318058E2 
Const C1H = 4.830222E1 
Const C2H = -1.646031 
Const C3H = 5.464731E-2 
Const C4H = -9.650715E-4 
Const C5H = 8.80219E-6 
Const C6H = -3.11081E-8 
Const C7H = 0.0 
Const C8H = 0.0 
Const C9H = 0.0 
Const cadj1=118.5976 
Const cadj2=-1.183432E-4 
Const cadj3=126.9696 
Dim Vadj,v0,v2,v3,v4,v5,v6,v7,v8,v9,v10 As Float 
{ 
Convert a temperature in the range -270C to 1372C to the Mv reading that will be seen 
with a type K thermocouple with the cold junction at 0 
} 


Public Function TypeKTemptoMv (ByVal tmeas As Float) As Float    //Accurate -270C to 1372C 

v0 =  tmeas 
v2 = v0 * v0 
v3 = v2 * v0 
v4 = v3 * v0 
v5 = v4 * v0 
v6 = v5 * v0 
v7 = v6 * v0 
v8 = v7 * v0 
v9 = v8 * v0 
v10= v9 * v0 
If tmeas >=0.0 Then 
    Vadj = comp0 + (comp1*v0) + (comp2*v2) + (comp3*v3) + (comp4*v4) + (comp5*v5/10.0) + (comp6*v6/10000.0) + (comp7*v7/10000000.0) + (comp8*v8/10000000.0/10000.0) + (comp9*v9/10000000000.0/10000.0) 
    If tmeas <600 Then 
        Vadj=Vadj+(cadj1*exp(cadj2*(tmeas -cadj3)* (tmeas -cadj3))) 
    EndIf 
Else 
    Vadj = (lcomp1*v0) + (lcomp2*v2) + (lcomp3*v3) + (lcomp4*v4) + (lcomp5*v5) + (lcomp6*v6/10.0) + (lcomp7*v7/1000.0) + (lcomp8*v8/100000) + (lcomp9*v9/100000000.0) + (lcomp10*v10/10000000.0/10000.0) 
EndIf 
    TypeKTemptoMv = Vadj/1000.0 

End Function 
{ 
Convert a Mv reading from a Type K thermocouple to a temperature in degree C assuming the cold junction is at 0 degree C 
} 
Public Function TypeKMvtoTemp (ByVal Mv As Float) As Float //Accurate -200C to 1372C 

v0 = Mv 
v2 = v0 * v0 
v3 = v2 * v0 
v4 = v3 * v0 
v5 = v4 * v0 
v6 = v5 * v0 
v7 = v6 * v0 
v8 = v7 * v0 
v9 = v8 * v0 

If Mv<0 Then 
    TypeKMvtoTemp = C0L + (C1L*v0) + (C2L*v2) + (C3L*v3) + (C4L*v4) + (C5L*v5) + (C6L*v6) + (C7L*v7) + (C8L*v8) + (C9L*v9) 
Else 
    If Mv <=20.644 Then 
        TypeKMvtoTemp = C0 + (C1*v0) + (C2*v2) + (C3*v3) + (C4*v4) + (C5*v5) + (C6*v6) + (C7*v7) + (C8*v8) + (C9*v9) 
    Else 
        TypeKMvtoTemp = C0H + (C1H*v0) + (C2H*v2) + (C3H*v3) + (C4H*v4) + (C5H*v5) + (C6H*v6) + (C7H*v7) + (C8H*v8) + (C9H*v9) 
    EndIf 
EndIf 

End Function 
{ 
Convert a Mv reading from a Type K thermocouple to a temperature in degree C given a non-zero cold junction temperature which is input in degree C 
} 
Public Function Kconvert (ByVal coldjunction As Float, ByVal mV As Float) As Float 
    Kconvert=TypeKMvtoTemp(TypeKTemptoMv(coldjunction)+mV) 
End Function 

End  Module 
Last edited by matherp on Sun Jun 12, 2011 3:14 pm, edited 2 times in total.

Jerry Messina
Swordfish Developer
Posts: 1470
Joined: Fri Jan 30, 2009 6:27 pm
Location: US

Post by Jerry Messina » Sun Jun 12, 2011 2:06 pm

Peter -

I haven't worked through all the math, but it would seem that a lot of the compensations are probably outside the range of single-precision floats, which only give you 6-7 decimal digits of precision.

When you have operations involving a wide range of numbers, operations like addition and subtraction lose accuracy since the numbers have to be normalized to do the operation, and all those extra digits just get lost in the noise.

Do you really see any difference past the first few compensation factors?

matherp
Registered User
Registered User
Posts: 31
Joined: Tue May 31, 2011 2:59 pm
Location: Cambridge

Post by matherp » Sun Jun 12, 2011 2:14 pm

Jerry


All the polynomial factors are critical because of the power function on the input value (temp or mV).

This is where I ran into difficulties re the post on the parsing bug in the compiler section.

10E-23 was setting as zero which when multipled by t^9 was very significant

To demonstrate this I've listed the calculated mV contributions for each of the polynomial terms for an input temperature of 600degree C

p0 -1.7600413686E-02
p1 2.3352722985E+01
p2 6.6811572115E+00
p3 -2.1482840061E+01
p4 4.1265865652E+01
p5 -4.3602244186E+01
p6 2.6162379555E+01
p7 -8.9637522748E+00
p8 1.6317662117E+00
p9 -1.2198770117E-01
Tot 2.4905466979E+01

As you can see errors in any of them will have an impact. The international thermocouple reference table give 24.905mV for this temperature so I'm pretty pleased with my result :D

Best Regards

Peter

Jon Chandler
Registered User
Registered User
Posts: 185
Joined: Mon Mar 10, 2008 8:20 am
Location: Seattle, WA USA
Contact:

Post by Jon Chandler » Sun Jun 12, 2011 7:58 pm

I wonder how this would compare in execution time and resources to my method of using a look up table to the nearest degree C and interpolation.
Jon

Check out the TAP-28 PIC Application board at http://www.clever4hire.com/throwawaypic/

matherp
Registered User
Registered User
Posts: 31
Joined: Tue May 31, 2011 2:59 pm
Location: Cambridge

Post by matherp » Mon Jun 13, 2011 3:38 pm

Jon

I'd suspect that the table lookup would be much quicker assuming you use a reasonably efficient search algorithm and it is all integer - I just like the mathematical approach :D
From a resource perspective I suspect the maths wins if you are already using floating point in your application but probably not otherwise
Best regards

Peter

Jon Chandler
Registered User
Registered User
Posts: 185
Joined: Mon Mar 10, 2008 8:20 am
Location: Seattle, WA USA
Contact:

Post by Jon Chandler » Mon Jun 13, 2011 4:49 pm

matherp wrote:Jon

...is all integer...

That is one slight limitation of my method. I confined the table to integer values, which limits the temperature range to 700=some degrees C instead of the 1100 to which a K-type thermocouple is rated. Not much of a limitation for anything I'm doing :)
Jon

Check out the TAP-28 PIC Application board at http://www.clever4hire.com/throwawaypic/

Post Reply