diff --git a/docs/G-Codes.md b/docs/G-Codes.md index b01d6487..7cd4b02b 100644 --- a/docs/G-Codes.md +++ b/docs/G-Codes.md @@ -101,6 +101,11 @@ The following standard commands are supported: - `QUERY_ENDSTOPS`: Probe the axis endstops and report if they are "triggered" or in an "open" state. This command is typically used to verify that an endstop is working correctly. +- `QUERY_ADC [NAME=] [PULLUP=]`: Report the last + analog value received for a configured analog pin. If NAME is not + provided, the list of available adc names are reported. If PULLUP is + provided (as a value in Ohms), the raw analog value along with the + equivalent resistance given that pullup is reported. - `GET_POSITION`: Return information on the current location of the toolhead. - `SET_GCODE_OFFSET [X=|X_ADJUST=] diff --git a/klippy/extras/adc_temperature.py b/klippy/extras/adc_temperature.py index 2e333792..7a4cc8d2 100644 --- a/klippy/extras/adc_temperature.py +++ b/klippy/extras/adc_temperature.py @@ -22,6 +22,8 @@ class PrinterADCtoTemperature: ppins = config.get_printer().lookup_object('pins') self.mcu_adc = ppins.setup_pin('adc', config.get('sensor_pin')) self.mcu_adc.setup_adc_callback(REPORT_TIME, self.adc_callback) + query_adc = config.get_printer().try_load_module(config, 'query_adc') + query_adc.register_adc(config.get_name(), self.mcu_adc) def setup_callback(self, temperature_callback): self.temperature_callback = temperature_callback def get_report_time_delta(self): diff --git a/klippy/extras/buttons.py b/klippy/extras/buttons.py index 5d5aac46..9eeee78e 100644 --- a/klippy/extras/buttons.py +++ b/klippy/extras/buttons.py @@ -107,6 +107,8 @@ class MCU_ADC_buttons: self.mcu_adc = ppins.setup_pin('adc', self.pin) self.mcu_adc.setup_minmax(ADC_SAMPLE_TIME, ADC_SAMPLE_COUNT) self.mcu_adc.setup_adc_callback(ADC_REPORT_TIME, self.adc_callback) + query_adc = printer.lookup_object('query_adc') + query_adc.register_adc('adc_button:' + pin.strip(), self.mcu_adc) def setup_button(self, min_value, max_value, callback): self.min_value = min(self.min_value, min_value) @@ -205,6 +207,7 @@ class RotaryEncoder: class PrinterButtons: def __init__(self, config): self.printer = config.get_printer() + self.printer.try_load_module(config, 'query_adc') self.mcu_buttons = {} self.adc_buttons = {} def register_adc_button(self, pin, min_val, max_val, pullup, callback): diff --git a/klippy/extras/query_adc.py b/klippy/extras/query_adc.py new file mode 100644 index 00000000..eb065396 --- /dev/null +++ b/klippy/extras/query_adc.py @@ -0,0 +1,36 @@ +# Utility for querying the current state of adc pins +# +# Copyright (C) 2019 Kevin O'Connor +# +# This file may be distributed under the terms of the GNU GPLv3 license. + +class QueryADC: + def __init__(self, config): + self.printer = config.get_printer() + self.adc = {} + gcode = self.printer.lookup_object('gcode') + gcode.register_command("QUERY_ADC", self.cmd_QUERY_ADC, + desc=self.cmd_QUERY_ADC_help) + def register_adc(self, name, mcu_adc): + self.adc[name] = mcu_adc + cmd_QUERY_ADC_help = "Report the last value of an analog pin" + def cmd_QUERY_ADC(self, params): + gcode = self.printer.lookup_object('gcode') + name = gcode.get_str('NAME', params, None) + if name not in self.adc: + objs = ['"%s"' % (n,) for n in sorted(self.adc.keys())] + msg = "Available ADC objects: %s" % (', '.join(objs),) + gcode.respond_info(msg) + return + value, timestamp = self.adc[name].get_last_value() + msg = 'ADC object "%s" has value %.6f (timestamp %.3f)' % ( + name, value, timestamp) + pullup = gcode.get_float('PULLUP', params, None, above=0.) + if pullup is not None: + v = max(.00001, min(.99999, value)) + r = pullup * v / (1.0 - v) + msg += "\n resistance %.3f (with %.0f pullup)" % (r, pullup) + gcode.respond_info(msg) + +def load_config(config): + return QueryADC(config) diff --git a/klippy/mcu.py b/klippy/mcu.py index dda02598..0a283452 100644 --- a/klippy/mcu.py +++ b/klippy/mcu.py @@ -392,6 +392,7 @@ class MCU_adc: self._sample_time = self._report_time = 0. self._sample_count = self._range_check_count = 0 self._report_clock = 0 + self._last_state = (0., 0.) self._oid = self._callback = None self._mcu.register_config_callback(self._build_config) self._inv_max_adc = 0. @@ -407,6 +408,8 @@ class MCU_adc: def setup_adc_callback(self, report_time, callback): self._report_time = report_time self._callback = callback + def get_last_value(self): + return self._last_state def _build_config(self): if not self._sample_count: return @@ -435,6 +438,7 @@ class MCU_adc: next_clock = self._mcu.clock32_to_clock64(params['next_clock']) last_read_clock = next_clock - self._report_clock last_read_time = self._mcu.clock_to_print_time(last_read_clock) + self._last_state = (last_value, last_read_time) if self._callback is not None: self._callback(last_read_time, last_value)