From 77201ab7534c34355b1d603157e1359471ed63f6 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 | 52 ++++++---- DallasTemperature.h | 214 ++++++++++++++++++++++++++++++++++++++---- 2 files changed, 229 insertions(+), 37 deletions(-) diff --git a/DallasTemperature.cpp b/DallasTemperature.cpp index 860957d..5894272 100644 --- a/DallasTemperature.cpp +++ b/DallasTemperature.cpp @@ -636,10 +636,12 @@ float DallasTemperature::getTempFByIndex(uint8_t deviceIndex) { } // 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 @@ -659,19 +661,27 @@ int32_t DallasTemperature::calculateTemperature(const uint8_t* deviceAddress, if (scratchPad[TEMP_LSB] & 1) { // Fault Detected if (scratchPad[HIGH_ALARM_TEMP] & 1) { //Serial.println("open detected"); - return DEVICE_FAULT_OPEN_RAW; + r.reading.raw = DEVICE_FAULT_OPEN_RAW; + r.error_code = DallasTemperature::device_error_code::device_fault_open; + return r; //return DEVICE_FAULT_OPEN_RAW; } else if (scratchPad[HIGH_ALARM_TEMP] >> 1 & 1) { //Serial.println("short to ground detected"); - return DEVICE_FAULT_SHORTGND_RAW; + r.reading.raw = DEVICE_FAULT_SHORTGND_RAW; + r.error_code = DallasTemperature::device_error_code::device_fault_shortgnd; + return r; } else if (scratchPad[HIGH_ALARM_TEMP] >> 2 & 1) { //Serial.println("short to Vdd detected"); - return DEVICE_FAULT_SHORTVDD_RAW; + r.reading.raw = DEVICE_FAULT_SHORTVDD_RAW; + r.error_code = DallasTemperature::device_error_code::device_fault_shortvdd; + return r; } else { // We don't know why there's a fault, exit with disconnect value - return DEVICE_DISCONNECTED_RAW; + r.reading.raw = DEVICE_DISCONNECTED_RAW; + r.error_code = DallasTemperature::device_error_code::device_disconnected; + return r; } } // We must mask out bit 1 (reserved) and 0 (fault) on TEMP_LSB @@ -715,7 +725,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 +733,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 +749,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 +761,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..b975b00 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,180 @@ class DallasTemperature { } }; + enum device_error_code { + device_connected = 0, + device_disconnected = 1, + device_fault_open = 2, + device_fault_shortgnd = 3, + device_fault_shortvdd = 4 + }; + + // 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; + + 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(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(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(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; + + // 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 = 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.celsius = 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 +351,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 +447,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 +494,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'