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-05
Revision:
19:0367cb46d003
Parent:
16:89778849e9f7
Child:
20:7933076df5af

File content as of revision 19:0367cb46d003:

// 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) : _oneWire(mbedPin)
{
    _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
        printf("Temp CRC Fail\r\n");
#endif
        return INVALID_TEMPERATURE;
    }
    else
    {
#ifdef SHOW_18B20_DEBUGGING
        double temperature = ((((int)(temperatureVals[1])) * 256) + temperatureVals[0])*0.0625;
        printf("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
        printf("Temp out of bounds\r\n");
#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::DebugPrintAddress(int addrIdx)
{
    // Check valid address
    if ((addrIdx >= _numValidAddresses) || (addrIdx < 0))
    {
        printf("Invalid addrIdx %d", addrIdx);
        return;
    }
    // Write out address
    printf(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
                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])
                validAddresses++;
#ifdef SHOW_18B20_DEBUGGING
            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;
            } 
#endif
        }
    }
    return validAddresses;
}