====== 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\n

401 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 } }