Showing posts with label battery. Show all posts
Showing posts with label battery. Show all posts

01 January 2015

Arduino Energy-meter

A few days ago I was contemplating a little device from a hobby store. It was a smart power gauge meter for tracking the charge and discharge of a battery.
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

Most viewed posts in last 30 days