Jim Thomas / Mbed 2 deprecated MCBBThermostat

Dependencies:   NetServices mbed AvailableMemory

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /*
00002     Copyright (c) 2011 Jim Thomas, jt@missioncognition.net
00003  
00004     Permission is hereby granted, free of charge, to any person obtaining a copy
00005     of this software and associated documentation files (the "Software"), to deal
00006     in the Software without restriction, including without limitation the rights
00007     to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00008     copies of the Software, and to permit persons to whom the Software is
00009     furnished to do so, subject to the following conditions:
00010  
00011     The above copyright notice and this permission notice shall be included in
00012     all copies or substantial portions of the Software.
00013  
00014     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00015     IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00016     FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00017     AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00018     LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00019     OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00020     THE SOFTWARE.
00021 */
00022 
00023 #include "mbed.h"
00024 #include "SDHCFileSystem.h"
00025 #include "EthernetNetIf.h"
00026 #include "HTTPClient.h"
00027 #include "NTPClient.h"
00028 #include "HTTPServer.h"
00029 #include "RPCFunction.h"
00030 #include "RPCVariable.h"
00031 #include "AvailableMemory.h"
00032 
00033 
00034 #define HOSTNAME "mbedSE"
00035 #define PORT 80
00036 
00037 // Setup the SD card file system on the /sd path
00038 SDFileSystem sd(p5, p6, p7, p8, "sd");
00039 
00040 EthernetNetIf eth(HOSTNAME);
00041 HTTPClient http;
00042 NTPClient ntp;
00043 HTTPServer svr;
00044 
00045 // Setup an analog input
00046 AnalogIn rawtemp(p15, "temp"); // "AIN1"
00047 
00048 // Setup Relay outputs
00049 DigitalOut relay1(p26, "relay1"); // "PWM1"
00050 DigitalOut relay2(p25, "relay2"); // "PWM2"
00051 
00052 // Setup some variables for a thermostat (degress F)
00053 float stat_heat_setpoint = 68.0;
00054 float stat_hysteresis = 1.0;
00055 float stat_cool_setpoint = 74.0;
00056 float stat_current_temp = 0.0; // Will be updated from the temp sensor reading
00057 
00058 // Make the variables RPC accessible individually
00059 RPCVariable<float> rpc_stat_heat_setpoint(&stat_heat_setpoint, "stat_heat_setpoint");
00060 RPCVariable<float> rpc_stat_hysteresis(&stat_hysteresis, "stat_hysteresis");
00061 RPCVariable<float> rpc_stat_cool_setpoint(&stat_cool_setpoint, "stat_cool_setpoint");
00062 RPCVariable<float> rpc_stat_current_temp(&stat_current_temp, "stat_current_temp");
00063 
00064 // Make the whole state readable all at once as a JSON dict
00065 void DoGetThermostat(char * input, char* output);
00066 RPCFunction GetThermostat(&DoGetThermostat, "GetThermostat");
00067 
00068 void DoGetThermostat(char * input, char* output) {
00069     // Input is ignored
00070     printf("Thermostat: %0.1f %0.1f %0.1f %0.1f\n", stat_heat_setpoint, stat_hysteresis, stat_cool_setpoint, stat_current_temp);
00071     printf("Relays: %d %d\n", relay1.read(), relay2.read());
00072 
00073     sprintf(output, "{\"hs\":%0.1f,\"hy\":%0.1f,\"cs\":%0.1f,\"ct\":%0.1f,\"rh\":%d,\"rc\":%d}",
00074             stat_heat_setpoint, stat_hysteresis, stat_cool_setpoint, stat_current_temp,
00075             relay1.read(), relay2.read());
00076 }
00077 
00078 // Setup the status LED
00079 DigitalOut led1(LED1, "led1");
00080 
00081 int main() {
00082     float aval;
00083     float res;
00084     int counter = 0;
00085 
00086     EthernetErr ethErr;
00087     int count = 0;
00088     do {
00089         printf("Setting up %d...\n", ++count);
00090         ethErr = eth.setup();
00091         if (ethErr) printf("Timeout\n", ethErr);
00092     } while (ethErr != ETH_OK);
00093 
00094     printf("Connected OK\n");
00095     const char* hwAddr = eth.getHwAddr();
00096     printf("HW address : %02x:%02x:%02x:%02x:%02x:%02x\n",
00097            hwAddr[0], hwAddr[1], hwAddr[2],
00098            hwAddr[3], hwAddr[4], hwAddr[5]);
00099 
00100     IpAddr ethIp = eth.getIp();
00101     printf("IP address : %d.%d.%d.%d\n", ethIp[0], ethIp[1], ethIp[2], ethIp[3]);
00102     printf("Check router DHCP table for name : %s\n", eth.getHostname());
00103 
00104     time_t ctTime;
00105     ctTime = time(NULL);
00106     printf("\nCurrent time is (UTC): %d %s\n", ctTime, ctime(&ctTime));
00107     printf("NTP setTime...\n");
00108     Host server(IpAddr(), 123, "pool.ntp.org");
00109     printf("Result : %d\n", ntp.setTime(server));
00110 
00111     ctTime = time(NULL);
00112     printf("\nTime is now (UTC): %d %s\n", ctTime, ctime(&ctTime));
00113 
00114     char ip[16];
00115     sprintf(ip, "%d.%d.%d.%d", ethIp[0], ethIp[1], ethIp[2], ethIp[3]);
00116 
00117     FSHandler::mount("/sd/www", "/"); //Mount uSD www path on web root path
00118 
00119     svr.addHandler<RPCHandler>("/rpc");  // Enable RPC functionality under the /rpc path
00120     svr.addHandler<FSHandler>("/"); // Add the file handler at the root
00121 
00122     svr.bind(PORT);
00123     printf("Server listening (port %d)\n", PORT);
00124     printf("- LED1 flashes server heartbeat\n");
00125     printf("- URL for RPC commands: %s/rpc \n", ip);
00126 
00127     Timer tm;
00128     tm.start();
00129 
00130     while (true) {
00131         Net::poll();
00132         if (tm.read() > 0.5) {
00133             tm.start();
00134 
00135             if (counter % 128 == 0) printf("Available memory (exact bytes) : %d\n", AvailableMemory(1));
00136 
00137             // Keep a loop counter
00138             counter++;
00139 
00140             // Toggle the LED
00141             led1 = !led1;
00142 
00143             // Read our rawtemp sensor and convert to degrees F
00144             // ref http://www.seeedstudio.com/wiki/index.php?title=Project_Seven_-_rawtemp
00145             // ref http://www.seeedstudio.com/wiki/index.php?title=GROVE_-_Starter_Bundle_V1.0b#rawtemp_Sensor_Twig
00146             aval = rawtemp.read();
00147             res = (10000.0 / aval) - 10000.0; // Reference resistor is 10k ohm
00148             stat_current_temp = (1.0 / ((log(res / 10000.0) / 3975.0) + 1 / 298.15) - 273.15) * 9.0 / 5.0 + 32.0;
00149 
00150             // Make sure that the setpoints don't cross
00151             if (stat_cool_setpoint < stat_heat_setpoint + 2 * stat_hysteresis)
00152                 stat_cool_setpoint = stat_heat_setpoint + 2 * stat_hysteresis;
00153 
00154             // Update relays once every 8 loops (~ 4 seconds)
00155             // ref http://www.seeedstudio.com/wiki/index.php?title=Project_Five_%E2%80%93_Relay_Control
00156             if (counter % 8 == 0) {
00157                 printf("Thermostat: %0.1f %0.1f %0.1f %0.1f\n", stat_heat_setpoint, stat_hysteresis, stat_cool_setpoint, stat_current_temp);
00158 
00159                 if ((stat_current_temp < stat_heat_setpoint - stat_hysteresis) && !relay1) {
00160                     relay1 = 1;
00161                     printf("Turning Relay 1 On\n");
00162                 }
00163                 if ((stat_current_temp > stat_heat_setpoint + stat_hysteresis) && relay1) {
00164                     relay1 = 0;
00165                     printf("Turning Relay 1 Off\n");
00166                 }
00167                 if ((stat_current_temp < stat_cool_setpoint - stat_hysteresis) && relay2) {
00168                     relay2 = 0;
00169                     printf("Turning Relay 2 Off\n");
00170                 }
00171                 if ((stat_current_temp > stat_cool_setpoint + stat_hysteresis) && !relay2) {
00172                     relay2 = 1;
00173                     printf("Turning Relay 2 On\n");
00174                 }
00175             }
00176         }
00177     }
00178 }