Thursday, December 17, 2009

TCTASK.C

/*
���������������������������������������������������������������������������͸
�                                                                           �
�                          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