View previous topic :: View next topic |
Author |
Message |
Neutone
Joined: 08 Sep 2003 Posts: 839 Location: Houston
|
Calibrate and scale an analog input |
Posted: Wed Nov 29, 2006 1:05 pm |
|
|
This code takes advantage of a shift division to preform fast scaling of an input. Changing calibration may be done on the fly by simply coping the RAW value to the correct cal value and recomputing the m value.
In older analog systems the low and high value were referred to as Zero and Span. They were adjusted with potentiometers and they effected each other. That is not a problem for a digital calibration.
Code: |
//*** Global variables
INT32 AI1_m; // m = dY/dX = 4095/(AI1_High-AI1_Low)
// m is stored as an interger shifted 16 bits
INT16 AI1_Low; // The minimum value expected for AI1_RAW
// This should be sampled from AI1_RAW with the input set to it's minimum value
INT16 AI1_High; // The Maximum value expected for AI1_RAW
// This should be sampled from AI1_RAW with the input set to it's Maximum value
INT16 AI1_RAW; // This value reflects the current unscaled input filtered to
// add 2 bits of resolution through filtering.
INT16 AI1; // This is the value used in the rest of the program for the input.
//*** Solve for the value of m if booting or changing the value for the high or low limit
if((AI1_Low+100 >= AI1_High) // High cal value al least 100 greater than low cal value
|| (AI1_High >= 0x1000)) // High cal value not outside input range
{ AI1_High=4095; // Default high cal value to upper range limit
AI1_Low=0; // Default low cal value to lower range limit
}
AI1_m=AI1_High-AI1_Low;
AI1_m=0x10000000/AI1_m;
//*** Solve for AI1 in a loop the runs frequently
AI1_RAW-=(AI1_RAW>>2); // Decrement by 1/4
AI1_RAW+=read_adc(); // Add current value to filtered reading
if(AI1_Low>=AI1_RAW) // Is signal below low range value
{ AI1=0; // Limit reported value to range minimum
}
Else
{ if(AI1_High<=AI1_RAW) // Is signal above high range value
{ AI1=4095; // Limit reported value to range maximum
}
else
{ AI1=((int32)(AI1_RAW-AI1_Low) * AI1_m) >> 16;
}
}
|
This same method works well for scaling an analog output. |
|
|
hansolo
Joined: 06 Oct 2006 Posts: 20
|
|
Posted: Wed Nov 29, 2006 6:15 pm |
|
|
Can you explain a little bit more detail of what the software is trying to achieve and how to use it?
I am doing a project using temperature sensor and interested in codes for calibrating the sensor.
Please tell us more.
Thanks.
Hansolo |
|
|
Neutone
Joined: 08 Sep 2003 Posts: 839 Location: Houston
|
|
Posted: Wed Nov 29, 2006 10:26 pm |
|
|
I guess I could have been more clear.
This only works for a linear input.
The most basic math for a strait line is.
Y=mX+B
If m and B are constants it can also be written like this
Y=(X-B)m
Assume your analog reference is 5 volts.
Assume you have to read a 4-20 mA signal dropped across 208 ohms.
The minimum in range signal voltage would be .83 volts.
The maximum in range signal voltage would be 4.16 volts.
You could in fact read a 0-24mA signal without exceeding the range of the analog input.
The RAW 10 bit ADC will read between 170 and 852.
To make this reading more useful you may wish to scale the value to 0 - 4095. The code I posted will do that and do a small amount of filtering.
So you would get
AI1= 0 @ 4mA
AI1= 2047 @ 12mA
AI1= 4095 @ 20mA
Now assume a different sensors signal range is 3.8-19.5mA
You just capture new limits and your still scaling 0-4095.
You can write the rest of your code assuming the input signal is always from 0 - 4095. You can save high and low limit values when you capture them and load them during power up. |
|
|
tavioman
Joined: 22 Feb 2006 Posts: 65
|
|
Posted: Tue Dec 05, 2006 7:27 am |
|
|
Very interesting! |
|
|
nicola_v_bogdan
Joined: 19 Jul 2006 Posts: 4
|
An simple advice .. |
Posted: Fri Apr 20, 2007 7:20 am |
|
|
In the past I have made an digital weight scale. Durring the test I change the Pic whit an other 16f876 whit 18f450 and whit 16f876a. The AD converter don't work good whit the same software, so be aware...
It is a good to have an software calibration but also an hardware calibration . Use custom voltage ref of the AD , you can use some variable R to change the voltage and a stable power source , also you must take care at the noise (must use allot of ground because for example some pics gone crazy if you have an mobile phone near ....)
if someone is intrest to see code + electric schema let me know |
|
|
tavioman
Joined: 22 Feb 2006 Posts: 65
|
|
Posted: Sat Apr 21, 2007 2:24 am |
|
|
You're right.
I have experienced different behavior on ADC with different PIC parts. |
|
|
Steele404
Joined: 01 Sep 2007 Posts: 3
|
|
Posted: Sat Sep 01, 2007 11:33 pm |
|
|
Can you show an example of how to actually implement this?
I tried it but it was only to filter it, not scale it between 0-4095 like you said it would.
Also, does this work with a 10 bit analog resolution? |
|
|
younus
Joined: 07 Feb 2010 Posts: 1 Location: Pakistan
|
|
Posted: Sun Feb 07, 2010 3:02 pm |
|
|
I want this code to be used with PIC16F877A to calibrate a weighing scale. I have completed the hardware and getting 0 to 1023 for zero to full scale using analog preset VRs. Can I use this code to 'tare', 'zero' and scale factor' settings ?
I must admit that I am not so good at Microcontrollers, but have implemented a few industrial projects using PIC16F877 and CCS. |
|
|
|