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
RdDS18B20.cpp
- Committer:
- Bobty
- Date:
- 2015-10-16
- Revision:
- 23:fd5a5a9f30bc
- Parent:
- 21:ccf053bab795
File content as of revision 23:fd5a5a9f30bc:
// Handles OneWire temperature sensors DB18S20 // Can handle multiple devices per pin // Rob Dobson, 2015 #include "RdDS18B20.h" // #define SHOW_18B20_DEBUGGING 1 // Construct onewire bus with desired pin DS18B20::DS18B20(PinName mbedPin, Logger &logger) : _oneWire(mbedPin), _logger(logger) { _numValidAddresses = 0; for (int i = 0; i < MAX_BUS_DEVICES; i++) { _temperatureTable[i] = INVALID_TEMPERATURE; _timeOfReadingTable[i] = 0; } } // Request conversion void DS18B20::ReqConvert() { // Request conversion begins _oneWire.init(); _oneWire.writeByte(0xCC); _oneWire.writeByte(0x44); } // Get temperature double DS18B20::ReadTemperature(int addrIdx) { // Check valid address if ((addrIdx >= _numValidAddresses) || (addrIdx < 0)) return INVALID_TEMPERATURE; // Init the bus and req reading _oneWire.init(); _oneWire.writeByte(0x55); // Send the address for (int i = 0; i < 8; i++) _oneWire.writeByte(_addrTable[addrIdx][i]); _oneWire.writeByte(0xBE); // Temperature val unsigned char temperatureVals[9]; // Read values back for (int i = 0; i < sizeof(temperatureVals)/sizeof(int); i++) { temperatureVals[i] = _oneWire.readByte(); } _oneWire.init(); // Check the CRC if (_oneWire.CRC(temperatureVals, sizeof(temperatureVals)/sizeof(int)-1) == temperatureVals[sizeof(temperatureVals)/sizeof(int)-1]) { #ifdef SHOW_18B20_DEBUGGING _logger.LogDebug("Temp CRC Fail addr %d", addrIdx); #endif return INVALID_TEMPERATURE; } else { #ifdef SHOW_18B20_DEBUGGING double temperature = ((((int)(temperatureVals[1])) * 256) + temperatureVals[0])*0.0625; _logger.LogDebug("Temp = %0.1f", temperature); #endif } // Convert temperature double temperature = ((((int)(temperatureVals[1])) * 256) + temperatureVals[0])*0.0625; // Do a bounds check if ((temperature < -10) || (temperature > 100)) { #ifdef SHOW_18B20_DEBUGGING _logger.LogDebug("Temp out of bounds"); #endif return INVALID_TEMPERATURE; } _temperatureTable[addrIdx] = temperature; _timeOfReadingTable[addrIdx] = time(NULL); return temperature; } // Get address for a device uint8_t* DS18B20::GetAddress(int addrIdx, uint8_t* addrBufPtr) { if ((addrIdx >= _numValidAddresses) || (addrIdx < 0)) return _addrTable[0]; // Make a copy if non-null pointer passed in if (addrBufPtr != NULL) { for( int i = 0; i < ONEWIRE_ADDR_BYTES; i++) addrBufPtr[i] = _addrTable[addrIdx][i]; } return _addrTable[addrIdx]; } // Get address as a string char* DS18B20::GetAddressStr(int addrIdx) { if ((addrIdx >= _numValidAddresses) || (addrIdx < 0)) return ""; 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]); return _addrStr; } // Debug print address void DS18B20::DebugGetAddress(int addrIdx, char* buf) { // Check valid address if ((addrIdx >= _numValidAddresses) || (addrIdx < 0)) { sprintf(buf, "Invalid addrIdx %d", addrIdx); return; } // Write out address strcpy(buf, GetAddressStr(addrIdx)); } double DS18B20::GetLatestTemperature(int addrIdx, time_t& timeOfReading) { if ((addrIdx >= _numValidAddresses) || (addrIdx < 0)) return INVALID_TEMPERATURE; timeOfReading = _timeOfReadingTable[addrIdx]; return _temperatureTable[addrIdx]; } int DS18B20::SearchToGetAddresses() { const int MAX_ADDR_SEARCH_RETRIES = 5; // 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) { // 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; } // Start another search validAddresses = 0; _oneWire.reset_search(); for (int addrIdx = 0; addrIdx < MAX_BUS_DEVICES; addrIdx++) { 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 // _logger.LogDebug("Search returned %s", _oneWire.GetErrorStr(rslt)); _logger.LogDebug("Search returned %d", rslt); #endif break; } for( int i = 0; i < ONEWIRE_ADDR_BYTES; i++) { // Copy to table tmpAddrTable[validAddresses][i] = addr[i]; } // Check CRC - only include if CRC is valid bool addrValid = (_oneWire.CRC(addr, ONEWIRE_ADDR_BYTES-1) == addr[ONEWIRE_ADDR_BYTES-1]); if (addrValid) validAddresses++; #ifdef SHOW_18B20_DEBUGGING _logger.LogDebug("Found addr (ROM) = %02x%02x%02x%02x%02x%02x%02x%02x %s %s", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7], (addrValid ? "CRC OK" : "CRC INVALID"), GetChipId(addr[0])); #endif } } return validAddresses; } char* DS18B20::GetChipId(int val) { // the first ROM byte indicates which chip switch (val) { case 0x10: return("Chip = DS18S20"); // or old DS1820 case 0x28: return("Chip = DS18B20"); case 0x22: return("Chip = DS1822"); } return("Chip NOT DS18x20 FAMILY"); }