Skip to content

Commit

Permalink
patch: add error code handling of temperatures
Browse files Browse the repository at this point in the history
tentative patch for handling issue milesburton#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
  • Loading branch information
Andersama committed Mar 11, 2023
1 parent e3c7276 commit c04633c
Show file tree
Hide file tree
Showing 2 changed files with 227 additions and 37 deletions.
51 changes: 34 additions & 17 deletions DallasTemperature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -636,10 +636,11 @@ 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,
raw_result_t DallasTemperature::calculateTemperature(const uint8_t* deviceAddress,
uint8_t* scratchPad) {

int32_t fpTemperature = 0;
raw_result_t r;
r.reading.raw = 0;
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
Expand All @@ -659,19 +660,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 = 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 = 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 = 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 = device_error_code::device_disconnected;
return r;
}
}
// We must mask out bit 1 (reserved) and 0 (fault) on TEMP_LSB
Expand Down Expand Up @@ -715,39 +724,47 @@ 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
// device's scratch pad cannot be read successfully.
// 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) {

raw_result_t DallasTemperature::getTemp(const uint8_t* deviceAddress) {
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 = device_error_code::device_disconnected;
return r;
}

// returns temperature in degrees C or DEVICE_DISCONNECTED_C if the
// device's scratch pad cannot be read successfully.
// 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));
celsius_result_t DallasTemperature::getTempC(const uint8_t* deviceAddress) {
celsius_result_t c;
raw_result_t r = getTemp(deviceAddress);
c.from_raw_result(r);
return c;
}

// returns temperature in degrees F or DEVICE_DISCONNECTED_F if the
// device's scratch pad cannot be read successfully.
// 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));
fahrenheit_result_t DallasTemperature::getTempF(const uint8_t* deviceAddress) {
fahrenheit_result_t f;
raw_result_t r = getTemp(deviceAddress);
f.from_raw_result(r);
return f;
}

// returns true if the bus requires parasite power
Expand Down
213 changes: 193 additions & 20 deletions DallasTemperature.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -149,6 +164,179 @@ class DallasTemperature {
}
};

enum device_error_code {
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;

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);

Expand All @@ -162,16 +350,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);
Expand Down Expand Up @@ -258,21 +446,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
Expand Down Expand Up @@ -320,7 +493,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'
Expand Down

0 comments on commit c04633c

Please sign in to comment.