Electricity Usage Monitor
We all know that excessive power use is costly - both in terms of the adverse effect on the environment and also the high prices that we pay for our utility bills. It is quite awkward to keep looking at the electricity meter, usually tucked away in a dark cupboard, to find out how much power has been used. Also, it is hard to be disciplined and write down the dates/times of readings taken and convert this to cash spent.
So it seemed a good idea to have the Cybiko help keep tabs on how much electricity is being used in my home. Fortunately, my electricity meter has a small light on the front. This flashes 800 times for every kWh of power consumed.
The idea is to have a small external circuit count the pulses of light from the LED.
Importantly, this can be done without any physical connection to the electricity meter itself. Whenever asked, the external circuit will pass the number of pulses counted, via RS232, to a Cybiko Classic. This Cybiko will then work out some stats regarding the power use. e.g. total count of kW hours shown on meter, current power 'burn rate' in kW hours, average power use for each hour in the last 24hrs, total cost of power used each day for the last week.
This info will then be sent, wirelessly, to another Cybiko, running RFTerm. This means that we now have a mobile unit that can be viewed easily. A neat feature would be the ability to specify a given power usage rate that, when exceeded, would sound an alarm on the RF Terminal Cybiko. This would be especially handy when living in a house where kids/partners leave lights/TVs/heaters switched on when not needed.
Ideally, the solution could also feed an internet connected PC. This would then allow publishing of the info to the internet. The MRTG software has the ability to generate this entire webpage. It can periodically call a user-supplied 'data gatherer' program. This simply returns one data sample value. The MRTG software then does all the work. Very cool.
Standalone meters can be purchased from from http://www.universalmeterservices.co.uk
A great way of adding MSN alerts to this system would be via the excellent X10Dispatcher program.
Sensor Hardware
Update at 14th Oct - tried a little pulse counter circuit using a TIL81 phototransistor and a resistor. This worked well when illuminated with a LED. However, when tested on an actual meter, it didn't catch the pulses of light. The light source in the meter is rather dimmer than a standard LED. A more sensitive circuit is needed…
Diagram (click image to zoom) | Description |
---|---|
Schematic for Pulse Counter. Incorporating the following sensor detector circuit http://offog.org/code/electricity.html |
|
PCB Layout |
Interesting Product
http://mashed08.backnetwork.com/feeds/post.aspx?postid=555
http://cumbers.wordpress.com/2008/05/07/breakdown-of-currentcost-xml-output/
AVR Firmware
Update at 28th Oct - now using an LDR … this works very nicely. Next thing is to hook up an AVR chip to do the counting of the pulses.
The PC executable will be called, periodically, from MRTG. When called, the .exe will send a '?' char to serialrelay. This will be routed to the AVR & will prompt the AVR to reply, via RS232, with the count of pulses received (string).
Idea, flash a LED on the AVR board to show that pulse detection is working.
Now, if SerialRelay was able to selectively route to a given Cybiko, we could also send some 'stats' to an RFTerm.
Update at 7th November - Brett knocked out some AVR code to count the pulses & send out the count over RS232 when a '?' character was received. Ran this up on an AVR 2313 development board. This runs very well. Tested using RFTerminal in 'direct RS232' mode. Great stuff. We are all but done. However, it would be nice to have a dedicated PCB for this project (see design above).
'******************************************************************** '* Pulse counter '* uP: AT90S2313 '* Language: BASCOM-AVR 1.11.7.9 '******************************************************************** $regfile = "2313def.dat" $crystal = 4000000 $baud = 9600 ' Configure these for the specific implementation. Config Pind.4 = INPUT , Pind.5 = OUTPUT Led ALIAS Pind.5 Sensor ALIAS Pind.4 ' serial Rx complete interrupt ON Urxc Readrs232 Enable Interrupts Enable Urxc DIM Count AS LONG Count = 0 ' Loop forever DO Bitwait Sensor , RESET ' wait until sensor is LOW RESET Led ' Turn the LED off Count = Count + 1 Bitwait Sensor , Set ' wait until Sensor is HIGH Set Led ' Turn the LED on. LOOP Readrs232: IF Udr = 63 THEN ' check for ? character PRINT Count Count = 0 END IF RETURN
PC Software
Here is a config file from MRTG. Note that MRTG is configured here to call an external .exe (getdata.exe) to gather the data to be plotted.
WorkDir: C:\mrtg RunAsDaemon: yes Target[hostAdisk]: `getdata.exe` Title[hostAdisk]: Electricity Usage at DK Home MaxBytes[hostAdisk]: 100000 PageTop[hostAdisk]: <H1>Power consumed</H1> Suppress[hostAdisk]: y LegendO[hostAdisk]: Stats Legend1[hostAdisk]: % used Legend2[hostAdisk]: YLegend[hostAdisk]: Watts ShortLegend[hostAdisk]: Electricity usage (W) Options[hostAdisk]: gauge, nopercent, noi
unit Unit1; { DK 13 Oct 2005 Designed to be called by MRTG The idea goes like this ... an AVR micro is running beside the electricity meter, counting pulses on the LED every 5 mins, MRTG calls this application. This app sends a '?' character to the serial port. This is serialrelayed to the cybiko connected to the AVR board. The AVR receives the '?' and responds with a string which holds the count of pulses since the last query. The count is then reset. This app receives the pulse count string and passes it back to MRTG. We probably want a timeout between sending the ? and waiting for a result back ... just in case we never get one. Code not finished yet! } interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, OoMisc, AdPort; type TForm1 = class(TForm) cp1: TApdComPort; procedure FormCreate(Sender: TObject); procedure cp1TriggerData(CP: TObject; TriggerHandle: Word); private { Private declarations } public { Public declarations } end; var Form1: TForm1; myVal : string; implementation {$R *.dfm} procedure TForm1.FormCreate(Sender: TObject); begin cp1.AddDataTrigger(':', True); cp1.PutChar('?'); //Send a '?' to the AVR sleep(100); allocConsole; writeln('0'); //in - not graphed (noi) writeln(myVal); //out - this is the data we want. writeln; //comment1 writeln; //comment2 freeConsole; Application.Terminate; end; procedure TForm1.cp1TriggerData(CP: TObject; TriggerHandle: Word); const LF: Char = chr(10); var ch : char; begin myVal := ''; repeat ch := cp1.GetChar; if ch <> LF then myVal := myVal + ch; until ch = LF; end; end.