From a90c6a0ca4cd6bb0f36676c2e380295ae3ade678 Mon Sep 17 00:00:00 2001 From: Andersama Date: Sat, 11 Mar 2023 03:28:20 -0800 Subject: [PATCH] patch: add error code handling of temperatures tentative patch for handling issue #236 - adds unit types to force handling of different units with respect to each other - implicit conversions to floats only for result types from existing functions - basic error codes added as an enum, edit as needed --- DallasTemperature.cpp | 83 +++++++++------- DallasTemperature.h | 226 ++++++++++++++++++++++++++++++++++++++---- 2 files changed, 255 insertions(+), 54 deletions(-) diff --git a/DallasTemperature.cpp b/DallasTemperature.cpp index 860957d..040767a 100644 --- a/DallasTemperature.cpp +++ b/DallasTemperature.cpp @@ -613,33 +613,40 @@ DallasTemperature::request_t DallasTemperature::requestTemperaturesByIndex(uint8 } // Fetch temperature for device index -float DallasTemperature::getTempCByIndex(uint8_t deviceIndex) { - +DallasTemperature::celsius_result_t DallasTemperature::getTempCByIndex(uint8_t deviceIndex) { + DallasTemperature::celsius_result_t c = {}; DeviceAddress deviceAddress; + if (!getAddress(deviceAddress, deviceIndex)) { - return DEVICE_DISCONNECTED_C; + c.value.celsius = DEVICE_DISCONNECTED_C; + c.error_code = DallasTemperature::device_error_code::device_fault_disconnected; + return c; } - return getTempC((uint8_t*) deviceAddress); + + return c = getTempC((uint8_t*)deviceAddress); } // Fetch temperature for device index -float DallasTemperature::getTempFByIndex(uint8_t deviceIndex) { - +DallasTemperature::fahrenheit_result_t DallasTemperature::getTempFByIndex(uint8_t deviceIndex) { + DallasTemperature::fahrenheit_result_t f = {}; DeviceAddress deviceAddress; if (!getAddress(deviceAddress, deviceIndex)) { - return DEVICE_DISCONNECTED_F; + f.value.fahrenheit = DEVICE_DISCONNECTED_F; + f.error_code = DallasTemperature::device_error_code::device_fault_disconnected; + return f; } - return getTempF((uint8_t*) deviceAddress); - + return f = getTempF((uint8_t*) deviceAddress); } // reads scratchpad and returns fixed-point temperature, scaling factor 2^-7 -int32_t DallasTemperature::calculateTemperature(const uint8_t* deviceAddress, +DallasTemperature::raw_result_t DallasTemperature::calculateTemperature(const uint8_t* deviceAddress, uint8_t* scratchPad) { - - int32_t fpTemperature = 0; + DallasTemperature::raw_result_t r = {}; + r.reading.raw = 0; + r.error_code = DallasTemperature::device_error_code::device_ok; + int32_t &fpTemperature = r.reading.raw; // looking thru the spec sheets of all supported devices, bit 15 is always the signing bit // Detected if signed @@ -657,22 +664,22 @@ int32_t DallasTemperature::calculateTemperature(const uint8_t* deviceAddress, if (deviceAddress[DSROM_FAMILY] == DS1825MODEL && scratchPad[CONFIGURATION] & 0x80 ) { //Serial.print(" Detected MAX31850"); if (scratchPad[TEMP_LSB] & 1) { // Fault Detected - if (scratchPad[HIGH_ALARM_TEMP] & 1) { - //Serial.println("open detected"); - return DEVICE_FAULT_OPEN_RAW; - } - else if (scratchPad[HIGH_ALARM_TEMP] >> 1 & 1) { - //Serial.println("short to ground detected"); - return DEVICE_FAULT_SHORTGND_RAW; + // backwards compatability magic number for default error + r.reading.raw = DEVICE_DISCONNECTED_RAW; // We don't know why there's a fault, exit with disconnect value + r.error_code = (scratchPad[HIGH_ALARM_TEMP] & 0x7) | DallasTemperature::device_error_code::device_fault_general; + + // for backwards compatability, new api could ignore this and send the raw data + if (scratchPad[HIGH_ALARM_TEMP] & DallasTemperature::device_error_code::device_fault_open) { + r.reading.raw = DEVICE_FAULT_OPEN_RAW; } else if (scratchPad[HIGH_ALARM_TEMP] >> 2 & 1) { - //Serial.println("short to Vdd detected"); - return DEVICE_FAULT_SHORTVDD_RAW; + r.reading.raw = DEVICE_FAULT_SHORTGND_RAW; } - else { - // We don't know why there's a fault, exit with disconnect value - return DEVICE_DISCONNECTED_RAW; + else if (scratchPad[HIGH_ALARM_TEMP] >> 2 & 1) { + r.reading.raw = DEVICE_FAULT_SHORTVDD_RAW; } + + return r; } // We must mask out bit 1 (reserved) and 0 (fault) on TEMP_LSB fpTemperature = (((int32_t) scratchPad[TEMP_MSB]) << 11) @@ -715,7 +722,7 @@ int32_t DallasTemperature::calculateTemperature(const uint8_t* deviceAddress, / scratchPad[COUNT_PER_C])) | neg; } - return fpTemperature; + return r; } // returns temperature in 1/128 degrees C or DEVICE_DISCONNECTED_RAW if the @@ -723,13 +730,15 @@ int32_t DallasTemperature::calculateTemperature(const uint8_t* deviceAddress, // the numeric value of DEVICE_DISCONNECTED_RAW is defined in // DallasTemperature.h. It is a large negative number outside the // operating range of the device -int32_t DallasTemperature::getTemp(const uint8_t* deviceAddress) { - +DallasTemperature::raw_result_t DallasTemperature::getTemp(const uint8_t* deviceAddress) { + DallasTemperature::raw_result_t r = {}; ScratchPad scratchPad; if (isConnected(deviceAddress, scratchPad)) - return calculateTemperature(deviceAddress, scratchPad); - return DEVICE_DISCONNECTED_RAW; - + return r = calculateTemperature(deviceAddress, scratchPad); + + r.reading.raw = DEVICE_DISCONNECTED_RAW; + r.error_code = DallasTemperature::device_error_code::device_disconnected; + return r; } // returns temperature in degrees C or DEVICE_DISCONNECTED_C if the @@ -737,8 +746,11 @@ int32_t DallasTemperature::getTemp(const uint8_t* deviceAddress) { // the numeric value of DEVICE_DISCONNECTED_C is defined in // DallasTemperature.h. It is a large negative number outside the // operating range of the device -float DallasTemperature::getTempC(const uint8_t* deviceAddress) { - return rawToCelsius(getTemp(deviceAddress)); +DallasTemperature::celsius_result_t DallasTemperature::getTempC(const uint8_t* deviceAddress) { + DallasTemperature::celsius_result_t c = {}; + DallasTemperature::raw_result_t r = getTemp(deviceAddress); + c.from_raw_result(r); + return c; } // returns temperature in degrees F or DEVICE_DISCONNECTED_F if the @@ -746,8 +758,11 @@ float DallasTemperature::getTempC(const uint8_t* deviceAddress) { // the numeric value of DEVICE_DISCONNECTED_F is defined in // DallasTemperature.h. It is a large negative number outside the // operating range of the device -float DallasTemperature::getTempF(const uint8_t* deviceAddress) { - return rawToFahrenheit(getTemp(deviceAddress)); +DallasTemperature::fahrenheit_result_t DallasTemperature::getTempF(const uint8_t* deviceAddress) { + DallasTemperature::fahrenheit_result_t f = {}; + DallasTemperature::raw_result_t r = getTemp(deviceAddress); + f.from_raw_result(r); + return f; } // returns true if the bus requires parasite power diff --git a/DallasTemperature.h b/DallasTemperature.h index 789880d..d758214 100644 --- a/DallasTemperature.h +++ b/DallasTemperature.h @@ -140,6 +140,21 @@ class DallasTemperature { void setCheckForConversion(bool); bool getCheckForConversion(void); + // convert from Celsius to Fahrenheit + static float toFahrenheit(float); + + // convert from Fahrenheit to Celsius + static float toCelsius(float); + + // convert from raw to Celsius + static float rawToCelsius(int32_t); + + // convert from Celsius to raw + static int16_t celsiusToRaw(float); + + // convert from raw to Fahrenheit + static float rawToFahrenheit(int32_t); + struct request_t { bool result; unsigned long timestamp; @@ -149,6 +164,192 @@ class DallasTemperature { } }; + enum device_error_code { + device_ok = 0, + device_connected = 0, + device_fault_open = 1, + device_fault_shortgnd = 2, + device_fault_shortvdd = 4, + device_fault_general = 8, + device_fault_disconnected = 16 + }; + + // Treat temperatures as their own distinct types + struct celsius_unit_t; + struct fahrenheit_unit_t; + struct kelvin_unit_t; + + // NOTE: conversions back to raw units? + struct raw_unit_t { + int32_t raw; + + raw_unit_t() = default; + + celsius_unit_t in_celsius() { + celsius_unit_t c; + c.celsius = rawToCelsius(raw); + return c; + }; + + kelvin_unit_t in_kelvin() { + kelvin_unit_t k; + k.kelvin = rawToCelsius(raw) + 273.15f; + return k; + }; + + fahrenheit_unit_t in_fahrenheit() { + fahrenheit_unit_t f; + f.fahrenheit = rawToFahrenheit(raw); + return f; + }; + }; + + struct celsius_unit_t { + float celsius; + + celsius_unit_t() = default; + + celsius_unit_t(raw_unit_t r) { + celsius = rawToCelsius(r.raw); + } + + void from_raw(raw_unit_t r) { + celsius = rawToCelsius(r.raw); + } + + celsius_unit_t in_celsius() { + return *this; + }; + + kelvin_unit_t in_kelvin() { + kelvin_unit_t k; + k.kelvin = celsius + 273.15f; + return k; + }; + + fahrenheit_unit_t in_fahrenheit() { + fahrenheit_unit_t f; + f.fahrenheit = toFahrenheit(celsius); + return f; + }; + }; + + struct fahrenheit_unit_t { + float fahrenheit; + + fahrenheit_unit_t() = default; + + fahrenheit_unit_t(raw_unit_t r) { + fahrenheit = rawToFahrenheit(r.raw); + } + + void from_raw(raw_unit_t r) { + fahrenheit = rawToFahrenheit(r.raw); + } + + celsius_unit_t in_celsius() { + celsius_unit_t c; + c.celsius = toCelsius(fahrenheit); + return c; + }; + + kelvin_unit_t in_kelvin() { + kelvin_unit_t k; + k.kelvin = toCelsius(fahrenheit) + 273.15f; + return k; + }; + + fahrenheit_unit_t in_fahrenheit() { + return *this; + }; + }; + + struct kelvin_unit_t { + float kelvin; + + kelvin_unit_t() = default; + + kelvin_unit_t(raw_unit_t r) { + kelvin = rawToCelsius(r.raw) + 273.15f; + } + + void from_raw(raw_unit_t r) { + kelvin = rawToCelsius(r.raw) + 273.15f; + } + + celsius_unit_t in_celsius() { + celsius_unit_t c; + c.celsius = kelvin - 273.15f; + return c; + }; + + kelvin_unit_t in_kelvin() { + return *this; + }; + + fahrenheit_unit_t in_fahrenheit() { + fahrenheit_unit_t f; + f.fahrenheit = toFahrenheit(kelvin - 273.15f); + return f; + }; + }; + + struct raw_result_t { + raw_unit_t reading; + uint32_t error_code; + + raw_result_t() = default; + + // NOTE: implicit conversion here is for backwards compatability + operator int32_t() { + return reading.raw; + } + }; + + struct celsius_result_t { + celsius_unit_t value; + uint32_t error_code = DallasTemperature::device_error_code::device_ok; + + void from_raw_result(raw_result_t r) { + value.celsius = rawToCelsius(r.reading.raw); + error_code = r.error_code; + } + + // NOTE: implicit conversion here is for backwards compatability + operator float() { + return value.celsius; + }; + }; + + struct fahrenheit_result_t { + fahrenheit_unit_t value; + uint32_t error_code; + + void from_raw_result(raw_result_t r) { + value.fahrenheit = rawToFahrenheit(r.reading.raw); + error_code = r.error_code; + } + + // NOTE: implicit conversion here is for backwards compatability + operator float() { + return value.fahrenheit; + }; + }; + + struct kelvin_result_t { + kelvin_unit_t value; + uint32_t error_code; + + void from_raw_result(raw_result_t r) { + value.kelvin = rawToCelsius(r.reading.raw) + 273.15f; + error_code = r.error_code; + } + + // NOTE: not including implicit conversion for kelvin simply because currently + // there are no functions that returns temperatures in kelvin no need to be + // backwards compatible here + }; + // sends command for all devices on the bus to perform a temperature conversion request_t requestTemperatures(void); @@ -162,16 +363,16 @@ class DallasTemperature { int32_t getTemp(const uint8_t*); // returns temperature in degrees C - float getTempC(const uint8_t*); + celsius_result_t getTempC(const uint8_t*); // returns temperature in degrees F - float getTempF(const uint8_t*); + fahrenheit_result_t getTempF(const uint8_t*); // Get temperature for device index (slow) - float getTempCByIndex(uint8_t); + celsius_result_t getTempCByIndex(uint8_t); // Get temperature for device index (slow) - float getTempFByIndex(uint8_t); + fahrenheit_result_t getTempFByIndex(uint8_t); // returns true if the bus requires parasite power bool isParasitePowerMode(void); @@ -258,21 +459,6 @@ class DallasTemperature { int16_t getUserData(const uint8_t*); int16_t getUserDataByIndex(uint8_t); - // convert from Celsius to Fahrenheit - static float toFahrenheit(float); - - // convert from Fahrenheit to Celsius - static float toCelsius(float); - - // convert from raw to Celsius - static float rawToCelsius(int32_t); - - // convert from Celsius to raw - static int16_t celsiusToRaw(float); - - // convert from raw to Fahrenheit - static float rawToFahrenheit(int32_t); - #if REQUIRESNEW // initialize memory area @@ -320,7 +506,7 @@ class DallasTemperature { OneWire* _wire; // reads scratchpad and returns the raw temperature - int32_t calculateTemperature(const uint8_t*, uint8_t*); + raw_result_t calculateTemperature(const uint8_t*, uint8_t*); // Returns true if all bytes of scratchPad are '\0'