I am new to this forum, so excuse me if my question isn't the best.
First of all, I am working on an oscilloscope made from an Arduino and other needed modules, of course, no point in reinventing the wheel! Measuring the voltage was pretty easy. Now, the problem is that the the values I am reading are not reliable for a long time, because the value you have to substract differs from time to time. First of all, ideally, you have to substract 2.5V and you would get the current flow. Well, not in my case:
Let's say to get the current at this moment ( t1 ), I have to substract 2.4683v. Everything is fine, for about 20 minutes. Then, I get readings that are off of about 0.5 or even 1 amp.
By connecting only the output of my ACS712 to Arduino MCU I get totally unreliable values. I tried this because the PSU would have a more consistent output, but in the big run it's even worse because of the unstable readings.
It's been a week of frustration, so any advice is welcome
Components used:
-Arduino Nano
-ACS712 30A model
-350W computer PSU
-Electrolysis as load
#define ACS A7 // Pin of ACS sensor
#define SENSITIVITY 66 // acs712 model SENSITIVITY in mv (30A model)
float zeroPoint;
char command;
void setup() {
Serial.begin(9600);
pinMode(ACS, INPUT);
zeroPoint = testAvgVoltage();
}
void loop() {
ampermeter();
}
int testAvgVoltage(){
float voltage = 0;
int reads = 0;
float avg;
for(int i=0; i<1000; i++){
voltage += analogRead(ACS) * (5.0/1023.0);
reads++;
avg = voltage/reads;
delay(5);
}
return voltage;
}
void ampermeter(){
int sampling = 250;
long long int sensor;
double amps;
float voltage = 0;
for(int i=0; i<sampling; i++){
sensor = analogRead(ACS);
voltage += sensor * (5.0/1023.0);
delay(1);
}
voltage /= sampling;
amps = ((voltage - zeroPoint) / 0.066);
Serial.print("\t Voltage: ");
Serial.print(voltage, 4);
Serial.print("\t Amps: ");
Serial.println(amps);
delay(5);
}
Let's say to get the current at this moment ( t1 ), I have to substract 2.4683v.
Using a fixed offset voltage will induce an error over time.
The A/D converter of the atMega328 does not have a precise, stable voltage reference. It uses the 5 volt power supply of the entire Arduino board.
The output of the ACS712 is said to be ratiometric which means at zero input, the output is 1/2 of the applied voltage. For the best precision, the applied voltage must be the same 5 volt supply of the Arduino board as this is the reference voltage for the A/D.
All the means is that you use the ACS712 in a specific way. Apply zero volts to the ACS712 and read the analog value. Record the result which should be approximately 512 which is 50% of the full scale A/D counts. Apply your test voltage and read the analog voltage. Subtract the previous zero reference count and multiply the remainder by the device constants.
(zeroValue - reading) / 1023 * 5 / 0.1
Where 0.1 is for the 20 amp unit. Use 0.066 for 30, 0.185 for the 5 amp.
For the best accuracy, you should reread the zero value of the sensor from time to time and especially before a measurement where you want the highest accuracy possible.
This equation and constants are directly taken from the ACS712 library code here:
I use these current sensors all the time (ACS758 and ACS770 though), with pretty reliable results.
How many samples are you taking for each read?
Not sure how you are re-reading the zero value, do you have some way of turning off power that the current sensor is measuring?
Is your sensor in relatively a stable temperature?
How much is the current fluctuating? (and is it AC or DC)?
I totally don't get your statement "apply zero volts to the sensor and then read the analog value. Unless this sensor is very different from the others in the ACS line, you apply zero current and then read the analog value--in which Vout = Vcc / 2.0 at I=0 (but depends on if you have the B or U unit.
I think your calculation needs to use floats (5 is not 5.0), I believe values will be computed to the lowest data type (ints in this case)
should it not be reading - zeroValue?? otherwise i'm guessing all your values will be negative (unless you are current going into I-
more questions, but looks like you have some digging to do.
PaulS:
I have no idea why you think that volts - volts = current. It does not. Current = voltage * resistance.
You do NOT subtract volts from amps.
So, when you connect something else, the laws of physics change, and your BS approach suddenly works? I find that VERY hard to believe.
Post a schematic. Post your code.
Look up the way ACS712 30A current sensor works before criticizing.
Let me tell you why using ACS current = voltage - voltage
When no current goes through the module, the output voltage is 2.5V (offset voltage). If you would have used an ACS, you would know that it seems only rational to use the next formula:
current = (outputVoltage - offsetVoltage) / moduleSensitivity
Will update when I run the next test. Right now I don't really have the time needed. Thanks for the answers!
Hi,
You are doing an average of 1000 readings, calculate the average, then dump all your raw data. THEN read in another 1000 reading and dump them.
This means a pause each time you average.
To increase your efficiency you can do a dynamic average.
You store each raw data reading, and when a new raw reading comes in, you do an average using it and the old data.
This way you get a new average value at each raw reading, but still using your 1000 readings.
I'd say you will get just a good result with 50 or a 100 readings.
ZentriXG:
When no current goes through the module, the output voltage is 2.5V (offset voltage).
Well, yes and no.
The ACS outputs VCC/2 (half of it's supply voltage) with no current through the sensor.
That could be 2.3volt when the Nano is powered from USB, or 2.6volt when powered from a 5.2volt computer supply.
Same for mV/Amp.
The datasheet assumes a 5.000 volt supply (which it rarely is).
mV/Amp value of the ACS712 is also ratiometric (goes up/down with supply voltage).
Coding in "volt" and "mV/Amp" works, but the numbers are meaningless.
I think it makes more sense to code with A/D values (A/D value directly to current).
float current = (analogRead(A0) - 512) * 0.0732; // is all you need
Leo..