aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorcombolek <4743344+combolek@users.noreply.github.com>2020-07-19 17:18:54 -0700
committerGitHub <noreply@github.com>2020-07-19 20:18:54 -0400
commit3835654116fd77f539bf643bf22c14fbf43d953b (patch)
tree603591ac21b940a6d47a273f91bd8932b250bb8a
parentb0901daa85d95a4020056a030c6aecb02df22d1e (diff)
downloadkutter-3835654116fd77f539bf643bf22c14fbf43d953b.tar.gz
kutter-3835654116fd77f539bf643bf22c14fbf43d953b.tar.xz
kutter-3835654116fd77f539bf643bf22c14fbf43d953b.zip
lm75: Added support for LM75/LM75A I2C connected temperature sensors (#3101)
Signed-off-by: Boleslaw Ciesielski <combolek@users.noreply.github.com>
-rw-r--r--config/example-extras.cfg24
-rw-r--r--klippy/extras/heaters.py2
-rw-r--r--klippy/extras/lm75.py107
3 files changed, 132 insertions, 1 deletions
diff --git a/config/example-extras.cfg b/config/example-extras.cfg
index f5f6bdb4..89279da9 100644
--- a/config/example-extras.cfg
+++ b/config/example-extras.cfg
@@ -1036,6 +1036,30 @@
#htu21d_report_time:
# interval in seconds between readings. Default is 30
+# LM75/LM75A two wire (I2C) connected temperature sensors.
+# These sensors have range up to 125 C, so are usable for e.g. chamber
+# temperature monitoring. They can also function as simple
+# fan/heater controllers but this mode is not used here.
+#[temperature_sensor my_sensor]
+# See the "temperature_sensor" section below for a description of its
+# parameters. The parameters below describe LM75 family sensor parameters.
+#sensor_type:
+# Must be "LM75"
+#i2c_address:
+# Default is 72 (0x48). Normal range is 72-79 (0x48-0x4F) and the 3 low
+# bits of the address are configured via pins on the chip (usually
+# with jumpers or hard wired).
+#i2c_mcu:
+# MCU the sensor is connected to. Default is the primary mcu.
+#i2c_bus:
+# The I2C bus the sensor is connected to. On some MCU platforms the default
+# is bus 0. On platforms without bus 0 this parameter is required.
+#i2c_speed:
+# The I2C speed (in Hz) to use when communicating with the sensor. Default
+# is 100000. On some MCUs changing this value has no effect.
+#lm75_report_time:
+# interval in seconds between readings. Default is 0.8, with minimum 0.5
+
# Generic heaters (one may define any number of sections with a
# "heater_generic" prefix). These heaters behave similarly to standard
# heaters (extruders, heated beds). Use the SET_HEATER_TEMPERATURE
diff --git a/klippy/extras/heaters.py b/klippy/extras/heaters.py
index e5cb4dbd..e66168c5 100644
--- a/klippy/extras/heaters.py
+++ b/klippy/extras/heaters.py
@@ -261,7 +261,7 @@ class PrinterHeaters:
return self.heaters[heater_name]
def setup_sensor(self, config):
modules = ["thermistor", "adc_temperature", "spi_temperature",
- "bme280", "htu21d"]
+ "bme280", "htu21d", "lm75"]
for module_name in modules:
self.printer.load_object(config, module_name)
sensor_type = config.get('sensor_type')
diff --git a/klippy/extras/lm75.py b/klippy/extras/lm75.py
new file mode 100644
index 00000000..ca6f474d
--- /dev/null
+++ b/klippy/extras/lm75.py
@@ -0,0 +1,107 @@
+# Support for I2C based LM75/LM75A temperature sensors
+#
+# Copyright (C) 2020 Boleslaw Ciesielski <combolek@users.noreply.github.com>
+#
+# This file may be distributed under the terms of the GNU GPLv3 license.
+import logging
+from . import bus
+
+LM75_CHIP_ADDR = 0x48
+LM75_I2C_SPEED = 100000
+LM75_REGS = {
+ 'TEMP' : 0x00,
+ 'CONF' : 0x01,
+ 'THYST' : 0x02,
+ 'TOS' : 0x03,
+ 'PRODID' : 0x07 # TI LM75A chips only?
+}
+LM75_REPORT_TIME = .8
+# Temperature can be sampled at any time but the read aborts
+# the current conversion. Conversion time is 300ms so make
+# sure not to read too often.
+LM75_MIN_REPORT_TIME = .5
+
+class LM75:
+ def __init__(self, config):
+ self.printer = config.get_printer()
+ self.name = config.get_name().split()[-1]
+ self.reactor = self.printer.get_reactor()
+ self.i2c = bus.MCU_I2C_from_config(
+ config,
+ default_addr=LM75_CHIP_ADDR,
+ default_speed=LM75_I2C_SPEED
+ )
+ self.mcu = self.i2c.get_mcu()
+ self.report_time = config.getint(
+ 'lm75_report_time',
+ LM75_REPORT_TIME,
+ minval=LM75_MIN_REPORT_TIME
+ )
+ self.temp = 0.0
+ self.sample_timer = self.reactor.register_timer(self._sample_lm75)
+ self.printer.add_object("lm75 " + self.name, self)
+ self.printer.register_event_handler("klippy:ready", self.handle_ready)
+
+ def handle_ready(self):
+ self._init_lm75()
+ self.reactor.update_timer(self.sample_timer, self.reactor.NOW)
+
+ def setup_minmax(self, min_temp, max_temp):
+ pass
+
+ def setup_callback(self, cb):
+ self._callback = cb
+
+ def get_report_time_delta(self):
+ return self.report_time
+
+ def degrees_from_sample(self, x):
+ # The temp sample is encoded in the top 9 bits of a 16-bit
+ # value. Resolution is 0.5 degrees C.
+ return x[0] + (x[1] >> 7) * 0.5
+
+ def _init_lm75(self):
+ # Check and report the chip ID but ignore errors since many
+ # chips don't have it
+ try:
+ prodid = self.read_register('PRODID', 1)[0]
+ logging.info("lm75: Chip ID %#x" % prodid)
+ except:
+ pass
+
+ def _sample_lm75(self, eventtime):
+ try:
+ sample = self.read_register('TEMP', 2)
+ self.temp = self.degrees_from_sample(sample)
+ except Exception:
+ logging.exception("lm75: Error reading data")
+ self.temp = 0.0
+ return self.reactor.NEVER
+
+ measured_time = self.reactor.monotonic()
+ self._callback(self.mcu.estimated_print_time(measured_time), self.temp)
+ return measured_time + self.report_time
+
+ def read_register(self, reg_name, read_len):
+ # read a single register
+ regs = [LM75_REGS[reg_name]]
+ params = self.i2c.i2c_read(regs, read_len)
+ return bytearray(params['response'])
+
+ def write_register(self, reg_name, data):
+ if type(data) is not list:
+ data = [data]
+ reg = LM75_REGS[reg_name]
+ data.insert(0, reg)
+ self.i2c.i2c_write(data)
+
+ def get_status(self, eventtime):
+ return {
+ 'temperature': self.temp,
+ }
+
+
+def load_config(config):
+ # Register sensor
+ pheaters = config.get_printer().load_object(config, "heaters")
+ pheaters.add_sensor_factory("LM75", LM75)