Black Lives Matter - Action and Equality. ... Adafruit joins the Stop Hate for Profit campaign.

ATMEGA168 ADC and voltage/current readings
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

ATMEGA168 ADC and voltage/current readings

by niksun on Tue Feb 10, 2009 11:07 am

So I've prototyped a bench PSU (0-24V variable, 0-3A limiting). All works quite well. I'm now working on displaying the voltage across the load and the current being drawn by the load on an LCD. Here's an early version of the breadboarded prototype:


Here's the current latest schematic:


Since my output voltage is 24VDC at its highest, I've designed a resistor divider that ensures <=5VDC coming in to one ADC on the uC (R1=120 KOhm, R2=470 KOhm): ~4.88VDC for a 24VDC voltage setting. The current drawn is measured across a 0.47 Ohm, 10W resistor placed in series with the load. I just measure the voltage across this resistor and use Ohm's law to calculate the current through the resistor. Since the most current possibly drawn is 3A, then the largest voltage measured across this resistor is 3A * 0.47 Ohms = 1.41V. The ATMEGA168 has several 10-bit ADC. My voltage range is 0-5V, so the resolution is 5V/1024 = 4.88mV.

I am using the BoArduino to work on the LCD prototype. Here's some simple testing code for voltage the measurement:

Code: Select all | TOGGLE FULL SIZE
#include <avr/io.h>

void setup()

  // set ADC prescaler to 128
  ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);
  // set ADC reference voltage to AVCC
  ADMUX |= (1 << REFS0);
  // left-align ADC value
  ADMUX |= (1 << ADLAR);

void loop()
  // enable ADC and measure
  ADCSRA |= (1 << ADEN) | (1 << ADSC);
  // display raw ADC
  double i = ADCH;
  i *= 1024.0 / 5.0;
  i *= (590000.0 / 120000.0) / 10000.0;
  Serial.print(i); Serial.println("V");

I'm not sure if I've set the prescaler correctly. I notice a 16MHz resonator on the BoArduino, and I'm not sure if the AVR is using it as its clock. I'm also not sure if I'm using the correct ADC reference voltage (I want to use the AVR's internal voltage unless it will cause errors in the reading). I'm also left-aligning the ADC reading, but I may want to not do that to get a more precise reading.

So what am I asking? Well, what would be the best way to accomplish what I want? How would I read the voltage read from both ADCH and ADCL? Am I doing the loop correctly with respect to re-enabling the ADC and getting a reading?

I seem to have large fluctuations in my voltage reading. If I set it at 24V for e.g., I get readings from 22.5V or so to 25.5V or so. Ideas?


If you thought before that science was certain--well, that is just an error on your part. -- Richard Feynman
Posts: 202
Joined: Sun Jul 27, 2008 9:59 pm

Re: ATMEGA168 ADC and voltage/current readings

by franklin97355 on Wed Feb 11, 2009 3:15 pm

Posts: 21498
Joined: Mon Apr 21, 2008 2:33 pm
Location: Lacomb, OR.

Re: ATMEGA168 ADC and voltage/current readings

by DMerriman on Mon Feb 16, 2009 6:22 pm

From the values you've given for your voltage divider, I see that you're using either 5% or 10% resistors. You're going to see that kind of reading range unless you go with higher-tolerance resistors. Ditto on your current monitor (not to mention the power you're wasting as heat). I know that you didn't ask for a design review of your power supply, but until/unless you've got stable inputs to the Boarduino....

Check around to see if you can get 2% (or better) resistors for your voltage divider, and do a search on "current shunt" to see about getting something better for current monitoring. I'm including a tutorial on voltage dividers that includes the normal value "stepping" for 10/5/2/1 percent tolerance resistor ranges, if you're interested.

If you're getting values that are a reasonable approximation of what you expect, then the likelihood is that your code is working. If you're still working with the circuit as a breadboard, then I'd suspect that the fluctuations were due to the "temporary" nature of the wiring; you should see greatly improved stability and reliability in the "production" version.

Me, I'd go with a 6:1 voltage divider (get your 24V down to 4V), and amplify the (normally) 50mV output of a commercial current shunt to bring it up to 4V, too - then you can either use an external 4V analog reference, or get better accuracy from the internal 5V. But that's just me - I'm only an engineering tech, not a full-on Engineer :-)
PDF document and txt files.
(94.32 KiB) Downloaded 262 times
Posts: 7
Joined: Sun Feb 15, 2009 3:30 pm

Please be positive and constructive with your questions and comments.