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
Revision 10:72eb217def1f, committed 2015-02-22
- Comitter:
- Bobty
- Date:
- Sun Feb 22 20:23:43 2015 +0000
- Parent:
- 9:0e103c2f869a
- Child:
- 11:30182b9aa833
- Commit message:
- Now sending complete broadcast message with gas count, temperatures and voltage sensing
Changed in this revision
--- a/PulsePin.cpp Sun Feb 22 11:57:12 2015 +0000 +++ b/PulsePin.cpp Sun Feb 22 20:23:43 2015 +0000 @@ -1,5 +1,6 @@ // Handles a pin that has a slow pulse applied // Written for a gas meter monitor +// Rob Dobson, 2015 #include "PulsePin.h"
--- a/RdDS18B20.cpp Sun Feb 22 11:57:12 2015 +0000
+++ b/RdDS18B20.cpp Sun Feb 22 20:23:43 2015 +0000
@@ -78,7 +78,7 @@
{
if ((addrIdx >= _numValidAddresses) || (addrIdx < 0))
return "";
- sprintf(_addrStr, "%02x %02x %02x %02x %02x %02x %02x %02x",
+ sprintf(_addrStr, "%02x%02x%02x%02x%02x%02x%02x%02x",
_addrTable[addrIdx][0], _addrTable[addrIdx][1], _addrTable[addrIdx][2],
_addrTable[addrIdx][3], _addrTable[addrIdx][4], _addrTable[addrIdx][5],
_addrTable[addrIdx][6], _addrTable[addrIdx][7]);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/VoltAlerter.cpp Sun Feb 22 20:23:43 2015 +0000
@@ -0,0 +1,34 @@
+// Detect stat of Volt-Alerter
+// Device produces a square wave when voltage detected
+// Cycle time of square wave around 100ms
+// Rob Dobson, 2015
+
+#include "VoltAlerter.h"
+
+VoltAlerter::VoltAlerter(PinName pinName) :
+ _inPin(pinName, PullUp)
+{
+ _curPinState = 0;
+ _consecutiveLows = 0;
+}
+
+void VoltAlerter::Service()
+{
+ // Check pin
+ if (!_inPin)
+ {
+ _curPinState = 1;
+ _consecutiveLows = 0;
+ return;
+ }
+
+ // Only set state low if we get X consecutive lows
+ _consecutiveLows++;
+ if (_consecutiveLows >= CONSECUTIVE_LOWS_REQD_FOR_LOW)
+ {
+ _curPinState = 0;
+ // The following is just to ensure the int doesn't overflow
+ _consecutiveLows = CONSECUTIVE_LOWS_REQD_FOR_LOW;
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/VoltAlerter.h Sun Feb 22 20:23:43 2015 +0000
@@ -0,0 +1,29 @@
+// Detect stat of Volt-Alerter
+// Device produces a square wave when voltage detected
+// Cycle time of square wave around 100ms
+// Rob Dobson, 2015
+
+#ifndef __VOLTALERTER__H
+#define __VOLTALERTER__H
+#include "mbed.h"
+
+class VoltAlerter
+{
+ public:
+ VoltAlerter(PinName pinName);
+ void Service();
+ int GetState()
+ {
+ return _curPinState;
+ };
+
+ static const int CONSECUTIVE_LOWS_REQD_FOR_LOW = 10;
+
+ private:
+ DigitalIn _inPin;
+ bool _curPinState;
+ int _consecutiveLows;
+};
+
+
+#endif
\ No newline at end of file
--- a/main.cpp Sun Feb 22 11:57:12 2015 +0000
+++ b/main.cpp Sun Feb 22 20:23:43 2015 +0000
@@ -4,6 +4,7 @@
#include "RdWebServer.h"
#include "GasUseCounter.h"
#include "Thermometers.h"
+#include "VoltAlerter.h"
#include <stdarg.h>
// Web and UDB ports
@@ -12,22 +13,25 @@
// Ticker collects data
//Ticker ticker;
-//const int TICK_MS = 250;
+//const int TICK_MS = 50;
const int LOOP_DELAY_IN_MS = 250;
// Debugging and status
RawSerial pc(USBTX, USBRX);
DigitalOut led1(LED1); //ticking (flashes)
-DigitalOut led2(LED2); //server listning status (flashes)
+DigitalOut led2(LED2); //
DigitalOut led3(LED3); //socket connecting status
DigitalOut led4(LED4); //server status
// Web server
EthernetInterface eth;
-NTPClient ntp;
UDPSocket sendUDPSocket;
Endpoint broadcastEndpoint;
+// Network Time Protocol (NTP)
+NTPClient ntp;
+const int NTP_REFRESH_INTERVAL_HOURS = 1;
+
// File system for SD card
SDFileSystem sd(p5, p6, p7, p8, "sd");
@@ -41,6 +45,28 @@
const PinName tempSensorPins[] = { p22 };
Thermometers thermometers(sizeof(tempSensorPins)/sizeof(PinName), tempSensorPins, LOOP_DELAY_IN_MS);
+// Voltage Sensors / Alerters
+const int NUM_VOLT_ALERTERS = 3;
+VoltAlerter voltAlerter1(p23);
+VoltAlerter voltAlerter2(p24);
+VoltAlerter voltAlerter3(p25);
+
+// Broadcast message
+const char broadcastMsgPrefix[] = "{\"e\":[";
+const char broadcastMsgGasFormat[] = "{\"n\":\"gasCount\",\"v\":%d},{\"n\":\"gasPulseRateMs\",\"v\":%d,\"u\":\"ms\"}";
+const char broadcastTemperatureFormat[] = "{\"n\":\"temp_%s\",\"v\":%0.1f,\"u\":\"degC\"}";
+const char broadcastVoltAlerterFormat[] = "{\"n\":\"pump_%d\",\"v\":%d}";
+const char broadcastMsgSuffix[] = "],\"bt\":%d}";
+
+// Format message
+const int broadcastMsgLen = sizeof(broadcastMsgPrefix) +
+ sizeof(broadcastMsgGasFormat) +
+ (sizeof(broadcastTemperatureFormat)*Thermometers::MAX_THERMOMETERS) +
+ (sizeof(broadcastVoltAlerterFormat)*NUM_VOLT_ALERTERS) +
+ sizeof(broadcastMsgSuffix) +
+ 60;
+char broadcastMsgBuffer[broadcastMsgLen];
+
// Utility function to log data
void LogData(const char* format, ...)
{
@@ -71,31 +97,54 @@
// Get temperature values
TemperatureValue tempValues[Thermometers::MAX_THERMOMETERS];
int numTempValues = thermometers.GetTemperatureValues(Thermometers::MAX_THERMOMETERS, tempValues, 100);
- char tempStr[200];
for (int tempIdx = 0; tempIdx < numTempValues; tempIdx++)
{
printf("Temp: %.1f, Addr: %s, Time: %d\r\n", tempValues[tempIdx].tempInCentigrade, tempValues[tempIdx].address, tempValues[tempIdx].timeStamp);
}
- // Format message
- char outBuf[200];
- sprintf(outBuf, "{\"e\":[{\"n\":\"gasCount\",\"v\":%d},{\"n\":\"gasPulseRateMs\",\"v\":%d,\"u\":\"ms\"}]}",
- gasUseCounter.GetCount(), gasUseCounter.GetPulseRateMs());
-
+ // Data format of the message - senml - https://tools.ietf.org/html/draft-jennings-senml-08
+ // {
+ // "e": [
+ // {"n":"gasCount","v":%d},
+ // {"n":"gasPulseRateMs","v":%d,"u":"ms"},
+ // {"n":"temp_%s","v":%0.1f,"u":"degC"},
+ // ...
+ // {"n":"pump_%d","v":%d},
+ // ...
+ // ],
+ // "bt": %d
+ // }
+
+ time_t timeNow = time(NULL);
+ strcpy(broadcastMsgBuffer, broadcastMsgPrefix);
+ sprintf(broadcastMsgBuffer+strlen(broadcastMsgBuffer), broadcastMsgGasFormat, gasUseCounter.GetCount(), gasUseCounter.GetPulseRateMs());
+ strcpy(broadcastMsgBuffer+strlen(broadcastMsgBuffer), ",");
+ for (int tempIdx = 0; tempIdx < numTempValues; tempIdx++)
+ {
+ sprintf(broadcastMsgBuffer+strlen(broadcastMsgBuffer), broadcastTemperatureFormat, tempValues[tempIdx].address, tempValues[tempIdx].tempInCentigrade);
+ strcpy(broadcastMsgBuffer+strlen(broadcastMsgBuffer), ",");
+ }
+ sprintf(broadcastMsgBuffer+strlen(broadcastMsgBuffer), broadcastVoltAlerterFormat, 1, voltAlerter1.GetState());
+ strcpy(broadcastMsgBuffer+strlen(broadcastMsgBuffer), ",");
+ sprintf(broadcastMsgBuffer+strlen(broadcastMsgBuffer), broadcastVoltAlerterFormat, 2, voltAlerter2.GetState());
+ strcpy(broadcastMsgBuffer+strlen(broadcastMsgBuffer), ",");
+ sprintf(broadcastMsgBuffer+strlen(broadcastMsgBuffer), broadcastVoltAlerterFormat, 3, voltAlerter3.GetState());
+ sprintf(broadcastMsgBuffer+strlen(broadcastMsgBuffer), broadcastMsgSuffix, timeNow);
+
// Send
- int bytesToSend = strlen(outBuf);
- int rslt = sendUDPSocket.sendTo(broadcastEndpoint, outBuf, bytesToSend);
+ int bytesToSend = strlen(broadcastMsgBuffer);
+ int rslt = sendUDPSocket.sendTo(broadcastEndpoint, broadcastMsgBuffer, bytesToSend);
if (rslt == bytesToSend)
{
- pc.printf("Broadcast Sent ok %s\n", outBuf);
+ pc.printf("Broadcast (len %d) Sent ok %s\r\n", bytesToSend, broadcastMsgBuffer);
}
else if (rslt == -1)
{
- pc.printf("Broadcast Failed to send %s\n", outBuf);
+ pc.printf("Broadcast Failed to send %s\r\n", broadcastMsgBuffer);
}
else
{
- pc.printf("Broadcast Didn't send all of %s\n", outBuf);
+ pc.printf("Broadcast Didn't send all of %s\r\n", broadcastMsgBuffer);
}
// Log
@@ -161,17 +210,21 @@
else
{
printf("Cannot set from NTP\r\n");
- }
- // 1 hour
- for (int i = 0; i < 60; i++)
+ }
+
+ // Refresh time every K hours
+ for (int k = 0; k < NTP_REFRESH_INTERVAL_HOURS; k++)
{
- for (int j = 0; j < 60; j++)
+ // 1 hour
+ for (int i = 0; i < 60; i++)
{
- osDelay(1000);
+ for (int j = 0; j < 60; j++)
+ {
+ osDelay(1000);
+ }
+ pc.printf("%d mins to next NTP time refresh\r\n", (NTP_REFRESH_INTERVAL_HOURS-k-1)*60 + (59-i));
}
- pc.printf("%d mins since NTP\r\n", i);
}
- break;
}
}
@@ -180,6 +233,8 @@
pc.baud(115200);
pc.printf("Gas Monitor V2 - Rob Dobson 2014\r\n");
+ printf("Broadcast Msg Len %d\r\n", broadcastMsgLen);
+
// ticker.attach(&TickFunction,TICK_MS / 1000.0);
// Initialise thermometers
@@ -224,6 +279,12 @@
SendInfoBroadcast();
timeOfLastBroadcast = time(NULL);
}
+
+ // Service volt alerters
+ voltAlerter1.Service();
+ voltAlerter2.Service();
+ voltAlerter3.Service();
+ led2 = voltAlerter1.GetState();
}
}