# Two point calibration; 8/16 bit MCU; complex operation

Discussion in 'Embedded Systems and Microcontrollers' started by aamirali, Sep 8, 2014.

1. ### aamirali Thread Starter Member

Feb 2, 2012
415
1
1. I have to measure voltage in 8/16 bit MCU & have to do its calibration also.
I have selected 2 point calibration as it corrects both gain & offset error.

2. Voltage to measure = 0-5V.
Let measured at two pint: Vm1 & Vm2
Let actual volatge at those point = Vo1 & Vo2

Gain error = (Vm2-Vm1)/ (Vo1-Vo2)
offset error = Vm1 - (gain_error * Vo1)

3. Problem is this involves complex math & generally goes to float. Now using float operation on 8/16 bit MCU is very intensive.

Queries:
1. Is there any better method for which I don't have to do such float calculation. If yes any example code?

2. If no to 1, can above method be made less operation intensive like by fixed point math. If yes any example code

2. ### NorthGuy Active Member

Jun 28, 2014
611
121
Is it self-calibrating, or you're doing the calibration once, do calculation outside MCU, and then program MCU to only do "reading = ..."?

3. ### MrChips Moderator

Oct 2, 2009
12,624
3,451
I never use floating-point for such simple calculations.

For example, I can convert from degrees C to F and F to C to two decimal places without having to resort to floating point.

4. ### aamirali Thread Starter Member

Feb 2, 2012
415
1
@NorthGuy : I have to do calibartion whenever user want t. So have to store values in MCU

@MrChips : Can you give one example

5. ### NorthGuy Active Member

Jun 28, 2014
611
121
For the calibration, you must do division, but even if done in MCU it is not done very often. "User" cannot want it at 10kHz, right? No need to optimize that part.

For your main fomula, you pre-calculate:

k = 65536/gain_error;

Then you do

(>>16 is the same as /65536 but is really fast)

Multiplication is way faster than division, so it'll be efficient.

Measure voltage in mV. Integers will give you enough resolution.

You will need to find a correct sze for your varibales so that it doesn't overflow.

6. ### MrChips Moderator

Oct 2, 2009
12,624
3,451
Give me your two calibration points and I will show you how to do it.

7. ### aamirali Thread Starter Member

Feb 2, 2012
415
1
@MrChips :

Done calibration at two pints 0.5V & 4.5V

Vm = 0.41V , 4.7V
Vo = .5V , 4.5V

So offset error = -0.12625
gain error = 1.0725

Edit: adc is 10 bit. Vref = 5V. Measurable range = 0-5V

Last edited: Sep 9, 2014
8. ### MrChips Moderator

Oct 2, 2009
12,624
3,451
What are you actually trying to do?
Is your software doing a floating point conversion and then displaying voltage as in a digital voltmeter?

9. ### aamirali Thread Starter Member

Feb 2, 2012
415
1
@MrChips :

1. actually I wanted to show how much voltage value I get when I apply 0.5v & 4.5V. It code i have only 10 bit adc data
2. Below are actual digital values which i get
3. V0 = 0.5V , digital data I get = 84
4. V0= 4.5V , digital data I get = 962

Now I have to apply offset error & gain error.

10. ### MrChips Moderator

Oct 2, 2009
12,624
3,451
I still do not understand what you are doing.
Forget about gain and offset error for now. I understand that and how to calculate the correct results.
What are you using to show the result?
What numbers do you want to display?

11. ### aamirali Thread Starter Member

Feb 2, 2012
415
1
1. I have measured the voltage 0-5V.
2. Since adc have offset & gain errors, I have to adjust them, before sending the final data over uart to PC.
I cannot put the error data to PC. Since user may connect the board I made to any PC. So have to calculate & store error correction values in MCU only.
3. As shown in previous post, calculating these errors, include float.

12. ### MrChips Moderator

Oct 2, 2009
12,624
3,451
There is no need to do floating point arithmetic or to transmit fractional decimals to a PC.
You can simplify the data transmission by sending data scaled to 0-500 or 0-1023.

I will assume that your calibration points are fixed at 0.5V and 4.5V.

Suppose the ADC recorded value at 0.5V input is x1.
Suppose the ADC recoded value at 4.5V input is x2.

We will scale the voltages by 100.

Then the slope m = (450 - 50)/(x2-x1) = 400/(x2 - x1)
Don't perform the calculation yet. Simply record the difference dx = x2 - x1
Hence the slope m = 400/dx

The intercept c = 50 - m*x1

Hence any ADC value x is corrected to value y given by

y = m*x + c

y = m*x + 50 - m*x1

y = m*(x - x1) + 50

y = (x-x1)*400/dx + 50

This reduces to one multiplication and one division using integer arithmetic.