How To Make An Arduino Based Energy Meter



I am supported by our readers and may earn a commission if you buy through our Affiliate Links at no cost to you. Thank you so much for your support. Read More

This is a fun project that I have wanted to build for a long time.  It’s  highly customizable energy meter that can measure:

      1. Voltage
      2. Watts
      3. Energy in aH or wH (example shows aH)

I intend to use mine to monitor the total energy consumpution of my telescope when I shoot all night long.  I have calculated this but cannot tell precisely how much energy is being consumed.  It’s important because I need to have enough storage capacity to go all night without external power.

Parts Required:


Arduino Nano (or similar)

AC712 Sensor and a precision  voltage sensor.  Kit to the right has both.

 

SH1106 OLED Dispaly

The video below shows step by step how to build the meter.  I noticed a bug in the code after I published the video.  In the video I had an elapsed time of 2 seconds, but I accidentally had 3 seconds of processing time.  Instead of hard coding the time in the loop – I changed the code to use the millis() function to measure the total time elapsed during the measurement phase.  This is a lot better and now the energy measurements will be accurate.

The millis() function in Arduino returns the time elapsed since the program started.  I used this to count how long in seconds had passed for each loop.

Energy is measured in watt (or amps) times time.  This will return either wH, kwH, or aH.  I chose aH since the math is easy and if you know your battery size such as 20 aH, it’s easy to see how much capacity you have left.

/**
 * My Engineering Projects - Current, power, and energy meter
 * current meter - Ac712
 * voltage meter - Voltage Sensor Module DC0-25V
 * connect current sensor to A0
 * connect battery voltage sensor to A1 
 */

#include 
#include 
#include 
#include 

#define i2c_Address 0x3c //initialize with the I2C addr 0x3C Typically eBay OLED's
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET -1   //   QT-PY / XIAO
Adafruit_SH1106G display = Adafruit_SH1106G(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

//const double scale_factor = 0.185; // 5A 185 mv/A
const double scale_factor = 0.1; // 20A 100 mv/A
//const double scale_factor = 0.066; // 30A 66 mv/A

double current_sensor_voltage = 0.00;
double current = 0;
double power = 0;
float energy = 0;
float twosec_energy = 0;
double zero_point = 2.5;
float current_sensor_value = 0;
int cycle_count = 1000;
float elapsed_time = 0;

//voltage divider
float battery_sensor_value = 0;
float battery_sendor_voltage = 0;
float battery_voltage = 0;
float R1 = 30000.0; 
float R2 = 7500.0;


void setup()   {

  Serial.begin(9600);
  delay(250); // wait for the OLED to power up
  display.begin(i2c_Address, true); // Address 0x3C default
  display.setContrast (0); // dim display
   // Clear the buffer.
  display.clearDisplay();
  //analogReference(INTERNAL); //Read from 0 to 1.1 V so we can measure millivolts
  analogReference(DEFAULT); // No need for this line if Default
   
}

void loop() {
  display.setTextSize(1); //options are 1, 2, or 3
  display.setTextColor(SH110X_WHITE);
  display.setCursor(0, 0);
  display.clearDisplay(); //must clear so displayed values can change from previous loop

  long current_milli = millis(); //need an accurate time elapsed value so energy can be calculated
  // Loop many times for better precison
  for(int i = 0; i < cycle_count; i++) {

    //Current
    current_sensor_value = analogRead(A0);
    current_sensor_voltage = (current_sensor_voltage + (current_sensor_value*5/1024 ) );

    //Voltage
    battery_sensor_value = analogRead(A1);
    battery_sendor_voltage = (battery_sensor_value * 5.0) / 1024.0; 
    battery_voltage = battery_sendor_voltage / (R2/(R1+R2)) + battery_voltage;
    delay(1); //1 milli second delay - total time is 1 second
  }

  delay(1000); //wait full 1 second

  // Calculate sensor voltage by dividing by cycle count
  current_sensor_voltage = current_sensor_voltage / cycle_count;
  battery_voltage = battery_voltage / cycle_count;
  
  // Convert current sensor voltage into Current using Scale Factor, any value above 2.5 is positive, below 2.5 is negative.  if at 2.5 current is zero
  current = (current_sensor_voltage - zero_point)/ scale_factor;     
  power = battery_voltage * current;

  //measure the elapsed time since loop started
  long now = millis();
  elapsed_time = (now - current_milli) / 1000; //outputs in seconds, should be 2
  
  twosec_energy = current * elapsed_time / 3600; // 3600 s per hour
  energy = twosec_energy + energy;  //show in aH

  // show results
  display.print ("Voltage:   "); display.print(battery_voltage); display.println(" V");
  display.print ("Current:   "); display.print(current); display.println(" A"); 
  display.print ("Power:     "); display.print(power); display.println(" W");
  display.print ("Energy:    "); display.print(energy); display.println(" aH");
  //display.print ("Elapsed Time:"); display.print(elapsed_time); display.println(" s"); //for debugging, shows elapsed time in seconds per loop (i.e. 2)
  display.display();
  //display.clearDisplay();  //don't clear the display here, clear it on start of loop

}

2 thoughts on “How To Make An Arduino Based Energy Meter”

Leave a Reply

Your email address will not be published. Required fields are marked *