EEVblog Electronics Community Forum

Electronics => Beginners => Topic started by: Vindhyachal.takniki on August 19, 2017, 08:12:52 am

Title: Pt100 code using direct mathematical equation & Piecewise Linear Approximation
Post by: Vindhyachal.takniki on August 19, 2017, 08:12:52 am
1. I have made to code to convert RTD resistance into temperature. It is attached. It used direct mathematical method. made using Analog device AN709.

2. Code is also measuring time in which conversion is done. Surprisingly for negative temperature values, it takes around 280us max & for positive temperature it takes around 144us max. 
Code is run on arduino Uno.
I thought it would take much higher time as lots of floats are involved.

3. Just made some random resistance value at step of 0.29 to see how much range is covered.

4. Any sample code in c for Piecewise Linear Approximation method?
In AN709, link point takes to different page.
I wanted to make code on array based also, as it will much less memory & less time.


5. Also in function 
static uint8_t pt100_res_to_temp(float res , float *r_tempc)

at starting i had checked for res parameter is negative, if its negative passed by error, system dont make incorrect calculations.
Now I want to check if res passed is NaN or not.
This is done so that all the correct/incorrect values checked should be tested in this function & function always return correct error codes & values.
Is this step correct to check if number is NaN

if(res != res)
{
}

Or some compilers may optimize it away?
if its incorrect what step should I use?

Code: [Select]
typedef float  float32_t;
#define f32_t  float32_t

#define RTD_NOM  (100.0f)

#define RTD_A    ((f32_t)3.9083e-3)
#define RTD_B    ((f32_t)-5.775e-7)
#define RTD_C    ((f32_t)ā€“4.183eā€“12)  /* not used */

#define RTD_Z1   (-RTD_A)
#define RTD_Z2   ((RTD_A * RTD_A) - (4.0f * RTD_B))
#define RTD_Z3   ((4.0f * RTD_B) / RTD_NOM)
#define RTD_Z4   (2.0f * RTD_B)

#define RTD_C0   ((f32_t)-242.02)
#define RTD_C1   ((f32_t)+2.2228)
#define RTD_C2   ((f32_t)+2.5859e-3)
#define RTD_C3   ((f32_t)-4.8260e-6)
#define RTD_C4   ((f32_t)-2.8183e-8)
#define RTD_C5   ((f32_t)+1.5243e-10)




void setup()
{
    Serial.begin(250000);

}

void loop()
{
    uint8_t err;
    uint32_t old_time, new_time;
    float resistance = 0.0f , tempc;
    uint16_t cnt;
   
    for(cnt = 0U ; cnt < 1360U ; cnt++)
    {
        resistance = cnt * 0.29f;
        old_time = micros();
        err = pt100_res_to_temp(resistance , &tempc);
        new_time = micros();
   
        Serial.println();
        Serial.print("Sno: ");
        Serial.print(cnt);
        Serial.print(" ; ");
        Serial.print("Time(us): ");
        Serial.print(new_time - old_time);
        Serial.print(" ; ");
        Serial.print("Resistance: ");
        Serial.print(resistance , 8);
        Serial.print(" ; ");
        Serial.print("Temperature: ");
        Serial.print(tempc , 8);
        Serial.print(" ; ");   
        Serial.print("Error: ");
        Serial.print(err);
    }

    while(1);

}


static uint8_t pt100_res_to_temp(float res , float *r_tempc)
{
    uint8_t out_of_range = 0U;
     
    float32_t temp;
    float32_t res_square;
    float32_t res_cube;
    float32_t res_quad;
    float32_t res_pent;

    if(res < 0.0f)
    {
        out_of_range = 1U;     /* resistance out of bound on lower side, cant be negative */
        temp = -999.999f;           
    }
    else
    {     
        temp = RTD_Z2 + (RTD_Z3 * res);
        if(temp < 0.0f)
        {
            out_of_range = 2U;     /* resistance out of bound on higher side */
            temp = +999.999f;
        }
        else
        {
            temp = ( RTD_Z1 + sqrt(temp) ) / RTD_Z4;
   
            if(temp < 0.0f)    /* if negative temp */
            {
                res_square =  res * res;
                res_cube   =  res_square * res;
                res_quad   =  res_cube   * res;
                res_pent   =  res_quad   * res;
   
                temp = +(RTD_C0)
                       +(RTD_C1 * res)
                       +(RTD_C2 * res_square)
                       +(RTD_C3 * res_cube)
                       +(RTD_C4 * res_quad)
                       +(RTD_C5 * res_pent);
            }         
        }
    }

    *r_tempc = temp;

    return out_of_range;
}


Title: Re: Pt100 code using direct mathematical equation & Piecewise Linear Approximation
Post by: mikeselectricstuff on August 19, 2017, 10:05:28 am
For a known pt100 and temp range, the Pt100 curve is close enough to a straight line that a lookup table with a couple of degrees resolution with linear inerpolation will usually get you close enough, with no need for floating point. 
Title: Re: Pt100 code using direct mathematical equation & Piecewise Linear Approximation
Post by: alm on August 19, 2017, 01:17:00 pm
To figure out if a float is NaN, use isnan from math.h (https://www.arduino.cc/en/Reference/MathHeader).
Title: Re: Pt100 code using direct mathematical equation & Piecewise Linear Approximation
Post by: Kalvin on August 19, 2017, 01:36:31 pm
Using integers and lookup table with piece-wise linear interpolation normalized to 0.1 Celcius accuracy should require less computation effort and would probably consume less code space.
Title: Re: Pt100 code using direct mathematical equation & Piecewise Linear Approximation
Post by: mikeselectricstuff on August 19, 2017, 01:53:51 pm
Using integers and lookup table with piece-wise linear interpolation normalized to 0.1 Celcius accuracy should require less computation effort and would probably consume less code space.
Esepecially if you're not already using floating point for something else - it's very easy to do lookup+interpolate with fixed-point
Title: Re: Pt100 code using direct mathematical equation & Piecewise Linear Approximation
Post by: max_torque on August 20, 2017, 01:28:36 pm
If you're using an arduino, is that also digitising the RTD values?  With a 10 bit converter, having a float based mathematical conversion is rather pointless as your resolution will be set by the ADC resolution so you'll end up with a stepped output anyway?  (unless you post filter / average it digitally)