Skip to content

Instantly share code, notes, and snippets.

@danjperron
Created September 15, 2018 22:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save danjperron/039e4430d0fa2ff7360c11c9ffab282a to your computer and use it in GitHub Desktop.
Save danjperron/039e4430d0fa2ff7360c11c9ffab282a to your computer and use it in GitHub Desktop.
#!/usr/bin/python3
import time
# Import the ADS1x15 module.
import Adafruit_ADS1x15
'''
Script to read current from ACS712 30A using ADS1115 converter
ACS Vout 2.5V with 66mv/per Amp
The range will be 0 to 2A so the ACS712-30A is ~66mv/A
0A is then VCC/2
2A is VCC/2 + 66mv*2
if VCC is 5V then 0A=2.5V and 2A = 2.632V
The Voltage on the ADS1115 is 3.3V from the Raspberry Pi we will need to take Vref = 2.048V.
Then we will need to reduce the Vout from the ASC712-39 below the 2V using a resistor divider
V IN0 = ACS712-30A Vout * R1 / (R1+R2)
ACS VCC Because ACS712-30 output is related to the VCC.
Ee will need to read the VCC at the ACS712-30 and compensate the return voltage from it.
I can't figure out if the 66mv/A is also proportional to VCC but I will assume it.
Then we should be able to compensate the VCC shift using 5V has reference. This eliminate
the recalibration of the offset if the voltage at the ACS712 change.
ADS1115 IN 0 ACS712-30A using a register divider R1/R2
IN 1 VCC of the ACS712-30 using a register divider R3/R4
register divider
R1 ACS712-30 output to ADS1115 IN0
R2 ADS1115 IN0 to GND
R3 VCC at ACS712-30 to ADS1115 IN1
R4 ADS115 IN1 to GND
'''
#constant definition
ACS712_mV_to_Amp = 66e-3
ACS712_VOffset = 2.5
R1 = 4500.0
R2 = 10000.0
R3 = 10000.0
R4 = 4500.0
#use 2.048 Vref
GAIN = 2
#Conversion of ADS1115 to Volt
def ConversionToVolt(values):
return(values * 2.048/32767.0)
#Calculate the ACS712-30 output
#From ADS1115 IN0 , calculate Vout before the resistor divider R1/R2
def getRealACS712Vout(Vin):
return(Vin * ( R1+R2)/(1.0 * R2))
#Calculate the ACS712-30 VCC
#From ADS1115 IN1 , calculate Vout before the resistor divider R3/R4
def getRealACS712Vcc(Vcc):
return(Vcc * ( R3+R4)/(1.0 * R4))
try:
while True:
#average 5 readings,IN0 and IN1 in alternance, to remove noise from DC/DC power supply
IN0Avg=0
IN1Avg=0
for i in range(5):
IN0Avg= IN0Avg + read_adc(0, gain=GAIN, data_rate=128)
IN1Avg= IN1Avg + read_adc(1, gain=GAIN, data_rate=128)
IN0Avg = IN0Avg /5.0
IN1Avg = IN1Avg /5.0
print("IN0:{} IN1:{}".format(ConversionToVolt(IN0Avg),
ConversionToVolt(IN1Avg)))
#calculate every thing now
#get ACS-712 Vout and VCC
ACS712Vout = getRealACS712Vout(ConversionToVolt(IN0Avg))
ACS712Vcc = getRealACS712Vcc(ConversionToVolt(IN1Avg))
print("Vout:{} VCC:{}".format(ACS712Vout,ACS712Vcc))
#Normalize ACS712 Vout for VCC=5.0
VNormalize = ACS712Vout * 5.0 / ACS712Vcc
#ok calculate the current
IOut = (VNormalize - ACS712_VOffset) / ACS712_mV_to_Amp
table=[]
#record IN0 A2D
table.append(IN0Avg)
#record IN1 A2D
table.append(IN1Avg)
#record IN0 Voltage
table.append(ACS712Vout)
#record IN1 VCC
table.append(ACS712Vcc)
#record ACS712 current
table.append(IOut)
print("0:{0:5} {2:1.3f}V {4:2.2f}A\t1:{1:5} {3:1.3f}V".format(*table))
time.sleep(0.5)
except KeyboardInterrupt:
pass
@bonusmiki
Copy link

Hello @danjperron
I have a question.
Where did you get these specific values for R1, R2, R3 and R4?
And why should R3 and R4 be in those specific places as you wrote?
"R3 VCC at ACS712-30 to ADS1115 IN1
R4 ADS1115 IN1 to GND"

@danjperron
Copy link
Author

I use Vref on the ADS115 to be 2.048V so voltage output can't be higher than 2.048V.

VCC on ACS712-30 is 5V so 0A is 2.5V.

So the resistor divider is to be sure that the ACs712 output is below 2.048V with the current on it.

if you have 2A on the ACS712-30 you will get (in theory) 2.5V + 2A*66e-3V/A => 2.632V.
Since the ACS can't read more than 2.048V than the resistor divider will put the voltage below 2.048V.

2.632V * (10000/(10000+45000)) => 1.81V

Depending of your current you will need to check what is you maximum current and set according to it.

But I got a better method now. I'm using a potentiometer to get the zero since the A/D could do differential. Adjusting
adc1 via the potentiometer to get 2.5V to be the same voltage than adc0 at no current. Using this method the ACS712 doesn't need resistor divider. Then the maximum ADC is 3.3V.

https://www.dropbox.com/s/7sxdzjxtyqslmg4/solar1_bb.jpg?dl=1

N.B. the current ADC library doesn't support differential but it is easy to add. Just check the data sheet and add it on the python library.

@bonusmiki
Copy link

@danjperron I sent an email to You with one more issue. Thank you in advance for your help!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment