Power Meter Monitor
A recent problem with the air conditioned inspired me to monitor the power usage in my house. The problem is rather simple, count infrared pulsed coming out of the utility power meter. Each time a kilowatt of power is consumed, the power meter emits a 10ms infrared pulse.
This problem has been solved in a variety of ways already. My approach using the mbed board has the following advantages:
- mbed connects to router directly via ethernet port and gets IP using DHCP.
- mbed interfaces directly to pachube.com for data collection and graphing (no need to have computers in-house to collect data).
- Cost is lower that arduino + ethernet shield.
Here is the result:
The hardware is trivial. Connect an ethernet socket to the mbed board. Connect a Radio Shack IR photodiode to pin 30 via 1K pull-up resistor to 3.3v. Using a 12V supply into the Vin pin.
The software is simple as well:
#include "mbed.h" #include "EthernetNetIf.h" #include "HTTPClient.h" extern "C" void mbed_reset(); DigitalOut led1(LED1); DigitalOut led2(LED2); DigitalOut led3(LED3); InterruptIn pulse(p30); static volatile long count = 0; Timer timer; Ticker ticker; Ethernet link; EthernetNetIf eth; void read_pulses(); void post_update(int value); void count_pulse(); void check_link(); #define USE_ETH 1 // **************************************************** // Watchdog timer // **************************************************** class Watchdog { public: // Load timeout value in watchdog timer and enable void kick(float s) { LPC_WDT->WDCLKSEL = 0x1; // Set CLK src to PCLK uint32_t clk = SystemCoreClock / 16; // WD has a fixed /4 prescaler, PCLK default is /4 LPC_WDT->WDTC = s * (float)clk; LPC_WDT->WDMOD = 0x3; // Enabled and Reset kick(); } // "kick" or "feed" the dog - reset the watchdog timer // by writing this required bit pattern void kick() { LPC_WDT->WDFEED = 0xAA; LPC_WDT->WDFEED = 0x55; } }; // Setup the watchdog timer Watchdog wdt; // **************************************************** // // **************************************************** int main() { // // Load the watchdog to expire in 10 sec // wdt.kick(15); // // Start the program // #ifdef USE_ETH printf("main: setting up eth...\r\n"); EthernetErr ethErr = eth.setup(); printf("\r\n"); if(ethErr) { printf("main: eth %d in setup.\r\n", ethErr); while(1); } #endif // // Schedule the reading and update of counter // wdt.kick(10); timer.start(); ticker.attach(&read_pulses, 60); pulse.rise(&count_pulse); // // Listen indefinitely // printf("main: staritng idle loop\r\n"); while(true) { #ifdef USE_ETH Net::poll(); #endif wdt.kick(); wait(1); led1 = !led1; } } // **************************************************** // // // // **************************************************** void read_pulses() { static int already_reading = 0; printf("read_pulses: at %f\r\n", timer.read()); if (already_reading) { printf("read_pulses: reading already in progress\r\n"); mbed_reset(); return; } already_reading = 1; led2 = 1; int pulse_count = count; count -= pulse_count; printf("read_pulses: found %d pulses\r\n", pulse_count); post_update(pulse_count); led2 = 0; already_reading = 0; } // **************************************************** // // Send data over to patchub // // **************************************************** void post_update(int value) { #ifdef USE_ETH if (!link.link()) { printf("read_pulses: lost ethernet connection\r\n"); mbed_reset(); } // copy API key from settings const string apiKey = "xxxxxxxxxxxxxxx"; // use feed ID const string feedID = "nnnnn"; // Create a value char value_str[100]; sprintf(value_str, "%d", value); string data(value_str); // for authentication, API key is set in client header HTTPClient client; client.setRequestHeader("X-PachubeApiKey", apiKey); // text object holds data to be posted HTTPText csvContent("text/csv"); csvContent.set(data); // uri for post includes feed ID and datastream ID string uri = "http://api.pachube.com/v1/feeds/" + feedID + ".csv?_method=put"; // result should be 0 and response should be 200 for successful post HTTPResult result = client.post(uri.c_str(), csvContent, NULL); int response = client.getHTTPResponseCode(); if (response != 200) { printf("post_update: error in responce %d\r\n", response); mbed_reset(); } #endif } // **************************************************** // // Interrupt which counts pulses // // **************************************************** void count_pulse() { led3 = !led3; count++; }
Here is how the project looks right now:
and a close up of the weatherproof case:
Please log in to post comments.