Continue to Site

# ADC Of Different Voltages

Status
Not open for further replies.

#### AtomSoft

##### Well-Known Member
Hello all. I have a simple question to which i think i know the answer.

I want to test 3 different voltages....

9v, 5v, 3.3v

I want to test whether the power is good meaning on spot. I want to use 1 micro to test the 3 and display on a LCD. The only thing i get confused on is what or how should i test them?

If i use the VREF = VSS then the test would be for 5v.

How would i test the 9v and 3.3v ?

Should i simple create a transistor circuit to switch the VREF pin to the different supplies?

I know i have to use a resistor scheme to check the 9v but for the 3.3v and 5v can i simply have the pic switch on a transistor for the 3.3v and when i want to check the 5v turn the 3.3v off and turn the 5v (transistor circuit) on?

Also how do i test the 9v supply?

One more thing....... is it possible to test how much current the supply is using with a pic? Since i know the limit for sink/source is 25mA typical.

Last edited:
What PIC are you using? Most (if not all) PIC's have multiple ADC inputs.

Assuming you have multiple inputs, use 5v for your analog reference.
For input one, just tie it straight to the 3.3v (maybe use a series resistor and a small cap to reduce noise)
For input two, use a voltage divider to make the 5v around 4v at the input to the PIC.
For input three, again, use a voltage divider to make the 9v around 4v at the input to the PIC.

When you read from the adc, you'll get a value from 0 to 1023. Voltage at the PIC's input is 5v * ADC value / 1023. Then, just do some simple math to get the actual voltage if this is either the 9v or the 5v input with the voltage divider.

As for the current your PIC is drawing, you can usually just estimate what it is. Digital inputs take virtually no current, and the outputs you should be able to calculate. Or you could just measure it directly.

One thing to think about:
What will be the source of VREF? If VREF is the same 5V supply that you want to test, then it should be obvious that it won't work because you'll always read 1023 for a 10bit result. ie: VREF would track the 5V supply, so you'd need a separate voltage reference IC.
For current sensing what you want to do is turn that current into a voltage with a shunt resistor. There are high side current sensor ICs made specifically for this. Basically, they are a differential amplifier with built in precision matched resistors. Low side monitoring is fairly easy with an OpAmp.

If you want to make a really nice job of this using a dedicated PIC, I would also use a dedicated 3.3v LDO regulator to run the PIC. Then power the regulator from both 5v and 9v supplies via diodes so it still will work perfectly even if any ONE of the three supplies fails completely.

The use voltage dividers for the 3 adc inputs to allow for +/- deviation and calibrate in software or even with 3 trimpots.

I also prefer the math 5v * (adc+1) / 1024 as this will round better (as both * and / result in rounding down issues) and only require binary division not a proper 16bit math division. If you use 500 * (adc+1) / 1024 you will get the voltage to 2 decimal places (ie 4.97v). In the case above you would use a different scaling factor than 500 to scale for your voltage dividers and still read in actial x.xx volts.

Grrr... I feel like I got one upped My wife was bugging me to come watch a movie. Here's what I use to take an ADC conversion and find the voltage at the input to the voltage divider.

Code:
Uint16 Calculate_Voltage( Uint32 value, Uint32 r_top, Uint32 r_bot )
{
Uint64 voltage;

voltage = value;
voltage *= (Uint64)VREF_X10;
voltage *= (Uint64)r_top + (Uint64)r_bot;
voltage /= (Uint64)r_bot;
voltage = (Uint64)(voltage) / (Uint64)(1<<ADC_BITS);

return (Uint16)voltage;
}

value was the ADC reading (0-1023)
VREF_X10 is 33 (in my system)
r_top and r_bot were the top and bottom resistors in the divider
and voltage is returned as v_x10 or whatever scaler you use on the vref

Ok, now I feel better

I had assumed from your original post that you were concerned about how much current your PIC was drawing. Is this the case? Or are you concerned about the total current draw of the entire system?

PS.. Before I get bashed for using 64 bit values, the voltage I was reading approached 600v and my resistors were in the mega-ohms range. I was getting overflows and casting everything to 64 bit was a better solution than dividing my resistor values by 100 or 1000 as then it wouldn't be quite as obvious to someone that had to maintain the code/schematic down the road. Besides, PIC32 is pretty quick and I wasn't hurting for time.

Ok too tired to fully understand the circuitry but the code i get

Ok maybe i should explain more lol

I want to create a master power supply which will have 9v, 5v, 3.3v

i just want to show on a LCD that the correct voltage is coming from each source. So my VREF would have to change am i correct? From the 9v source(dropped to 4v-5v) and my 5v VREF is ok, and my 3.3v VREF would be fine.

I am tired once again lol
. in fact ill make a quick schematic ok

Last edited:
Remember i still of course need to find values of R1 set and R2 set of resistors. I know there are online calculators for such things.

But would this be around how its done...?

#### Attachments

• circuit.png
11.9 KB · Views: 898
Last edited:
That would be fine. As long as the 3.3V for the PIC's Vdd (pin 20) comes from a separate regulator. I would also add a resistor in series with pin 2 (RA0/AN0) of the PIC in case something causes the 3.3V line to be pulled higher than 3.3V (A power supply fault or someone feeding 12V into the 3.3V output, etc.)
You could also run the PIC on 5V if you wanted to.

No, your VREF will not have to change, and if you have the pins, it will be easier and cheaper to use 3 separate ADC inputs to read the 3 voltages instead of using 3 transistors to switch between them.

However, as someone else pointed out, you cannot use the same 5v as your reference as you use as your 5v power source. The reason is because as the 5v power line droops, your 5v reference will droop, and the ADC will result in the same value.

I just formatted my computer so I can't draw a good schematic for you, but here's an example of my awesome MS Paint Skillz yo

**broken link removed**

Just use a voltage divider, read the ADC value, then pass it to the function and it'll tell you what the input voltage is. Generate the 3.3v reference from an LDO off of the 5v rail.

Edit: Beat me to it, but yeah, we're on pretty much the same page. And if you want to read 3.3v on the ADC, and you're using 3.3v as power/reference, then you should put a divider on the 3v line as well otherwise you won't see if its above 3.3v.

Last edited:
Seriously think about a variable voltage output too. The reason is to solve the very problem you are confronted with. Which is to scale a voltage divider to fit your needs.

O.K. plenty of good advice out there, here's another slightly different angle. Use a device that has a voltage reference module built in, that also contains a fixed voltage reference (FVR) register. The FVR is supposed to work with the a-d as an alternate to Vdd or Vref. It works internally and is independent of the supply voltage, (so says the data sheet), with 1.024V, 2.048V, 3.072V, or 4.096V settings. I know that a 18f14k50 has it, probably others too.

Using the 4.096V setting, and voltage dividers for the 9V, and 5V supplies, would be one way. Use even multiple to keep the math down if you like. So for the 9V supply, use 3 x 4.096, lets say 12.3V, for the scale (that gives a 12mv resolution per bit). Find a resistor divider combo that will give 4.1V out with a 12.3V in. Ditto 5V supply. There's the reason to have a variable supply.

Hello all. I have a simple question to which i think i know the answer.

I want to test 3 different voltages....

9v, 5v, 3.3v

I want to test whether the power is good meaning on spot. I want to use 1 micro to test the 3 and display on a LCD. The only thing i get confused on is what or how should i test them?

Check my analogue PIC tutorial, which does pretty well everything you want - I would suggest using the same scaling as the tutorial does (10.23V FSD) which will cover your range nicely, and give 10mV resolution.

To measure current, you need to monitor the voltage drop across a low value resistor with a differential input opamp, and generate a positive going voltage from it.

Awesome info thanks guys. I will try it when im fully awake NIGEL i will check out your tut AsAP as your info is usually very helpful

Nigel i might be using the 18LF2550 (since i have a bunch), but i plan to buy some 18LF1320.

So if i use 5v as the VREF then 5/1023 = 0.004887585... 4.88mV using the 10bit resolution correct?

If i use 3.3v then its 3.3/1023= 0.0032258064.... 3.22mV each right.

so i would multiply the .003225 * (ADRESH+ADRESL) to get the voltage right?

#### Attachments

• a.JPG
11.5 KB · Views: 569
Last edited:
No - that gives horrible results, try it on a calculator and see.

You want to attenuate the inputs (all three of them) so that 10.23V on each input gives 1023 as a result - that way you get exact matching, and no messy maths to spoil the display. It also gives 10mV resolution, and the least significant digit changes by one perfect digit at a time.

For your example it would read in turn from zero:

0.003225
0.006450
0.012900
0.025800

So the only sensible digit is still 10mV, just as with my simpler example (except your way doesn't change in a linear fashion) - you really don't want to display digits that jump up in more than ones, it looks horrible.

Im not sure what you mean by "10.23V on each input" ?

If i never reach 10.23v... Or do you want me to set it up in a way that i can test upto 10.23v on each input and all be the same. Would this give me ok results for the 3.3v?

If so a 3.3v would give me a value of 0.033 correct?

Using a 12v Supply and making a divider i can use ..

R1 = 1.2k
R2 = 7k

OutV = 12.244v is that close enough?

Last edited:
I think what he means is use a voltage divider so that if the input voltage were 10.23v, the voltage at the ADC pin would be the same as your Vref. I never considered doing that, and I like the fact that all you have to do is divide the ADC value by 100 to get the voltage, but I disagree with his reasoning behind it. The micro will hide the math from you, so unless you're pressed for cycles or flash space, I wouldn't worry about it. And you only have to show the digits that you want to show.

But I write 99% of my code in C, so it's quite easy for me to do that.

Last edited:
Calibrating the hardware is old school, and really nice for when you are using assembler and need absolute minimum code size etc.

But if you're using C I agree with Noggin (although I don't agree with his haircut )

I would choose voltage dividers that give the max resolution of the ADC, and calibrate in software. In C the math is easy, and you can average multiple samples and get even finer resolution than the native 10bit for the ADC.

Assuming you are using a text LCD you can add as many decimal places as you like. It will still only be as accurate as the calibration and ADC drift etc but the extra digits look very cool and will still show some PSU voltage conditions like sag and heat cycling etc.

If you average readings over a fixed period of one complete mains cycle the ADC will average all the ripple, giving you finer resolution because of the varying values and it will also give you a more accurate DC voltage reading (ie the average will also negate the ripple).

You're both missing the point, it's not about avoiding the math (which is trivial in assembler anyway), it's about avoiding the messy results it produces - as shown in the examples I gave.

Doing it the way I suggested gives a display that increments in a perfectly linear fashion, 0.01V, 0,02V, 0.03V etc.

Doing it by scaling with maths produces a horrible progression, unless you reduce the displayed resolution to LESS than my method. As his required voltages are all under 10.23V it's a perfect simple solution.

I fully understand your desire to use the full range of the ADC, but that's going to produce a poorer resolution than this simpler method - or a really amateur looking display.

Ok, I made a spreadsheet and I see where you're coming from.

With your method, by definition, a voltage input of 1.67v would give an ADC conversion of 167. The voltage calculated from that would then be 1.67v.

If I were to do it my way, I would scale the voltage divider so that at a 5v input to the voltage divider, I'd get a 3.0v input to the ADC (using a 3.3v reference). A 1.67v input to the divider would put 1.00v at the input to the PIC. With a reference of 3.3v, that would come out to a conversion of 310. After converting back to the original voltage, I would get 1.66v instead of 1.67v.

So, by decreasing the resolution you increase the accuracy. Somewhat counter-intuitive if you ask me. So do you have those magic resistor values handy for 3.3v, 5.0v, and any other voltage references?

Looks like 9.76k and 4.64k would make a good divider for a 3.3v reference and 10k and 9.76k would work with about 1.1% error for a 5v reference.

But what about when I'm measuring and input over 500v?

Ok, I made a spreadsheet and I see where you're coming from.

With your method, by definition, a voltage input of 1.67v would give an ADC conversion of 167. The voltage calculated from that would then be 1.67v.

If I were to do it my way, I would scale the voltage divider so that at a 5v input to the voltage divider, I'd get a 3.0v input to the ADC (using a 3.3v reference). A 1.67v input to the divider would put 1.00v at the input to the PIC. With a reference of 3.3v, that would come out to a conversion of 310. After converting back to the original voltage, I would get 1.66v instead of 1.67v.

Yes, but if you use the full value the numbers are excessively messy.

So, by decreasing the resolution you increase the accuracy. Somewhat counter-intuitive if you ask me. So do you have those magic resistor values handy for 3.3v, 5.0v, and any other voltage references?

I't called a preset

Looks like 9.76k and 4.64k would make a good divider for a 3.3v reference and 10k and 9.76k would work with about 1.1% error for a 5v reference.

But what about when I'm measuring and input over 500v?

Scale to 1023V, and read to the nearest volt.

Status
Not open for further replies.