Picture of DIY Amp / Watt Hour Volt Meter - Arduino
acs715 output.PNG

Major corrections and additions made 9/9/2014

For my off-grid Ham Radio and Solar projects, I needed a way to measure volts, amps, watts, amp hours and watt hours. There's a couple of commercial products that can do this, but not with the flexibility I wanted. I designed a Arduino micro-controller based solution that is very extensible. Right now it monitors the above values of attached gear, and I'm thinking about adding web monitoring and a sd card for data collection. Well, let's get started.

Step 1: Voltage Divider

Picture of Voltage Divider

UPDATE 9/9/2014 !

The Arduino can accept up to 5v on a analog input. Our voltage can range as high as 20vdc in certain situations (open circuit pv voltage), so we designed a voltage divider that would provide 5v at 20v battery voltage, and less at various lower voltages. See for more information on Voltage Dividers.

First we visit our friendly Voltage Divider Calculator. I input 20v as the input, 5v as the output, and 3k for R2 (experiment with <10k resistors till you get a likely pair). This calculates a R1 of 9K. Try to keep the values as close to, but under 10k Ohms as possible.

R1 = 9k Ohms

R2 = 3k Ohms

Vout = (R1 / (R1 + R2)) * Vin

Vout = (9000 / (9000 + 3000)) * 20v

Vout = (9000 / 12000) * 20v

Vout = .75 * 20v

Vout = 5v

Ratio = Vin / Vout

Ratio = 4

Because the Arduino has a 10-bit ADC, it outputs 0-1023 (1024 steps) for a 0-5v input. That's 0.00488v / step.

With a Voltage Divider with R1 = 9k Ohm and R2 = 3k Ohm, A 12v battery would calculate as follows:

12v / Ratio = 3v on the A4 pin.

3v / .00488 = 615 (ADC Reading - round up)

so A4 pin Voltage = .00488 * ADC reading (615 in this case), or 3.00 volts.

Then battery voltage = A4 pin voltage * Ratio (3 * 4 = 12)

The code to read that value is as follows:

ADCVal = analogRead(batMonPin); // read the voltage on the divider on pin A4
pinVoltage = ADCVal * 0.00488; // Calculate the voltage on the A/D pin
// A reading of 1 for the A/D = 0.00488mV
// if we multiply the A/D reading by 0.00488 then
// we get the voltage on the pin.

batteryVoltage = pinVoltage * Ratio; // Use the Ratio calculated for the voltage divider
// to calculate the battery voltage, Ratio = Vin / Vout

More details at


Improved voltage reading circuit and sketch at AC Volt Meter (works with DC as well). Rock solid voltage measurement, and very accurate.

Remove these adsRemove these ads by Signing Up
1-40 of 45Next »

I really find it hard to find the components used. like the arduino.
can i use gizduino mini atmega 168 for this set up? we dont really have
acs715 in our country right now. can i get somehow the coding if i use
IC LMP8480? very much appreciated it! thankksss

anushk32012 days ago

Thanks for sharing! Hi. can i get the list of all equipment you used for this project? and If i use IC LMP8480 what will i change in the coding for it to work? thanks I appreciated your help!

sspence (author)  vipzsflinchsz13 days ago
I listed the components. An ACS715 (current sensor) and two resistors (voltage sensor). The 8480 outputs a voltage when it senses current, so it should not be too hard to use, see the info at

ayasbek1 year ago
Thanks for sharing!

I have an idea about why you have that 0.00610 multiplier instead of the ideal 0.0048... your code is only taking the simple ratio of the resistors - it should maybe be
ratio = (float(R1) +float(R2))/ float(R2)? Please let me know if this correct?

I love the instructable. I am using it to create an amp-hour battery gauge for my new-to-me electric car. The car already has a shunt (400A - 50 mV) so I will be using that. I may use an op-amp to boost the mV signal. Then again the 4.8 mV resolution on the arduino might be fine.
sspence (author)  ayasbek1 month ago

I've corrected and simplified the readings. for a voltage input that will never exceed 20vdc, make R1 15k ohm, R2 5kohm. For a 12v system, 0-20v input will output 0-5v to the adc. 5v / 1024 = .00488 / step. so adc reading * .00488 = voltage on A0. Voltage on A0 * 4 = voltage input, becasue 20v / 5v = 4.

myfaithnka3 months ago

sorry for my ignorance, Can i use this IC instead of Hall effect sensors ? LMP8480
thank you,


sspence (author)  myfaithnka3 months ago

Yes you can. Code will look a bit different, but not drastically.

:) Thank you sir,This saves my day.
kobniala5 months ago

hello everyone!..

someone here tried to add up the wattage...

for example, if given 24 hours how much wattage did the system consumed.

it will be a great help from us if anybody can teach us how..thnx

sspence (author)  kobniala5 months ago
100w * 24h = 2400 watt hours (2.4 kWh)
musu5 months ago

I`m using this project for my off grid setup, battery 90ah, solar pannel 50W.. the problem is when connecting the current sensor with the system, no values are given on the LCD screen ( indication of incoming power) i would like some help what can be done thanks.

sspence (author)  musu5 months ago
did you put the current sensor in series with the positive lead of the solar panel?
musu sspence5 months ago

yes, i did as shown in the diagram given :

mainly the LCD screen is giving just 0.53v and the other vaules are 0w and 0A

Johnnysenex10 months ago
Hi, I would like to get some help.
I have a 5kw inverter (24v) on 720 ah of batteries, with 1000 w solar panels.
I want to measure the what hours in, and the watt hours out, to be able to make sure I don't drain my batteries.
Therefor, I would like to build two watt hour meters to do so.
Obviously, the design must be such that it does not hamper my amps when I'm pulling a big load. ( my fuse is a 400amp fuse' and my cables are 70mm^2)
Thanks, and looking forward to your answer!
sspence (author)  Johnnysenex10 months ago
You would only have to have one unit between the battery and the rest of the system. Will need to customize the code to read amps in (+) and amps out (-) to get a amp hours left in the battery. These units are non obtrusive (hall affect), unlike a shunt. The sensor I used is not rated for 200 amps, so a different sensor will need to be used. I'll have to do more research for you.
svendickman11 months ago
Thanks for the reply.
I understand that the grounds must be common, but isnt there a risk for different circuits to share a DC ground?

I read the part about the ADC optimization and did not really understand as I do not see any S/H capacitors anywhere. As my load will be a DC-DC converter it wil have a high impedence and thus the lower impedence of the voltage divider will trickle discharge the battery.
sspence (author)  svendickman11 months ago
the capacitors are inside the atmel 328p. No, there is no risk with shared ground.
svendickman11 months ago
Thanks for the article.
I'm setting up a similar project and I have two little questions.
Is there any risk with sharing ground between the battery and the arduino and possibiliy the ground of a DC-5VDC converter?
Also, wouldnt using higher value resistors lower the battery drain of the volt meter?
sspence (author)  svendickman11 months ago
The grounds must be common.

ATMEL says:
" The ADC is optimized for analog signals with an output impedance of approximately 10 kΩ or less. If such a source is used, the sampling time will be negligible. If a source with higher impedance is used, the sampling time will depend on how long time the source needs to charge the S/H capacitor, with can vary widely. The user is recommended to only use low impedance sources with slowly varying signals, since this minimizes the required charge transfer to the S/H capacitor."
Thanks a lot for that great idea. Does anyone already tried to write a small visual basic program that shows the results a little clearer.
sspence (author)  Schneiderlein1 year ago
Visual basic does not run on a arduino, What is not clear?
It should be possible to read the things sent by arduino to the serial port. I already made st like a serial monitor in vb but I want vb to write the results in different labels. One for current, one for voltage and so on. Any idea?
sspence (author)  Schneiderlein1 year ago
oh, you are connecting a computer to the arduino and displaying serial output on the pc. yes, you can do this in VB, Processing, php, any language that can read the serial port. I am not interested in having a computer hooked up, although putting a ethernet shield on here and hosting the data on the arduino web server gives you great html creative control for any web browser to read.
For everybody who wants to visualize the results on an pc. Logview is a easy to use and cheap posibility. Just use this code instead of the normal serial.print. (This is logview's openformat.)

(removed by author or community request)
sspence (author)  DELETED_Moonlight271 year ago
By using the ACS714 bidirectional current sensor, and a 220vac to 12vdc non regulated power pack for voltage monitoring.
(removed by author or community request)
sspence (author)  DELETED_Moonlight271 year ago
You "isolate" the mains with a transformer.
sspence (author)  DELETED_Moonlight271 year ago
Stay tuned, I'll be putting up a ac version of this project in the near future. Current sensors are by definition isolated.
Flooter1 year ago
Nicely done!
But just want to add on top of what author said: I use ACS712 current sensor (5A Max) and it gave me a lot of headache.
First of all, you need to calibrate it inside your program. I do that by doing first 10 or 20 readings, taking the average and using it as "zero" point (of course it is done when no current is flowing through the sensor).
It is necessary because hall-sensor is very very sensitive and could even react to earth magnetic field, so watch out.
Use as good multimeter as you can find to verify current.
After that my average dispersion is about +/- 20 mA (which is 0.02A), at least I hope it is :)

However I don't know why honestly. Here is my code:

float readCurrent() {

  int raw1,raw2,raw3;
  unsigned long refV1,refV2,refV3;
  float raw0,refV0, current;
  float x,xx;
  int i;

  raw0 = 0;
  for (i=1;i<=samplesToTake;i++) {
    raw0 = raw0+analogRead (currentSensor);
  raw0 = (float)raw0/samplesToTake;
  x = raw0;
  if (setupCurrentYES == 0 ) {
    initialCurrentX = x;
    setupCurrentYES = 1;

  xx = abs(x-initialCurrentX );
  current = xx*multiplier;
  return current;

"multiplier" has been defined in other part but I did that manually, based on numbers that sensor gave me and comparing them to my multimeter value.
So now it equal to 0.0266 but I don't know why because if the sensor gives you 512-1024 readings for the current from 0-5A it does not have much sense.

Anyone may have a clue?

Secondly, when you measure Voltage - 5V is a "theoretical" value.
It is how Arduino built - it uses "reference" value that is supposed to be +5 but it is not always true. It is better to measure real reference voltage (plz google how to do that) and then use this number instead of just 5.
Alternatively you may supply power to your arduino board from other than your PC-USB port source. Some external PSU with 7-12V would be good - doing that you'll get more stable reference voltage.
I have a small solar array, I am looking at this instructable to build a monitor for it. I'd like to monitor voltage of battery & Amps of incoming juice. Will this get me in that direction?
I am no electrical engineer, and this is definitely in a language I feel like I'd have to learn to do this! Would love it you could "write it in english" ;) Obviously, there are many here who love the language of such an 'able, but for us eager DIY'rs who've not tackled the likes... just sayin' ;)
sspence (author)  rrepass jr.1 year ago
It will do what you are looking to do, and it is in as p[lain English as possible. You need to learn the "language" in order to understand what you are doing. Otherwise, just buy one.
Sean_ork2 years ago
well - i've now managed to bodge together some logging code using the adafruit SD card shield

but - i'm troubled by non zero outputs when there's no voltage or current on the inputs - display is showing approx 15 volts and just under 15 amps when they should both be zero

I'm now unsure if i am seeing the fully updated code here as it as shown here will give inaccurate results if used with the ACS714

The bi-directional ACS714 output is centered on 2.5v - so zero current flow gives 2.5v - and not the 500mv as mentioned here and within the supplied code

Also, the output of the ACS714 is 66mv/A rather than 133mV/A as mentioned here and within the supplied code

hope this helps someone from having a confusing couple of hours as I have just experienced

sspence (author)  Sean_ork2 years ago
This instructable is for the unidirectional acs715. I have not published a instructable for the acs714 as of yet.
unplugging the SD card resolves the non zero volts - but i'm seeing 2.5v from the current sensor (to gnd) even when it's output pin isnt connected
sspence (author)  Sean_ork2 years ago
Floating inputs won't be zero unless connected to ground through a resistor.
Sean_ork2 years ago
cool project - did you ever get any data logging code running with this ?
sspence (author)  Sean_ork2 years ago
Not yet. Need to get a sdcard attachment.
1-40 of 45Next »