From 2de170018684dc4aff2b0072c9cc1eb4baaeb7fd Mon Sep 17 00:00:00 2001 From: Klippy-Tools-Bot Date: Thu, 1 Aug 2024 03:06:58 +0000 Subject: [PATCH] Autogenerated - Upstream 171e3bf --- klippy/.version | 2 +- klippy/docs/API_Server.md | 30 +++++ klippy/docs/Config_Reference.md | 89 ++++++++++++++ klippy/extras/ads1220.py | 187 +++++++++++++++++++++++++++++ klippy/extras/hx71x.py | 170 ++++++++++++++++++++++++++ klippy/extras/load_cell.py | 30 +++++ testcases/configs/ar100.config | 2 + testcases/configs/stm32f042.config | 2 + 8 files changed, 511 insertions(+), 1 deletion(-) create mode 100644 klippy/extras/ads1220.py create mode 100644 klippy/extras/hx71x.py create mode 100644 klippy/extras/load_cell.py diff --git a/klippy/.version b/klippy/.version index ec910b8..b2b0e8d 100644 --- a/klippy/.version +++ b/klippy/.version @@ -1 +1 @@ -6f5b54c +171e3bf diff --git a/klippy/docs/API_Server.md b/klippy/docs/API_Server.md index cc0922e..f29bbeb 100644 --- a/klippy/docs/API_Server.md +++ b/klippy/docs/API_Server.md @@ -364,6 +364,36 @@ and might later produce asynchronous messages such as: The "header" field in the initial query response is used to describe the fields found in later "data" responses. +### hx71x/dump_hx71x + +This endpoint is used to subscribe to raw HX711 and HX717 ADC data. +Obtaining these low-level ADC updates may be useful for diagnostic +and debugging purposes. Using this endpoint may increase Klipper's +system load. + +A request may look like: +`{"id": 123, "method":"hx71x/dump_hx71x", +"params": {"sensor": "load_cell", "response_template": {}}}` +and might return: +`{"id": 123,"result":{"header":["time","counts"]}}` +and might later produce asynchronous messages such as: +`{"params":{"data":[[3292.432935, 562534], [3292.4394937, 5625322]]}}` + +### ads1220/dump_ads1220 + +This endpoint is used to subscribe to raw ADS1220 ADC data. +Obtaining these low-level ADC updates may be useful for diagnostic +and debugging purposes. Using this endpoint may increase Klipper's +system load. + +A request may look like: +`{"id": 123, "method":"ads1220/dump_ads1220", +"params": {"sensor": "load_cell", "response_template": {}}}` +and might return: +`{"id": 123,"result":{"header":["time","counts"]}}` +and might later produce asynchronous messages such as: +`{"params":{"data":[[3292.432935, 562534], [3292.4394937, 5625322]]}}` + ### pause_resume/cancel This endpoint is similar to running the "PRINT_CANCEL" G-Code command. diff --git a/klippy/docs/Config_Reference.md b/klippy/docs/Config_Reference.md index 9be53df..f19f0eb 100644 --- a/klippy/docs/Config_Reference.md +++ b/klippy/docs/Config_Reference.md @@ -4645,6 +4645,95 @@ adc2: # above parameters. ``` +## Load Cells + +### [load_cell] +Load Cell. Uses an ADC sensor attached to a load cell to create a digital +scale. + +``` +[load_cell] +sensor_type: +# This must be one of the supported sensor types, see below. +``` + +#### XH711 +This is a 24 bit low sample rate chip using "bit-bang" communications. It is +suitable for filament scales. +``` +[load_cell] +sensor_type: hx711 +sclk_pin: +# The pin connected to the HX711 clock line. This parameter must be provided. +dout_pin: +# The pin connected to the HX711 data output line. This parameter must be +# provided. +#gain: A-128 +# Valid values for gain are: A-128, A-64, B-32. The default is A-128. +# 'A' denotes the input channel and the number denotes the gain. Only the 3 +# listed combinations are supported by the chip. Note that changing the gain +# setting also selects the channel being read. +#sample_rate: 80 +# Valid values for sample_rate are 80 or 10. The default value is 80. +# This must match the wiring of the chip. The sample rate cannot be changed +# in software. +``` + +#### HX717 +This is the 4x higher sample rate version of the HX711, suitable for probing. +``` +[load_cell] +sensor_type: hx717 +sclk_pin: +# The pin connected to the HX717 clock line. This parameter must be provided. +dout_pin: +# The pin connected to the HX717 data output line. This parameter must be +# provided. +#gain: A-128 +# Valid values for gain are A-128, B-64, A-64, B-8. +# 'A' denotes the input channel and the number denotes the gain setting. +# Only the 4 listed combinations are supported by the chip. Note that +# changing the gain setting also selects the channel being read. +#sample_rate: 320 +# Valid values for sample_rate are: 10, 20, 80, 320. The default is 320. +# This must match the wiring of the chip. The sample rate cannot be changed +# in software. +``` + +#### ADS1220 +The ADS1220 is a 24 bit ADC supporting up to a 2Khz sample rate configurable in +software. +``` +[load_cell] +sensor_type: ads1220 +cs_pin: +# The pin connected to the ADS1220 chip select line. This parameter must +# be provided. +#spi_speed: 512000 +# This chip supports 2 speeds: 256000 or 512000. The faster speed is only +# enabled when one of the Turbo sample rates is used. The correct spi_speed +# is selected based on the sample rate. +#spi_bus: +#spi_software_sclk_pin: +#spi_software_mosi_pin: +#spi_software_miso_pin: +# See the "common SPI settings" section for a description of the +# above parameters. +data_ready_pin: +# Pin connected to the ADS1220 data ready line. This parameter must be +# provided. +#gain: 128 +# Valid gain values are 128, 64, 32, 16, 8, 4, 2, 1 +# The default is 128 +#sample_rate: 660 +# This chip supports two ranges of sample rates, Normal and Turbo. In turbo +# mode the chips c internal clock runs twice as fast and the SPI communication +# speed is also doubled. +# Normal sample rates: 20, 45, 90, 175, 330, 600, 1000 +# Turbo sample rates: 40, 90, 180, 350, 660, 1200, 2000 +# The default is 660 +``` + ## Board specific hardware support ### [sx1509] diff --git a/klippy/extras/ads1220.py b/klippy/extras/ads1220.py new file mode 100644 index 0000000..fba7418 --- /dev/null +++ b/klippy/extras/ads1220.py @@ -0,0 +1,187 @@ +# ADS1220 Support +# +# Copyright (C) 2024 Gareth Farrington +# +# This file may be distributed under the terms of the GNU GPLv3 license. +import logging +from . import bulk_sensor, bus + +# +# Constants +# +BYTES_PER_SAMPLE = 4 # samples are 4 byte wide unsigned integers +MAX_SAMPLES_PER_MESSAGE = bulk_sensor.MAX_BULK_MSG_SIZE // BYTES_PER_SAMPLE +UPDATE_INTERVAL = 0.10 +RESET_CMD = 0x06 +START_SYNC_CMD = 0x08 +RREG_CMD = 0x20 +WREG_CMD = 0x40 +NOOP_CMD = 0x0 +RESET_STATE = bytearray([0x0, 0x0, 0x0, 0x0]) + +# turn bytearrays into pretty hex strings: [0xff, 0x1] +def hexify(byte_array): + return "[%s]" % (", ".join([hex(b) for b in byte_array])) + + +class ADS1220(): + def __init__(self, config): + self.printer = printer = config.get_printer() + self.name = config.get_name().split()[-1] + self.last_error_count = 0 + self.consecutive_fails = 0 + # Chip options + # Gain + self.gain_options = {'1': 0x0, '2': 0x1, '4': 0x2, '8': 0x3, '16': 0x4, + '32': 0x5, '64': 0x6, '128': 0x7} + self.gain = config.getchoice('gain', self.gain_options, default='128') + # Sample rate + self.sps_normal = {'20': 20, '45': 45, '90': 90, '175': 175, + '330': 330, '600': 600, '1000': 1000} + self.sps_turbo = {'40': 40, '90': 90, '180': 180, '350': 350, + '660': 660, '1200': 1200, '2000': 2000} + self.sps_options = self.sps_normal.copy() + self.sps_options.update(self.sps_turbo) + self.sps = config.getchoice('sps', self.sps_options, default='660') + self.is_turbo = str(self.sps) in self.sps_turbo + # SPI Setup + spi_speed = 512000 if self.is_turbo else 256000 + self.spi = bus.MCU_SPI_from_config(config, 1, default_speed=spi_speed) + self.mcu = mcu = self.spi.get_mcu() + self.oid = mcu.create_oid() + # Data Ready (DRDY) Pin + drdy_pin = config.get('data_ready_pin') + ppins = printer.lookup_object('pins') + drdy_ppin = ppins.lookup_pin(drdy_pin) + self.data_ready_pin = drdy_ppin['pin'] + drdy_pin_mcu = drdy_ppin['chip'] + if drdy_pin_mcu != self.mcu: + raise config.error("ADS1220 config error: SPI communication and" + " data_ready_pin must be on the same MCU") + # Bulk Sensor Setup + self.bulk_queue = bulk_sensor.BulkDataQueue(self.mcu, oid=self.oid) + # Clock tracking + chip_smooth = self.sps * UPDATE_INTERVAL * 2 + # Measurement conversion + self.ffreader = bulk_sensor.FixedFreqReader(mcu, chip_smooth, " +# +# This file may be distributed under the terms of the GNU GPLv3 license. +import logging +from . import bulk_sensor + +# +# Constants +# +UPDATE_INTERVAL = 0.10 +SAMPLE_ERROR_DESYNC = -0x80000000 +SAMPLE_ERROR_LONG_READ = 0x40000000 + +# Implementation of HX711 and HX717 +class HX71xBase(): + def __init__(self, config, sensor_type, + sample_rate_options, default_sample_rate, + gain_options, default_gain): + self.printer = printer = config.get_printer() + self.name = config.get_name().split()[-1] + self.last_error_count = 0 + self.consecutive_fails = 0 + self.sensor_type = sensor_type + # Chip options + dout_pin_name = config.get('dout_pin') + sclk_pin_name = config.get('sclk_pin') + ppins = printer.lookup_object('pins') + dout_ppin = ppins.lookup_pin(dout_pin_name) + sclk_ppin = ppins.lookup_pin(sclk_pin_name) + self.mcu = mcu = dout_ppin['chip'] + self.oid = mcu.create_oid() + if sclk_ppin['chip'] is not mcu: + raise config.error("%s config error: All pins must be " + "connected to the same MCU" % (self.name,)) + self.dout_pin = dout_ppin['pin'] + self.sclk_pin = sclk_ppin['pin'] + # Samples per second choices + self.sps = config.getchoice('sample_rate', sample_rate_options, + default=default_sample_rate) + # gain/channel choices + self.gain_channel = int(config.getchoice('gain', gain_options, + default=default_gain)) + ## Bulk Sensor Setup + self.bulk_queue = bulk_sensor.BulkDataQueue(mcu, oid=self.oid) + # Clock tracking + chip_smooth = self.sps * UPDATE_INTERVAL * 2 + self.ffreader = bulk_sensor.FixedFreqReader(mcu, chip_smooth, " 0: + logging.error("%s: Forced sensor restart due to error", self.name) + self._finish_measurements() + self._start_measurements() + elif overflows > 0: + self.consecutive_fails += 1 + if self.consecutive_fails > 4: + logging.error("%s: Forced sensor restart due to overflows", + self.name) + self._finish_measurements() + self._start_measurements() + else: + self.consecutive_fails = 0 + return {'data': samples, 'errors': self.last_error_count, + 'overflows': self.ffreader.get_last_overflows()} + + +class HX711(HX71xBase): + def __init__(self, config): + super(HX711, self).__init__(config, "hx711", + # HX711 sps options + {80: 80, 10: 10}, 80, + # HX711 gain/channel options + {'A-128': 1, 'B-32': 2, 'A-64': 3}, 'A-128') + + +class HX717(HX71xBase): + def __init__(self, config): + super(HX717, self).__init__(config, "hx717", + # HX717 sps options + {320: 320, 80: 80, 20: 20, 10: 10}, 320, + # HX717 gain/channel options + {'A-128': 1, 'B-64': 2, 'A-64': 3, + 'B-8': 4}, 'A-128') + + +HX71X_SENSOR_TYPES = { + "hx711": HX711, + "hx717": HX717 +} diff --git a/klippy/extras/load_cell.py b/klippy/extras/load_cell.py new file mode 100644 index 0000000..14f3c29 --- /dev/null +++ b/klippy/extras/load_cell.py @@ -0,0 +1,30 @@ +# Load Cell Implementation +# +# Copyright (C) 2024 Gareth Farrington +# +# This file may be distributed under the terms of the GNU GPLv3 license. +from . import hx71x +from . import ads1220 + +# Printer class that controls a load cell +class LoadCell: + def __init__(self, config, sensor): + self.printer = printer = config.get_printer() + self.sensor = sensor # must implement BulkAdcSensor + + def _on_sample(self, msg): + return True + + def get_sensor(self): + return self.sensor + +def load_config(config): + # Sensor types + sensors = {} + sensors.update(hx71x.HX71X_SENSOR_TYPES) + sensors.update(ads1220.ADS1220_SENSOR_TYPE) + sensor_class = config.getchoice('sensor_type', sensors) + return LoadCell(config, sensor_class(config)) + +def load_config_prefix(config): + return load_config(config) diff --git a/testcases/configs/ar100.config b/testcases/configs/ar100.config index 6c91748..a133517 100644 --- a/testcases/configs/ar100.config +++ b/testcases/configs/ar100.config @@ -4,3 +4,5 @@ CONFIG_WANT_DISPLAYS=n CONFIG_WANT_SOFTWARE_I2C=n CONFIG_WANT_SOFTWARE_SPI=n CONFIG_WANT_LIS2DW=n +CONFIG_WANT_HX71X=n +CONFIG_WANT_ADS1220=n diff --git a/testcases/configs/stm32f042.config b/testcases/configs/stm32f042.config index 12cc092..53cf128 100644 --- a/testcases/configs/stm32f042.config +++ b/testcases/configs/stm32f042.config @@ -4,3 +4,5 @@ CONFIG_MACH_STM32F042=y CONFIG_WANT_SOFTWARE_I2C=n CONFIG_WANT_LIS2DW=n CONFIG_WANT_LDC1612=n +CONFIG_WANT_HX71X=n +CONFIG_WANT_ADS1220=n