I was wondering if I cannot do it by myself with a Arduino Uno board and some current sensor.
As I'm not a code-freak dude, I did a little research and found a nice start for my project, right here.
I do have a ACS-712 for 5 Amps and also for 30 Amps.
I decided to start with the little one as my project is designated for my portable HF backpack based on ICOM IC-703.As the Arduino ADC input cannot accept more than 5V, a voltage divider has to be used.
Is the classic one, in wich I used a 10 kOhm from A4 to ground and a 100 kOhm from A4 to the probe. I used SMD resistors but after I measured the ratio I found that the real ratio is not 10 to 1 but somewhere around 10.93:1.
It is important as this ratio will be used to calculate the voltage into the Arduino code.
I modified the code from Instructables because it had some major measurement errors inside as it was written for ACS715 and I do have some problems here with the libraries since I tried to do some tests with I2C LCDs... Also, I found a lot of discussions about how that code is not working properly.
So, below is my version of the code of the Energy meter with ACS-712-05T.
The code is heavily commented so, I believe is easy to understand what is about.
#include <Arduino.h>
#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal.h>
/* This sketch describes how to connect a ACS712 - Bidirectional Current Sense Carrier
to the Arduino, and read current flowing through the sensor.
*/
LiquidCrystal lcd(8, 9, 4, 5, 6, 7); // Easy to connect the LCD Shield
/*
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
*/
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;
void setup()
{
// initialize serial communications at 9600 bps:
Serial.begin(9600);
lcd.begin(20, 4);
}
void loop()
{
int sampleBVal = 0;
int avgBVal = 0;
int sampleAmpVal = 0;
int avgSAV = 0;
for (int x = 0; x < 20; x++) // run through loop 20x
{
// 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 / 20;
// convert to milli amps
outputValue = (((long)avgSAV * 4980 / 1024) - 2485 ) * 1000 / 130;
/*
Modified by Adrian YO3HJV for real life ACS712-05A
Sensor outputs about 2.485 V 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.
"5000"mV is ideal value, my board has 4.985 V measured with a precision Voltmeter
Therefore, we have a 2485mv offset to subtract.
The unit produces 185 mv per amp of current, so divide by 0.185 to convert mV to mA.
The documentation said that the ACS has 185mV/Amp but I measured 130 mV/ Amp.
*/
avgBVal = sampleBVal / 20; //divide by 20 (number of samples) to get a steady reading
pinVoltage = (avgBVal * 5.0) / 1024;
// 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.
It is a good practice to measure the Vcc with a good voltmeter and
to adjust the 5.0 V to the measured value.
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.
*/
batteryVoltage = pinVoltage * 10.93; /* 10.93 is the voltage divider ratio
measured with a voltmeter.
First, measure the input voltage (ex. 12V)
Then, measure the voltage at pin A4 (V input).
Then make the ratio between and write it here.
*/
amps = (float) outputValue / 1000;
float watts = amps * batteryVoltage;
//Here we print the data output to serial port.
//Usefull for some data logging onto PC
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);
lcd.setCursor(0, 0);
lcd.print(batteryVoltage, 2);
lcd.print(" V ");
lcd.setCursor(11, 0);
lcd.print(amps, 2);
lcd.setCursor(16, 0);
lcd.print(" A ");
lcd.setCursor(0, 1);
lcd.print(watts, 2 );
lcd.setCursor(7, 1);
lcd.print(" W ");
lcd.setCursor(11, 1);
lcd.print(time/3600);
lcd.setCursor(16, 1);
lcd.print(" H ");
lcd.setCursor(0, 2);
lcd.print(ampHours, 2);
lcd.print(" Ah ");
lcd.setCursor(11, 2);
lcd.print(wattHours, 2);
lcd.print(" Wh ");
lcd.setCursor(0, 3);
lcd.print("Ch/Dsc: ");
lcd.print(totalCharge, 0);
lcd.print("mA");
// lcd.print(avgBVal);
// wait 10 milliseconds before the next loop
// for the analog-to-digital converter to settle
// after the last reading:
delay(10);
}
//END of void loop ()
I have some plans to develop even further this project... I think is suitable for a smart monitor for my holiday house...
73 de Adrian