Monitor for central heating system (e.g. 2zones+hw) Supports up to 15 temp probes (DS18B20/DS18S20) 3 valve monitors Gas pulse meter recording Use stand-alone or with nodeEnergyServer See http://robdobson.com/2015/09/central-heating-monitor

Dependencies:   EthernetInterfacePlusHostname NTPClient Onewire RdWebServer SDFileSystem-RTOS mbed-rtos mbed-src

Committer:
Bobty
Date:
Sat Feb 21 19:00:08 2015 +0000
Revision:
8:5980547ae71c
Parent:
7:113c68639d10
Child:
9:0e103c2f869a
Working with thermometer test code

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Bobty 0:f6611c8f453c 1 #include "mbed.h"
Bobty 0:f6611c8f453c 2 #include "EthernetInterface.h"
Bobty 5:5bccf48799d4 3 #include "NTPClient.h"
Bobty 5:5bccf48799d4 4 #include "RdWebServer.h"
Bobty 5:5bccf48799d4 5 #include "GasUseCounter.h"
Bobty 8:5980547ae71c 6 #include "RdDS18B20.h"
Bobty 5:5bccf48799d4 7 #include <stdarg.h>
Bobty 5:5bccf48799d4 8
Bobty 5:5bccf48799d4 9 // Web and UDB ports
Bobty 5:5bccf48799d4 10 const int WEBPORT = 80; // Port for web server
Bobty 5:5bccf48799d4 11 const int BROADCAST_PORT = 42853; // Arbitrarily chosen port number
Bobty 5:5bccf48799d4 12
Bobty 5:5bccf48799d4 13 // Ticker collects data
Bobty 6:b7064d33e402 14 //Ticker ticker;
Bobty 6:b7064d33e402 15 //const int TICK_MS = 250;
Bobty 5:5bccf48799d4 16
Bobty 5:5bccf48799d4 17 // Debugging and status
Bobty 5:5bccf48799d4 18 RawSerial pc(USBTX, USBRX);
Bobty 5:5bccf48799d4 19 DigitalOut led1(LED1); //ticking (flashes)
Bobty 5:5bccf48799d4 20 DigitalOut led2(LED2); //server listning status (flashes)
Bobty 5:5bccf48799d4 21 DigitalOut led3(LED3); //socket connecting status
Bobty 5:5bccf48799d4 22 DigitalOut led4(LED4); //server status
Bobty 5:5bccf48799d4 23
Bobty 5:5bccf48799d4 24 // Web server
Bobty 5:5bccf48799d4 25 EthernetInterface eth;
Bobty 5:5bccf48799d4 26 NTPClient ntp;
Bobty 5:5bccf48799d4 27 UDPSocket sendUDPSocket;
Bobty 5:5bccf48799d4 28 Endpoint broadcastEndpoint;
Bobty 5:5bccf48799d4 29
Bobty 5:5bccf48799d4 30 // File system for SD card
Bobty 4:0d3a207680b0 31 SDFileSystem sd(p5, p6, p7, p8, "sd");
Bobty 5:5bccf48799d4 32
Bobty 5:5bccf48799d4 33 // Gas use counter
Bobty 5:5bccf48799d4 34 DigitalIn gasPulsePin(p21);
Bobty 5:5bccf48799d4 35 const char* gasPulseFileName = "/sd/curPulse.txt";
Bobty 5:5bccf48799d4 36 const char* logFilename = "/sd/log.txt";
Bobty 5:5bccf48799d4 37 GasUseCounter gasUseCounter(gasPulseFileName, gasPulsePin, pc);
Bobty 5:5bccf48799d4 38
Bobty 8:5980547ae71c 39 // Thermometers - DS18B20 OneWire Thermometer connections
Bobty 8:5980547ae71c 40 const PinName tempSensorPins[] = { p22 };
Bobty 8:5980547ae71c 41 const int NUM_THERM_BUSES = sizeof(tempSensorPins)/sizeof(int);
Bobty 8:5980547ae71c 42 DS18B20* thermometerBuses[NUM_THERM_BUSES];
Bobty 8:5980547ae71c 43
Bobty 5:5bccf48799d4 44 void LogData(const char* format, ...)
Bobty 5:5bccf48799d4 45 {
Bobty 5:5bccf48799d4 46 FILE* fp = fopen(logFilename, "a");
Bobty 5:5bccf48799d4 47 if (fp == NULL)
Bobty 5:5bccf48799d4 48 {
Bobty 5:5bccf48799d4 49 pc.printf ("Log ... Filename %s not found\r\n", logFilename);
Bobty 5:5bccf48799d4 50 }
Bobty 5:5bccf48799d4 51 else
Bobty 5:5bccf48799d4 52 {
Bobty 5:5bccf48799d4 53 va_list argptr;
Bobty 5:5bccf48799d4 54 va_start(argptr, format);
Bobty 5:5bccf48799d4 55 vfprintf(fp, format, argptr);
Bobty 5:5bccf48799d4 56 va_end(argptr);
Bobty 5:5bccf48799d4 57 fclose(fp);
Bobty 5:5bccf48799d4 58 }
Bobty 5:5bccf48799d4 59 }
Bobty 5:5bccf48799d4 60
Bobty 5:5bccf48799d4 61 void SendInfoBroadcast()
Bobty 5:5bccf48799d4 62 {
Bobty 5:5bccf48799d4 63 led3 = true;
Bobty 5:5bccf48799d4 64 // Init the sending socket
Bobty 5:5bccf48799d4 65 sendUDPSocket.init();
Bobty 5:5bccf48799d4 66 sendUDPSocket.set_broadcasting();
Bobty 5:5bccf48799d4 67 broadcastEndpoint.set_address("255.255.255.255", BROADCAST_PORT);
Bobty 5:5bccf48799d4 68
Bobty 5:5bccf48799d4 69 // Format message
Bobty 5:5bccf48799d4 70 char outBuf[200];
Bobty 5:5bccf48799d4 71 sprintf(outBuf, "{\"e\":[{\"n\":\"gasCount\",\"v\":%d},{\"n\":\"gasPulseRateMs\",\"v\":%d,\"u\":\"ms\"}]}",
Bobty 5:5bccf48799d4 72 gasUseCounter.GetCount(), gasUseCounter.GetPulseRateMs());
Bobty 5:5bccf48799d4 73
Bobty 5:5bccf48799d4 74 // Send
Bobty 5:5bccf48799d4 75 int bytesToSend = strlen(outBuf);
Bobty 5:5bccf48799d4 76 int rslt = sendUDPSocket.sendTo(broadcastEndpoint, outBuf, bytesToSend);
Bobty 5:5bccf48799d4 77 if (rslt == bytesToSend)
Bobty 5:5bccf48799d4 78 {
Bobty 5:5bccf48799d4 79 pc.printf("Broadcast Sent ok %s\n", outBuf);
Bobty 5:5bccf48799d4 80 }
Bobty 5:5bccf48799d4 81 else if (rslt == -1)
Bobty 5:5bccf48799d4 82 {
Bobty 5:5bccf48799d4 83 pc.printf("Broadcast Failed to send %s\n", outBuf);
Bobty 5:5bccf48799d4 84 }
Bobty 5:5bccf48799d4 85 else
Bobty 5:5bccf48799d4 86 {
Bobty 5:5bccf48799d4 87 pc.printf("Broadcast Didn't send all of %s\n", outBuf);
Bobty 5:5bccf48799d4 88 }
Bobty 5:5bccf48799d4 89
Bobty 5:5bccf48799d4 90 // Log
Bobty 5:5bccf48799d4 91 char timeBuf[32];
Bobty 5:5bccf48799d4 92 time_t seconds = time(NULL);
Bobty 5:5bccf48799d4 93 strftime(timeBuf, 32, "%Y-%m-%d %H:%M:%S", localtime(&seconds));
Bobty 5:5bccf48799d4 94 LogData("%s\t%d\t%d ms\n", timeBuf, gasUseCounter.GetCount(), gasUseCounter.GetPulseRateMs());
Bobty 5:5bccf48799d4 95
Bobty 5:5bccf48799d4 96 led3 = false;
Bobty 5:5bccf48799d4 97 }
Bobty 0:f6611c8f453c 98
Bobty 5:5bccf48799d4 99 // Ticker's tick function
Bobty 6:b7064d33e402 100 //void TickFunction()
Bobty 6:b7064d33e402 101 //{
Bobty 6:b7064d33e402 102 //}
Bobty 5:5bccf48799d4 103
Bobty 5:5bccf48799d4 104 char* getGasUseCallback(int method, char* cmdStr, char* argStr)
Bobty 5:5bccf48799d4 105 {
Bobty 5:5bccf48799d4 106 char* pResp = gasUseCounter.getGasUseCallback(cmdStr, argStr);
Bobty 5:5bccf48799d4 107 pc.printf("Returning gas use %s\r\n", pResp);
Bobty 5:5bccf48799d4 108 return pResp;
Bobty 5:5bccf48799d4 109 }
Bobty 5:5bccf48799d4 110
Bobty 5:5bccf48799d4 111 char* setGasUseCallback(int method, char* cmdStr, char* argStr)
Bobty 5:5bccf48799d4 112 {
Bobty 5:5bccf48799d4 113 pc.printf("Setting gas use count %s\n\r", argStr);
Bobty 5:5bccf48799d4 114 int newGasUse = 0;
Bobty 5:5bccf48799d4 115 char* eqStr = strchr(argStr, '=');
Bobty 5:5bccf48799d4 116 if (eqStr == NULL)
Bobty 5:5bccf48799d4 117 return "SetGasValue FAILED";
Bobty 5:5bccf48799d4 118 sscanf(eqStr+1, "%d", &newGasUse);
Bobty 5:5bccf48799d4 119 gasUseCounter.SetCount(newGasUse);
Bobty 5:5bccf48799d4 120 return "SetGasValue OK";
Bobty 5:5bccf48799d4 121 }
Bobty 5:5bccf48799d4 122
Bobty 5:5bccf48799d4 123 void http_thread(void const* arg)
Bobty 5:5bccf48799d4 124 {
Bobty 5:5bccf48799d4 125 char* baseWebFolder = "/sd/";
Bobty 5:5bccf48799d4 126
Bobty 5:5bccf48799d4 127 RdWebServer webServer;
Bobty 5:5bccf48799d4 128 webServer.addCommand("", RdWebServerCmdDef::CMD_SDORUSBFILE, NULL, "index.htm", false);
Bobty 5:5bccf48799d4 129 webServer.addCommand("gear-gr.png", RdWebServerCmdDef::CMD_SDORUSBFILE, NULL, NULL, true);
Bobty 5:5bccf48799d4 130 webServer.addCommand("getgascount", RdWebServerCmdDef::CMD_CALLBACK, &getGasUseCallback);
Bobty 5:5bccf48799d4 131 webServer.addCommand("setgascount", RdWebServerCmdDef::CMD_CALLBACK, &setGasUseCallback);
Bobty 0:f6611c8f453c 132
Bobty 5:5bccf48799d4 133 webServer.init(WEBPORT, &led4, baseWebFolder);
Bobty 5:5bccf48799d4 134
Bobty 5:5bccf48799d4 135 webServer.run();
Bobty 5:5bccf48799d4 136 }
Bobty 5:5bccf48799d4 137
Bobty 5:5bccf48799d4 138 void ntp_thread(void const* arg)
Bobty 5:5bccf48799d4 139 {
Bobty 5:5bccf48799d4 140 while (1)
Bobty 5:5bccf48799d4 141 {
Bobty 5:5bccf48799d4 142 pc.printf("Trying to update time...\r\n");
Bobty 5:5bccf48799d4 143 if (ntp.setTime("0.pool.ntp.org") == 0)
Bobty 5:5bccf48799d4 144 {
Bobty 5:5bccf48799d4 145 printf("Set time successfully\r\n");
Bobty 5:5bccf48799d4 146 time_t ctTime;
Bobty 5:5bccf48799d4 147 ctTime = time(NULL);
Bobty 5:5bccf48799d4 148 printf("Time is set to (UTC): %s\r\n", ctime(&ctTime));
Bobty 5:5bccf48799d4 149 }
Bobty 5:5bccf48799d4 150 else
Bobty 5:5bccf48799d4 151 {
Bobty 5:5bccf48799d4 152 printf("Cannot set from NTP\r\n");
Bobty 5:5bccf48799d4 153 }
Bobty 5:5bccf48799d4 154 // 1 hour
Bobty 5:5bccf48799d4 155 for (int i = 0; i < 60; i++)
Bobty 5:5bccf48799d4 156 {
Bobty 5:5bccf48799d4 157 for (int j = 0; j < 60; j++)
Bobty 5:5bccf48799d4 158 {
Bobty 5:5bccf48799d4 159 osDelay(1000);
Bobty 5:5bccf48799d4 160 }
Bobty 5:5bccf48799d4 161 pc.printf("Waited %d mins\r\n", i);
Bobty 5:5bccf48799d4 162 }
Bobty 6:b7064d33e402 163 break;
Bobty 5:5bccf48799d4 164 }
Bobty 5:5bccf48799d4 165 }
Bobty 5:5bccf48799d4 166
Bobty 0:f6611c8f453c 167 int main()
Bobty 0:f6611c8f453c 168 {
Bobty 0:f6611c8f453c 169 pc.baud(115200);
Bobty 5:5bccf48799d4 170 pc.printf("Gas Monitor V2 - Rob Dobson 2014\r\n");
Bobty 0:f6611c8f453c 171
Bobty 6:b7064d33e402 172 // ticker.attach(&TickFunction,TICK_MS / 1000.0);
Bobty 5:5bccf48799d4 173
Bobty 8:5980547ae71c 174 // Setup the thermometers
Bobty 8:5980547ae71c 175 for (int thermIdx = 0; thermIdx < NUM_THERM_BUSES; thermIdx++)
Bobty 8:5980547ae71c 176 thermometerBuses[thermIdx] = new DS18B20(tempSensorPins[thermIdx]);
Bobty 8:5980547ae71c 177
Bobty 8:5980547ae71c 178 // Initialise thermometers
Bobty 8:5980547ae71c 179 for (int thermIdx = 0; thermIdx < NUM_THERM_BUSES; thermIdx++)
Bobty 8:5980547ae71c 180 {
Bobty 8:5980547ae71c 181 DS18B20* pThermBus = thermometerBuses[thermIdx];
Bobty 8:5980547ae71c 182 pThermBus->SearchToGetAddresses();
Bobty 8:5980547ae71c 183 pThermBus->ReqConvert();
Bobty 8:5980547ae71c 184 }
Bobty 8:5980547ae71c 185
Bobty 5:5bccf48799d4 186 // Get the current count from the SD Card
Bobty 5:5bccf48799d4 187 gasUseCounter.Init();
Bobty 0:f6611c8f453c 188
Bobty 5:5bccf48799d4 189 // setup ethernet interface
Bobty 5:5bccf48799d4 190 eth.init(); //Use DHCP
Bobty 5:5bccf48799d4 191 eth.connect();
Bobty 2:6bfef0839102 192
Bobty 5:5bccf48799d4 193 pc.printf("IP Address is %s\n\r", eth.getIPAddress());
Bobty 8:5980547ae71c 194
Bobty 8:5980547ae71c 195 // NTP Time setter
Bobty 5:5bccf48799d4 196 Thread ntpTimeSetter(&ntp_thread);
Bobty 0:f6611c8f453c 197
Bobty 8:5980547ae71c 198 // Web Server
Bobty 6:b7064d33e402 199 Thread httpServer(&http_thread, NULL, osPriorityNormal, (DEFAULT_STACK_SIZE * 3));
Bobty 5:5bccf48799d4 200
Bobty 8:5980547ae71c 201 const int loopDelayInMs = 250;
Bobty 8:5980547ae71c 202 const int numSecondsBetweenThermReadings = 10;
Bobty 8:5980547ae71c 203 const int numLoopsPerThermReading = numSecondsBetweenThermReadings*1000/loopDelayInMs;
Bobty 8:5980547ae71c 204 const int timeForThermReadingInSecs = 2;
Bobty 8:5980547ae71c 205 const int loopCountForRequestingThermReading = numLoopsPerThermReading - (timeForThermReadingInSecs*1000/loopDelayInMs);
Bobty 8:5980547ae71c 206 int countForThermReadings = 0;
Bobty 8:5980547ae71c 207 const int reGetThermometerAddressesAfterNumReadings = 100;
Bobty 8:5980547ae71c 208 int countForGetThermometerAddresses = 0;
Bobty 5:5bccf48799d4 209 while(true)
Bobty 0:f6611c8f453c 210 {
Bobty 8:5980547ae71c 211 osDelay(loopDelayInMs);
Bobty 5:5bccf48799d4 212 led1 = !led1;
Bobty 5:5bccf48799d4 213
Bobty 5:5bccf48799d4 214 // Service gas count
Bobty 5:5bccf48799d4 215 if (gasUseCounter.Service())
Bobty 5:5bccf48799d4 216 SendInfoBroadcast();
Bobty 8:5980547ae71c 217
Bobty 8:5980547ae71c 218 // Check if thermometer addresses need to be got
Bobty 8:5980547ae71c 219 if (countForThermReadings++ == 0)
Bobty 8:5980547ae71c 220 {
Bobty 8:5980547ae71c 221 if (countForGetThermometerAddresses++ == 0)
Bobty 8:5980547ae71c 222 {
Bobty 8:5980547ae71c 223 printf("Requested Addresses\n\r");
Bobty 8:5980547ae71c 224 for (int thermIdx = 0; thermIdx < NUM_THERM_BUSES; thermIdx++)
Bobty 8:5980547ae71c 225 {
Bobty 8:5980547ae71c 226 DS18B20* pThermBus = thermometerBuses[thermIdx];
Bobty 8:5980547ae71c 227 pThermBus->SearchToGetAddresses();
Bobty 8:5980547ae71c 228 }
Bobty 8:5980547ae71c 229 }
Bobty 8:5980547ae71c 230 else if (countForGetThermometerAddresses > reGetThermometerAddressesAfterNumReadings)
Bobty 8:5980547ae71c 231 {
Bobty 8:5980547ae71c 232 countForGetThermometerAddresses = 0;
Bobty 8:5980547ae71c 233 }
Bobty 8:5980547ae71c 234 }
Bobty 8:5980547ae71c 235 else
Bobty 8:5980547ae71c 236 {
Bobty 8:5980547ae71c 237 // Check if time to request thermometer readings
Bobty 8:5980547ae71c 238 if (countForThermReadings == loopCountForRequestingThermReading)
Bobty 8:5980547ae71c 239 {
Bobty 8:5980547ae71c 240 printf("Requested Convert\n\r");
Bobty 8:5980547ae71c 241 for (int thermIdx = 0; thermIdx < NUM_THERM_BUSES; thermIdx++)
Bobty 8:5980547ae71c 242 {
Bobty 8:5980547ae71c 243 DS18B20* pThermBus = thermometerBuses[thermIdx];
Bobty 8:5980547ae71c 244 printf("Bus %d Num therms %d\n\r", thermIdx, pThermBus->GetNumAddresses());
Bobty 8:5980547ae71c 245 pThermBus->ReqConvert();
Bobty 8:5980547ae71c 246 }
Bobty 8:5980547ae71c 247 }
Bobty 8:5980547ae71c 248
Bobty 8:5980547ae71c 249 // Read thermometers
Bobty 8:5980547ae71c 250 if (countForThermReadings > numLoopsPerThermReading)
Bobty 8:5980547ae71c 251 {
Bobty 8:5980547ae71c 252 countForThermReadings = 0;
Bobty 8:5980547ae71c 253 printf("Reading Temp\n\r");
Bobty 8:5980547ae71c 254 for (int thermIdx = 0; thermIdx < NUM_THERM_BUSES; thermIdx++)
Bobty 8:5980547ae71c 255 {
Bobty 8:5980547ae71c 256 DS18B20* pThermBus = thermometerBuses[thermIdx];
Bobty 8:5980547ae71c 257 for (int addrIdx = 0; addrIdx < pThermBus->GetNumAddresses(); addrIdx++)
Bobty 8:5980547ae71c 258 {
Bobty 8:5980547ae71c 259 printf("Bus %d Therm %d === %.2fC ... Addr = ", thermIdx, addrIdx, pThermBus->GetTemperature(addrIdx));
Bobty 8:5980547ae71c 260 pThermBus->DebugPrintAddress(addrIdx);
Bobty 8:5980547ae71c 261 printf("\r\n");
Bobty 8:5980547ae71c 262 }
Bobty 8:5980547ae71c 263 }
Bobty 8:5980547ae71c 264 }
Bobty 8:5980547ae71c 265 }
Bobty 0:f6611c8f453c 266 }
Bobty 5:5bccf48799d4 267 }