Author Topic: Pt100 code using direct mathematical equation & Piecewise Linear Approximation  (Read 1735 times)

0 Members and 1 Guest are viewing this topic.

Offline Vindhyachal.taknikiTopic starter

  • Frequent Contributor
  • **
  • Posts: 487
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;
}


 

Offline mikeselectricstuff

  • Super Contributor
  • ***
  • Posts: 13693
  • Country: gb
    • Mike's Electric Stuff
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. 
Youtube channel:Taking wierd stuff apart. Very apart.
Mike's Electric Stuff: High voltage, vintage electronics etc.
Day Job: Mostly LEDs
 

Offline alm

  • Super Contributor
  • ***
  • Posts: 2840
  • Country: 00
To figure out if a float is NaN, use isnan from math.h.

Offline Kalvin

  • Super Contributor
  • ***
  • Posts: 2145
  • Country: fi
  • Embedded SW/HW.
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.
 

Offline mikeselectricstuff

  • Super Contributor
  • ***
  • Posts: 13693
  • Country: gb
    • Mike's Electric Stuff
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
Youtube channel:Taking wierd stuff apart. Very apart.
Mike's Electric Stuff: High voltage, vintage electronics etc.
Day Job: Mostly LEDs
 

Offline max_torque

  • Super Contributor
  • ***
  • Posts: 1272
  • Country: gb
    • bitdynamics
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)
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf