CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug Reports on this forum. Send them to support@ccsinfo.com

Calibrate and scale an analog input

 
Post new topic   Reply to topic    CCS Forum Index -> Code Library
View previous topic :: View next topic  
Author Message
Neutone



Joined: 08 Sep 2003
Posts: 839
Location: Houston

View user's profile Send private message

Calibrate and scale an analog input
PostPosted: Wed Nov 29, 2006 1:05 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Nov 29, 2006 6:15 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Nov 29, 2006 10:26 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Dec 05, 2006 7:27 am     Reply with quote

Very interesting!
nicola_v_bogdan



Joined: 19 Jul 2006
Posts: 4

View user's profile Send private message

An simple advice ..
PostPosted: Fri Apr 20, 2007 7:20 am     Reply with quote

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

View user's profile Send private message

PostPosted: Sat Apr 21, 2007 2:24 am     Reply with quote

You're right.
I have experienced different behavior on ADC with different PIC parts.
Steele404



Joined: 01 Sep 2007
Posts: 3

View user's profile Send private message

PostPosted: Sat Sep 01, 2007 11:33 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Sun Feb 07, 2010 3:02 pm     Reply with quote

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.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> Code Library All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group