Current shunts are very popular with the Ham Radio, boating, electric vehicle and solar / wind off grid folks, as they allow them to monitor solar and wind power production, power consumption of devices, and the estimated amp hours left in the battery bank, sort of like a “gas gauge” for your batteries.
Previous ADS1115 Arduino / Raspberry Pi post!
Unlike the solid state hall effect types, current shunts drop a small voltage across a calibrated resistor, indicating the amps being passed through the shunt. This allows shunts to report massive amounts of current, in excess of a 1000 amps, depending on the design of the shunt.
Become the Maker you were born to be. Try Arduino Academy for FREE!
Common shunts are rated at 50mv, 75mv, and 100mv output at maximum current (do not exceed 66% of name plate current). The Arduino has a few issues with these shunts. Since the maximum output is just 100 millivolts compared to the Arduino’s range of 0-5v, it’s like trying to read a 5 inch ruler from 10 miles away (worse with the 50mv and 75mv versions). The second issue is the Arduino has a 10 bit analog to digital converter (ADC), so a 100amp / 100mv shunt would have a 4.88 mv per step resolution, or about 5 amps per step (a total of 1024 steps).
We can solve this with a higher bit ADC with an onboard amplifier. We chose a 16 bit ADC that has over 64000 steps (+/- 32768), and up to 16x amplification. This matches a 100mv shunt very well.
The ADC we chose is the adafruit ADS1115. It has 4 single ended channels, or two differential channels. We chose to use differential mode, to eliminate electrical interference (the third issue) in the monitoring circuit, giving us very stable results. This means we can use two shunts per ADS1115. The ADS1115 can have 4 different user selectable I2C addresses, so with only 2 data lines (SCL & SDA), you can monitor up to 8 shunts.
Connections are very simple. Adafruit gives a very comprehensive tutorial on connecting and using this sensor for a variety of different purposes, and you can read about it (and download the library) at https://learn.adafruit.com/adafruit-4-channel-adc-breakouts. For our purposes, this is what we needed:
VDD – Arduino +5v
GND to Arduino GND
SCL to Arduino A5
SDA to Arduino A4
ADDR to Arduino GND (one of 4 possible address combinations, see adafruit tutorial for the the others)
A0 to Current Shunt
A1 to Current Shunt
Although we are using a 100a / 100mv shunt, if you are using a 75mv or 50mv shunt, we added two additional lines in the code you can uncomment depending on which shunt you are using.
#include <Wire.h> #include <Adafruit_ADS1015.h>
Adafruit_ADS1115 ads; /* Use this for the 16-bit version */
ads.setGain(GAIN_SIXTEEN); // 16x gain +/- 0.256V 1 bit = 0.125mV 0.0078125mV
results = ads.readADC_Differential_0_1();
float amps = ((float)results * 256.0) / 32768.0;//100mv shunt
//amps = amps * 1.333; //uncomment for 75mv shunt
//amps = amps * 2; //uncomment for 50mv shunt
Become the Maker you were born to be. Try Arduino Academy for FREE!
Order a complete current sensor board with 100a / 100mv shunt for only $65
Thank you Steve. This works a treat! Bookmarked!
I had a bit of a hard time with the math in this line:
`ads.setGain(GAIN_SIXTEEN); // 16x gain +/- 0.256V 1 bit = 0.125mV`
I just couldn’t understand why 1 bit would be 0.125mV.
Until I finally realized, that the line came from Adafruit’s code for ADS1015 (12-bit, 1 bit for the signing, leaving 11 bits = 0..2047 range for the value, 0.256V / 2048 = 0.125mV).
For ADS1115 at 16x gain: 1 bit = 7.8125µV.
Which means one ADS1115 can measure up to only 2 shunt resistor in a one time isn’t?
Is it have a way how to get 4 shunt reading in one arduino?
And now I get fluctuating result use your sketch above..even though i put RC Low Pass Filter before ADS..any Idea why?
I designed a simple solar lead acid battery charger & wanted to measure the current going in to (or out of) the battery bank via a 75mV/50A shunt.
I tried putting the shunt on the high side & using a differential input to measure the voltage across the shunt as shown. Charger, battery bank & Arduino ground were all tied together/common. Charger positive output was put through the shunt before going to the battery bank positive terminal.
Once power was applied the ADS1115 doing the differential reading immediately popped & let out the magic smoke. The other ADS1115 reading the voltages continued to work.
So it appears as if I’m missing something when it comes to high side differential voltage measurement with a common ground. After some research I think I will go with a INA219 based circuit for my design.
If you measure a negative current, you will have a negative voltage relative to your digital ground and even though your differential negative voltage will be fine, an absolutely negative voltage input to your ADS is not allowed according to the datasheet. Any solutions?
Thanks for taking the time to write this… I had a problem with my project and fixed it reading your blog.
In your solar system, how to you manage the grounds? Ie the shunt is presumably low side, and the battery and monitoring grounds in common, or at least the more negative side of the shunt as the common ground?
The shunt can be on the low side or the high side. you are just measuring the difference across it. It can even be bidirectional.
I understand the circuit and how it works. My question is about having a common ground. If you were to power your circuit from the same power source being measured(in your picture it looks like a vehicle), you would be supplying 12+ volts to the analog input pins in reference to ground. I was not sure if this would be a safe condition. Where you are asking the board to only measure difference, I wasn't sure if this would keep the board safe or if it measured A0 to ground and A1 to ground and then determined the difference.
If this would cause a problem, how could you power the Arduino from the same source safely?
Last question, powering the Arduino from the same source, however it would have to be, could you then safely measure the source voltage through the appropriate divider on a third analog input? A divider would require a common ground wouldn't it?
The short question if you will, how can I safely power a circuit from the same source it is measuring current and voltage?
I am not delivering 12v to the analog pins. I am measuring the voltage across the two points of measurement. Not ground. There is no problem powering thew arduino from the same source you are measuring. Yes, you can measure voltage using a voltage divider, and have 12v on the top of the divider, and common ground on the bottom.
Awesome!! thanks a lot this is super helpful as I already have a shunt with my battery monitor and the dc hall sensors are very expensive.
what happened to your website? seems to be down. is there anywhere we can see your whole monitor setup?
Build it! Thanks! It will be in a Sailing boat for measuring the Amp for loading the battery banks.
Great you added the diferent shunts. Makes it a lot easyer.
Thanks for sharing!!!
Hello dear friend
Thank you so much for sharing
but i can't understand how you calculate the current for each amount of shunt.
can you explain the current formula in your sketch?
See the gain calcualtions at https://learn.adafruit.com/adafruit-4-channel-adc-breakouts/programming
Will this all work fine if it is bidirectional i.e. charging/discharging = (100A 75mV) -75mV/+75mV?
Or would it need to be modified to point 2.5V = 0A?
Thank you for your tutorial. Can you please explain me the math of this line:
float amps = ((float)results * 256.0) / 32768.0;
I'm trying to use this script for a 300A 75mV shunt.
Thanks a lot.
We are using a gain of 16 (the 256 value) and a 16 bit adc (the 32768 value). See https://learn.adafruit.com/adafruit-4-channel-adc-breakouts/programming
We are using the differential mode, so we are only measuring the difference across the points, not a polarity.
I'm using ADS 1115 and module I2C and sadly I2C and ADS1115 use the same analogic door (A4 and A5), Can I change it ? if I can, how? I'm waiting for your answer. thank you.
The ADS1115 is I2C. I2C can handle many devices, as each have their own address. Just connect in parallel, and make sure each device has a different address. The ADS1115 address can be changed if it conflicts with another device.
I just smoked my pi, you do need something if there is a common ground.
A pi does not have a analog input. Did you use a ads1115 ADC? That would have isolated the connections to the pi. Did you power the ADS1115 with 3.3v? That would give you the capability to measure a maximum differential voltage of 3.6v. If you powered with 5v, then you need a level shifter on the I2C lines.
G'day. I can't seem to get any other read out other than .02amp. Any suggestions on where I can start to problem solve. I have had up to 50amps pulling thru my 100amp, 50mv shunt just to try and get a reading.
Thanks in advance