-
-
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 |
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.
@danjperron I sent an email to You with one more issue. Thank you in advance for your help!
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"