Major corrections and additions made 9/9/2014

See the new and improved 2015 version at http://www.green-trust.org/jmc

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

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 http://en.wikipedia.org/wiki/Voltage_divider 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 10k for R2 (experiment with <10k resistors till you get a likely pair). This calculates a R1 of 30K.

R1 = 30k Ohms

R2 = 10k Ohms

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

Vout = (10000 / (30000 + 10000)) * 20v

Vout = (10000 / 40000) * 20v

Vout = .25 * 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 = 30k Ohm and R2 = 10k 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 http://arduinotronics.blogspot.com/2012/04/voltage-monitor.html


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

<p>just curious.</p><p>you call R1 30k and R2 10k yet the schem shows 9k and 3k ?</p><p>There is quite a difference and I just wondered which one was correct before I attempt this one.</p><p>I would like to use this with a 7 seg display for my boat battery (12V) and have already made a sketch for it but before I hook it up I want to be sure I am not going to fry anything.</p><p>Also am going to use a 3.3v pro mini so thinking that I should swap out the 5v (Vout) for 3.3 ??</p>
with a 12v input, R1=30k and r2 = 10k or r1 = 9k and r2 = 3k both return 3v. It's the same thing. I prefer using higher values to reduce power consumption. for your app R1= 120k, and r2=25k will return 2.931v at 17v input. should be good. http://www.raltron.com/cust/tools/voltage_divider.asp
<p>using this code we can calculate ah accurately only if battery is completly drained before connecting it to arduino.. This code will not be able to find the pre stored ah in the battery... can any one tell how to find the ah of battery exactly..</p>
<p>This code measures the consumed ah, not the ah stored in a battery. The only way to tell the capacity left in the battery is as you mention, periodically drain it, then refill it. </p>
<p>Hi, when I copied your source code and tried to compile it, there is error:</p><p>&quot;diymeter:58: error: redefinition of 'int ratio'<br><br> int ratio = 0; // Calculated from Vin / Vout<br><br> ^<br><br>diymeter:36: error: 'int ratio' previously declared here<br><br> int ratio = Vin / Vout; // Calculated from Vin / Vout<br><br> ^<br><br>C:\Users\Arek\Desktop\diymeter\diymeter.ino: In function 'void loop()':<br><br>diymeter:103: error: 'avgBVal' was not declared in this scope<br><br> pinVoltage = avgBVal * .00488; // Calculate the voltage on the A/D pin<br><br> ^<br><br>exit status 1<br>redefinition of 'int ratio' &quot;</p><p>Why is it so?</p>
<p>I'm trying to understand before I go buy this for my wind turbine project. Also, is the Uno good for this project?</p><p>In the calculation of current, I am a little confused. I need to put this in my paper so I need to fully understand it. </p><p>Does the sensor rest at 100 sensor value at 0V=0A? And where does the 1A = 133mV come from? Is it from the datasheet?</p><p>Can you please see what I'm wrong in the below?</p><p>5000mv = 30000mA, ratio is 1:6</p><p>ACS715OutputVoltage = (SensorValue - 100)* 5000/1024</p><p>Current = ACS715Voltage * 6</p>
<p>dear all,</p><p>where the formula below come from?</p><p>// convert to milli amps<br> outputValue = (((long)sensorValue * 5000 / 1024) - 500 ) * 1000 / 133;<br> amps = (float) outputValue / 1000;</p><p>some one can explain to me about those formula and the meaning of value 5000, 500, 133 ???</p>
I finished my project.<br> <br> First, depends on model, the current sensor would have different current range. They used ACS715 in this instructable:<br> <br> From datasheet <strong>(remember different model has different value)</strong>, its input current is 0-30A, and it outputs&nbsp;133mV/A,<br> <br> with &quot;Zero Current Output Voltage = Vcc * 0.1,<br> Vcc is supply voltage = 5V<br> so the current sensor should output 500mV at 0A.<br> <br> You should already know (from voltmeter part) arduino only reads 0-5000mV, with 1024 steps. So:<br> ((long)sensorValue * 5000 / 1024) is the voltage the arduino reads.<br> <br> minus the zeroing 500mv<br> <br> divide 133mV, times 1A = the current the sensor reads.<br> <br> <br>
<p>dear all,</p><p>where the formula below come from?</p><p>// convert to milli amps<br> outputValue = (((long)sensorValue * 5000 / 1024) - 500 ) * 1000 / 133;<br> amps = (float) outputValue / 1000;</p><p>some one can explain to me about those formula and the meaning of value 5000, 500, 133 ???</p>
<p>dear all,</p><p>where the formula below come from?</p><p>// convert to milli amps<br> outputValue = (((long)sensorValue * 5000 / 1024) - 500 ) * 1000 / 133;<br> amps = (float) outputValue / 1000;</p><p>some one can explain to me about those formula and the meaning of value 5000, 500, 133 ???</p>
well - i've now managed to bodge together some logging code using the adafruit SD card shield <br> <br>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 <br> <br>confused
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 <br> <br>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 <br> <br>Also, the output of the ACS714 is 66mv/A rather than 133mV/A as mentioned here and within the supplied code <br> <br>hope this helps someone from having a confusing couple of hours as I have just experienced <br> <br>
This instructable is for the unidirectional acs715. I have not published a instructable for the acs714 as of yet.
<p>how about ACS712?</p><p>I missunderstand between readings of voltage divider and ACS712 sensor,</p><p>would you explain to me about ACS712 function on your project? (detail please)</p><p>thank you before,</p><p>best regards</p>
<p>the acs is a current sensor. the voltage divider is the voltage sensor.</p>
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
Floating inputs won't be zero unless connected to ground through a resistor.
<p>good , pls. how resistor i must use to input voltage max 50v ? </p>
http://www.raltron.com/cust/tools/voltage_divider.asp says that R1 = 252k and R2 = 28k would be good values.
<p>thanks :)</p>
I have a strange problem...i duplicated your protoboard circuit (ammeter and voltage divider), and it served to work as expected. I then thought it should be easy to add an lm7805 voltage regulator to power the arduino from the measured voltage, and connected 7805's Vin to the voltage divider's input voltage, 7805's GND and Vout to the 4pin header's GND and VCC. Powered up, everything looks great so far... then i reconnected a small load to the hall sensor, and the arduino blacked out. Remove the load, it comes on and works again. Why is this happening and how might i correct it?
<p>Isn't the lm7805 have a maximum of 18 Volts? Maybe you burnt the lm7805...</p>
What is the source of your measured voltage? Does it have enough current capability to run the arduino and it's load?
Where should i put the test probes?
for measuring current, typically in series with the negative cable. some industries like the boating industry prefer the positive lead.Does not really matter.
<p>Can i use this with my battery from a truck... ??? i thinking there would be a high current on the resistors................</p>
There's no high current going through any resistors. Yes, it will work with your truck battery.
<p>Thanks for sharing your code. I immediately build one for a battery test I am buzy with.</p>
<p>I'm curious about using the Pololu current sensors. If I understand, they carry the full current of whatever they're measuring. I have a couple of them but I've avoided using them because I don't understand the max current limits and it is going in my RV. In theory I should not ever see more than maybe 10-15 amps max but when I looked at those little circuit boards that seemed like a lot for such a wee little thing. Thanks.</p>
<p>Hi,</p><p>If I want to use this Amp Hour meter for high current (10-15 A) and 10V, what must I change?</p><p>Thanks for the answer!</p>
It will work fine as is. It's designed to read up to 20v and 20-30 amps.
<p>I am thinking of using <a href="http://www.ebay.com/itm/301238145798" rel="nofollow">these 10k potentiometers</a> instead of the thin film resistors as referenced in your blog post link. Does this seem correct? </p><p>I am using a <a href="http://www.ebay.com/itm/100W-Watts-Solar-Panel-Poly-12V-Volt-PV-Polycrystalline-Off-Grid-for-RV-Boat-/271222475269" rel="nofollow">100w solar panel</a> that has an open circuit voltage of 22.4V.</p>
Yes, you can use potentiometers, but you will have to measure their resistance and put that into the code. Don't ever adjust them once you have the finalized values. It's easier to use fixed value 1% resistors.
<p>20V to 5V using voltage dividers? OUCH.</p><p>You are going to have to deal with serious heat issues! And not to mention high watt resistors. Why not go for a 7805 voltage regulator?</p>
<p>How would a schematic look if I were to use the voltage regulator instead.</p>
It wouldn't work. You are trying to measure change. There's no change with a voltage regulator.
Very little heat, as there's not much current flow. Arduino inputs are high impedance. A voltage regulator would not allow a voltage change, so how would you know when the source changes?
<p>Hi i made a similar meter to monitor a battery but its not giving a liner output. The resisters on my devider are much larger then yours could that be the problem! </p>
<p>Hi sspence.</p><p>Great project and it helps me a lot. Thank you. I just wanna ask about LCD display. are u using LCD serial or Parallel.</p>
This one was parallel, I use I2C LCD's now to save pin counts.
<p>Thank you!</p>
<p>Do you think this may work accurately (+-1%) in the range of 0-20mA and from 1-35V? I want to count the total mA used in an electrolysis process.</p>
with a different sensor, and a smaller aref, sure.
<p>The whole thing is quite genius i must say , but in the calculation 0.75*20 =5 ?! , you arrived at that because its not &quot;Vout = (R1 / (R1 + R2)) * Vin &quot; that's completely wrong! Its quit the opposite. &quot;Vout = (R2 / (R1 + R2)) * Vin&quot;. so its 0.25*20=5. The links you provided are awesome ! Your blog is too good! Kudos !</p>
<p>Very nicely done tutorial! I'm happy I have found it.</p><p>I do have one question, though. You recommend not to use resistors with values over 10K in the voltage divider. What is the reason for this? Theoretically it would be good to use higher values for the resistors, so that the internal power consumption of the voltage divider is as low as possible. With photovoltaic panels it's a shame to waste even a milliwatt. Thank you!</p>
It has to do with the impedance of the ADC on the Arduino. The lower the resistor value, the more accurate the tracking. Have to find a happy medium.
<p>Thank you! Any idea what kind of accuracy loss we are talking about with 10K, what about with 100K? Thanks!</p>
<p>I don't know, I'm just going with atmel recommendations.</p>
<p>Allright, thank you again very much for the excelent tutotrial and for your quick answers!</p>
<p>Hi Spence</p><p>What use is the sample counter for (in the loop), and what happens after 9,10 hurs ? .. As the sample is only made as an Integer. Will it calculate negative ?</p>

About This Instructable




Bio: Professionally, I'm an IT Engineer (Executive Level) and Electronics Tech. I'm a Amateur Radio Operator (KK4HFJ). I lived off grid, with Solar (PV ... More »
More by sspence:DIY I2C LCD Display with InputsRaspberry Pi & the Neo 6M GPSEarthquake / Vibration Sensor
Add instructable to: