Skip to content

Commit

Permalink
Merge pull request #28 from diegosolano/main
Browse files Browse the repository at this point in the history
Added SPI baudrate argument, high res temperature reading, and autoconvert function
  • Loading branch information
FoamyGuy authored Mar 11, 2024
2 parents 05844e4 + 764aec4 commit a30c936
Showing 1 changed file with 60 additions and 3 deletions.
63 changes: 60 additions & 3 deletions adafruit_max31856.py
Original file line number Diff line number Diff line change
Expand Up @@ -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**
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)"""
Expand Down Expand Up @@ -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.
Expand All @@ -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:
Expand Down

0 comments on commit a30c936

Please sign in to comment.