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 RdDS18B20.cpp Source File

RdDS18B20.cpp

00001 // Handles OneWire temperature sensors DB18S20
00002 // Can handle multiple devices per pin
00003 // Rob Dobson, 2015
00004 
00005 #include "RdDS18B20.h"
00006 
00007 // #define SHOW_18B20_DEBUGGING 1
00008 
00009 // Construct onewire bus with desired pin
00010 DS18B20::DS18B20(PinName mbedPin, Logger &logger) : _oneWire(mbedPin), _logger(logger)
00011 {
00012     _numValidAddresses = 0;
00013     for (int i = 0; i < MAX_BUS_DEVICES; i++)
00014     {
00015         _temperatureTable[i] = INVALID_TEMPERATURE;
00016         _timeOfReadingTable[i] = 0;    
00017     }
00018 }
00019 
00020 // Request conversion
00021 void DS18B20::ReqConvert()
00022 {
00023     // Request conversion begins
00024     _oneWire.init();
00025     _oneWire.writeByte(0xCC);
00026     _oneWire.writeByte(0x44);
00027 }
00028 
00029 // Get temperature
00030 double DS18B20::ReadTemperature(int addrIdx)
00031 {
00032     // Check valid address
00033     if ((addrIdx >= _numValidAddresses) || (addrIdx < 0))
00034         return INVALID_TEMPERATURE;
00035     
00036     // Init the bus and req reading
00037     _oneWire.init();
00038     _oneWire.writeByte(0x55);
00039     
00040     // Send the address
00041     for (int i = 0; i < 8; i++)
00042         _oneWire.writeByte(_addrTable[addrIdx][i]);
00043     _oneWire.writeByte(0xBE);
00044 
00045     // Temperature val
00046     unsigned char temperatureVals[9];
00047 
00048     // Read values back
00049     for (int i = 0; i < sizeof(temperatureVals)/sizeof(int); i++)
00050     {
00051         temperatureVals[i] = _oneWire.readByte();
00052     }
00053     _oneWire.init();
00054     
00055     // Check the CRC
00056     if (_oneWire.CRC(temperatureVals, sizeof(temperatureVals)/sizeof(int)-1) == temperatureVals[sizeof(temperatureVals)/sizeof(int)-1])
00057     {
00058 #ifdef SHOW_18B20_DEBUGGING
00059         _logger.LogDebug("Temp CRC Fail addr %d", addrIdx);
00060 #endif
00061         return INVALID_TEMPERATURE;
00062     }
00063     else
00064     {
00065 #ifdef SHOW_18B20_DEBUGGING
00066         double temperature = ((((int)(temperatureVals[1])) * 256) + temperatureVals[0])*0.0625;
00067         _logger.LogDebug("Temp = %0.1f", temperature);
00068 #endif
00069     }
00070     
00071     // Convert temperature
00072     double temperature = ((((int)(temperatureVals[1])) * 256) + temperatureVals[0])*0.0625;
00073     
00074     // Do a bounds check
00075     if ((temperature < -10) || (temperature > 100))
00076     {
00077 #ifdef SHOW_18B20_DEBUGGING
00078         _logger.LogDebug("Temp out of bounds");
00079 #endif
00080         return INVALID_TEMPERATURE;
00081     }
00082     _temperatureTable[addrIdx] = temperature;
00083     _timeOfReadingTable[addrIdx] = time(NULL);
00084     return temperature; 
00085 }
00086 
00087 // Get address for a device
00088 uint8_t* DS18B20::GetAddress(int addrIdx, uint8_t* addrBufPtr)
00089 {
00090     if ((addrIdx >= _numValidAddresses) || (addrIdx < 0))
00091         return _addrTable[0];
00092     // Make a copy if non-null pointer passed in
00093     if (addrBufPtr != NULL)
00094     {
00095         for( int i = 0; i < ONEWIRE_ADDR_BYTES; i++) 
00096             addrBufPtr[i] = _addrTable[addrIdx][i];
00097     }
00098     return _addrTable[addrIdx];
00099 }
00100 
00101 // Get address as a string
00102 char* DS18B20::GetAddressStr(int addrIdx)
00103 {
00104     if ((addrIdx >= _numValidAddresses) || (addrIdx < 0))
00105         return "";
00106     sprintf(_addrStr, "%02x%02x%02x%02x%02x%02x%02x%02x", 
00107         _addrTable[addrIdx][0], _addrTable[addrIdx][1], _addrTable[addrIdx][2], 
00108         _addrTable[addrIdx][3], _addrTable[addrIdx][4], _addrTable[addrIdx][5], 
00109         _addrTable[addrIdx][6], _addrTable[addrIdx][7]);
00110     return _addrStr;
00111 }
00112     
00113 // Debug print address
00114 void DS18B20::DebugGetAddress(int addrIdx, char* buf)
00115 {
00116     // Check valid address
00117     if ((addrIdx >= _numValidAddresses) || (addrIdx < 0))
00118     {
00119         sprintf(buf, "Invalid addrIdx %d", addrIdx);
00120         return;
00121     }
00122     // Write out address
00123     strcpy(buf, GetAddressStr(addrIdx));
00124 }
00125 
00126 double DS18B20::GetLatestTemperature(int addrIdx, time_t& timeOfReading)
00127 {
00128     if ((addrIdx >= _numValidAddresses) || (addrIdx < 0))
00129         return INVALID_TEMPERATURE;
00130     timeOfReading = _timeOfReadingTable[addrIdx];
00131     return _temperatureTable[addrIdx];
00132 }
00133 
00134 int DS18B20::SearchToGetAddresses()
00135 {
00136     const int MAX_ADDR_SEARCH_RETRIES = 5;
00137 
00138     // Address Table
00139     uint8_t tmpAddrTable[MAX_BUS_DEVICES][ONEWIRE_ADDR_BYTES];
00140     int validAddresses = 0;
00141     bool okResultAchieved = false;
00142         
00143     // Try a number of times
00144     for (int retryCount = 0; retryCount < MAX_ADDR_SEARCH_RETRIES; retryCount++)
00145     {
00146         // Check if the last search was ok (if there was one)
00147         if (okResultAchieved)
00148         {
00149             // Copy found addresses
00150             for (int addrIdx = 0; addrIdx < validAddresses; addrIdx++)
00151             {
00152                 for( int i = 0; i < ONEWIRE_ADDR_BYTES; i++) 
00153                     _addrTable[addrIdx][i] = tmpAddrTable[addrIdx][i];
00154             }
00155             _numValidAddresses = validAddresses;
00156             break;
00157         }
00158         
00159         // Start another search
00160         validAddresses = 0;
00161         _oneWire.reset_search();
00162         for (int addrIdx = 0; addrIdx < MAX_BUS_DEVICES; addrIdx++)
00163         {
00164             uint8_t addr[8];
00165             uint8_t rslt = _oneWire.search(addr);
00166             if (rslt == ONEWIRE_SEARCH_ALL_DONE)
00167             {
00168                 if (validAddresses >= _numValidAddresses)
00169                     okResultAchieved = true;
00170                 break;
00171             }
00172             if (rslt != ONEWIRE_OK)
00173             {
00174 #ifdef SHOW_18B20_DEBUGGING
00175 //                _logger.LogDebug("Search returned %s", _oneWire.GetErrorStr(rslt));
00176                 _logger.LogDebug("Search returned %d", rslt);
00177 #endif
00178                 break;
00179             }
00180             
00181             for( int i = 0; i < ONEWIRE_ADDR_BYTES; i++) 
00182             {
00183                 // Copy to table
00184                 tmpAddrTable[validAddresses][i] = addr[i];
00185             }
00186         
00187             // Check CRC - only include if CRC is valid
00188             bool addrValid = (_oneWire.CRC(addr, ONEWIRE_ADDR_BYTES-1) == addr[ONEWIRE_ADDR_BYTES-1]);
00189             if (addrValid)
00190                 validAddresses++;
00191 
00192 #ifdef SHOW_18B20_DEBUGGING
00193             _logger.LogDebug("Found addr (ROM) = %02x%02x%02x%02x%02x%02x%02x%02x %s %s", 
00194                 addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7],
00195                 (addrValid ? "CRC OK" : "CRC INVALID"),
00196                 GetChipId(addr[0]));
00197 #endif
00198         }
00199         
00200     }
00201     return validAddresses;
00202 }
00203 
00204 char* DS18B20::GetChipId(int val)
00205 {
00206     // the first ROM byte indicates which chip
00207     switch (val)
00208     {
00209         case 0x10:
00210             return("Chip = DS18S20");  // or old DS1820
00211         case 0x28:
00212             return("Chip = DS18B20");
00213         case 0x22:
00214             return("Chip = DS1822");
00215     } 
00216     return("Chip NOT DS18x20 FAMILY");
00217 }