Measure current and voltage

Hi
I have just started my little project to measure current and voltage from my new solarpanel.
But before im testiing my solarpanel, I have connected a powersupply and a fan.
I´m using a Arduino uno and a “ACS712 current sensor” connected as picture "ACS712_1.JPG and “ACS712_1.JPG”
When up and running I get the result as in picture “Arduino_current_measure.JPG” and I get the same result when disconnecting the fan.
I guess my Sketch is wrong configured.
Hope I will get some help with this problem.

ACS712_1.JPG

ACS712_2.JPG

ACS712_1.JPG
410e5d533a00ba3a0e4f2e773fdf0561a1fd46af.jpg
ACS712_1.JPG
0aedd19c03dedd0b924828ebf91c5fbd91fd3b45.jpg
ACS712 current sensor
73b5c47e88c3f7225197095b8bc1f38d0fea6d05.jpg

Please post your Sketch.

Please read the two posts at the top of this Forum by Nick Gammon on guidelines for posting here, especially the use of code tags ("</>") when posting source code files. Also, before posting the code, use Ctrl-T in the IDE to reformat the code in a standard format, which makes it easier for us to read.

Can you please read Sticky Topic How to use this forum - please read.

Can you please post a copy of your sketch, using code tags?
They are made with the </> icon in the reply Menu.
See section 7 http://forum.arduino.cc/index.php/topic,148850.0.html

Hi
Here is my Sketch

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

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

void loop() {

  RawValue = analogRead(analogIn);
  Voltage = (RawValue / 1023.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, 1); // 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);

}

The ACS712 has an output voltage range of ~4volt (0.5volt to 4.5volt) when connected to a 5volt supply.
2.5volt@zero current, 4.5volt for the rated current in one direction, and 0.5volt for that current in the other direction.
So 2volt span for the full rated current in one direction. 2/5 of the A/D range. 1024/5 = ~410 steps.
A 20A sensor could have trouble with one decimal place. Worse with a 60A sensor.
Your code is trying to display 3 decimal places.
Leo..

@Wawa Thanks for your quick answer.
Can you please explain to me what I should change ?
I have just played with my Arduino a few days and don´t really understand.
I appreciate all help

To get a basic understanding of the capabilities and limitations of an Arduino, you should first work through the examples that come with the IDE.
When you start playing with sensors like this, see what problems other people had before you.
Enter e.g. “ACS712” in the search box on top of this page.
Then you will find that pre-read and multiple reads (smoothing) are needed for these (and other) sensors.
I cobbled something together. Untested, but it should work.
Read the comments. Set the serial monitor to the baud rate in the sketch.
Leo…

// 20A bi-directional ACS712

int sensorPin = A0; // the pin that the sensor is connected to

// YOUR calibration
float offset = 511.5; // zeroing bi-directional sensor | could be 510.0 to 513.0
float span = 0.04883; // span | depends on type of sensor used (e.g. 20A) | finetune max readout

const byte numReadings = 32; // number of readings for smoothing (max 64)
int readings[numReadings]; // raw A/D readings
byte index = 0; // index of the current reading
unsigned int total = 0; // running total
float current; // resulting current

void setup() {
  Serial.begin(115200); // ***set serial monitor to this value***
  for (index = 0; index < numReadings; index++) { // fast-fill the array at startup
    readings[index] = analogRead(sensorPin);
    total = total + readings[index];
  }
  index = 0; // reset index
}

void loop() {
  total = total - readings[index]; // subtract the last reading
  readings[index] = analogRead(sensorPin); // one unused reading to clear any ghost charge
  readings[index] = analogRead(sensorPin); // read the sensor
  total = total + readings[index]; // add the reading to the total
  index = index + 1; // advance to the next position in the array
  if (index >= numReadings) // if we're at the end of the array
    index = 0; // wrap around to the beginning

  // convert value to current
  current = (total / numReadings - offset) * span; // value to current conversion

  // print to serial monitor
  Serial.print("Current is  ");
  Serial.print(current); // default two decimal places | ...(current, 1);  is one decimal place
  Serial.println("  Amp");

  delay(100); // use a non-blocking delay when combined with other code
}

Thanks a lot for Your help and the Sketch.
When I try it and the fan is off, my monitor show "Current is -0.12 Amp"
When I start the fan I get "Current is -0.27 Amp"
Is that a "right" value I get ?

Slightly change the offset value (511.5 in the sketch), and re-upload, untill you have ~0Amp without current.
That could be al little as 115.8 or 115.2
Change it in small steps.

The sensor is bi-directional, so you can e.g. use it to see charging(+) and discharging(-) of e.g. a battery.
If load (fan) current is displaying negative numbers, flip the current wires to the sensor.
Leo..

:slight_smile: Thanks again.
Changed the value from 511.5 to 508.9 and now the current is = 0.00 Amp
with fan running, -0.14/-0.09

Is it possible to also display the voltage in the Serial monitor ?

Is it possible to display Voltage at the same time as the Ampere in the serial.monitor ?

Yes & No, As a single core microcontroller the arduino executes one instruction at a time.
But it executes 16 million instructions per second so it can appear as if it is at the same time to us slow humans.

In this code snippet taken from Wawa's code above, you'll notice 2 Serial.print statements followed by a Serial.println .

  // print to serial monitor
  Serial.print("Current is  ");
  Serial.print(current); // default two decimal places | ...(current, 1);  is one decimal place
  Serial.println(" Amp");

The Serial.println is what makes it start a new line after it has printed so you can have as many Serial.print's as you want and then use Serial.println to end the line as long as you dont exceed the line length of the display.

  // print to serial monitor
  Serial.print("Current is  ");
  Serial.print(current); // default two decimal places | ...(current, 1);  is one decimal place
  Serial.print(" Amp "); // CHANGED to Serial.print
  Serial.print("Voltage is ");
  Serial.print(voltage); 
  Serial.println(" Volts");  // end of line

I think I have to add something more in my Sketch after adding serial.print for Voltage ?
Got this error when upload to Arduino : ´voltage´was not declared in this scope

Can you please help me to understand what I missed.

// 20A bi-directional ACS712

int sensorPin = A0; // the pin that the sensor is connected to

// YOUR calibration
float offset = 510.9; // zeroing bi-directional sensor | could be 510.0 to 513.0
float span = 0.04883; // span | depends on type of sensor used (e.g. 20A) | finetune max readout

const byte numReadings = 32; // number of readings for smoothing (max 64)
int readings[numReadings]; // raw A/D readings
byte index = 0; // index of the current reading
unsigned int total = 0; // running total
float current; // resulting current

void setup() {
  Serial.begin(115200); // ***set serial monitor to this value***
  for (index = 0; index < numReadings; index++) { // fast-fill the array at startup
    readings[index] = analogRead(sensorPin);
    total = total + readings[index];
  }
  index = 0; // reset index
}

void loop() {
  total = total - readings[index]; // subtract the last reading
  readings[index] = analogRead(sensorPin); // one unused reading to clear any ghost charge
  readings[index] = analogRead(sensorPin); // read the sensor
  total = total + readings[index]; // add the reading to the total
  index = index + 1; // advance to the next position in the array
  if (index >= numReadings) // if we're at the end of the array
    index = 0; // wrap around to the beginning

  // convert value to current
  current = (total / numReadings - offset) * span; // value to current conversion

  // print to serial monitor
  Serial.print("Current is  ");
  Serial.print(current); // default two decimal places | ...(current, 1);  is one decimal place
  Serial.print(" Amp "); // CHANGED to Serial.print
  Serial.print("Voltage is ");
  Serial.print(voltage); 
  Serial.println(" Volts");  // end of line

  delay(100); // use a non-blocking delay when combined with other code
}

You didn’t miss I did.

You haven’t mentioned the voltage of the solar panel so I will give an example for 12v panel.

First you will need a voltage divider
which is simply 2 resistors.

if resistor R1 is 100k Ohm’s
and resistor R2 is 50k Ohm’s

connect Vin to power from the solar panel
connect Vout to a arduino analog pin

this will allow you to read 0-15v on a analog pin.(little safety margin)

Then add this code to your sketch

// at the beginning of your sketch
int voltagePin = A2; // pin connected to voltage divider(pick which pin you wish to use)
float voltage;       // variable to store voltage value


// in void loop()
voltage = analogRead(voltagePin);  // Read voltagePin
voltage = (voltage*15.0)/1024.0;   // calculates actual voltage

If it is a different voltage you will need different value resistors and calculation value

Thanks a lot for your quick answer @Hutkikz
Should the Vout be connected to the terminals on my ACS712 ?
(or don´t I need the ACS712?)

no 2 different things, the ACS712 is for current and the voltage divider is for voltage.
I put Vout connected to pin A2 on the arduino but you can change it to another analog pin , just change the code for int voltagePin also.

Hi again
I don´t get my configuration working.
The measured values is not right.
Can You please help me again.

// 20A bi-directional ACS712

int sensorPin = A0; // the pin that the sensor is connected to
int voltagePin = A1; // pin connected to voltage divider(pick which pin you wish to use)
float voltage;       // variable to store voltage value

// YOUR calibration
float offset = 510.9; // zeroing bi-directional sensor | could be 510.0 to 513.0
float span = 0.04883; // span | depends on type of sensor used (e.g. 20A) | finetune max readout

const byte numReadings = 32; // number of readings for smoothing (max 64)
int readings[numReadings]; // raw A/D readings
byte index = 0; // index of the current reading
unsigned int total = 0; // running total
float current; // resulting current

void setup() {
  Serial.begin(115200); // ***set serial monitor to this value***
  for (index = 0; index < numReadings; index++) { // fast-fill the array at startup
    readings[index] = analogRead(sensorPin);
    total = total + readings[index];
  }
  index = 0; // reset index
}

void loop() {
  total = total - readings[index]; // subtract the last reading
  readings[index] = analogRead(sensorPin); // one unused reading to clear any ghost charge
  readings[index] = analogRead(sensorPin); // read the sensor
  total = total + readings[index]; // add the reading to the total
  index = index + 1; // advance to the next position in the array
  if (index >= numReadings) // if we're at the end of the array
    index = 0; // wrap around to the beginning

  // convert value to current
  current = (total / numReadings - offset) * span; // value to current conversion
  
  // volt
  voltage = analogRead(voltagePin);  // Read voltagePin
  voltage = (voltage*15.0)/1024.0;   // calculates actual voltage

  // print to serial monitor
  Serial.print("Current is  ");
  Serial.print(current); // default two decimal places | ...(current, 1);  is one decimal place
  Serial.print(" Amp "); // CHANGED to Serial.print
  Serial.print("Voltage is ");
  Serial.print(voltage); 
  Serial.println(" Volts");  // end of line

  delay(100); // use a non-blocking delay when combined with other code
}

gnagis:
The measured values is not right.

What does that mean.
Leo..

Did you share battery ground with Arduino ground.
Not needed for the current sensor, but needed for the voltage part.

If you use a voltage divider with high value resistors (>10k), you also have to add a (100n) cap from that analogue input to ground.
Leo..

Nothing is changing with the measured Amps when I connect the Solar panel.
The same problem with my measured Voltage from my Voltage divider.