aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/Config_Changes.md4
-rw-r--r--docs/G-Codes.md26
-rw-r--r--klippy/extras/adxl345.py170
3 files changed, 95 insertions, 105 deletions
diff --git a/docs/Config_Changes.md b/docs/Config_Changes.md
index e0521245..24d4b3e4 100644
--- a/docs/Config_Changes.md
+++ b/docs/Config_Changes.md
@@ -8,6 +8,10 @@ All dates in this document are approximate.
## Changes
+20210830: The adxl345 ACCELEROMETER_MEASURE command no longer supports
+a RATE parameter. To alter the query rate, update the printer.cfg
+file and issue a RESTART command.
+
20210821: Several config settings in `printer.configfile.settings`
will now be reported as lists instead of raw strings. If the actual
raw string is desired, use `printer.configfile.config` instead.
diff --git a/docs/G-Codes.md b/docs/G-Codes.md
index 745c63db..1c2644f3 100644
--- a/docs/G-Codes.md
+++ b/docs/G-Codes.md
@@ -725,21 +725,19 @@ is enabled:
The following commands are available when an
[adxl345 config section](Config_Reference.md#adxl345) is enabled:
-- `ACCELEROMETER_MEASURE [CHIP=<config_name>] [RATE=<value>]
- [NAME=<value>]`: Starts accelerometer measurements at the requested
- number of samples per second. If CHIP is not specified it defaults
- to "default". Valid rates are 25, 50, 100, 200, 400, 800, 1600,
- and 3200. The command works in a start-stop mode: when executed for
- the first time, it starts the measurements, next execution stops
- them. If RATE is not specified, then the default value is used
- (either from `printer.cfg` or `3200` default value). The results of
- measurements are written to a file named
+- `ACCELEROMETER_MEASURE [CHIP=<config_name>] [NAME=<value>]`: Starts
+ accelerometer measurements at the requested number of samples per
+ second. If CHIP is not specified it defaults to "default". The
+ command works in a start-stop mode: when executed for the first
+ time, it starts the measurements, next execution stops them. The
+ results of measurements are written to a file named
`/tmp/adxl345-<chip>-<name>.csv` where `<chip>` is the name of the
- accelerometer chip (`my_chip_name` from `[adxl345 my_chip_name]`) and
- `<name>` is the optional NAME parameter. If NAME is not specified it
- defaults to the current time in "YYYYMMDD_HHMMSS" format. If the
- accelerometer does not have a name in its config section (simply
- `[adxl345]`) <chip> part of the name is not generated.
+ accelerometer chip (`my_chip_name` from `[adxl345 my_chip_name]`)
+ and `<name>` is the optional NAME parameter. If NAME is not
+ specified it defaults to the current time in "YYYYMMDD_HHMMSS"
+ format. If the accelerometer does not have a name in its config
+ section (simply `[adxl345]`) then `<chip>` part of the name is not
+ generated.
- `ACCELEROMETER_QUERY [CHIP=<config_name>] [RATE=<value>]`: queries
accelerometer for the current value. If CHIP is not specified it
defaults to "default". If RATE is not specified, the default value
diff --git a/klippy/extras/adxl345.py b/klippy/extras/adxl345.py
index 23167ffc..1cddf0dd 100644
--- a/klippy/extras/adxl345.py
+++ b/klippy/extras/adxl345.py
@@ -96,10 +96,85 @@ class ADXL345Results:
write_proc.daemon = True
write_proc.start()
+# Helper class for G-Code commands
+class ADXLCommandHelper:
+ def __init__(self, config, chip):
+ self.printer = config.get_printer()
+ self.chip = chip
+ self.name = "default"
+ if len(config.get_name().split()) > 1:
+ self.name = config.get_name().split()[1]
+ self.register_commands(self.name)
+ if self.name == "default":
+ self.register_commands(None)
+ def register_commands(self, name):
+ # Register commands
+ gcode = self.printer.lookup_object('gcode')
+ gcode.register_mux_command("ACCELEROMETER_MEASURE", "CHIP", name,
+ self.cmd_ACCELEROMETER_MEASURE,
+ desc=self.cmd_ACCELEROMETER_MEASURE_help)
+ gcode.register_mux_command("ACCELEROMETER_QUERY", "CHIP", name,
+ self.cmd_ACCELEROMETER_QUERY,
+ desc=self.cmd_ACCELEROMETER_QUERY_help)
+ gcode.register_mux_command("ADXL345_DEBUG_READ", "CHIP", name,
+ self.cmd_ADXL345_DEBUG_READ,
+ desc=self.cmd_ADXL345_DEBUG_READ_help)
+ gcode.register_mux_command("ADXL345_DEBUG_WRITE", "CHIP", name,
+ self.cmd_ADXL345_DEBUG_WRITE,
+ desc=self.cmd_ADXL345_DEBUG_WRITE_help)
+ cmd_ACCELEROMETER_MEASURE_help = "Start/stop accelerometer"
+ def cmd_ACCELEROMETER_MEASURE(self, gcmd):
+ if not self.chip.is_measuring():
+ # Start measurements
+ self.chip.start_measurements()
+ gcmd.respond_info("adxl345 measurements started")
+ return
+ # End measurements
+ name = gcmd.get("NAME", time.strftime("%Y%m%d_%H%M%S"))
+ if not name.replace('-', '').replace('_', '').isalnum():
+ raise gcmd.error("Invalid adxl345 NAME parameter")
+ res = self.chip.finish_measurements()
+ # Write data to file
+ if self.name == "default":
+ filename = "/tmp/adxl345-%s.csv" % (name,)
+ else:
+ filename = "/tmp/adxl345-%s-%s.csv" % (self.name, name,)
+ res.write_to_file(filename)
+ gcmd.respond_info("Writing raw accelerometer data to %s file"
+ % (filename,))
+ cmd_ACCELEROMETER_QUERY_help = "Query accelerometer for the current values"
+ def cmd_ACCELEROMETER_QUERY(self, gcmd):
+ if self.chip.is_measuring():
+ raise gcmd.error("adxl345 measurements in progress")
+ self.chip.start_measurements()
+ self.printer.lookup_object('toolhead').dwell(1.)
+ result = self.chip.finish_measurements()
+ values = result.decode_samples()
+ if not values:
+ raise gcmd.error("No adxl345 measurements found")
+ _, accel_x, accel_y, accel_z = values[-1]
+ gcmd.respond_info("adxl345 values (x, y, z): %.6f, %.6f, %.6f"
+ % (accel_x, accel_y, accel_z))
+ cmd_ADXL345_DEBUG_READ_help = "Query accelerometer register (for debugging)"
+ def cmd_ADXL345_DEBUG_READ(self, gcmd):
+ if self.chip.is_measuring():
+ raise gcmd.error("adxl345 measurements in progress")
+ reg = gcmd.get("REG", minval=29, maxval=57, parser=lambda x: int(x, 0))
+ val = self.chip.read_reg(reg)
+ gcmd.respond_info("ADXL345 REG[0x%x] = 0x%x" % (reg, val))
+ cmd_ADXL345_DEBUG_WRITE_help = "Set accelerometer register (for debugging)"
+ def cmd_ADXL345_DEBUG_WRITE(self, gcmd):
+ if self.chip.is_measuring():
+ raise gcmd.error("adxl345 measurements in progress")
+ reg = gcmd.get("REG", minval=29, maxval=57, parser=lambda x: int(x, 0))
+ val = gcmd.get("VAL", minval=0, maxval=255, parser=lambda x: int(x, 0))
+ self.chip.set_reg(reg, val)
+
# Printer class that controls ADXL345 chip
class ADXL345:
def __init__(self, config):
self.printer = config.get_printer()
+ ADXLCommandHelper(config, self)
self.query_rate = 0
self.last_tx_time = 0.
am = {'x': (0, SCALE), 'y': (1, SCALE), 'z': (2, SCALE),
@@ -127,34 +202,6 @@ class ADXL345:
mcu.register_config_callback(self._build_config)
mcu.register_response(self._handle_adxl345_start, "adxl345_start", oid)
mcu.register_response(self._handle_adxl345_data, "adxl345_data", oid)
- # Register commands
- self.name = "default"
- if len(config.get_name().split()) > 1:
- self.name = config.get_name().split()[1]
- gcode = self.printer.lookup_object('gcode')
- gcode.register_mux_command("ACCELEROMETER_MEASURE", "CHIP", self.name,
- self.cmd_ACCELEROMETER_MEASURE,
- desc=self.cmd_ACCELEROMETER_MEASURE_help)
- gcode.register_mux_command("ACCELEROMETER_QUERY", "CHIP", self.name,
- self.cmd_ACCELEROMETER_QUERY,
- desc=self.cmd_ACCELEROMETER_QUERY_help)
- gcode.register_mux_command("ADXL345_DEBUG_READ", "CHIP", self.name,
- self.cmd_ADXL345_DEBUG_READ,
- desc=self.cmd_ADXL345_DEBUG_READ_help)
- gcode.register_mux_command("ADXL345_DEBUG_WRITE", "CHIP", self.name,
- self.cmd_ADXL345_DEBUG_WRITE,
- desc=self.cmd_ADXL345_DEBUG_WRITE_help)
- if self.name == "default":
- gcode.register_mux_command("ACCELEROMETER_MEASURE", "CHIP", None,
- self.cmd_ACCELEROMETER_MEASURE)
- gcode.register_mux_command("ACCELEROMETER_QUERY", "CHIP", None,
- self.cmd_ACCELEROMETER_QUERY)
- gcode.register_mux_command("ADXL345_DEBUG_READ", "CHIP", None,
- self.cmd_ADXL345_DEBUG_READ,
- desc=self.cmd_ADXL345_DEBUG_READ_help)
- gcode.register_mux_command("ADXL345_DEBUG_WRITE", "CHIP", None,
- self.cmd_ADXL345_DEBUG_WRITE,
- desc=self.cmd_ADXL345_DEBUG_WRITE_help)
def is_initialized(self):
# In case of miswiring, testing ADXL345 device ID prevents treating
# noise or wrong signal as a correctly initialized device
@@ -213,10 +260,9 @@ class ADXL345:
reg, val, stored_val))
def is_measuring(self):
return self.query_rate > 0
- def start_measurements(self, rate=None):
+ def start_measurements(self):
if self.is_measuring():
return
- rate = rate or self.data_rate
if not self.is_initialized():
self.initialize()
# Setup chip in requested query rate
@@ -225,7 +271,7 @@ class ADXL345:
clock = self.mcu.print_time_to_clock(self.last_tx_time)
self.set_reg(REG_POWER_CTL, 0x00, minclock=clock)
self.set_reg(REG_FIFO_CTL, 0x00)
- self.set_reg(REG_BW_RATE, QUERY_RATES[rate])
+ self.set_reg(REG_BW_RATE, QUERY_RATES[self.data_rate])
self.set_reg(REG_FIFO_CTL, 0x80)
# Setup samples
print_time = self.printer.lookup_object('toolhead').get_last_move_time()
@@ -234,9 +280,9 @@ class ADXL345:
self.samples_start1 = self.samples_start2 = print_time
# Start bulk reading
reqclock = self.mcu.print_time_to_clock(print_time)
- rest_ticks = self.mcu.seconds_to_clock(4. / rate)
+ rest_ticks = self.mcu.seconds_to_clock(4. / self.data_rate)
self.last_tx_time = print_time
- self.query_rate = rate
+ self.query_rate = self.data_rate
self.query_adxl345_cmd.send([self.oid, reqclock, rest_ticks],
reqclock=reqclock)
def finish_measurements(self):
@@ -263,64 +309,6 @@ class ADXL345:
logging.info("ADXL345 finished %d measurements: %s",
res.total_count, res.get_stats())
return res
- def end_query(self, name, gcmd):
- if not self.is_measuring():
- return
- res = self.finish_measurements()
- # Write data to file
- if self.name == "default":
- filename = "/tmp/adxl345-%s.csv" % (name,)
- else:
- filename = "/tmp/adxl345-%s-%s.csv" % (self.name, name,)
- res.write_to_file(filename)
- gcmd.respond_info(
- "Writing raw accelerometer data to %s file" % (filename,))
- cmd_ACCELEROMETER_MEASURE_help = "Start/stop accelerometer"
- def cmd_ACCELEROMETER_MEASURE(self, gcmd):
- if self.is_measuring():
- name = gcmd.get("NAME", time.strftime("%Y%m%d_%H%M%S"))
- if not name.replace('-', '').replace('_', '').isalnum():
- raise gcmd.error("Invalid adxl345 NAME parameter")
- self.end_query(name, gcmd)
- gcmd.respond_info("adxl345 measurements stopped")
- else:
- rate = gcmd.get_int("RATE", self.data_rate)
- if rate not in QUERY_RATES:
- raise gcmd.error("Not a valid adxl345 query rate: %d" % (rate,))
- self.start_measurements(rate)
- gcmd.respond_info("adxl345 measurements started")
- cmd_ACCELEROMETER_QUERY_help = "Query accelerometer for the current values"
- def cmd_ACCELEROMETER_QUERY(self, gcmd):
- if self.is_measuring():
- raise gcmd.error("adxl345 measurements in progress")
- self.start_measurements()
- reactor = self.printer.get_reactor()
- eventtime = starttime = reactor.monotonic()
- while not self.raw_samples:
- eventtime = reactor.pause(eventtime + .1)
- if eventtime > starttime + 3.:
- # Try to shutdown the measurements
- self.finish_measurements()
- raise gcmd.error("Timeout reading adxl345 data")
- result = self.finish_measurements()
- values = result.decode_samples()
- _, accel_x, accel_y, accel_z = values[-1]
- gcmd.respond_info("adxl345 values (x, y, z): %.6f, %.6f, %.6f" % (
- accel_x, accel_y, accel_z))
- cmd_ADXL345_DEBUG_READ_help = "Query accelerometer register (for debugging)"
- def cmd_ADXL345_DEBUG_READ(self, gcmd):
- if self.is_measuring():
- raise gcmd.error("adxl345 measurements in progress")
- reg = gcmd.get("REG", minval=29, maxval=57, parser=lambda x: int(x, 0))
- val = self.read_reg(reg)
- gcmd.respond_info("ADXL345 REG[0x%x] = 0x%x" % (reg, val))
- cmd_ADXL345_DEBUG_WRITE_help = "Set accelerometer register (for debugging)"
- def cmd_ADXL345_DEBUG_WRITE(self, gcmd):
- if self.is_measuring():
- raise gcmd.error("adxl345 measurements in progress")
- reg = gcmd.get("REG", minval=29, maxval=57, parser=lambda x: int(x, 0))
- val = gcmd.get("VAL", minval=0, maxval=255, parser=lambda x: int(x, 0))
- self.set_reg(reg, val)
def load_config(config):
return ADXL345(config)