====== Home monitor ======
~~META:description abstract=Set of uC powered devices to monitor the house~~
{{tag>microcontroller sensor web http power}}
Set of uC powered devices to monitor the house, including :
* Electrical power consumption
* Water consumption
* Temperature (inside/outside)
All compatible with collected datalogger.
===== Features =====
* Electrical power measurement (main, heaters, water heater, server, box freezer, box main ...)
* Water consumption sensor
* Inside and outside temperature monitor
===== Environment =====
The devices are to operate inside the home network, over TCP/IP protocol, HTTP was chosen for its easier debugging as well as its versatility.
The datalogger server is to fetch the data by itself, eg the sensors just have to implement a web server.
The sensors will expose data as plain ascii text.
===== Sensing =====
==== Power ====
Measuring power deals with measuring current as well as peak voltage (always a sine wave).
In the following subsections we are dealing with home-made CTs.
=== Current Transformers (CTs) ===
{{current_sense_article.pdf|Document on Current Transformers}}
== Things to care when dealing with Current Transformers ==
* No open-loop use
* The higher the turns the higher the quality
* Same goes with the impedance
* One should care not to saturate the core, keep a 30% current handling margin
== Formulaes ==
Excitation current : delim{|}{dI/dt}{|} = e / L, e is the output voltage (V), L is the inductance (H) and the result is in A/s
This current should be at the very most equal to a 10th of the minimum sample current.
Measured voltage : V_eff = R * I_eff / n, R is the burden resistor (Ω), Ieff is the primary current and the result is in V.
=== Fixed load ===
In this case we just need a way to know whether the monitored device is powered or not. Simple apparatus like CT + rectifier + smoother + detector may be used.
=== Resistive load ===
In this case we are interested in the peak value of the current. CT + rectifier + well designed smoother will do.
=== Unpredictable load ===
Most complicate case since we need to get the RMS value of the current. CT + ADE7755 + constant voltage feed seems to be a good solution.
=== Main supply ===
The main panel streams data about consumption by itself, only a few components are needed to get the data.
==== Water ====
The water meter emits data on a regular basis using an open-source protocol, we just need a compatible receiver and the according spec.
==== Temperature ====
Most simple data to gather, the only concern should be the sturdiness of the outdoor sensor.
===== Rendering =====
Data exposure is done using the TCP/IP/HTTP stack from [[http://tuxgraphics.org|tuxgraphics]], latest version is available [[http://tuxgraphics.org/electronics/200905/embedded-tcp-ip-stack.shtml|here]].
The device can be asked for individual **named** values or for a pipe separated list of all available **named** values.
Code should be as reusable as possible.
Example (WIP) :
#include
#include
#include
#include "ip_arp_udp_tcp.h"
#include "enc28j60.h"
#include "timeout.h"
#include "avr_compat.h"
#include "net.h"
//static uint8_t mymac[6] = {0x54, 0x55, 0x58, 0x10, 0x00, 0x24};
// mac[4] = 0x01 : YHome device
// mac[5] = device id
static uint8_t mymac[6] = {0x40, 0x00, 0x00, 0x00, 0x01, 0x01}; // 0x01 : EDF, 0x02 : Box, 0x03 : Tmp
static uint8_t myip[4] = {192, 168, 0, 201}; // 201 : EDF, 202 : Box, 203 : Tmp ...
#define MYWWWPORT 80
#define BUFFER_SIZE 550
static uint8_t buf[BUFFER_SIZE+1];
#define N_MES 4
typedef struct {
uint16_t ips; // count per sec
uint16_t msp; // 100us per imp
uint16_t cnt; // 100us counter
} Tmeasure;
volatile Tmeasure measure[N_MES];
volatile float sensorips[N_MES] = {139.123, 139.123, 139.123, 139.123};
volatile uint16_t tcnt = 0;
volatile uint8_t fetch = 0;
volatile float I[N_MES];
SIGNAL(##INT) {
uint8_t ch = ##get_ch();
measure[ch].ips++;
measure[ch].msp = measure[ch].cnt;
measure[ch].cnt = 0;
}
SIGNAL(TIMER0_COMPARE_A) { // Setup with compare
TCNT0 = 0x00;
uint8_t i;
for(i=0; i measure[i].msp) {
I[i] = measure[i].ips / sensorips[i];
}else{
I[i] = 10000 / (sensorips[i] * measure[i].msp);
}
fetch = 0;
}
plen = packetloop_icmp_tcp(buf, enc28j60PacketReceive(BUFFER_SIZE, buf));
if(plen == 0) continue;
if(strncmp("GET ", (char *)&(buf[plen]), 4) != 0) { // head, post and other methods
plen = fill_tcp_data_p(buf, 0, PSTR("HTTP/1.0 401 Unauthorized\r\nContent-Type: text/html\r\n\r\n401 Unauthorized
"));
}else if(strncmp("/ ", (char *)&(buf[plen+4]), 2) == 0) { // catch all
plen = fill_tcp_data_p(buf, 0, PSTR("HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\nPragma: no-cache\r\n\r\n"));
for(i=0; i= 0x30) && (&(buf[plen+5]) <= 0x39)) { // specific sensor
i = &(buf[dat_p+5]) - 0x30;
plen = fill_tcp_data_p(buf, 0, PSTR("HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\nPragma: no-cache\r\n\r\n"));
if(i401 Unauthorized"));
}
www_server_reply(buf, plen); // send web page data
}
}