Searching \ for '[PIC] Need help with simple calibration constants' in subject line. ()
Make payments with PayPal - it's fast, free and secure! Help us get a faster server
FAQ page: www.piclist.com/techref/microchip/devices.htm?key=pic
Search entire site for: 'Need help with simple calibration constants'.

Exact match. Not showing close matches.
PICList Thread
'[PIC] Need help with simple calibration constants'
2010\01\07@150606 by Dwayne Reid

flavicon
face
Good day to all.

I'm working on a project and having a real brain-fart kind of a
day.  I'm hoping that someone here will kick me out of the rut I'm in
and point me in the right direction.

This project uses a simple zener diode for the power supply: 5.1V
plus or minus 5%.  I need to measure an input voltage with about 1% accuracy.

What I want to do is have the PIC measure an external, accurate
reference during test, then have it calculate a calibration constant
that is stored in eeprom.  That calibration constant will be used
either to adjust the reading from the a/d convertor or, more likely,
adjust the fixed thresholds that the a/d reading is used to compare
against.  This project is fairly simple in that I simply need to know
it the input is within a certain range (4 points).

The idea is that, although the initial accuracy of the zener diode is
lousy, the long term stability is pretty reasonable.  Certainly much
better than 1% over a period of several years on the zener diodes
that I've tested in years gone by.

The external reference I want to use will be either 2.500V or
4.096V.  Either is fine.

The reference will be connected to the board on its first or second
power-up cycle.  The board will, on each power-up cycle, check to see
if the calibration eeprom locations are blank.  If so, it then checks
to see if the applied reference is in the ballpark.  If not, the PIC
assumes that the reference isn't connected and the program
bails.  However, if the eeprom locations are blank and the reference
voltage is read as being approximately correct, the program will
calculate the calibration constant and store it in eeprom.

The way I'd normally do this is something like (Vref-Vmeasured)/Vref
which gives me a calibration constant that is either positive or
negative.  However, I'm thinking that there just has to be a better way.

I should mention at this point that I do NOT need to know what the
corrected a/d reading is.  What I need to do is compare the a/d
reading against 4 constants.  I mention this because what I'd like to
do is have the PIC adjust the value of those constants on each
power-up cycle and store the adjusted constants in RAM.  The a/d
comparisons are then done with those adjusted values rather than the
hard-coded values stored in ROM.  If the eeprom locations containing
the calibration constant are blank, the PIC will just load those RAM
values with the hard-coded values.

The reason for adjusting the constants rather than the individual a/d
readings is run-time speed.  Its faster to adjust and store the 4
constants one time on power-up than it is to have to adjust the a/d
value each time the a/d is read (every millisecond).  The main loop
then only has to compare the a/d reading against those adjusted
constants - nice and quick.

I'd like to use Nikolai Golovchenko's really cool constdivmul
routines for both ends of the calibration if possible.  And - that's
how I got into the rut I'm in.

I should be able to calculate the initial calibration constant: I
know what the reference voltage is and therefore what the a/d reading
SHOULD be.

Then, given that I have that calibration value and 4 fixed constants,
it should be easy to calculate 4 adjusted constants.

I'm spinning me wheels right now.  Anyone want to nudge me in the
right direction?

Many thanks!

dwayne

--
Dwayne Reid   <spam_OUTdwaynerTakeThisOuTspamplanet.eon.net>
Trinity Electronics Systems Ltd    Edmonton, AB, CANADA
(780) 489-3199 voice          (780) 487-6397 fax
http://www.trinity-electronics.com
Custom Electronics Design and Manufacturing

2010\01\07@162736 by Dave Tweed

face
flavicon
face
Dwayne Reid wrote:
> This project uses a simple zener diode for the power supply: 5.1V
> plus or minus 5%.  I need to measure an input voltage with about 1% accuracy.
>
> What I want to do is have the PIC measure an external, accurate
> reference during test, then have it calculate a calibration constant
> that is stored in eeprom.  That calibration constant will be used
> either to adjust the reading from the a/d convertor or, more likely,
> adjust the fixed thresholds that the a/d reading is used to compare
> against.  This project is fairly simple in that I simply need to know
> it the input is within a certain range (4 points).

[snip]

> I'm spinning me wheels right now.  Anyone want to nudge me in the
> right direction?

It sounds like if Vref is the nominal value of the external reference
(2.500V or 4.096V, represented in ADC units), then you should simply
calculate a scale factor for the actual reading you get from the ADC
(Vmeasured, also in ADC units) as SF = Vmeasured/Vref.

SF will be a number within a few percent of 1.000, based on the initial
accuracy of the zener diode. In other words, if the ADC is reading a bit
low, this number will be less than one, and if it's reading a bit high,
it will be greater than one. You can store this factor in EEPROM as a
unsigned fixed-point number that has one integer bit and the rest of the
value is fractional bits.

For example, let's assume you're using a 16-bit variable to hold this
SF value. if the SF is exactly 1.000, you would represent it as 0x8000.
If it's 1.100, it would be stored as 0x8CCC. If it's 0.950, it would be
stored as 0x7999, etc.

One way to accomplish this is to shift the Vmeasured value to the left
by 15 bits before doing an integer division (by Vref).

Then, each time you boot, you can take your four fixed constants and
multiply them by this SF to get the "calibrated" values you store in
RAM to compare with the raw ADC values.

If we assume that your constants are also 16-bit unsigned numbers, you
can do an unsigend integer multiplication, and then shift the result to
the right by 15 bits to account for the position of the "binary point"
in the SF value.

Does this help?

-- Dave Tweed

2010\01\07@173549 by Dwayne Reid

flavicon
face
You've pretty much nailed what I want to do.  But - I'm still stuck.

Lets assume that I'm using a 2.5V reference.  Assuming the supply
voltage is at exactly 5.00Vdc, the 10bit result would be 0x1FF or
0x200.  Now I need to turn that into my desired Scale Factor (good
term, by the way) of 0x800.

Plus - I'd like to use Nikolai's constmuldiv code generator if possible.

Like I said - this has been one of those brain-fart days.  This stuff
is normally pretty easy for me.

dwayne


At 02:27 PM 1/7/2010, Dave Tweed wrote:
{Quote hidden}

>

2010\01\07@180316 by Richard Prosser

picon face
Dwayne
When I get stuck like this I generally find it useful to set up a
spreadsheet (excel etc)  & try out the maths on that. It seems to
assist in clarifying things (for me anyway)..

Have you tried this approach?

Richard P

2010/1/8 Dwayne Reid <.....dwaynerKILLspamspam@spam@planet.eon.net>:
{Quote hidden}

>>

2010\01\07@183629 by Dave Tweed

face
flavicon
face
Dwayne Reid wrote:
> You've pretty much nailed what I want to do.  But - I'm still stuck.
>
> Lets assume that I'm using a 2.5V reference.  Assuming the supply
> voltage is at exactly 5.00Vdc, the 10bit result would be 0x1FF or
> 0x200.  Now I need to turn that into my desired Scale Factor (good
> term, by the way) of 0x800.

You need to express the nominal reference value in the same units as
the ADC is using -- in this case, it would be Vref = 0x200.

1. Generate a sequence of code that will divide by 0x200 (or multiply
  by 1/0x200).

2. Take your ADC reading -- let's say it's 0x1FF -- and shift it to the
  left by 15 bits to get 0xFF8000.

3. Run this number through the code generated in step one, which gives
  you 0x7FC0, your scale factor.

4. Now, express each of your constants as a 10-bit value in the same
  way we did with Vref. Suppose one of them is 2.000V, which would
  be 0x199.

5. Generate a sequence of code that will multiply by 0x199.

6. At boot time, run the scale factor 0x7FC0 (stored in the EEPROM)
  through the code generated in step 5, giving 0xCC19C0.

7. Shift this value to the right 15 times, giving the 10-bit value
  0x198, which is the "calibrated" value you store in RAM for that
  constant.

8. Repeats steps 4-7 for each of the remaining constants. You'll end
  up with four code sequences, and you run the scale factor value
  from the EEPROM through each of them.

> Plus - I'd like to use Nikolai's constmuldiv code generator if possible.

I assume you mean "constdivmul"; i.e.:

  http://www.piclist.com/codegen/constdivmul

In that case, you can combine the shift operations with the multiplications.
For step one, take Vref = 2.500, and convert it to a 10-bit ADC value:

   2.500V * 0x400 / 5.000V = 0x200

Generate code to multiply by 0x8000 (a 15-bit left shift) divided by 0x200:

  0x8000/0x200 = 64

This is the number you plug into the code generator. Specify a 10-bit input
size, and an allowed error of 0.1%. This becomes a fairly trivial example,
but the corresponding number for a 4.096V reference would be 39.0625.

For step 5, convert each of your constants to an ADC value, for example:

  2.000V * 0x400 / 5.000V = 0x199

Then, generate code to multiply by 0x199 divided by 0x8000 (a 15-bit right
shift):

 0x199/0x8000 = 0.0124817

For these, specify a 16-bit input size, but keep in mind that the results
will be 10-bit values. Again, specify the allowed error as 0.1%

-- Dave Tweed

2010\01\07@190711 by Dwayne Reid

flavicon
face
At 04:36 PM 1/7/2010, Dave Tweed wrote:

>You need to express the nominal reference value in the same units as
>the ADC is using -- in this case, it would be Vref = 0x200.

<snip>

Many thanks, Dave.

This is exactly what I needed.

dwayne

--
Dwayne Reid   <dwaynerspamKILLspamplanet.eon.net>
Trinity Electronics Systems Ltd    Edmonton, AB, CANADA
(780) 489-3199 voice          (780) 487-6397 fax
http://www.trinity-electronics.com
Custom Electronics Design and Manufacturing

2010\01\08@024640 by Terry Harris

picon face
On Thu, 07 Jan 2010 13:05:47 -0700, Dwayne Reid wrote:

>I'm spinning me wheels right now.  Anyone want to nudge me in the
>right direction?

Why do you need a calibration factor and calculations on reset?

Can't you afford 6 more bytes of EEPROM to store the 4 limit values instead
of storing a calibration factor and calculating limits?

Why not 'program' the limits by applying the actual limit voltages in some
defined sequence? That makes the limits programmable which might be a
benefit and includes 'calibration' without the need to make any
calculation.

2010\01\08@053551 by Alan B. Pearce

face picon face
>Then, each time you boot, you can take your four fixed
>constants and multiply them by this SF to get the
>"calibrated" values you store in RAM to compare with
>the raw ADC values.

Why do it each time it boots? Why not do it in the cycle he reads the
accurate reference, and then store the scaled values?

2010\01\08@114206 by Dwayne Reid

flavicon
face
At 12:43 AM 1/8/2010, Terry Harris wrote:
>On Thu, 07 Jan 2010 13:05:47 -0700, Dwayne Reid wrote:
>
> >I'm spinning me wheels right now.  Anyone want to nudge me in the
> >right direction?
>
>Why do you need a calibration factor and calculations on reset?
>
>Can't you afford 6 more bytes of EEPROM to store the 4 limit values instead
>of storing a calibration factor and calculating limits?
>
>Why not 'program' the limits by applying the actual limit voltages in some
>defined sequence? That makes the limits programmable which might be a
>benefit and includes 'calibration' without the need to make any
>calculation.

Thanks for asking.

The first version of this project used an accurate reference for the
PIC'a a/d convertor.  No calibration constants were needed - the PIC
simply compared the a/d readings against the hard-coded limits in the code.

This version is different.  The accurate reference is gone and what
replaces it is a zener diode with a spec of 5% initial
tolerance.  The board needs to determine whether an analog signal is
within certain limits with better than 1% accuracy.  Although the
zener diode has lousy initial accuracy, its long term stability is
excellent.  Thus - it makes a good reference for the a/d - it just
needs to be calibrated.

I don't want to have to calibrate each unit manually.  It sounds as
if that is what you are suggesting.  Instead, I supply a very
accurate voltage reference into an unused a/d input, have the PIC
read that very accurate voltage, then have the PIC calculate a
calibration value that scales the readings.  That calibration
constant gets stored into eeprom and is used during actual operation.

The very accurate reference is present only during the first or
second power-up cycles on the board - its part of the board's test jig.

The limits I'm testing for are part of the customer's spec and don't
change from unit to unit.  All I have to do is make sure that the
board can detect whether the input is within those limits or not.

The reason I want to have the PIC adjust the limit values rather than
the a/d readings is simply for run-time speed.  Because I don't care
what the actual a/d value is, I don't need to calibrate each
reading.  Instead, I simply adjust the limit values by applying the
calibration constant to them when the unit first boots, then do all
limit comparisons with the adjusted values stored in RAM.

In other words, its a lot easier for me to spend a few hundred cycles
adjusting the limit values one time only while the board is booting
than it is to spend a few hundred cycles applying the calibration
constant to each and every a/d reading.  I could probably afford the
time (at least, right now) but I don't know what else the customer is
going to throw at me.

This project has been kind of a moving target.  We completed the
first version of this card and delivered it several months ago.  The
customer was able to use that card to fine-tune their requirements
and delivered a revised spec completely different from the initial
spec.  The changes were so major that we actually redesigned the
board from the ground up.  I'm now working on the second iteration of
that new version.

Its worth it, though.  The customer is estimating an initial
production quantity of about 5000 units per year and their product
lifetimes are measured in decades.

Thanks again!

dwayne

--
Dwayne Reid   <.....dwaynerKILLspamspam.....planet.eon.net>
Trinity Electronics Systems Ltd    Edmonton, AB, CANADA
(780) 489-3199 voice          (780) 487-6397 fax
http://www.trinity-electronics.com
Custom Electronics Design and Manufacturing

2010\01\08@122125 by Terry Harris

picon face
On Fri, 08 Jan 2010 09:41:28 -0700, Dwayne Reid wrote:

>>Why not 'program' the limits by applying the actual limit voltages in some
>>defined sequence? That makes the limits programmable which might be a
>>benefit and includes 'calibration' without the need to make any
>>calculation.

>I don't want to have to calibrate each unit manually.  It sounds as
>if that is what you are suggesting.  Instead, I supply a very
>accurate voltage reference into an unused a/d input, have the PIC
>read that very accurate voltage, then have the PIC calculate a
>calibration value that scales the readings.  That calibration
>constant gets stored into eeprom and is used during actual operation.

No I was suggesting that instead of applying a very  accurate reference
voltage you supply a very accurate limit voltage (the voltage that the
thing will actually be trying to detect in operation). Reading that voltage
and storing the reading in EEPROM gives you a calibrated value with no
calculation at all.

Because you have 4 limit voltages your calibration/test rig would have to
cycle through 4 very accurate limit voltages and have some scheme so the
PIC knows which is which. Perhaps on a time basis if the PIC reset can be
synced with the test/calibration rig, or perhaps the PIC can figure out
which is which just from the magnitude.

It uses 6 more bytes of EEPROM and the limits are controlled by the
test/calibration rig not the PIC firmware which may or may not be an
advantage.

More... (looser matching)
- Last day of these posts
- In 2010 , 2011 only
- Today
- New search...