How nice would it be, if you could view your home's energy use online. More and more households can be equipped with so-called smart energy meters. Those that are not so fortunate, may read on.
I will describe my attempt to use an Arduino UNO in a DIY project to measure my own home's energy use. I will start with measuring electricity. My home has a Ferraris meter installed. This meter had a rotating disc, which is silver colored. It's edge is interupted by a black stripe of about 1 cm. The C-value is 600, which means that 600 rotations equal 1 kWh.
The ultimate goal is to view my home's energy use online. But it will take some steps to get there. The first prototype measures each disc rotation and logs a timestamp to a SD Card. Each disc rotation is followed by blinking the LED.
Prototype
For my prototype I used the following components (the numbers correspond with the diagram below):
(1) Arduino Uno
(2) and (3) SD Card reader from LC Studio (and 3x2.2k Ohm and 1x1.0k Ohm and 2x3.3k Ohm resistors and a SD Card (1GB)
(4) LED and 270 Ohm resistor
(5) IR LED (and 1x100 Ohm resistor)
(6) IR photodiode (BP104) (and 2x47k Ohm resistor and 1xBC548 transistor)
and some cables and some pieces of experiment board
This is my diagram connecting everything together:
Sensor
At first I tried to use a CNY70 as a sensor to detect the black spoton the disc. But from the measurements from the CNY70 I could not derive a peak to discern an actual rotation. Also I had difficulty with daylight which interfered with the measuring. The alternative was to use a separate IR LED and IR photodiode. I chose for IR photodiode the BP104. The BP104 filters out the daylight. I placed both in front of the disc as you can see in the following picture. Left is the IR LED and right is the IR photodiode. When the black spot is in front of the IR photodiode less infrared light is reflected.
First I use a small program called Sensor01 which displays the sensor input:
/*
Home energy sensor
*/
int sensorPin = A0; // Analog input pin
int sensorValue = 0; // variable to store the value coming from the sensor
void setup() {
Serial.begin(9600);
}
void loop() {
// read the value from the sensor:
sensorValue = analogRead(sensorPin);
Serial.println(sensorValue);
delay(200);
}
I use this program and a photo camera (a photo camera shows infrared on the display) to make sure the sensor is correctly aligned with the disc. The values also give a sense of the range within which the sensor detects infrared.SD Card
Second is the SD Card reader. In this first prototype the SD Card is used to log every timestamp (millis) for each rotation. From the multiple ways to connect the SD Card reader from LC Studio, I used the following schedule with 6 resistors (of which I used slightly different values, because I replaced the 2x1.8k Ohm with 2x2.2k Ohm).
HomeEnergy program
Now all hardware is in place, the software can be uploaded. This is what I wrote.
/*
Home Energy Use
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see www.gnu.org.
Author: Dick Bos
Company: DayDreamz.nl software
Date: 21 april 2013
*/
// include the SD library:
#include <SD.h>
int led = 2; // Signalling LED pin
File myFile;
// Number of calibrations
const int numCalibration = 1600;
// Variables
int readValue = 0;
int minValue = 1024;
int maxValue = 0;
boolean sdcard = false;
int delta = 25;
int inputPin = A0;
unsigned long time;
int golow = 0;
int numLows = 9;
// State High = true Low = false
boolean state = false;
void setup()
{
// initialize serial communication with computer:
Serial.begin(9600);
Serial.print("Initializing SD card...");
// On the Ethernet Shield, CS is pin 4. It's set as an output by default.
// Note that even if it's not used as the CS pin, the hardware SS pin
// (10 on most Arduino boards, 53 on the Mega) must be left as an output
// or the SD library functions will not work.
pinMode(SS, OUTPUT);
pinMode(led, OUTPUT);
if (!SD.begin(10)) {
Serial.println("initialization failed!");
// Blink signalling LED to show
int x=0;
while ( x < 10)
{
x++;
digitalWrite(led, HIGH);
delay (500);
digitalWrite(led, LOW);
delay (500);
}
} else
{
Serial.println("initialization done.");
sdcard=true;
// find min and max values
for (int i = 0; i < numCalibration; i++)
{
readValue = analogRead(inputPin);
if (i > 10)
{
if (readValue < minValue)
{
minValue=readValue;
Serial.print("New Min: ");
Serial.println(minValue);
digitalWrite(led, HIGH);
} else
digitalWrite(led, LOW);
if (readValue > maxValue)
{
maxValue=readValue;
Serial.print("New Max: ");
Serial.println(maxValue);
digitalWrite(led, HIGH);
} else
digitalWrite(led, LOW);
}
delay(10);
}
Serial.print("Min Value: ");
Serial.print(minValue);
Serial.print(" Max Value: ");
Serial.print(maxValue);
}
}
void loop() {
if (sdcard)
{
readValue = analogRead(inputPin);
if ((readValue >= ( maxValue - delta )))
{
if (!state)
{
digitalWrite(led, HIGH);
golow = 0;
state=true;
myFile = SD.open("power.txt", FILE_WRITE);
// if the file opened okay, write to it:
if (myFile) {
Serial.print("Writing to power.txt...");
time = millis();
Serial.print(readValue);
Serial.print("...");
Serial.print(time);
myFile.println(time);
myFile.close(); // close the file
Serial.println("...done.");
}
}
} else
{
if (state)
{
// change state to low only after a number of successive low reads
golow++;
Serial.print("..");
Serial.print(golow);
if (golow > numLows)
{
digitalWrite(led, LOW);
state= false;
Serial.println("..done.");
}
}
}
delay(5);
}
}
In the setup the SD Card is initialized. If it fails the program will blink the LED and nothing will run. Then assuming the disc rotates once, the minimum and maximum values are detected and the setup is finished.
The loop is started with getting the sensor value with an analogRead. A delta is defined to determine the value range for the black spot against the maximum value. If the read value is the black spot that the state goes to high and the timestamp is written to the SD Card and the loop continues. The state will remain high as long as the same black spot is detected. If no black spot was detected the loop continues. The loop finishes with a small delay. The state will go from high to low only after a number of successive 'low reads', because sometimes, when the disc rotates really slow, a low is detected on the black spot.
Output
At this moment the result is one file (called power.txt). If I want I can disconnect the arduino and get the SD Card and copy the file to my laptop. I rename the file to the start time like this: 20130420_1000_POWER.txt. I wrote a small windows program to analyze the data and be able to export it to excel for a nice graph. The program looks like this.
I select the data file and enter the start datetime and the C-value (for me 600). On the left the timestamp is shown and the interval with the previous timestamp and the calculated value for Watts based on the rotation time. On the right I can select a reporting period and generate a report for the kWh usage. This data can be copied to excel and made into a graph like this.
It is a complete solution, but there are disadvantages in using this. So the next step will be to add an Aduino Ethernet shield (W5100) and to be able to look at the data online.


