# Scaling Numbers or how avoid floating point.

Part I: The voltage divider.

Because eight bit mircocontrollers lack floating point instructions using floating point can consume a lot of processor cycles.

In this article I will illustrate how to measure up to 100VDC with an analog to digital converter, ADC, with a positive voltage reference of 5V, +Vref, and a negative voltage reference at gnd -Vref.

The input to the the ADC must never exceed the 5V value of +Vref. We can use a simple voltage divider to accomplish this. To specify the resistors in out divider need to find the divider ratio.

dividerRatio = VmaxInput/VmaxOutput

100V/5V = 20

Note that our result 20 is a pure number and this is how we use it.

Resistor must be R1=19xR2.

Scaled Voltage = Original Voltage (R2/(R1+R2)

If we pick R2 to be 1 we need an R2 of 19 to get a ratio of 20.

sv = ov (1R/(1R+19R)
sv = ov (1/20)

Which is exactly what we want but for the fact that this bit of circuit will waste more current then we would like.

I = V/R = 100V/20R = 5A

and

P = I**2(R) = 5*5*20 = 500 watts !

Looks like we need to reduce that current with more resistance. We can multiply R1 and R2 by any number as long as we do it to both. The 20:1 ratio will remain the same. Lets multiply both resistors by 1000 for a R1 of 1K and R2 of 19K. You may have to use 2 resistors in series to get 19K. Lets calculate the current for our new circuit.

I = V/R = 100V/20000R = .005A or 5mA

and

P = I**2(R) = .005*.005*2000 = .05 watts

At this point we have a circuit that will scale 100V to 5V.

Part II: The micro controller code.

Lets start by assuming our micro controller has a 10 bit ADC , Analog to Digital Converter. Each conversion will result in a number between 0 and 1023. 0 volts maps to 0 and 5V to 1023.

Recall that we are not interested in the voltage at the ADC but rather then the input to the voltage divide. For that voltage 0V still maps to 0 but 100V maps to 1023. Knowing this we can calculate the value in volts of each count. Lets call it vpc. A calculator gives the following result.

vpc = 100V/1024 = 0.0977

Actually the calculator result was 0.09765625 but that is way more precision the we have with 1% resistors.

At this point we could just multiply the ADC result by .0977 using floating point math. But the floating point library routines take a lot of memory and are slow.

This is where scaling comes in. I like scaling by 1000 because it allows us to intrepert the readings directly as mV rather then V. So lets scale the input voltage by 1000 and and round to the nearest integer.

vpc = (1000*100V)/1024 = 97.6 = 98

We have some error in this method. At full scale the error is.

error = (1024*98)-100000 = 352

Recall that we scaled the original value by 1000. To get the true error we need to divide the 254 by 1000 which means our actual error is 0.25V for a full scale reading.

We need to be careful to use a data type that will accept the largest possible number resulting from the adc reading times the vpc.

In our example that is 1024*98 or 100352, in hex this is 0x18800, a 17 bit number. Had we chosen a 16 bit unsigned int we would have been in trouble. We need to use a 24 bit data type (unsigned short long) or a 32 bit data type (unsigned long).
Excellent article. This is especially useful to ASM programmers, as it's the only real way to do things.
1. DerStrom8 -
Thanks for the link 3v0. That'll help a lot!
1. zinda -
great work 3v0
useful thing
1. RichTheDude -
Nice article 3V0 , only thing I would like to comment on is the possible inclusion of two diodes to clamp the voltage as seen at the ADC pin.

@Sceadwian: It sure is, if portability and your time are not of concern. Plus for hobbyists who cares what language is used if the job gets done?
1. ericgibbs -
Originally Posted by RichTheDude
Nice article 3V0 , only thing I would like to comment on is the possible inclusion of two diodes to clamp the voltage as seen at the ADC pin.

@Sceadwian: It sure is, if portability and your time are not of concern. Plus for hobbyists who cares what language is used if the job gets done?
PIC's already have internal clamping diodes to 0V and Vsup.
1. christianarmand -
Well done !
1. Mike odom -
wouldn't the vpc = 100v/1023, since the max count is 1023 at 100v? Which would be .0975 vs .0976, not a big deal at this range, but might be if you were scaling a 12v input and needed more precesion. I just did a voltmeter project where my reference was 1.024V and I needed to read precesion millivolt readings. the max input of which was 1.010V, and the extra count would have made a big difference.
1. Mike odom -
Originally Posted by christianarmand
PIC's already have internal clamping diodes to 0V and Vsup. .
but why risk blowing up your PIC chip on a voltage surge. External clamping really is needed here, especially if you are interfacing your controller pin to the outside world. The internal clamps are puny and if the energy of the surge is too great, you also risk blowing up anything else connected to the 5V pic supply.

Also, your 1k/19k divider is pretty much the max impedance your ADC wants to see on the input. Most ADCs call for an impedance of 1K or less. Your divider yields an impedance of 952Ω.
1. 3v0 -
Please note Mark Odom's comment on the max impedance.

The picture of the voltage divider was lost in the disk crash. I have it in my computer but can not find a way to add it here.
Electronic Circuits  |  Learning Electronics

Join our community with over 100,000 Members! It's free, easy and when you're logged in you have many more features! Click to register.
Page Time: 0.10360 seconds      Memory: 9,821 KB      Queries: 58      Templates: 0