/*
���������������������������������������������������������������������������
� �
� THERMOCOUPLE TASK �
� �
� Copyright (c) 1994 �
� by Lutfi Shahab �
� Instrumentation and Controls Laboratory �
� Dept. of Engineering Physics �
� Institut Teknologi Bandung �
� �
� Date: 20/11/94 �
� �
� Platform : Motorola 68HC16 Microcontroller �
� running mcx16 multitasking kernel �
� Compiler : Whitesmith HC16 Compiler �
� Target : EPROM-targeted binary code �
� �
� Description: �
� This module contains routines for Thermocouple Linearization using �
� polynomial curvefitting. Only thermocouple type K can be calculated. �
� Temperature adjusted to Celcius. �
� �
���������������������������������������������������������������������������;
*/
#define _WSC_
#define _FAR_
#ifdef _WSC_
#include <wslxa.h>
#else
enum {ADC_1, ADC_2, ADC_3, ADC_4, ADC_5,ADC_6, ADC_7, ADC_8, N_ADC_CHANNELS};
#endif
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <stdio.h>
#ifdef _WSC_
#include "mcxapi.h"
#include "sysdef.h"
#endif
#define VREF_PLUS +2500.0 /* mV */
#define VREF_MIN -2500.0 /* mV */
#define RESOLUTION 10 /* bits */
#define KELVIN_TO_C 273.20 /* based on IPTS-68 */
#define LM335_VT 10.00 /* mV per Kelvin degree */
#define TC_GAIN_AMP (10000/40) /* gain of TC op-amp; uV/uV */
#define DIGIT_TO_MILLIVOLT(d) (((d)*scale)+VREF_MIN) /* mV */
/* seebeck coefficients for all TC types */
#define SEEBECK_COEF_K 40.01 /* uV/K */
#define SEEBECK_COEF_TC 5.20
#define SEEBECK_COEF_BN 18.05
#define SEEBECK_COEF_E 59.80
#define SEEBECK_COEF_JT 51.08
#define SEEBECK_COEF_JP 17.94
#define SEEBECK_COEF_JN 33.10
#define SEEBECK_COEF_K 40.01
#define SEEBECK_COEF_KP 26.47
#define SEEBECK_COEF_KN 13.54
#define SEEBECK_COEF_R 5.62
#define SEEBECK_COEF_S 5.70
#define SEEBECK_COEF_T 39.67
#define SEEBECK_COEF_TP 6.33
#define SEEBECK_COEF_TN 33.32
#define SEEBECK_COEF SEEBECK_COEF_K
/* number of linearization polynomial equations as T(V) */
#define NUMEQN_V 5
/* number of linearization polynomial equations as V(T) */
#define NUMEQN_T 2
#define ORDE_T 10
#define ORDE_V 4
#define TC_VOLT_MIN tc_table.v_range[0].min
#define TC_VOLT_MAX tc_table.v_range[NUMEQN_V-1].max
typedef struct {
double min, max;
}RANGE;
typedef struct {
RANGE t_range[NUMEQN_T]; /* temperature range */
RANGE v_range[NUMEQN_V]; /* voltage range */
double coef_t[NUMEQN_T][ORDE_T+1]; /* polynomial coefficients for every equation of V(T) */
double coef_v[NUMEQN_V][ORDE_V+1]; /* polynomial coefficients for every equation of T(V) */
} TCRECTYPE;
TCRECTYPE tc_table = {
/* Temperature ranges (in C) for each polynomial equation of type K */
{
{-270.00, 0.00},
{ 0.00, 1372.00},
},
/* Voltage ranges in microvolts */
{
{-6.457816e+03, -6.441148e+03},
{-6.441148e+03, -5.891361e+03},
{-5.891361e+03, 1.853306e+01},
{ 1.853306e+01, 8.136555e+03},
{ 8.136555e+03, 5.487490e+04}
},
{
/* Coefficients for each polynomial equation V(T) */
{
0.0000000000E+00, 3.9475433139E+01, 2.7465251138E-02,
-1.6565406716E-04,-1.5190912392E-06,-2.4581670924E-08,
-2.4757917816E-10,-1.5585276173E-12,-5.9729921255E-0015,
-1.2688801216E-17,-1.1382797374E-20
},
{
-1.8533063273E+01, 3.8918344612E+01, 1.6645154356E-02,
-7.8702374448E-05, 2.2835785557E-07,-3.5700231258E-10,
2.9932909136E-13,-1.2849848798E-16, 2.2239974336E-20,
0.00, 0.00
}
},
/* Coefficients for each polynomial equation T(V) in C */
{
{-8.887677e+05,-2.054743e+02, 1.307316e-02, 5.611858e-06, 3.034392e-10},
{-1.215521e+06,-7.993152e+02,-1.971155e-01,-2.160351e-05,-8.879453e-10},
{0.0000000e+00, 2.382475e-02,-2.372981e-06,-6.567714e-10,-9.208444e-14},
{0.0000000e+00, 2.548081e-02,-5.270562e-07, 7.989244e-11,-3.520933e-15},
{-1.035821e+01, 2.712314e-02,-1.781781e-07, 3.243000e-12,-1.166816e-17}
}
};
double scale; /* transformation scale */
/* calculate seebeck voltage value for a given temperature and TC */
/*
double calc_seebeck(double tempin)
{
return (SEEBECK_COEF * tempin);
}
*/
/* calculate TC temperature given volts using polynomial equations */
double volt2temp_poly(double voltin) /* input voltage */
{
int pi; /* index to appropriate polynom */
int i;
double yout;
if (voltin < TC_VOLT_MIN) /* check to see if voltage in valid range */
{
voltin = TC_VOLT_MIN;
}
else if (voltin > TC_VOLT_MAX)
{
voltin = TC_VOLT_MAX;
}
pi = 0;
/* search through breakpoint list looking for proper interval */
while ( (pi < NUMEQN_V) &&
!((voltin >= tc_table.v_range[pi].min) &&
(voltin <= tc_table.v_range[pi].max)))
{
pi++;
}
/* calculate TC temperature as a function of volts */
yout = tc_table.coef_v[pi][ORDE_V];
for (i=ORDE_V-1; i<=0; i--)
{
/* efficient, nested polynomial calculation */
yout = yout*voltin+tc_table.coef_v[pi][i];
}
return (yout);
}
/******************************************************************************
CONVERTS TC VOLTS TO TEMPERATURE
--------------------------------
Reference temperature sensored by IC LM335Z, which has output
characteristic: 10 mV/K. Scale has been stated 5/1023 = 4.9 mV/LSB,
so if we have vi (in integer), it must be multiplied by scale to convert
to voltage temperature, and divided it by resolution of sensor to get
real temperature. ref_scale = scale/LM335_VT = (4.9 mV/LSB)/(10 mV/K) =
0.49 K/LSB. Increasing vi in its LSB will increase temperature by 0.49 K.
When calibrate (T=25 C), LM335 generate 2.982 volts (273.2+25) according
to his current temperature. In Differential op-amp, this temperature-based
voltage used to compute temperature reference. We don't need to compute it
in MCU.
All of 'kerumitan' has been handled by op-amps.
*******************************************************************************/
void tc_converter(unsigned int *vi, /* measured TC volts */
double *temp) /* linearized temperature */
/* return: error code, 0 = no error */
{
int i;
double v;
for (i=ADC_1; i<=ADC_8; i++)
{
v = DIGIT_TO_MILLIVOLT(vi[i])/TC_GAIN_AMP*1000; /* unit in microvolts !*/
temp[i] = volt2temp_poly(&v);
}
}
double lin_t[N_ADC_CHANNELS]; /* linearized temperature */
void TC_Task(void)
{
unsigned int *mbx;
/* ADC resolution */
scale = (double)(VREF_PLUS-VREF_MIN)/(double)((1<<RESOLUTION)-1); /* mV/bit */
#ifdef _WSC_
FOREVER
{
mbx = _mcx_receive_w(CNV_SEMA);
tc_converter((mbx, (double *)lin_t);
_mcx_send_mbx_w(TC_MBX, lin_t, CNV_FINISH_SEMA);
_mcx_msg_done(mbx);
}
#endif
}
No comments:
Post a Comment