Hackster is hosting Hackster Holidays, Ep. 6: Livestream & Giveaway Drawing. Watch previous episodes or stream live on Monday!Stream Hackster Holidays, Ep. 6 on Monday!
Sridhar Rajagopal
Published © GPL3+

How to Build an Arduino Energy Monitor and Data Logger

How I built an Arduino energy monitor and data logger to collect energy data for different loads and plotted that data using Excel.

IntermediateFull instructions provided28,329
How to Build an Arduino Energy Monitor and Data Logger

Things used in this project

Hardware components

Arduino UNO
Arduino UNO
×1
Enclosure for Dr. Wattson Energy Monitoring Board
×1
Adafruit MicroSD card breakout board+
×1
LED (generic)
LED (generic)
×1
Adafruit Tactile Button
×1
Resistor 221 ohm
Resistor 221 ohm
×1
Dr. Wattson Energy Monitoring Board V2
ProtoStax Dr. Wattson Energy Monitoring Board V2
×1

Software apps and online services

Arduino IDE
Arduino IDE

Story

Read more

Schematics

Arduino Energy Logger Circuit with Dr. Wattson

Code

Code snippet #1

Plain text
// see if the card is present and can be initialized:
  if (!SD.begin(CHIP_SELECT)) {
    Serial.println(F("Card failed, or not present"));
    // don't do anything more:
  }
   
  wattson.begin(); // Pass in the appropriate address. Defaults to 0x74

Code snippet #3

Plain text
#define BUTTON_PIN 4       //Connect a tactile button switch (or something similar)
                           //from Arduino pin 4 to ground.
                           
#define PULLUP true        //To keep things simple, we use the Arduino's internal pullup resistor.
#define INVERT true        //Since the pullup resistor will keep the pin high unless the
                           //switch is closed, this is negative logic, i.e. a high state
                           //means the button is NOT pressed. (Assuming a normally open switch.)
#define DEBOUNCE_MS 20     //A debounce time of 20 milliseconds usually works well for tactile button switches.Button myBtn(BUTTON_PIN, PULLUP, INVERT, DEBOUNCE_MS);    //Declare the button

Code snippet #4

Plain text
char filename[] = "DATA00.CSV";

setup() {   ...
   // create a new file
   for (uint8_t i = 0; i < 100; i++) {
      filename[4] = i/10 + '0';
      filename[5] = i%10 + '0';
      if (! SD.exists(filename)) {
         Serial.print(F("Data file is ")); Serial.println(filename);
         // only open a new file if it doesn't exist
         break;  // leave the loop! filename will now be the one we desire
      }
   }
...
}

Code snippet #5

Plain text
  myBtn.read();                    //Read the button
  if (myBtn.wasReleased()) {       //If the button was released, change the LED state
        readData = !readData;
        digitalWrite(LED, readData);
  }
  
  if (readData) {
     ... // read data and save to SD card, etc ....

Code snippet #7

Plain text
      // if the file is available, write to it:
      File dataFile = SD.open(filename, FILE_WRITE);      if (dataFile) {
        dataFile.print(currentMillis);
        dataFile.print(",");
        dataFile.print(data.currentRMS);
        dataFile.print(",");
        dataFile.print(data.activePower);
        dataFile.print(",");
        dataFile.print(data.reactivePower);
        dataFile.print(",");
        dataFile.println(data.apparentPower);       
  
        // print to the serial port too:
        dataFile.close();
      }  
      // if the file isn't open, pop up an error:
      else {
        Serial.print(F("error opening ")); Serial.println(filename);
      } 

Code snippet #11

Plain text
/*************************************************** 
  This is a example sketch for Upbeat Labs Dr. Wattson Energy Monitoring Breakout

The communication happens over I2C. 2 pins are required to interface. 
  There are 4 selectable I2C address possibilities per board (selectable
  via two solder jumpers (that select each pin to be high or low). Based 
  on this, there are 4 possible addresses:

I2C address  SJ1   SJ2
  0x74         LOW   LOW
  0x75         LOW   HIGH
  0x76         HIGH  LOW
  0x77         HIGH  HIGH

Dr. Wattson has two outputs, ZCD or Event, that are 
  used for notifications, and therefore will usually be 
  connected to an externally interruptable pin 
  (like pin2 or pin3 on Arduino Uno). In this example,
  ZCD and Event are not used.

Button is connected to pin 4.
  
  * SD card attached to SPI bus as follows:
  ** MOSI - pin 11
  ** MISO - pin 12
  ** CLK - pin 13
  ** CS - pin 10
  
  LED is connected to pin 9
   
  Written by Sridhar Rajagopal for Upbeat Labs LLC.
  BSD license. All text above must be included in any redistribution
 */
 
#include <Wire.h>
#include "MCP39F521.h"
#include <SD.h>
#include <Button.h>        //https://github.com/JChristensen/Button

#define BUTTON_PIN 4       //Connect a tactile button switch (or something similar)
                           //from Arduino pin 4 to ground.
                           
#define PULLUP true        //To keep things simple, we use the Arduino's internal pullup resistor.
#define INVERT true        //Since the pullup resistor will keep the pin high unless the
                           //switch is closed, this is negative logic, i.e. a high state
                           //means the button is NOT pressed. (Assuming a normally open switch.)
#define DEBOUNCE_MS 20     //A debounce time of 20 milliseconds usually works well for tactile button switches.

Button myBtn(BUTTON_PIN, PULLUP, INVERT, DEBOUNCE_MS);    //Declare the button

#define LED 9 // Connect an LED (via a 220ohm resistor) from pin 9 (anode) to GND (cathode).

#define CHIP_SELECT 10

MCP39F521 wattson = MCP39F521();

bool readData = false;

char filename[] = "DATA00.CSV";

void setup() {       
  Serial.begin(9600);  //turn on serial communication
  Serial.println(F("**Upbeat Labs Dr. Wattson Example Sketch**"));
  
  // initialize the digital pin as an output.
  pinMode(LED, OUTPUT);     
  pinMode(10, OUTPUT);
    
  // see if the card is present and can be initialized:
  if (!SD.begin(CHIP_SELECT)) {
    Serial.println(F("Card failed, or not present"));
    // don't do anything more:
  }
   
  wattson.begin(); // Pass in the appropriate address. Defaults to 0x74

// create a new file
  for (uint8_t i = 0; i < 100; i++) {
    filename[4] = i/10 + '0';
    filename[5] = i%10 + '0';
    if (! SD.exists(filename)) {
      Serial.print(F("Data file is ")); Serial.println(filename);
      // only open a new file if it doesn't exist
      break;  // leave the loop! filename will now be the one we desire
    }
  }
  
  Serial.println(F("**initialization complete.**"));
  
}

// This is what MCP39F521Data looks like, for reference!
//typedef struct MCP39F521Data {
//        uint16_t systemStatus;
//        uint16_t systemVersion;
//        uint16_t voltageRMS;
//        uint16_t lineFrequency;
//        uint16_t analogInputVoltage;
//        int16_t powerFactor;
//        uint32_t currentRMS;
//        uint32_t activePower;
//        uint32_t reactivePower;
//        uint32_t apparentPower;
//} MCP39F521Data;
 
void loop() {
  myBtn.read();                    //Read the button
  if (myBtn.wasReleased()) {       //If the button was released, change the LED state
        readData = !readData;
        digitalWrite(LED, readData);
  }
  
  if (readData) {
    MCP39F521Data data;
    int readMCPretval = wattson.readMCP39F521(&data, NULL);
    unsigned long currentMillis = millis();
    
    if (readMCPretval) {
      // Print stuff out
      Serial.write("\x1B" "c"); // Clear the screen on a regular terminal                               
      wattson.printMCP39F521Data(&data);
              
      // if the file is available, write to it:
      File dataFile = SD.open(filename, FILE_WRITE);if (dataFile) {
        dataFile.print(currentMillis);
        dataFile.print(",");
        dataFile.print(data.currentRMS);
        dataFile.print(",");
        dataFile.print(data.activePower);
        dataFile.print(",");
        dataFile.print(data.reactivePower);
        dataFile.print(",");
        dataFile.println(data.apparentPower);       
  
        // print to the serial port too:
        dataFile.close();
      }  
      // if the file isn't open, pop up an error:
      else {
        Serial.print(F("error opening ")); Serial.println(filename);
      } 
      
    } else {
     Serial.println(F("Error!")); 
    }
  }
}

Github

https://github.com/JChristensen/Button

Upbeat Labs Dr. Wattson Energy Monitoring Board Library

Libraries for use with Dr. Wattson Energy Monitoring Board Dr. Wattson is an Energy Monitoring Breakout Board for Arduino, Raspberry Pi and other Maker-Friendly Microcontrollers. Easily integrate quality AC energy measurements into your next project! Based on the MCP39F521, a single-phase power monitoring chip from Microchip, the board is designed to be tolerant of a wide range of voltages, which means that it can also be used with the Raspberry Pi or any other 3.3v MCUs just as easily. The unit comes pre-calibrated (enabling measurements from 1mA up to 4A) to enable you to start taking quality measurements on the get-go with just a couple of simple commands. You don't need any additional CT or other components. If you are a more advanced user, you have a wide range of functionality available from the rich library, as well as the ability to tweak the hardware to suit your needs and recalibrate using the library.

Credits

Sridhar Rajagopal

Sridhar Rajagopal

19 projects • 58 followers
Entrepreneur. Software Engineer. Maker. Tinkerer. Internet-of-things addict.

Comments