Web enabled thermostat demo using the Mission Cognition baseboard.
Dependencies: NetServices mbed AvailableMemory
Diff: main.cpp
- Revision:
- 0:2e82bfc9dc19
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Mon Oct 03 21:45:56 2011 +0000 @@ -0,0 +1,178 @@ +/* + Copyright (c) 2011 Jim Thomas, jt@missioncognition.net + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +#include "mbed.h" +#include "SDHCFileSystem.h" +#include "EthernetNetIf.h" +#include "HTTPClient.h" +#include "NTPClient.h" +#include "HTTPServer.h" +#include "RPCFunction.h" +#include "RPCVariable.h" +#include "AvailableMemory.h" + + +#define HOSTNAME "mbedSE" +#define PORT 80 + +// Setup the SD card file system on the /sd path +SDFileSystem sd(p5, p6, p7, p8, "sd"); + +EthernetNetIf eth(HOSTNAME); +HTTPClient http; +NTPClient ntp; +HTTPServer svr; + +// Setup an analog input +AnalogIn rawtemp(p15, "temp"); // "AIN1" + +// Setup Relay outputs +DigitalOut relay1(p26, "relay1"); // "PWM1" +DigitalOut relay2(p25, "relay2"); // "PWM2" + +// Setup some variables for a thermostat (degress F) +float stat_heat_setpoint = 68.0; +float stat_hysteresis = 1.0; +float stat_cool_setpoint = 74.0; +float stat_current_temp = 0.0; // Will be updated from the temp sensor reading + +// Make the variables RPC accessible individually +RPCVariable<float> rpc_stat_heat_setpoint(&stat_heat_setpoint, "stat_heat_setpoint"); +RPCVariable<float> rpc_stat_hysteresis(&stat_hysteresis, "stat_hysteresis"); +RPCVariable<float> rpc_stat_cool_setpoint(&stat_cool_setpoint, "stat_cool_setpoint"); +RPCVariable<float> rpc_stat_current_temp(&stat_current_temp, "stat_current_temp"); + +// Make the whole state readable all at once as a JSON dict +void DoGetThermostat(char * input, char* output); +RPCFunction GetThermostat(&DoGetThermostat, "GetThermostat"); + +void DoGetThermostat(char * input, char* output) { + // Input is ignored + printf("Thermostat: %0.1f %0.1f %0.1f %0.1f\n", stat_heat_setpoint, stat_hysteresis, stat_cool_setpoint, stat_current_temp); + printf("Relays: %d %d\n", relay1.read(), relay2.read()); + + sprintf(output, "{\"hs\":%0.1f,\"hy\":%0.1f,\"cs\":%0.1f,\"ct\":%0.1f,\"rh\":%d,\"rc\":%d}", + stat_heat_setpoint, stat_hysteresis, stat_cool_setpoint, stat_current_temp, + relay1.read(), relay2.read()); +} + +// Setup the status LED +DigitalOut led1(LED1, "led1"); + +int main() { + float aval; + float res; + int counter = 0; + + EthernetErr ethErr; + int count = 0; + do { + printf("Setting up %d...\n", ++count); + ethErr = eth.setup(); + if (ethErr) printf("Timeout\n", ethErr); + } while (ethErr != ETH_OK); + + printf("Connected OK\n"); + const char* hwAddr = eth.getHwAddr(); + printf("HW address : %02x:%02x:%02x:%02x:%02x:%02x\n", + hwAddr[0], hwAddr[1], hwAddr[2], + hwAddr[3], hwAddr[4], hwAddr[5]); + + IpAddr ethIp = eth.getIp(); + printf("IP address : %d.%d.%d.%d\n", ethIp[0], ethIp[1], ethIp[2], ethIp[3]); + printf("Check router DHCP table for name : %s\n", eth.getHostname()); + + time_t ctTime; + ctTime = time(NULL); + printf("\nCurrent time is (UTC): %d %s\n", ctTime, ctime(&ctTime)); + printf("NTP setTime...\n"); + Host server(IpAddr(), 123, "pool.ntp.org"); + printf("Result : %d\n", ntp.setTime(server)); + + ctTime = time(NULL); + printf("\nTime is now (UTC): %d %s\n", ctTime, ctime(&ctTime)); + + char ip[16]; + sprintf(ip, "%d.%d.%d.%d", ethIp[0], ethIp[1], ethIp[2], ethIp[3]); + + FSHandler::mount("/sd/www", "/"); //Mount uSD www path on web root path + + svr.addHandler<RPCHandler>("/rpc"); // Enable RPC functionality under the /rpc path + svr.addHandler<FSHandler>("/"); // Add the file handler at the root + + svr.bind(PORT); + printf("Server listening (port %d)\n", PORT); + printf("- LED1 flashes server heartbeat\n"); + printf("- URL for RPC commands: %s/rpc \n", ip); + + Timer tm; + tm.start(); + + while (true) { + Net::poll(); + if (tm.read() > 0.5) { + tm.start(); + + if (counter % 128 == 0) printf("Available memory (exact bytes) : %d\n", AvailableMemory(1)); + + // Keep a loop counter + counter++; + + // Toggle the LED + led1 = !led1; + + // Read our rawtemp sensor and convert to degrees F + // ref http://www.seeedstudio.com/wiki/index.php?title=Project_Seven_-_rawtemp + // ref http://www.seeedstudio.com/wiki/index.php?title=GROVE_-_Starter_Bundle_V1.0b#rawtemp_Sensor_Twig + aval = rawtemp.read(); + res = (10000.0 / aval) - 10000.0; // Reference resistor is 10k ohm + stat_current_temp = (1.0 / ((log(res / 10000.0) / 3975.0) + 1 / 298.15) - 273.15) * 9.0 / 5.0 + 32.0; + + // Make sure that the setpoints don't cross + if (stat_cool_setpoint < stat_heat_setpoint + 2 * stat_hysteresis) + stat_cool_setpoint = stat_heat_setpoint + 2 * stat_hysteresis; + + // Update relays once every 8 loops (~ 4 seconds) + // ref http://www.seeedstudio.com/wiki/index.php?title=Project_Five_%E2%80%93_Relay_Control + if (counter % 8 == 0) { + printf("Thermostat: %0.1f %0.1f %0.1f %0.1f\n", stat_heat_setpoint, stat_hysteresis, stat_cool_setpoint, stat_current_temp); + + if ((stat_current_temp < stat_heat_setpoint - stat_hysteresis) && !relay1) { + relay1 = 1; + printf("Turning Relay 1 On\n"); + } + if ((stat_current_temp > stat_heat_setpoint + stat_hysteresis) && relay1) { + relay1 = 0; + printf("Turning Relay 1 Off\n"); + } + if ((stat_current_temp < stat_cool_setpoint - stat_hysteresis) && relay2) { + relay2 = 0; + printf("Turning Relay 2 Off\n"); + } + if ((stat_current_temp > stat_cool_setpoint + stat_hysteresis) && !relay2) { + relay2 = 1; + printf("Turning Relay 2 On\n"); + } + } + } + } +} \ No newline at end of file