Amp-hour meter question

Hello all,

In my next project, I want to create an energy meter that will show current and count amp hours for one of my home built electric vehicles. I am planning on using a 75mv 500 amp shunt or the like. My question isn't really about how to amplify that 75mv into the arduino while keeping that high voltage isolated from my 12V system.

My question is, given that the arduino is reading the current in amps already, how do I count amp hours in my Arduino (probably oging to use an uno or nano)? I understand how counting amp hours works, but I am just not sure how to do it in the arduino IDE! I guess I don't understand how it would work needing a timer and such to physically count the amp hours in the program. I more or less just need help with the theory and how this works and how to go about it. Since it is in my electric car, current draw is constantly going up and down and changing by the second, so I would need to be reading many times per second and also measure as accurate as possible.

Any help would be greatly appreciated! Thanks!

What kind of power control driver does Your car use? My guess is that it swiches, or PWMs the motor. That will give You a very nasty, very difficult current to read. Sophisticated filtering would be needed.

Assuming you can read amps correctly (see above), adding up amp hours should be relatively simple.

Assuming that you read the amps at 12:00:00 and it was 50 and you read it again at 12:00:01 and it is 60: You can assume that the 50 was used for 1 second so accumulate 50 amps * 1 second time difference / 3600 seconds in an hour and you have amp hours. If you read again at 12:00:02 and it's 70, you accumulate 60 * 1 * 3600. And so on. Of course, you could also average the old reading and the new reading (50 + 60) / 2 * 1 / 3600...

That should be easy enough. However... when do you reset it? Do you want to accumulate amp hours from the beginning until end of time, or only for the last x readings/seconds/days? That would be a bit more complicated because you have to know which readings to ignore/remove.

Of course, as you said, you would call the Routine multiple times per second so my 3600 may have to be a different constant (3600 * 1000 milliseconds?).

You mean a resistor and capacitor between the shunt and analog input?

It does highlight some of the problems with digital signal processing. To get the "right" answer from the digital reading, you need analog filtering.

I would use an analog filter with a very long time constant. Like 1 second. Then you just take one reading per second. Add them all up and you have amp-seconds. (It will be a very large number. Make sure you use an appropriate type of variable.) Then divide by 3600 for display.

Also record volts at each second, multiply up to watts and then you can do watt-hours too.

Thank you all so much for your replies!

Railroader,

Yes, the motor controller switches using PWM..I guess this is going to get a lot more difficult :frowning:

JaBa,

Thanks for this explanation, this was exactly what I needed to help me understand this more! I think what I would do is constantly record amp hours and then simply use some kind of external button to reset the variable of amp hours.

MorganS,

Can you explain this a little further? And analog filtering? Also, how could I measure voltage while also keeping the high voltage pack isolated from my arduino and low voltage systems? Don't want that high voltage tied to the chassis of the car somehow...haha


I know some kind of filtering is going to have to be done as you guys have said, but I am definitely a newbie when it comes to trying to "filter". :confused: Check out the image I have attached, it is the previous amp hour meter I once used. Anyone know what kind of filtering that used? But then again, it was fairly accurate I guess, but it just didn't seem to update current fast enough. Plus, with the current, and amp hours in arduino, there are so many other things I can do with it!

A simple [u]Low pass RC filter[/u] will convert the PWM to a (moving) average DC voltage (proportional to the PWM/pulsing current through your shunt).

s a starting-point you can calculate the [u]RC time constant[/u] (RxC). For example 1uF and 1M gives you a 1 second time constant. (1 Meghom is a little high, so that's just an example.)

DVDdoug:
A simple [u]Low pass RC filter[/u] will convert the PWM to a (moving) average DC voltage (proportional to the PWM/pulsing current through your shunt).

s a starting-point you can calculate the [u]RC time constant[/u] (RxC). For example 1uF and 1M gives you a 1 second time constant. (1 Meghom is a little high, so that's just an example.)

So I didn’t know what any of that meant so I just spent an hour on YouTube learning:) thanks for the reply! So I understand the time constant and how to calculate that and such. Now how is that relevant when filtering? Does the voltage of the capacitor or type of capacitor I use matter? Does the time constant affect how often I can measure with Arduino?

The voltage of the capacitor must be higher than any voltage it receives in service. Otherwise it can be damaged or even explode with severe over-voltage.

Electrolytic capacitors usually have very large values available cheaply. But they are polarized. You must connect plus to plus, minus to minus. Ceramic capacitors are cheap for smaller values and aren't polarized. Tantalum caps are smaller than electrolytic for the same value+voltage so that is what is inside your phone. There are a few other chemicals used sometimes.

The time constant tells you how slowly the signal changes. To take a specific example, I had a project controlling a motor with a chip that has a current feedback pin. I could measure the current going into the motor to determine if it was being over-driven. The control was coming from an Arduino PWM pin at 480Hz. Using analogRead() on the feedback just randomly saw too-much current or none-at-all depending on the exact timing with the 480Hz input.

So I added a resistor and capacitor with a time constant of 0.01 seconds and fixed the analogRead() to a period of 0.005 seconds.

I'd recommend to use a specialized power meter like PZEM-004 and just interface it with your arduino.

Looks like a useful device but for mains AC only.

For an electric bike, it may not be appropriate. There are lots of chips suitable for bike type DC. Something like the Sparkfun ACS723. They used to stock AttoPilot products. I have one of those which measures both current and voltage.

MorganS:
The voltage of the capacitor must be higher than any voltage it receives in service. Otherwise it can be damaged or even explode with severe over-voltage.

Electrolytic capacitors usually have very large values available cheaply. But they are polarized. You must connect plus to plus, minus to minus. Ceramic capacitors are cheap for smaller values and aren't polarized. Tantalum caps are smaller than electrolytic for the same value+voltage so that is what is inside your phone. There are a few other chemicals used sometimes.

The time constant tells you how slowly the signal changes. To take a specific example, I had a project controlling a motor with a chip that has a current feedback pin. I could measure the current going into the motor to determine if it was being over-driven. The control was coming from an Arduino PWM pin at 480Hz. Using analogRead() on the feedback just randomly saw too-much current or none-at-all depending on the exact timing with the 480Hz input.

So I added a resistor and capacitor with a time constant of 0.01 seconds and fixed the analogRead() to a period of 0.005 seconds.

Thanks for this explanation, makes more sense now! But why did you choose the time constant or 0.01 seconds and the analogRead() to run every 0.005 seconds?

On another note, measuring the voltage drop on the shunt would still be dangerous because I am referencing high voltage and I do not want to do that...I know an opto coupler might be useful here. I have learned how to get the opto coupler to simply let you know if there is high voltage there, well simply, whether the internal IR led is on or off. But how would you use that to transmit the physical mV value you are measuring off of the shunt so you can amplify that afterwords?

Since this is for an electric car, keeping the high voltage pack isolated from chassis ground is super important! Thanks to everyone for all of the replies so far!

I was going to suggest you look up the Nyquist Sampling Theorem but the Wikipedia page on it is very very dry. Basically it says, to digitize any analog signal you must sample at twice the frequency of any frequency existing in the signal. So that is why I picked those values.

The shunt should be on the negative side of the battery. So the voltage it makes is within the range the Arduino can read.

Thanks for that explanation, that makes much more sense. I’ll have to lookup my controller’s PWM frequenters but I think it’s around 18kHz. I can then calculate how many times to measure per second as per what you said! Makes sense now.

Yes the shunt is on the negative side of my battery pack. But how can I measure that voltage drop across the shunt while keeping my Arduino isolated from the high voltage?

Thanks

The frequency of the PWM should be irrelevant after the filtering, instead it becomes the RC time constant of your filter that is key.

I'd go for an RC of 10-100 times the PWM period. 18 kHz is 56 µs per pulse, so 100 nF and 10kΩ should make for a good filter: RC = 1 ms, so 18 times slower than the PWM signal. This way the output should be very stable yet follow the source with minimal delay. The Nyquist theorem should not apply to the RC filter, as the expected output is a (relative) slow changing signal.

Then there's the problem of amplifying the 0-75 mV signal. The HX711 may work, but it seems its range is limited to 0-40 mV. Or you can connected to an ADS1115 external ADC, it has a 256 mV reference available. It's a 16-bit ADC, for your signal you end up at an effective 13 bits resolution. Should be good enough.

Thanks for your reply! That makes it a little clearer now!

But how would I go about isolating all of this from the high voltage? I have to make sure none of this gets in contact with chassis ground, but I’m just not sure what the best way to go about it is. Measuring the mV off that shunt, plus measuring the high voltage from a voltage divider, really means I need to have good isolation. Any ideas?

Regular insulated wire should be OK. Put the Arduino part of the project in a plastic box.

You are working at the 2nd layer of protection. There is no problem if part of your project touches the chassis. It is only if another part of the wiring also touches AND that is not a "ground" wire: that would cause damaging current to flow.

How is that battery wired? In many applications the negative pole is connected to the chassis (aka ground). If so you should be able to share that ground with the Arduino (assuming it's reasonably clean). Place your shunt in the return wire of the motor you want to monitor, then one end of the shunt is connected to ground.

Analog signals are very hard to fully isolate.

Thanks for your replies!

Well i don’t want to have the ground potential tied to chassis because when doing battery work, if my body touches ground while my hands are wiring terminals, I’m gonna get shocked. And believe me, I know from experience:)

And no, unfortunately the battery pack isn’t tied to chassis ground at all, it is completely isolated, which makes this whole issue of isolation that much harder..:frowning: