Files
brewpi/components/sensor/tempSensor_max31865.py
T
jensandClaude Sonnet 5 698c019581 refactor: make ATemperatureSensor's temp observable directly on the sensor
TempSensorSim/TempSensor_max31865's temperature() now stores its
reading on self.temp, so ATemperatureSensor's inherited AttributeChange
(previously never triggered by anything) actually fires. TempSensorTask
no longer keeps its own shadow copy of the reading - it registers its
websocket-push callback on self.sensor directly and just drives the
read each tick; server/brewpi.py's TC-feeding registration moved from
sensor_task to sensor for the same reason.

Priming read happens before registering the callback (not after) since
all tasks are built synchronously at module level, before the asyncio
event loop starts - registering first would fire on_temp_changed's
asyncio.create_task() with no running loop.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GpePKZiEZWbGo9HrfuML6U
2026-07-02 22:03:50 +02:00

130 lines
2.4 KiB
Python
Executable File

#!/usr/bin/env python3
import time
from components import ATemperatureSensor, TemperatureSensorException
import spidev
class TempSensor_max31865(ATemperatureSensor):
def name(self):
return "Max31865"
def __init__(self, temp_offset=0, **kwargs):
ATemperatureSensor.__init__(self)
# Open SPI bus
self.spi = spidev.SpiDev()
self.spi.open(0, 0)
self.spi.max_speed_hz = 50000
self.spi.mode = 0b01
self.temp_offset = temp_offset
self.write_reg(0x00, 0xA3)
def read_reg(self, addr):
reg = self.spi.xfer([addr, 0xFF])
return reg[1]
def write_reg(self, addr, data):
self.spi.xfer([addr+0x80, data])
def read_digits(self):
for i in range(0, 10):
reg = self.read_reg(0x00)
if (0x20 & reg) == 0:
break
time.sleep(0.01)
digits = 0
msb = self.read_reg(0x01)
lsb = self.read_reg(0x02)
self.write_reg(0x00, 0xA3)
if lsb & 0x01 == 0x00:
digits = (256*msb + lsb) >> 1
else:
raise TemperatureSensorException("Could not read sensor!")
return digits
def temperature(self):
digits = self.read_digits()
self.temp = self.temp_offset + self.to_temperature(digits)
return self.temp
@staticmethod
def to_temperature(digits):
T = 0
R = __class__.calc_R(430, digits)
T = __class__.vanDusen_temp(R)
return T
@staticmethod
def calc_R(Rref, digits):
k = float(digits) / 32768
R = k*Rref
return R
@staticmethod
def vanDusen_temp(Rmeas):
RLut, TLut = __class__.vanDusenLut(100, -150, +500, 1.0)
# Find candidate
i = 0
for R in RLut:
if R > Rmeas:
break
i += 1
# Linear interpolation
R0 = RLut[i-1]
R1 = RLut[i]
T0 = TLut[i-1]
T1 = TLut[i]
dR = R1 - R0
dT = T1 - T0
k = (Rmeas-R0)/dR
T = T0 + dT*k
return T
@staticmethod
def vanDusenLut (R0, Tmin, Tmax, dT):
a = +3.90830e-03
b = -5.77500e-07
c = -4.18301e-12
Rv = []
Tv = []
T = Tmin
while T <= Tmax:
R = R0*(1 + a*T + b*T**2)
if T < 0.0:
R += R0*c*(T - 100)*T**3
Rv.append(R)
Tv.append(T)
T += dT
return Rv, Tv
# Main
if __name__ == '__main__':
sensor = TempSensor_max31865()
for k in range (0, 100):
for i in range (0, 8):
print("Reg[0x{}]: 0x{:02X}".format(i, sensor.read_reg(i)))
digits = sensor.read_digits()
print("Digits = {:04X}".format(digits))
print("Temperature = {:0.2f} °C".format(TempSensor_max31865.to_temperature(digits)))
time.sleep(0.5)
print("End of program")