From 2f2219b4b7f07cdb710000f97c5307f680bdec66 Mon Sep 17 00:00:00 2001 From: Kevin O'Connor Date: Tue, 17 Feb 2026 13:10:16 -0500 Subject: [PATCH] buttons: Use ADC batching for ADC based buttons Increase ADC report time from every 15ms to every 10ms and batch every 5 reports into a single message. This should improve the responsiveness and reduce the communication overhead when using ADC buttons. Signed-off-by: Kevin O'Connor --- klippy/extras/buttons.py | 56 +++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/klippy/extras/buttons.py b/klippy/extras/buttons.py index b3432f853..4ffb3c38b 100644 --- a/klippy/extras/buttons.py +++ b/klippy/extras/buttons.py @@ -86,10 +86,11 @@ class MCU_buttons: # ADC button tracking ###################################################################### -ADC_REPORT_TIME = 0.015 +ADC_REPORT_TIME = 0.010 ADC_DEBOUNCE_TIME = 0.025 ADC_SAMPLE_TIME = 0.001 ADC_SAMPLE_COUNT = 6 +ADC_BATCH_COUNT = 5 class MCU_ADC_buttons: def __init__(self, printer, pin, pullup): @@ -105,7 +106,8 @@ class MCU_ADC_buttons: ppins = printer.lookup_object('pins') self.mcu_adc = ppins.setup_pin('adc', self.pin) self.mcu_adc.setup_adc_sample(ADC_REPORT_TIME, - ADC_SAMPLE_TIME, ADC_SAMPLE_COUNT) + ADC_SAMPLE_TIME, ADC_SAMPLE_COUNT, + batch_num=ADC_BATCH_COUNT) self.mcu_adc.setup_adc_callback(self.adc_callback) query_adc = printer.lookup_object('query_adc') query_adc.register_adc('adc_button:' + pin.strip(), self.mcu_adc) @@ -116,35 +118,35 @@ class MCU_ADC_buttons: self.buttons.append((min_value, max_value, callback)) def adc_callback(self, samples): - read_time, read_value = samples[-1] - adc = max(.00001, min(.99999, read_value)) - value = self.pullup * adc / (1.0 - adc) + for read_time, read_value in samples: + adc = max(.00001, min(.99999, read_value)) + value = self.pullup * adc / (1.0 - adc) - # Determine button pressed - btn = None - if self.min_value <= value <= self.max_value: - for i, (min_value, max_value, cb) in enumerate(self.buttons): - if min_value < value < max_value: - btn = i - break + # Determine button pressed + btn = None + if self.min_value <= value <= self.max_value: + for i, (min_value, max_value, cb) in enumerate(self.buttons): + if min_value < value < max_value: + btn = i + break - # If the button changed, due to noise or pressing: - if btn != self.last_button: - # reset the debouncing timer - self.last_debouncetime = read_time + # If the button changed, due to noise or pressing: + if btn != self.last_button: + # reset the debouncing timer + self.last_debouncetime = read_time - # button debounce check & new button pressed - if ((read_time - self.last_debouncetime) >= ADC_DEBOUNCE_TIME - and self.last_button == btn and self.last_pressed != btn): - # release last_pressed - if self.last_pressed is not None: - self.call_button(self.last_pressed, False) - self.last_pressed = None - if btn is not None: - self.call_button(btn, True) - self.last_pressed = btn + # button debounce check & new button pressed + if ((read_time - self.last_debouncetime) >= ADC_DEBOUNCE_TIME + and self.last_button == btn and self.last_pressed != btn): + # release last_pressed + if self.last_pressed is not None: + self.call_button(self.last_pressed, False) + self.last_pressed = None + if btn is not None: + self.call_button(btn, True) + self.last_pressed = btn - self.last_button = btn + self.last_button = btn def call_button(self, button, state): minval, maxval, callback = self.buttons[button]