(solved) acs712 current dc incorrect output in code

hi everyone, hope having better day then me :slight_smile:

aim of this project is for my camper trailer , to monitor solar input , load acc and acs714 for battery -30=30+ and data log it to sd, see graph results , but just starting with basics first , i do have all parts i need.

im running voltage divider R1 10.2k & R2 1.13k 0-50v output is correct 13.7v
acs712 works fine in basic code 1amp load on it but in over code , i must be missing something it runs at 66mv but get output of 30amps

olts = 13.71	 Current (amps) = 31.62	 Power (Watts) = 433.58	 Time (hours) = 0.00	 Amp Hours (ah) = 0.01	 Watt Hours (wh) = 0.17
Volts = 13.71	 Current (amps) = 31.62	 Power (Watts) = 433.58	 Time (hours) = 0.00	 Amp Hours (ah) = 0.02	 Watt Hours (wh) = 0.26
Volts = 13.71	 Current (amps) = 31.41	 Power (Watts) = 430.68	 Time (hours) = 0.00	 Amp Hours (ah) = 0.02	 Watt Hours (wh) = 0.34
Volts = 13.71	 Current (amps) = 31.41	 Power (Watts) = 430.68	 Time (hours) = 0.00	 Amp Hours (ah) = 0.03	 Watt Hours (wh) = 0.42
Volts = 13.71	 Current (amps) = 31.41	 Power (Watts) = 430.68	 Time (hours) = 0.00	 Amp Hours (ah) = 0.04	 Watt Hours (wh) = 0.50
Volts = 13.71	 Current (amps) = 31.33	 Power (Watts) = 429.63	 Time (hours) = 0.00	 Amp Hours (ah) = 0.04	 Watt Hours (wh) = 0.58
Volts = 13.71	 Current (amps) = 31.33	 Power (Watts) = 429.63	 Time (hours) = 0.00	 Amp Hours (ah) = 0.05	 Watt Hours (wh) = 0.66
Volts = 13.71	 Current (amps) = 31.33	 Power (Watts) = 429.63	 Time (hours) = 0.00	 Amp Hours (ah) = 0.05	 Watt Hours (wh) = 0.74
Volts = 13.71	 Current (amps) = 31.33	 Power (Watts) = 429.63	 Time (hours) = 0.00	 Amp Hours (ah) = 0.06	 Watt Hours (wh) = 0.82
Volts = 13.71	 Current (amps) = 31.33	 Power (Watts) = 429.63	 Time (hours) = 0.00	 Amp Hours (ah) = 0.07	 Watt Hours (wh) = 0.90

here’s code im using

/* My INFO acs712 30a with devider 0-50v R1=10.2k & R2=1.13k
 *  future addon 2 x amp and volt sensors inputs
 *  and data log to sd card and tft screen
 */


/*

Vcc on carrier board to Arduino +5v
GND on carrier board to Arduino GND
OUT on carrier board to Arduino A0



Insert the power lugs into the loads positive lead circuit, 
arrow on carrier board points to load, other lug connects to 
power supply positive

Voltage Divider

11.66 from + to A4
4.62k from A4 to Gnd
Ratio 2.5238


*/
int batMonPin = A4;    // input pin for the voltage divider
int batVal = 0;       // variable for the A/D value
float pinVoltage = 0; // variable to hold the calculated voltage
float batteryVoltage = 0;

int analogInPin = A0;  // Analog input pin that the carrier board OUT is connected to
int sensorValue = 0;        // value read from the carrier board
int outputValue = 0;        // output in milliamps
unsigned long msec = 0;
float time = 0.0;
int sample = 0;
float totalCharge = 0.0;
float averageAmps = 0.0;
float ampSeconds = 0.0;
float ampHours = 0.0;
float wattHours = 0.0;
float amps = 0.0;

int R1 = 30002; // Resistance of R1 in ohms
int R2 = 7501; // Resistance of R2 in ohms

float ratio = 0;  // Calculated from R1 / R2

void setup() {
  // initialize serial communications at 9600 bps:
  Serial.begin(9600); 
}

void loop() {
  
int sampleBVal = 0;
int avgBVal = 0;  
int sampleAmpVal = 0;
int avgSAV = 0;
  
 for (int x = 0; x < 10; x++){ // run through loop 10x
 
  // read the analog in value:
  sensorValue = analogRead(analogInPin);   
  sampleAmpVal = sampleAmpVal + sensorValue; // add samples together

  batVal = analogRead(batMonPin);    // read the voltage on the divider 
  sampleBVal = sampleBVal + batVal; // add samples together
  
  delay (10); // let ADC settle before next sample

 }
 
 avgSAV = sampleAmpVal / 10;
 
  // convert to milli amps
  outputValue = (((long)avgSAV * 5000 / 1024) - 500 ) * 1000 / 66;  
  
/* sensor outputs about 100 at rest. 
Analog read produces a value of 0-1023, equating to 0v to 5v.
"((long)sensorValue * 5000 / 1024)" is the voltage on the sensor's output in millivolts.
There's a 500mv offset to subtract. 
The unit produces 133mv per amp of current, so
divide by 0.133 to convert mv to ma
          
*/

 
 avgBVal = sampleBVal / 10; //divide by 10 (number of samples) to get a steady reading
 
  pinVoltage = avgBVal * 0.00610;       //  Calculate the voltage on the A/D pin
                                /*  A reading of 1 for the A/D = 0.0048mV
                                    if we multiply the A/D reading by 0.00488 then 
                                    we get the voltage on the pin.  
                                   
                                    NOTE! .00488 is ideal. I had to adjust 
                                    to .00610 to match fluke meter.
                                    
                                    Also, depending on wiring and 
                                    where voltage is being read, under 
                                    heavy loads voltage displayed can be 
                                    well under voltage at supply. monitor 
                                    at load or supply and decide.
*/

  ratio = (float)R1 / (float)R2;
  batteryVoltage = pinVoltage * ratio;    //  Use the ratio calculated for the voltage divider
                                          //  to calculate the battery voltage
                                          
                                            
  amps = (float) outputValue / 1000;
  float watts = amps * batteryVoltage;
    
  Serial.print("Volts = " );                       
  Serial.print(batteryVoltage);      
  Serial.print("\t Current (amps) = ");      
  Serial.print(amps);  
  Serial.print("\t Power (Watts) = ");   
  Serial.print(watts);   
  
    
  sample = sample + 1;
  
  msec = millis();
  
  
  
 time = (float) msec / 1000.0;
  
 totalCharge = totalCharge + amps;
  
 averageAmps = totalCharge / sample;
  
 ampSeconds = averageAmps*time;

 ampHours = ampSeconds/3600;
  
 wattHours = batteryVoltage * ampHours;
  
 



  Serial.print("\t Time (hours) = ");
  Serial.print(time/3600);
  
  Serial.print("\t Amp Hours (ah) = ");
  Serial.print(ampHours);
  Serial.print("\t Watt Hours (wh) = ");
  Serial.println(wattHours);
  

  
  // wait 10 milliseconds before the next loop
  // for the analog-to-digital converter to settle
  // after the last reading:
  delay(500);                     
}

i been trying things for week now im going crazy

“There’s a 500mv offset to subtract.”
Is there?
I thought zero current was VCC/2, not 0.5volt.
Maybe I’m looking at the wrong sensor.

Maybe best to take multiple A/D samples, and store them e.g. in an unsigned int (<=64 samples).
Then subtract a “zero current” value (about 511-512 * the number of samples).
And then convert that value to current.

Milliamps is wishful thinking.
A bi-directional sensor and a 10-bit A/D has a span of about 450 values over it’s uni directional current range. With a 30Amp sensor, granularity (steps) is about 67mA.
A 0.1Amp readout is more realistic.

Try to make the current sensor work on it’s own, before adding it to the program.
Leo…

hi, thanks for helping

i did test it before but here's results with my multimeter within spec for me 0.01-+ even if it was 0.1 would still be ok

Raw Value = 518  mV = 2529.297   Amps = 0.595
Raw Value = 518  mV = 2529.297   Amps = 0.595
Raw Value = 517  mV = 2524.414   Amps = 0.521
Raw Value = 509  mV = 2485.352   Amps = -0.070
Raw Value = 510  mV = 2490.234   Amps = 0.004
Raw Value = 510  mV = 2490.234   Amps = 0.004

this is code i used

/*
Measuring Current Using ACS712
*/
const int analogIn = A0;
int mVperAmp = 66; // use 100 for 20A Module and 66 for 30A Module
int RawValue= 0;
int ACSoffset = 2490.2; 
double Voltage = 0;
double Amps = 0;

void setup(){ 
 Serial.begin(9600);
}

void loop(){

 RawValue = analogRead(analogIn);
 Voltage = (RawValue / 1024.0) * 5000; // Gets you mV
 Amps = ((Voltage - ACSoffset) / mVperAmp);


 Serial.print("Raw Value = " ); // shows pre-scaled value 
 Serial.print(RawValue); 
 Serial.print("\t mV = "); // shows the voltage measured 
 Serial.print(Voltage,3); // the '3' after voltage allows you to display 3 digits after decimal point
 Serial.print("\t Amps = "); // shows the voltage measured 
 Serial.println(Amps,3); // the '3' after voltage allows you to display 3 digits after decimal point
 delay(2500); 

}

thanks, Luke

Why go from value to voltage to current.
You can go from value directly to current.
Try this example I just cobbled together (only tested with a pot).
Leo…

// current sensor connected to A0, 5volt and ground

float numReadings = 64; // number of readings for averaging
unsigned int total; // total A/D readings
float offset = 511.49; // >>>calibrate zero current here<<<
float span = 0.0651; // >>>calibrate span here<<<
float amps; // final current

void setup() {
  Serial.begin(9600);
}

void loop() {
  total = 0; // reset
  for (int x = 0; x < numReadings; x++) { // read sensor multiple times
    total = total + analogRead(A0); // add each value
  }
  amps = ((total / numReadings) - offset) * span;
  Serial.println(amps);
  delay(100); // use  millis() timing in final code
}

Edit:

  1. Disconnect current terminals, and adjust offset for 0.00 current in the serial monitor (upload every time). It should be around 511.00. Add a decimal place if you need to.
  2. Push a known (high) current through the sensor, and calibrate span.
    Swap terminals if current goes negative (discharge current).

thanks for quick response, today my day off, hope i get some where

here's output, i calibrate it too 0 close as possible and with meter it only -0.04 so i get 0.56a witch is ok with change off set to 509.55

0.51
0.51
0.51
0.52
0.00
-0.00
0.00
0.01

so that working much better now , how i go about adding over code so i get volts and ah, Watt's, WH

at same time im testing sd card shield with rtc on another board make sure it works

cheer's

Everything that measures and finally calculates "amps" can be replaced with my sketch.

I have renamed "current" in my sketch to "amps", to make it esier to merge.

Upload the new sketch if you are having problems. Leo..

:slight_smile: :slight_smile: thanks for all for help, big time :slight_smile: :slight_smile:

did get 2 errors think was conflict with your code so i removed them

output

Volts = 13.52	 Current (amps) = 0.53	 Power (Watts) = 7.18	 Time (hours) = 0.03	 Amp Hours (ah) = 0.01	 Watt Hours (wh) = 0.12
Volts = 13.52	 Current (amps) = 0.53	 Power (Watts) = 7.20	 Time (hours) = 0.03	 Amp Hours (ah) = 0.01	 Watt Hours (wh) = 0.13
Volts = 13.52	 Current (amps) = 0.54	 Power (Watts) = 7.16	 Time (hours) = 0.03	 Amp Hours (ah) = 0.01	 Watt Hours (wh) = 0.13

i like your code it was much cleaner, is there way clean up code so much easier to read and setup so i can have 2 voltage inputs and 2 currents inputs, any advice or help will be great :slight_smile:

here’s code im using now

// current sensor connected to A0, 5volt and ground

// voltage sensor A4, 5v , GND
int batMonPin = A4;    // input pin for the voltage divider
int batVal = 0;       // variable for the A/D value
float pinVoltage = 0; // variable to hold the calculated voltage
float batteryVoltage = 0;

//current sensor
float numReadings = 64; // number of readings for averaging
unsigned int total; // total A/D readings
float offset = 509.50; // >>>calibrate zero current here<<<
float span = 0.0651; // >>>calibrate span here<<<
float amps; // final current

//reset to zero
unsigned long msec = 0;
float time = 0.0;
int sample = 0;
float totalCharge = 0.0;
float averageAmps = 0.0;
float ampSeconds = 0.0;
float ampHours = 0.0;
float wattHours = 0.0;

//resistance size
int R1 = 30002; // Resistance of R1 in ohms
int R2 = 7501; // Resistance of R2 in ohms
float ratio = 0;  // Calculated from R1 / R2

void setup() {
  Serial.begin(9600);
}

void loop() {
  //voltage
  int sampleBVal = 0;
int avgBVal = 0; 
for (int x = 0; x < 10; x++){ // run through loop 10x
  batVal = analogRead(batMonPin);    // read the voltage on the divider 
  sampleBVal = sampleBVal + batVal; // add samples together
  
  delay (10); // let ADC settle before next sample
}
//volts
avgBVal = sampleBVal / 10; //divide by 10 (number of samples) to get a steady reading
 
  pinVoltage = avgBVal * 0.00610;       //  Calculate the voltage on the A/D pin
  
  ratio = (float)R1 / (float)R2;
  batteryVoltage = pinVoltage * ratio;    //  Use the ratio calculated for the voltage divider
                                          //  to calculate the battery voltage
                                          
                                            
 
  float watts = amps * batteryVoltage;
  // current 
  total = 0; // reset
  for (int x = 0; x < numReadings; x++) { // read sensor multiple times
    total = total + analogRead(A0); // add each value
  }
  amps = ((total / numReadings) - offset) * span;
  Serial.print("Volts = " );                       
  Serial.print(batteryVoltage);      
  Serial.print("\t Current (amps) = ");      
  Serial.print(amps);  
  Serial.print("\t Power (Watts) = ");   
  Serial.print(watts);   
  
    
  sample = sample + 1;
  
  msec = millis();
  
  
  
 time = (float) msec / 1000.0;
  
 totalCharge = totalCharge + amps;
  
 averageAmps = totalCharge / sample;
  
 ampSeconds = averageAmps*time;

 ampHours = ampSeconds/3600;
  
 wattHours = batteryVoltage * ampHours;
  
 



  Serial.print("\t Time (hours) = ");
  Serial.print(time/3600);
  
  Serial.print("\t Amp Hours (ah) = ");
  Serial.print(ampHours);
  Serial.print("\t Watt Hours (wh) = ");
  Serial.println(wattHours);
  

  
  // wait 10 milliseconds before the next loop
  // for the analog-to-digital converter to settle
  // after the last reading:
  delay(500);                     
}