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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Thermometers.cpp Source File

Thermometers.cpp

00001 // Handles temperature collection from a number of DS18B20 devices
00002 // Rob Dobson, 2015
00003 
00004 #include "Thermometers.h"
00005 
00006 #define SHOW_THERMOMETER_DEBUGGING 1
00007 const int DEBUG_EXPECTED_THERMOMETER_COUNT = 3;
00008 
00009 Thermometers::Thermometers(int numTempSensorPins, const PinName tempSensorPins[], int serviceIntervalInMs, Logger &logger) :
00010     _logger(logger)
00011 {
00012     _numTempSensorPins = numTempSensorPins;
00013     _tempSensorPins = tempSensorPins;
00014     _serviceIntervalInMs = serviceIntervalInMs;
00015     _numThermometerBuses = 0;
00016     _failAddrCount = 0;
00017     _failReadCount = 0;
00018 }
00019 
00020 void Thermometers::Init()
00021 {
00022     // Setup the thermometers
00023     for (int busIdx = 0; busIdx < _numTempSensorPins; busIdx++)
00024     {
00025         if (busIdx >= MAX_ONEWIRE_BUSES)
00026             break;
00027         _thermometerBuses[busIdx] = new DS18B20(_tempSensorPins[busIdx], _logger);
00028         DS18B20* pThermBus = _thermometerBuses[busIdx];
00029         pThermBus->SearchToGetAddresses();
00030         pThermBus->ReqConvert();
00031         _numThermometerBuses++;
00032     }
00033 }
00034 
00035 void Thermometers::Service()
00036 {
00037     int numLoopsPerThermReading = numSecondsBetweenThermReadings*1000/_serviceIntervalInMs;
00038     int loopCountForRequestingThermReading = numLoopsPerThermReading - (timeForThermReadingInSecs*1000/_serviceIntervalInMs);
00039 
00040     // Check if thermometer addresses need to be got
00041     if (_countForThermReadings++ == 0)
00042     {
00043         if (_countForGetThermometerAddresses++ == 0)
00044         {
00045 #ifdef SHOW_THERMOMETER_DEBUGGING
00046             _logger.LogDebug("ThermReqAddr");
00047 #endif
00048             for (int busIdx = 0; busIdx < _numThermometerBuses; busIdx++)
00049             {
00050                 DS18B20* pThermBus = _thermometerBuses[busIdx];
00051                 int numTherms = pThermBus->SearchToGetAddresses();
00052                 if (numTherms != DEBUG_EXPECTED_THERMOMETER_COUNT)
00053                     _failAddrCount++;
00054             }
00055             
00056 #ifdef SHOW_THERMOMETER_DEBUGGING
00057             for (int busIdx = 0; busIdx < _numThermometerBuses; busIdx++)
00058             {
00059                 DS18B20* pThermBus = _thermometerBuses[busIdx];
00060                 if(_failAddrCount == 0 && _failReadCount == 0)
00061                 {
00062                     _logger.LogDebug("Therm B%d N%d OK", busIdx, pThermBus->GetNumAddresses());
00063                 }
00064                 else
00065                 {
00066                     _logger.LogDebug("Therm B%d N%d FailAddr %d FailRead %d", busIdx, pThermBus->GetNumAddresses(),
00067                             _failAddrCount, _failReadCount);
00068                 }
00069                 for (int addrIdx = 0; addrIdx < pThermBus->GetNumAddresses(); addrIdx++)
00070                 {
00071                     char buf [40];
00072                     pThermBus->DebugGetAddress(addrIdx, buf);
00073                     _logger.LogDebug("Therm B%d N%d %s", busIdx, addrIdx, buf);
00074                 }
00075             }
00076 #endif
00077         }
00078         else if (_countForGetThermometerAddresses > reGetThermometerAddressesAfterNumReadings)
00079         {
00080             _countForGetThermometerAddresses = 0;
00081         }
00082     }
00083     else
00084     {
00085         // Check if time to request thermometers to take readings
00086         if (_countForThermReadings == loopCountForRequestingThermReading)
00087         {
00088 #ifdef SHOW_THERMOMETER_DEBUGGING
00089 //            _logger.LogDebug("ThermReqConv");
00090 #endif
00091             for (int busIdx = 0; busIdx < _numThermometerBuses; busIdx++)
00092             {
00093                 DS18B20* pThermBus = _thermometerBuses[busIdx];
00094                 pThermBus->ReqConvert();
00095             }                
00096         }
00097     
00098         // Check if it is time to get the values from the thermometers
00099         if (_countForThermReadings > numLoopsPerThermReading)
00100         {
00101             _countForThermReadings = 0;
00102             for (int busIdx = 0; busIdx < _numThermometerBuses; busIdx++)
00103             {
00104                 DS18B20* pThermBus = _thermometerBuses[busIdx];
00105                 for (int addrIdx = 0; addrIdx < pThermBus->GetNumAddresses(); addrIdx++)
00106                 {
00107                     double tempValue = pThermBus->ReadTemperature(addrIdx);
00108                     if (tempValue == DS18B20::INVALID_TEMPERATURE)
00109                         _failReadCount++;
00110                 }
00111             }                
00112 
00113 #ifdef SHOW_THERMOMETER_DEBUGGING
00114             char tempStrBuf[140];
00115             tempStrBuf[0] = 0;
00116             for (int busIdx = 0; busIdx < _numThermometerBuses; busIdx++)
00117             {
00118                 DS18B20* pThermBus = _thermometerBuses[busIdx];
00119                 for (int addrIdx = 0; addrIdx < pThermBus->GetNumAddresses(); addrIdx++)
00120                 {
00121                     time_t timeOfReading = 0;
00122                     double tempValue = pThermBus->GetLatestTemperature(addrIdx, timeOfReading);
00123                     int ageInSecs = time(NULL) - timeOfReading;
00124                     if (tempValue == DS18B20::INVALID_TEMPERATURE)
00125                         sprintf(tempStrBuf+strlen(tempStrBuf), "%.1fC (INVALID) ", tempValue);
00126                     else if (ageInSecs <= 2)
00127                         sprintf(tempStrBuf+strlen(tempStrBuf), "%.1fC ", tempValue);
00128                     else
00129                         sprintf(tempStrBuf+strlen(tempStrBuf), "%.1fC (%dS ago) ", tempValue, ageInSecs);
00130                 }
00131             }
00132             _logger.LogDebug("Therm %s", tempStrBuf);
00133 #endif
00134 
00135         }        
00136     }
00137 }
00138 
00139 int Thermometers::GetTemperatureValues(int maxTempValues, TemperatureValue* tempValues, int maxAgeInSecs)
00140 {
00141     // Go through available values
00142     int curTempValueIdx = 0;
00143     for (int busIdx = 0; busIdx < _numThermometerBuses; busIdx++)
00144     {
00145         DS18B20* pThermBus = _thermometerBuses[busIdx];
00146         for (int addrIdx = 0; addrIdx < pThermBus->GetNumAddresses(); addrIdx++)
00147         {
00148             time_t timeOfReading = 0;
00149             double tempValue = pThermBus->GetLatestTemperature(addrIdx, timeOfReading);
00150             if (tempValue != DS18B20::INVALID_TEMPERATURE)
00151             {
00152                 if ((time(NULL) - timeOfReading) < maxAgeInSecs)
00153                 {
00154                     tempValues[curTempValueIdx].timeStamp = timeOfReading;
00155                     strncpy(tempValues[curTempValueIdx].address, pThermBus->GetAddressStr(addrIdx), DS18B20::ONEWIRE_ADDR_STRLEN-1);
00156                     tempValues[curTempValueIdx].tempInCentigrade = tempValue;
00157                     curTempValueIdx++;
00158                     if (curTempValueIdx >= maxTempValues)
00159                         break;
00160                 }
00161             }
00162         }
00163         if (curTempValueIdx >= maxTempValues)
00164             break;
00165     }
00166     return curTempValueIdx;
00167 }
00168 
00169