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

Files at this revision

API Documentation at this revision

Comitter:
Bobty
Date:
Mon Oct 05 14:05:33 2015 +0000
Parent:
18:d419ccebc666
Child:
20:7933076df5af
Commit message:
Added retries on getting addresses from thermometers; Doubled up on non-volatile storage of latest gas count

Changed in this revision

GasUseCounter.cpp Show annotated file Show diff for this revision Revisions of this file
GasUseCounter.h Show annotated file Show diff for this revision Revisions of this file
Onewire.lib Show annotated file Show diff for this revision Revisions of this file
RdDS18B20.cpp Show annotated file Show diff for this revision Revisions of this file
Thermometers.cpp Show annotated file Show diff for this revision Revisions of this file
Watchdog.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
--- a/GasUseCounter.cpp	Mon Sep 28 11:16:46 2015 +0000
+++ b/GasUseCounter.cpp	Mon Oct 05 14:05:33 2015 +0000
@@ -1,3 +1,6 @@
+// Gas usage based on pulses from a gas meter
+// Rob Dobson 2015
+
 #include "GasUseCounter.h"
 
 // Callback from web server to handle getting current gas count
@@ -36,36 +39,59 @@
 // Get the current usage count from SD card
 void GasUseCounter::GetGasCountFromSD()
 {
-    FILE* fp = fopen(_gasUseFilename, "r");
-    if (fp == NULL)
-    {
-        _pc.printf ("Read Gas ... Filename %s not found\r\n", _gasUseFilename);
-    }
-    else
+    int count0 = 0;
+    int count1 = 0;
+    for (int i = 0; i < 2; i++)
     {
-        int curCount = 0;
-        int retVal = fscanf(fp, "%d", &curCount);
-        fclose(fp);
-        if (retVal == 1)
-            _pc.printf ("Read from SD last gas count = %d\r\n", curCount);
+        const char* fname = _gasUseFilename1;
+        if (i == 1)
+            fname = _gasUseFilename2;
+        FILE* fp = fopen(fname, "r");
+        if (fp == NULL)
+        {
+            _pc.printf ("Read Gas ... Filename %s not found\r\n", fname);
+        }
         else
-            _pc.printf ("Failed to read gas count from SD card\r\n");
-        _lastWrittenGasCount = curCount;
-        _pulseDetector->SetPulseCount(curCount);
+        {
+            int curCount = 0;
+            int retVal = fscanf(fp, "%d", &curCount);
+            fclose(fp);
+            if (retVal == 1)
+                _pc.printf ("Read from file %s last gas count = %d\r\n", fname, curCount);
+            else
+                _pc.printf ("Failed to read gas count from file %s\r\n", fname);
+            if (i == 0)
+                count0 = curCount;
+            else
+                count1 = curCount;
+        }
     }
+    // Find the highest count
+    int maxCount = count0;
+    if (count1 > count0)
+        maxCount = count1;
+    _lastWrittenGasCount = maxCount;
+    _pulseDetector->SetPulseCount(maxCount);
+    _pc.printf ("Pulse count set to %d\r\n", maxCount);
 }
 
 void GasUseCounter::WriteGasCountToSD()
 {
-    FILE* fp = fopen(_gasUseFilename, "w");
-    if (fp == NULL)
+    for (int i = 0; i < 2; i++)
     {
-        _pc.printf ("WriteGas ... Filename %s not found\r\n", _gasUseFilename);
-    }
-    else
-    {
-        fprintf(fp, "%d", GetCount());
-        _pc.printf ("Written to SD last gas count = %d\r\n", GetCount());
-        fclose(fp);
+        const char* fname = _gasUseFilename1;
+        if (i == 1)
+            fname = _gasUseFilename2;
+        FILE* fp = fopen(fname, "w");
+        if (fp == NULL)
+        {
+            _pc.printf ("WriteGas ... Filename %s not found\r\n", fname);
+        }
+        else
+        {
+            fprintf(fp, "%d", GetCount());
+            _pc.printf ("Written to %s last gas count = %d\r\n", fname, GetCount());
+            fclose(fp);
+        }
     }
 }
--- a/GasUseCounter.h	Mon Sep 28 11:16:46 2015 +0000
+++ b/GasUseCounter.h	Mon Oct 05 14:05:33 2015 +0000
@@ -12,10 +12,11 @@
 {
     public:
         // Constructor
-        GasUseCounter(const char* gasUseFilename, DigitalIn& gasPulsePin, RawSerial &pc) :
+        GasUseCounter(const char* gasUseFilename1, const char* gasUseFilename2, DigitalIn& gasPulsePin, RawSerial &pc) :
                 _gasPulsePin(gasPulsePin), _pc(pc)
         {
-            _gasUseFilename = gasUseFilename;
+            _gasUseFilename1 = gasUseFilename1;
+            _gasUseFilename2 = gasUseFilename2;
             _lastWrittenGasCount = 0;
             _pulseDetector = new PulsePin(_gasPulsePin, false, 200);
         }
@@ -54,7 +55,8 @@
         
     private:
         // Gas use filename for non-volatile
-        const char* _gasUseFilename;
+        const char* _gasUseFilename1;
+        const char* _gasUseFilename2;
         int _curGasCount;
         int _lastWrittenGasCount;
         char _gasCountStr [MAX_GAS_COUNT_STR_LEN];
--- a/Onewire.lib	Mon Sep 28 11:16:46 2015 +0000
+++ b/Onewire.lib	Mon Oct 05 14:05:33 2015 +0000
@@ -1,1 +1,1 @@
-https://developer.mbed.org/users/Bobty/code/Onewire/#45b6a39002f1
+https://developer.mbed.org/users/Bobty/code/Onewire/#d2452e9b169b
--- a/RdDS18B20.cpp	Mon Sep 28 11:16:46 2015 +0000
+++ b/RdDS18B20.cpp	Mon Oct 05 14:05:33 2015 +0000
@@ -133,58 +133,90 @@
 
 int DS18B20::SearchToGetAddresses()
 {
-    _numValidAddresses = 0;
-    for (int addrIdx = 0; addrIdx < MAX_BUS_DEVICES; addrIdx++)
-    {
-        uint8_t addr[8];
+    
+    const int MAX_ADDR_SEARCH_RETRIES = 5;
 
-        if ( !_oneWire.search(addr))
+    // Address Table
+    uint8_t tmpAddrTable[MAX_BUS_DEVICES][ONEWIRE_ADDR_BYTES];
+    int validAddresses = 0;
+    bool okResultAchieved = false;
+        
+    // Try a number of times
+    for (int retryCount = 0; retryCount < MAX_ADDR_SEARCH_RETRIES; retryCount++)
+    {
+        // Check if the last search was ok (if there was one)
+        if (okResultAchieved)
         {
-#ifdef SHOW_18B20_DEBUGGING
-            printf("No more addresses.\r\n");
-#endif
-            _oneWire.reset_search();
+            // Copy found addresses
+            for (int addrIdx = 0; addrIdx < validAddresses; addrIdx++)
+            {
+                for( int i = 0; i < ONEWIRE_ADDR_BYTES; i++) 
+                    _addrTable[addrIdx][i] = tmpAddrTable[addrIdx][i];
+            }
+            _numValidAddresses = validAddresses;
             break;
         }
         
-#ifdef SHOW_18B20_DEBUGGING
-        printf("Found device addr (ROM) =");
-#endif
-        for( int i = 0; i < ONEWIRE_ADDR_BYTES; i++) 
+        // Start another search
+        validAddresses = 0;
+        _oneWire.reset_search();
+        for (int addrIdx = 0; addrIdx < MAX_BUS_DEVICES; addrIdx++)
         {
-            // Copy to table
-            _addrTable[_numValidAddresses][i] = addr[i];
+            uint8_t addr[8];
+            uint8_t rslt = _oneWire.search(addr);
+            if (rslt == ONEWIRE_SEARCH_ALL_DONE)
+            {
+                if (validAddresses >= _numValidAddresses)
+                    okResultAchieved = true;
+                break;
+            }
+            if (rslt != ONEWIRE_OK)
+            {
 #ifdef SHOW_18B20_DEBUGGING
-            printf(" %02x", addr[i]);
+                printf("Search returned %s\r\n", (rslt == ONEWIRE_SEARCH_INIT_FAIL) ? "InitFail" : ((rslt == ONEWIRE_SEARCH_NOT_FOUND) ? "NotFound" : "UnknownError"));
+#endif
+                break;
+            }
+            
+#ifdef SHOW_18B20_DEBUGGING
+            printf("Found device addr (ROM) =");
 #endif
-        }
+            for( int i = 0; i < ONEWIRE_ADDR_BYTES; i++) 
+            {
+                // Copy to table
+                tmpAddrTable[validAddresses][i] = addr[i];
+#ifdef SHOW_18B20_DEBUGGING
+                printf(" %02x", addr[i]);
+#endif
+            }
         
-        // Check CRC - only include if CRC is valid
-        if (_oneWire.CRC(addr, ONEWIRE_ADDR_BYTES-1) == addr[ONEWIRE_ADDR_BYTES-1])
-            _numValidAddresses++;
+            // Check CRC - only include if CRC is valid
+            if (_oneWire.CRC(addr, ONEWIRE_ADDR_BYTES-1) == addr[ONEWIRE_ADDR_BYTES-1])
+                validAddresses++;
 #ifdef SHOW_18B20_DEBUGGING
-        else
-            printf(" (CRC INVALID!)");
+            else
+                printf(" (CRC INVALID!)");
 #endif
 
 #ifdef SHOW_18B20_DEBUGGING        
-        // the first ROM byte indicates which chip
-        switch (addr[0])
-        {
-            case 0x10:
-                printf("  Chip = DS18S20\r\n");  // or old DS1820
-                break;
-            case 0x28:
-                printf("  Chip = DS18B20\r\n");
-                break;
-            case 0x22:
-                printf("  Chip = DS1822\r\n");
-                break;
-            default:
-                printf("  NOT DS18x20 FAMILY\r\n");
-                break;
-        } 
+            // the first ROM byte indicates which chip
+            switch (addr[0])
+            {
+                case 0x10:
+                    printf("  Chip = DS18S20\r\n");  // or old DS1820
+                    break;
+                case 0x28:
+                    printf("  Chip = DS18B20\r\n");
+                    break;
+                case 0x22:
+                    printf("  Chip = DS1822\r\n");
+                    break;
+                default:
+                    printf("  NOT DS18x20 FAMILY\r\n");
+                    break;
+            } 
 #endif
+        }
     }
-    return _numValidAddresses;
+    return validAddresses;
 }
--- a/Thermometers.cpp	Mon Sep 28 11:16:46 2015 +0000
+++ b/Thermometers.cpp	Mon Oct 05 14:05:33 2015 +0000
@@ -4,6 +4,7 @@
 #include "Thermometers.h"
 
 #define SHOW_THERMOMETER_DEBUGGING 1
+const int DEBUG_EXPECTED_THERMOMETER_COUNT = 3;
 
 Thermometers::Thermometers(int numTempSensorPins, const PinName tempSensorPins[], int serviceIntervalInMs)
 {
@@ -47,7 +48,7 @@
             {
                 DS18B20* pThermBus = _thermometerBuses[busIdx];
                 int numTherms = pThermBus->SearchToGetAddresses();
-                if (numTherms != 3)
+                if (numTherms != DEBUG_EXPECTED_THERMOMETER_COUNT)
                     _failAddrCount++;
             }
         }
@@ -58,7 +59,7 @@
     }
     else
     {
-        // Check if time to request thermometer readings
+        // Check if time to request thermometers to take readings
         if (_countForThermReadings == loopCountForRequestingThermReading)
         {
 #ifdef SHOW_THERMOMETER_DEBUGGING
@@ -75,7 +76,7 @@
             }                
         }
     
-        // Read thermometers
+        // Check if it is time to get the values from the thermometers
         if (_countForThermReadings > numLoopsPerThermReading)
         {
             _countForThermReadings = 0;
--- a/Watchdog.h	Mon Sep 28 11:16:46 2015 +0000
+++ b/Watchdog.h	Mon Oct 05 14:05:33 2015 +0000
@@ -20,8 +20,10 @@
         // by writing this required bit pattern
         void Feed() 
         {
+            __disable_irq();
             LPC_WDT->WDFEED = 0xAA;
             LPC_WDT->WDFEED = 0x55;
+            __enable_irq();
         }
         
         bool WatchdogCausedRestart()
--- a/main.cpp	Mon Sep 28 11:16:46 2015 +0000
+++ b/main.cpp	Mon Oct 05 14:05:33 2015 +0000
@@ -1,3 +1,10 @@
+// Gas usage monitor
+// Counts pulses from a gas meter
+// Monitors temperature sensors
+// Monitors valve/pump activity
+// Web interface and UDP broadcast
+// Rob Dobson 2015
+
 #include "mbed.h"
 #include "EthernetInterface.h"
 #include "NTPClient.h"
@@ -37,7 +44,8 @@
 SDFileSystem sd(p5, p6, p7, p8, "sd");
 
 // Log file names
-const char* gasPulseFileName = "/sd/curPulse.txt";
+const char* gasPulseFileName1 = "/sd/curPulse.txt";
+const char* gasPulseFileName2 = "/sd/curPulse2.txt";
 const char* eventLogFileName = "/sd/log.txt";
 const char* dataLogFileBase = "/sd/";
 
@@ -46,7 +54,7 @@
 
 // Gas use counter
 DigitalIn gasPulsePin(p21);
-GasUseCounter gasUseCounter(gasPulseFileName, gasPulsePin, pc);
+GasUseCounter gasUseCounter(gasPulseFileName1, gasPulseFileName2, gasPulsePin, pc);
 
 // Thermometers - DS18B20 OneWire Thermometer connections
 const PinName tempSensorPins[] = { p22 };
@@ -196,14 +204,15 @@
         pc.printf("Trying to update time...\r\n");
         if (ntp.setTime("0.pool.ntp.org") == NTP_OK)
         {
-          printf("Set time successfully\r\n");
-          time_t ctTime;
-          ctTime = time(NULL);
-          printf("Time is set to (UTC): %s\r\n", ctime(&ctTime));
+            osDelay(1000);  // This delay is simply to try to improve printf output
+            printf("Set time successfully\r\n");
+            time_t ctTime;
+            ctTime = time(NULL);
+            pc.printf("Time is set to (UTC): %s\r\n", ctime(&ctTime));
         }
         else
         {
-          printf("Cannot set from NTP\r\n");
+            pc.printf("Cannot set from NTP\r\n");
         }
         
         // Refresh time every K hours
@@ -231,7 +240,7 @@
 int main()
 {
     pc.baud(115200);
-    pc.printf("Gas Monitor V2 - Rob Dobson 2014\r\n");
+    pc.printf("\r\n\r\nGas Monitor V2 - Rob Dobson 2014\r\n");
 
     // Initialise thermometers
     thermometers.Init();
@@ -239,7 +248,6 @@
     // Get the current count from the SD Card
     gasUseCounter.Init();
     
-    
     // Setup ethernet interface
     char macAddr[6];
     mbed_mac_address(macAddr);
@@ -283,9 +291,15 @@
             {
                 // Record the reason for restarting in the log file
                 if (watchdogCausedRestart)
+                {
                     logger.LogEvent("Watchdog Restart");
+                    pc.printf("Watchdog Restart\r\n");
+                }
                 else
+                {
                     logger.LogEvent("Normal Restart");
+                    pc.printf("Normal Restart\r\n");
+                }
                 restartCauseRecorded = true;
             }
         }