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
Thermometers.cpp
- Committer:
- Bobty
- Date:
- 2015-10-13
- Revision:
- 20:7933076df5af
- Parent:
- 19:0367cb46d003
- Child:
- 21:ccf053bab795
File content as of revision 20:7933076df5af:
// Handles temperature collection from a number of DS18B20 devices // Rob Dobson, 2015 #include "Thermometers.h" #define SHOW_THERMOMETER_DEBUGGING 1 const int DEBUG_EXPECTED_THERMOMETER_COUNT = 3; Thermometers::Thermometers(int numTempSensorPins, const PinName tempSensorPins[], int serviceIntervalInMs, Logger &logger) : _logger(logger) { _numTempSensorPins = numTempSensorPins; _tempSensorPins = tempSensorPins; _serviceIntervalInMs = serviceIntervalInMs; _numThermometerBuses = 0; _failAddrCount = 0; _failReadCount = 0; } void Thermometers::Init() { // Setup the thermometers for (int busIdx = 0; busIdx < _numTempSensorPins; busIdx++) { if (busIdx >= MAX_ONEWIRE_BUSES) break; _thermometerBuses[busIdx] = new DS18B20(_tempSensorPins[busIdx], _logger); DS18B20* pThermBus = _thermometerBuses[busIdx]; pThermBus->SearchToGetAddresses(); pThermBus->ReqConvert(); _numThermometerBuses++; } } void Thermometers::Service() { int numLoopsPerThermReading = numSecondsBetweenThermReadings*1000/_serviceIntervalInMs; int loopCountForRequestingThermReading = numLoopsPerThermReading - (timeForThermReadingInSecs*1000/_serviceIntervalInMs); // Check if thermometer addresses need to be got if (_countForThermReadings++ == 0) { if (_countForGetThermometerAddresses++ == 0) { #ifdef SHOW_THERMOMETER_DEBUGGING _logger.LogDebug("ThermReqAddr"); #endif for (int busIdx = 0; busIdx < _numThermometerBuses; busIdx++) { DS18B20* pThermBus = _thermometerBuses[busIdx]; int numTherms = pThermBus->SearchToGetAddresses(); if (numTherms != DEBUG_EXPECTED_THERMOMETER_COUNT) _failAddrCount++; } #ifdef SHOW_THERMOMETER_DEBUGGING for (int busIdx = 0; busIdx < _numThermometerBuses; busIdx++) { DS18B20* pThermBus = _thermometerBuses[busIdx]; if(_failAddrCount == 0 && _failReadCount == 0) { _logger.LogDebug("Therm B%d N%d OK", busIdx, pThermBus->GetNumAddresses()); } else { _logger.LogDebug("Therm B%d N%d FailAddr %d FailRead %d", busIdx, pThermBus->GetNumAddresses(), _failAddrCount, _failReadCount); } for (int addrIdx = 0; addrIdx < pThermBus->GetNumAddresses(); addrIdx++) { char buf [40]; pThermBus->DebugGetAddress(addrIdx, buf); _logger.LogDebug("Therm B%d N%d %s", busIdx, addrIdx, buf); } } #endif } else if (_countForGetThermometerAddresses > reGetThermometerAddressesAfterNumReadings) { _countForGetThermometerAddresses = 0; } } else { // Check if time to request thermometers to take readings if (_countForThermReadings == loopCountForRequestingThermReading) { #ifdef SHOW_THERMOMETER_DEBUGGING // _logger.LogDebug("ThermReqConv"); #endif for (int busIdx = 0; busIdx < _numThermometerBuses; busIdx++) { DS18B20* pThermBus = _thermometerBuses[busIdx]; pThermBus->ReqConvert(); } } // Check if it is time to get the values from the thermometers if (_countForThermReadings > numLoopsPerThermReading) { _countForThermReadings = 0; for (int busIdx = 0; busIdx < _numThermometerBuses; busIdx++) { DS18B20* pThermBus = _thermometerBuses[busIdx]; for (int addrIdx = 0; addrIdx < pThermBus->GetNumAddresses(); addrIdx++) { double tempValue = pThermBus->ReadTemperature(addrIdx); if (tempValue == DS18B20::INVALID_TEMPERATURE) _failReadCount++; } } #ifdef SHOW_THERMOMETER_DEBUGGING char tempStrBuf[140]; tempStrBuf[0] = 0; for (int busIdx = 0; busIdx < _numThermometerBuses; busIdx++) { DS18B20* pThermBus = _thermometerBuses[busIdx]; for (int addrIdx = 0; addrIdx < pThermBus->GetNumAddresses(); addrIdx++) { time_t timeOfReading = 0; double tempValue = pThermBus->GetLatestTemperature(addrIdx, timeOfReading); int ageInSecs = time(NULL) - timeOfReading; if (tempValue == DS18B20::INVALID_TEMPERATURE) sprintf(tempStrBuf+strlen(tempStrBuf), "%.2fC (INVALID) ", tempValue); else if (ageInSecs == 0) sprintf(tempStrBuf+strlen(tempStrBuf), "%.2fC ", tempValue); else sprintf(tempStrBuf+strlen(tempStrBuf), "%.2fC (%dS ago) ", tempValue, ageInSecs); } } _logger.LogDebug("Therm %s", tempStrBuf); #endif } } } int Thermometers::GetTemperatureValues(int maxTempValues, TemperatureValue* tempValues, int maxAgeInSecs) { // Go through available values int curTempValueIdx = 0; for (int busIdx = 0; busIdx < _numThermometerBuses; busIdx++) { DS18B20* pThermBus = _thermometerBuses[busIdx]; for (int addrIdx = 0; addrIdx < pThermBus->GetNumAddresses(); addrIdx++) { time_t timeOfReading = 0; double tempValue = pThermBus->GetLatestTemperature(addrIdx, timeOfReading); if (tempValue != DS18B20::INVALID_TEMPERATURE) { if ((time(NULL) - timeOfReading) < maxAgeInSecs) { tempValues[curTempValueIdx].timeStamp = timeOfReading; strncpy(tempValues[curTempValueIdx].address, pThermBus->GetAddressStr(addrIdx), DS18B20::ONEWIRE_ADDR_STRLEN-1); tempValues[curTempValueIdx].tempInCentigrade = tempValue; curTempValueIdx++; if (curTempValueIdx >= maxTempValues) break; } } } if (curTempValueIdx >= maxTempValues) break; } return curTempValueIdx; }