diff --git a/adafruit_max31856.py b/adafruit_max31856.py index 867b20e..4427d4b 100644 --- a/adafruit_max31856.py +++ b/adafruit_max31856.py @@ -124,8 +124,7 @@ class MAX31856: :param ~microcontroller.Pin cs: The pin used for the CS signal. :param ~adafruit_max31856.ThermocoupleType thermocouple_type: The type of thermocouple.\ Default is Type K. - :param ~int sampling: Number of samples to be averaged [1,2,4,8,16] - :param ~bool filter_50hz: Filter 50Hz mains frequency instead of 60Hz + :param ~int baudrate: The SPI baudrate. Default is 500000. **Quickstart: Importing and using the MAX31856** @@ -164,8 +163,9 @@ def __init__( spi: SPI, cs: DigitalInOut, # pylint: disable=invalid-name thermocouple_type: int = ThermocoupleType.K, + baudrate: int = 500000, ) -> None: - self._device = SPIDevice(spi, cs, baudrate=500000, polarity=0, phase=1) + self._device = SPIDevice(spi, cs, baudrate=baudrate, polarity=0, phase=1) # assert on any fault self._write_u8(_MAX31856_MASK_REG, 0x0) @@ -253,6 +253,35 @@ def unpack_temperature(self) -> float: return temp_float + def read_high_res_temp(self) -> float: + """Reads 19-bit temperature data from the sensor and returns it in degrees Celsius. + + Reading must have already been initiated via: + `initiate_one_shot_measurement` or `start_autoconverting`. + + Returns: + float: temperature in degrees Celsius + """ + # Per datasheet, temperature resolution in °C per LSB + resolution = 0.0078125 + + # Read the temperature registers + raw_bytes = self._read_sequential_registers(_MAX31856_LTCBH_REG, 3) + # Extract individual bytes from the byte array + high_byte = raw_bytes[0] # First byte + mid_byte = raw_bytes[1] # Second byte + low_byte = raw_bytes[2] # Third byte + + # Combine the bytes into a single 19-bit value + combined = (high_byte << 11) | (mid_byte << 3) | (low_byte >> 5) + + # Adjust for two's complement (sign extension for negative values) + if combined & 0x40000: # Check if 19th bit is set (negative temperature) + combined = combined - 0x80000 + + # Convert to temperature using the resolution + return combined * resolution + @property def reference_temperature(self) -> float: """Wait to retrieve temperature of the cold junction in degrees Celsius. (read-only)""" @@ -363,6 +392,21 @@ def initiate_one_shot_measurement(self) -> None: # write it back with the new values, prompting the sensor to perform a measurement self._write_u8(_MAX31856_CR0_REG, conf_reg_0) + def start_autoconverting(self) -> None: # pylint: disable=no-self-use + """Starts autoconverting temperature measurements. + The sensor will perform a measurement every ~100ms. + """ + # read the current value of the first config register + conf_reg_0 = self._read_register(_MAX31856_CR0_REG, 1)[0] + + # and the complement to guarantee the oneshot bit is unset + conf_reg_0 &= ~_MAX31856_CR0_1SHOT + # or the autoconvert bit to ensure it is set + conf_reg_0 |= _MAX31856_CR0_AUTOCONVERT + + # write it back with the new values, prompting the sensor to perform a measurement + self._write_u8(_MAX31856_CR0_REG, conf_reg_0) + @property def oneshot_pending(self) -> bool: """A boolean indicating the status of the one-shot flag. @@ -386,6 +430,19 @@ def _read_register(self, address: int, length: int) -> bytearray: device.readinto(self._BUFFER, end=length) return self._BUFFER[:length] + def _read_sequential_registers(self, start_addr, num_registers=3) -> bytearray: + """ + Read a sequence of `num_registers` registers, starting from `start_addr`. + """ + assert num_registers >= 1, "Number of registers to read must be at least 1" + buf = bytearray(num_registers) + with self._device as device: + # Send read command and start address + device.write(bytearray([start_addr & 0x7F])) + # Read the specified number of registers into the buffer + device.readinto(buf) + return buf + def _write_u8(self, address: int, val: int) -> None: # Write an 8-bit unsigned value to the specified 8-bit address. with self._device as device: