mirror of
https://github.com/Klipper3d/klipper.git
synced 2026-03-06 01:54:42 -07:00
Merge branch 'Klipper3d:master' into feature/vsdlist_sorters
This commit is contained in:
commit
6c0dabf48b
14 changed files with 517 additions and 83 deletions
|
|
@ -8,6 +8,14 @@ All dates in this document are approximate.
|
|||
|
||||
## Changes
|
||||
|
||||
20241203: The resonance test has been changed to include slow sweeping
|
||||
moves. This change requires that testing point(s) have some clearance
|
||||
in X/Y plane (+/- 30 mm from the test point should suffice when using
|
||||
the default settings). The new test should generally produce more
|
||||
accurate and reliable test results. However, if required, the previous
|
||||
test behavior can be restored by adding options `sweeping_period: 0` and
|
||||
`accel_per_hz: 75` to the `[resonance_tester]` config section.
|
||||
|
||||
20241201: In some cases Klipper may have ignored leading characters or
|
||||
spaces in a traditional G-Code command. For example, "99M123" may have
|
||||
been interpreted as "M123" and "M 321" may have been interpreted as
|
||||
|
|
|
|||
|
|
@ -1790,11 +1790,14 @@ section of the measuring resonances guide for more information on
|
|||
# auto-calibration (with 'SHAPER_CALIBRATE' command). By default no
|
||||
# maximum smoothing is specified. Refer to Measuring_Resonances guide
|
||||
# for more details on using this feature.
|
||||
#move_speed: 50
|
||||
# The speed (in mm/s) to move the toolhead to and between test points
|
||||
# during the calibration. The default is 50.
|
||||
#min_freq: 5
|
||||
# Minimum frequency to test for resonances. The default is 5 Hz.
|
||||
#max_freq: 133.33
|
||||
# Maximum frequency to test for resonances. The default is 133.33 Hz.
|
||||
#accel_per_hz: 75
|
||||
#accel_per_hz: 60
|
||||
# This parameter is used to determine which acceleration to use to
|
||||
# test a specific frequency: accel = accel_per_hz * freq. Higher the
|
||||
# value, the higher is the energy of the oscillations. Can be set to
|
||||
|
|
@ -1808,6 +1811,13 @@ section of the measuring resonances guide for more information on
|
|||
# hz_per_sec. Small values make the test slow, and the large values
|
||||
# will decrease the precision of the test. The default value is 1.0
|
||||
# (Hz/sec == sec^-2).
|
||||
#sweeping_accel: 400
|
||||
# An acceleration of slow sweeping moves. The default is 400 mm/sec^2.
|
||||
#sweeping_period: 1.2
|
||||
# A period of slow sweeping moves. Setting this parameter to 0
|
||||
# disables slow sweeping moves. Avoid setting it to a too small
|
||||
# non-zero value in order to not poison the measurements.
|
||||
# The default is 1.2 sec which is a good all-round choice.
|
||||
```
|
||||
|
||||
## Config file helpers
|
||||
|
|
@ -5045,8 +5055,9 @@ serial:
|
|||
### [angle]
|
||||
|
||||
Magnetic hall angle sensor support for reading stepper motor angle
|
||||
shaft measurements using a1333, as5047d, or tle5012b SPI chips. The
|
||||
measurements are available via the [API Server](API_Server.md) and
|
||||
shaft measurements using a1333, as5047d, mt6816, mt6826s,
|
||||
or tle5012b SPI chips.
|
||||
The measurements are available via the [API Server](API_Server.md) and
|
||||
[motion analysis tool](Debugging.md#motion-analysis-and-data-logging).
|
||||
See the [G-Code reference](G-Codes.md#angle) for available commands.
|
||||
|
||||
|
|
@ -5054,7 +5065,7 @@ See the [G-Code reference](G-Codes.md#angle) for available commands.
|
|||
[angle my_angle_sensor]
|
||||
sensor_type:
|
||||
# The type of the magnetic hall sensor chip. Available choices are
|
||||
# "a1333", "as5047d", and "tle5012b". This parameter must be
|
||||
# "a1333", "as5047d", "mt6816", "mt6826s", and "tle5012b". This parameter must be
|
||||
# specified.
|
||||
#sample_period: 0.000400
|
||||
# The query period (in seconds) to use during measurements. The
|
||||
|
|
|
|||
|
|
@ -127,6 +127,14 @@ use this tool the Python "numpy" package must be installed (see the
|
|||
[measuring resonance document](Measuring_Resonances.md#software-installation)
|
||||
for more information).
|
||||
|
||||
#### ANGLE_CHIP_CALIBRATE
|
||||
`ANGLE_CHIP_CALIBRATE CHIP=<chip_name>`: Perform internal sensor calibration,
|
||||
if implemented (MT6826S/MT6835).
|
||||
|
||||
- **MT68XX**: The motor should be disconnected
|
||||
from any printer carriage before performing calibration.
|
||||
After calibration, the sensor should be reset by disconnecting the power.
|
||||
|
||||
#### ANGLE_DEBUG_READ
|
||||
`ANGLE_DEBUG_READ CHIP=<config_name> REG=<register>`: Queries sensor
|
||||
register "register" (e.g. 44 or 0x2C). Can be useful for debugging
|
||||
|
|
@ -1059,6 +1067,21 @@ CYCLE_TIME parameter is not stored between SET_PIN commands (any
|
|||
SET_PIN command without an explicit CYCLE_TIME parameter will use the
|
||||
`cycle_time` specified in the pwm_cycle_time config section).
|
||||
|
||||
### [quad_gantry_level]
|
||||
|
||||
The following commands are available when the
|
||||
[quad_gantry_level config section](Config_Reference.md#quad_gantry_level)
|
||||
is enabled.
|
||||
|
||||
#### QUAD_GANTRY_LEVEL
|
||||
`QUAD_GANTRY_LEVEL [RETRIES=<value>] [RETRY_TOLERANCE=<value>]
|
||||
[HORIZONTAL_MOVE_Z=<value>] [<probe_parameter>=<value>]`: This command
|
||||
will probe the points specified in the config and then make
|
||||
independent adjustments to each Z stepper to compensate for tilt. See
|
||||
the PROBE command for details on the optional probe parameters. The
|
||||
optional `RETRIES`, `RETRY_TOLERANCE`, and `HORIZONTAL_MOVE_Z` values
|
||||
override those options specified in the config file.
|
||||
|
||||
### [query_adc]
|
||||
|
||||
The query_adc module is automatically loaded.
|
||||
|
|
@ -1448,11 +1471,13 @@ The following commands are available when the
|
|||
[z_tilt config section](Config_Reference.md#z_tilt) is enabled.
|
||||
|
||||
#### Z_TILT_ADJUST
|
||||
`Z_TILT_ADJUST [HORIZONTAL_MOVE_Z=<value>] [<probe_parameter>=<value>]`: This
|
||||
command will probe the points specified in the config and then make independent
|
||||
adjustments to each Z stepper to compensate for tilt. See the PROBE command for
|
||||
details on the optional probe parameters. The optional `HORIZONTAL_MOVE_Z`
|
||||
value overrides the `horizontal_move_z` option specified in the config file.
|
||||
`Z_TILT_ADJUST [RETRIES=<value>] [RETRY_TOLERANCE=<value>]
|
||||
[HORIZONTAL_MOVE_Z=<value>] [<probe_parameter>=<value>]`: This command
|
||||
will probe the points specified in the config and then make
|
||||
independent adjustments to each Z stepper to compensate for tilt. See
|
||||
the PROBE command for details on the optional probe parameters. The
|
||||
optional `RETRIES`, `RETRY_TOLERANCE`, and `HORIZONTAL_MOVE_Z` values
|
||||
override those options specified in the config file.
|
||||
|
||||
### [temperature_probe]
|
||||
|
||||
|
|
|
|||
|
|
@ -694,6 +694,24 @@ If you are doing a shaper re-calibration and the reported smoothing for the
|
|||
suggested shaper configuration is almost the same as what you got during the
|
||||
previous calibration, this step can be skipped.
|
||||
|
||||
### Unreliable measurements of resonance frequencies
|
||||
|
||||
Sometimes the resonance measurements can produce bogus results, leading to
|
||||
the incorrect suggestions for the input shapers. This can be caused by a
|
||||
variety of reasons, including running fans on the toolhead, incorrect
|
||||
position or non-rigid mounting of the accelerometer, or mechanical problems
|
||||
such as loose belts or binding or bumpy axis. Keep in mind that all fans
|
||||
should be disabled for resonance testing, especially the noisy ones, and
|
||||
that the accelerometer should be rigidly mounted on the corresponding
|
||||
moving part (e.g. on the bed itself for the bed slinger, or on the extruder
|
||||
of the printer itself and not the carriage, and some people get better
|
||||
results by mounting the accelerometer on the nozzle itself). As for
|
||||
mechanical problems, the user should inspect if there is any fault that
|
||||
can be fixed with a moving axis (e.g. linear guide rails cleaned up and
|
||||
lubricated and V-slot wheels tension adjusted correctly). If none of that
|
||||
helps, a user may try the other shapers from the produced list besides the
|
||||
one recommended by default.
|
||||
|
||||
### Testing custom axes
|
||||
|
||||
`TEST_RESONANCES` command supports custom axes. While this is not really
|
||||
|
|
|
|||
|
|
@ -411,6 +411,196 @@ class HelperTLE5012B:
|
|||
parser=lambda x: int(x, 0))
|
||||
self._write_reg(reg, val)
|
||||
|
||||
class HelperMT6816:
|
||||
SPI_MODE = 3
|
||||
SPI_SPEED = 10000000
|
||||
def __init__(self, config, spi, oid):
|
||||
self.printer = config.get_printer()
|
||||
self.spi = spi
|
||||
self.oid = oid
|
||||
self.mcu = spi.get_mcu()
|
||||
self.mcu.register_config_callback(self._build_config)
|
||||
self.spi_angle_transfer_cmd = None
|
||||
self.is_tcode_absolute = False
|
||||
self.last_temperature = None
|
||||
name = config.get_name().split()[-1]
|
||||
gcode = self.printer.lookup_object("gcode")
|
||||
gcode.register_mux_command("ANGLE_DEBUG_READ", "CHIP", name,
|
||||
self.cmd_ANGLE_DEBUG_READ,
|
||||
desc=self.cmd_ANGLE_DEBUG_READ_help)
|
||||
def _build_config(self):
|
||||
cmdqueue = self.spi.get_command_queue()
|
||||
self.spi_angle_transfer_cmd = self.mcu.lookup_query_command(
|
||||
"spi_angle_transfer oid=%c data=%*s",
|
||||
"spi_angle_transfer_response oid=%c clock=%u response=%*s",
|
||||
oid=self.oid, cq=cmdqueue)
|
||||
def _send_spi(self, msg):
|
||||
return self.spi.spi_transfer(msg)
|
||||
def get_static_delay(self):
|
||||
return .000001
|
||||
def _read_reg(self, reg):
|
||||
msg = [reg, 0, 0]
|
||||
params = self._send_spi(msg)
|
||||
resp = bytearray(params['response'])
|
||||
val = (resp[1] << 8) | resp[2]
|
||||
return val
|
||||
def start(self):
|
||||
pass
|
||||
cmd_ANGLE_DEBUG_READ_help = "Query low-level angle sensor register"
|
||||
def cmd_ANGLE_DEBUG_READ(self, gcmd):
|
||||
reg = 0x83
|
||||
val = self._read_reg(reg)
|
||||
gcmd.respond_info("ANGLE REG[0x%02x] = 0x%04x" % (reg, val))
|
||||
angle = val >> 2
|
||||
parity = bin(val >> 1).count("1") % 2
|
||||
gcmd.respond_info("Angle %i ~ %.2f" % (angle, angle * 360 / (1 << 14)))
|
||||
gcmd.respond_info("No Mag: %i" % (val >> 1 & 0x1))
|
||||
gcmd.respond_info("Parity: %i == %i" % (parity, val & 0x1))
|
||||
|
||||
class HelperMT6826S:
|
||||
SPI_MODE = 3
|
||||
SPI_SPEED = 10000000
|
||||
def __init__(self, config, spi, oid):
|
||||
self.printer = config.get_printer()
|
||||
self.stepper_name = config.get('stepper', None)
|
||||
self.spi = spi
|
||||
self.oid = oid
|
||||
self.mcu = spi.get_mcu()
|
||||
self.mcu.register_config_callback(self._build_config)
|
||||
self.spi_angle_transfer_cmd = None
|
||||
self.is_tcode_absolute = False
|
||||
self.last_temperature = None
|
||||
name = config.get_name().split()[-1]
|
||||
gcode = self.printer.lookup_object("gcode")
|
||||
gcode.register_mux_command("ANGLE_DEBUG_READ", "CHIP", name,
|
||||
self.cmd_ANGLE_DEBUG_READ,
|
||||
desc=self.cmd_ANGLE_DEBUG_READ_help)
|
||||
gcode.register_mux_command("ANGLE_CHIP_CALIBRATE", "CHIP", name,
|
||||
self.cmd_ANGLE_CHIP_CALIBRATE,
|
||||
desc=self.cmd_ANGLE_CHIP_CALIBRATE_help)
|
||||
self.status_map = {
|
||||
0: "No Calibration",
|
||||
1: "Running Calibration",
|
||||
2: "Calibration Failed",
|
||||
3: "Calibration Successful"
|
||||
}
|
||||
def _build_config(self):
|
||||
cmdqueue = self.spi.get_command_queue()
|
||||
self.spi_angle_transfer_cmd = self.mcu.lookup_query_command(
|
||||
"spi_angle_transfer oid=%c data=%*s",
|
||||
"spi_angle_transfer_response oid=%c clock=%u response=%*s",
|
||||
oid=self.oid, cq=cmdqueue)
|
||||
def _send_spi(self, msg):
|
||||
params = self.spi.spi_transfer(msg)
|
||||
return params
|
||||
def get_static_delay(self):
|
||||
return .00001
|
||||
def _read_reg(self, reg):
|
||||
reg = 0x3000 | reg
|
||||
msg = [reg >> 8, reg & 0xff, 0]
|
||||
params = self._send_spi(msg)
|
||||
resp = bytearray(params['response'])
|
||||
return resp[2]
|
||||
def _write_reg(self, reg, data):
|
||||
reg = 0x6000 | reg
|
||||
msg = [reg >> 8, reg & 0xff, data]
|
||||
self._send_spi(msg)
|
||||
def crc8(self, data):
|
||||
polynomial = 0x07
|
||||
crc = 0x00
|
||||
for byte in data:
|
||||
crc ^= byte
|
||||
for _ in range(8):
|
||||
if crc & 0x80:
|
||||
crc = (crc << 1) ^ polynomial
|
||||
else:
|
||||
crc <<= 1
|
||||
crc &= 0xFF
|
||||
return crc
|
||||
def _read_angle(self, reg):
|
||||
reg = 0x3000 | reg
|
||||
msg = [reg >> 8, reg & 0xff, 0, 0, 0, 0]
|
||||
params = self._send_spi(msg)
|
||||
resp = bytearray(params['response'])
|
||||
angle = (resp[2] << 7) | (resp[3] >> 1)
|
||||
status = resp[4]
|
||||
crc_computed = self.crc8([resp[2], resp[3], resp[4]])
|
||||
crc = resp[5]
|
||||
return angle, status, crc, crc_computed
|
||||
def start(self):
|
||||
val = self._read_reg(0x00d)
|
||||
# Set histeresis to 0.003 degree
|
||||
self._write_reg(0x00d, (val & 0xf8) | 0x5)
|
||||
def get_microsteps(self):
|
||||
configfile = self.printer.lookup_object('configfile')
|
||||
sconfig = configfile.get_status(None)['settings']
|
||||
stconfig = sconfig.get(self.stepper_name, {})
|
||||
microsteps = stconfig['microsteps']
|
||||
full_steps = stconfig['full_steps_per_rotation']
|
||||
return microsteps, full_steps
|
||||
cmd_ANGLE_CHIP_CALIBRATE_help = "Run MT6826s calibration sequence"
|
||||
def cmd_ANGLE_CHIP_CALIBRATE(self, gcmd):
|
||||
fmove = self.printer.lookup_object('force_move')
|
||||
mcu_stepper = fmove.lookup_stepper(self.stepper_name)
|
||||
if self.stepper_name is None:
|
||||
gcmd.respond_info("stepper not defined")
|
||||
return
|
||||
|
||||
gcmd.respond_info("MT6826S Run calibration sequence")
|
||||
gcmd.respond_info("Motor will do 18+ rotations -" +
|
||||
" ensure pulley is disconnected")
|
||||
req_freq = self._read_reg(0x00e) >> 4 & 0x7
|
||||
# Minimal calibration speed
|
||||
rpm = (3200 >> req_freq) + 1
|
||||
rps = rpm / 60
|
||||
move = fmove.manual_move
|
||||
# Move stepper several turns (to allow internal sensor calibration)
|
||||
microsteps, full_steps = self.get_microsteps()
|
||||
step_dist = mcu_stepper.get_step_dist()
|
||||
full_step_dist = step_dist * microsteps
|
||||
rotation_dist = full_steps * full_step_dist
|
||||
move(mcu_stepper, 2 * rotation_dist, rps * rotation_dist)
|
||||
self._write_reg(0x155, 0x5e)
|
||||
move(mcu_stepper, 20 * rotation_dist, rps * rotation_dist)
|
||||
val = self._read_reg(0x113)
|
||||
code = val >> 6
|
||||
gcmd.respond_info("Status: %s" % (self.status_map[code]))
|
||||
while code == 1:
|
||||
move(mcu_stepper, 5 * rotation_dist, rps * rotation_dist)
|
||||
val = self._read_reg(0x113)
|
||||
code = val >> 6
|
||||
gcmd.respond_info("Status: %s" % (self.status_map[code]))
|
||||
if code == 2:
|
||||
gcmd.respond_info("Calibration failed")
|
||||
if code == 3:
|
||||
gcmd.respond_info("Calibration success, please poweroff sensor")
|
||||
cmd_ANGLE_DEBUG_READ_help = "Query low-level angle sensor register"
|
||||
def cmd_ANGLE_DEBUG_READ(self, gcmd):
|
||||
reg = gcmd.get("REG", minval=0, maxval=0x155,
|
||||
parser=lambda x: int(x, 0))
|
||||
if reg == 0x003:
|
||||
angle, status, crc1, crc2 = self._read_angle(reg)
|
||||
gcmd.respond_info("ANGLE REG[0x003] = 0x%02x" %
|
||||
(angle >> 7))
|
||||
gcmd.respond_info("ANGLE REG[0x004] = 0x%02x" %
|
||||
((angle << 1) & 0xff))
|
||||
gcmd.respond_info("Angle %i ~ %.2f" % (angle,
|
||||
angle * 360 / (1 << 15)))
|
||||
gcmd.respond_info("Weak Mag: %i" % (status >> 1 & 0x1))
|
||||
gcmd.respond_info("Under Voltage: %i" % (status >> 2 & 0x1))
|
||||
gcmd.respond_info("CRC: 0x%02x == 0x%02x" % (crc1, crc2))
|
||||
elif reg == 0x00e:
|
||||
val = self._read_reg(reg)
|
||||
gcmd.respond_info("GPIO_DS = %i" % (val >> 7))
|
||||
gcmd.respond_info("AUTOCAL_FREQ = %i" % (val >> 4 & 0x7))
|
||||
elif reg == 0x113:
|
||||
val = self._read_reg(reg)
|
||||
gcmd.respond_info("Status: %s" % (self.cal_status[val >> 6]))
|
||||
else:
|
||||
val = self._read_reg(reg)
|
||||
gcmd.respond_info("REG[0x%04x] = 0x%02x" % (reg, val))
|
||||
|
||||
|
||||
BYTES_PER_SAMPLE = 3
|
||||
SAMPLES_PER_BLOCK = bulk_sensor.MAX_BULK_MSG_SIZE // BYTES_PER_SAMPLE
|
||||
|
||||
|
|
@ -427,8 +617,11 @@ class Angle:
|
|||
self.start_clock = self.time_shift = self.sample_ticks = 0
|
||||
self.last_sequence = self.last_angle = 0
|
||||
# Sensor type
|
||||
sensors = { "a1333": HelperA1333, "as5047d": HelperAS5047D,
|
||||
"tle5012b": HelperTLE5012B }
|
||||
sensors = { "a1333": HelperA1333,
|
||||
"as5047d": HelperAS5047D,
|
||||
"tle5012b": HelperTLE5012B,
|
||||
"mt6816": HelperMT6816,
|
||||
"mt6826s": HelperMT6826S }
|
||||
sensor_type = config.getchoice('sensor_type', {s: s for s in sensors})
|
||||
sensor_class = sensors[sensor_type]
|
||||
self.spi = bus.MCU_SPI_from_config(config, sensor_class.SPI_MODE,
|
||||
|
|
|
|||
|
|
@ -45,42 +45,96 @@ def _parse_axis(gcmd, raw_axis):
|
|||
"Unable to parse axis direction '%s'" % (raw_axis,))
|
||||
return TestAxis(vib_dir=(dir_x, dir_y))
|
||||
|
||||
class VibrationPulseTest:
|
||||
class VibrationPulseTestGenerator:
|
||||
def __init__(self, config):
|
||||
self.printer = config.get_printer()
|
||||
self.gcode = self.printer.lookup_object('gcode')
|
||||
self.min_freq = config.getfloat('min_freq', 5., minval=1.)
|
||||
# Defaults are such that max_freq * accel_per_hz == 10000 (max_accel)
|
||||
self.max_freq = config.getfloat('max_freq', 10000. / 75.,
|
||||
self.max_freq = config.getfloat('max_freq', 135.,
|
||||
minval=self.min_freq, maxval=300.)
|
||||
self.accel_per_hz = config.getfloat('accel_per_hz', 75., above=0.)
|
||||
self.accel_per_hz = config.getfloat('accel_per_hz', 60., above=0.)
|
||||
self.hz_per_sec = config.getfloat('hz_per_sec', 1.,
|
||||
minval=0.1, maxval=2.)
|
||||
|
||||
self.probe_points = config.getlists('probe_points', seps=(',', '\n'),
|
||||
parser=float, count=3)
|
||||
def get_start_test_points(self):
|
||||
return self.probe_points
|
||||
def prepare_test(self, gcmd):
|
||||
self.freq_start = gcmd.get_float("FREQ_START", self.min_freq, minval=1.)
|
||||
self.freq_end = gcmd.get_float("FREQ_END", self.max_freq,
|
||||
minval=self.freq_start, maxval=300.)
|
||||
self.accel_per_hz = gcmd.get_float("ACCEL_PER_HZ",
|
||||
self.accel_per_hz, above=0.)
|
||||
self.hz_per_sec = gcmd.get_float("HZ_PER_SEC", self.hz_per_sec,
|
||||
above=0., maxval=2.)
|
||||
def run_test(self, axis, gcmd):
|
||||
self.test_accel_per_hz = gcmd.get_float("ACCEL_PER_HZ",
|
||||
self.accel_per_hz, above=0.)
|
||||
self.test_hz_per_sec = gcmd.get_float("HZ_PER_SEC", self.hz_per_sec,
|
||||
above=0., maxval=2.)
|
||||
def gen_test(self):
|
||||
freq = self.freq_start
|
||||
res = []
|
||||
sign = 1.
|
||||
time = 0.
|
||||
while freq <= self.freq_end + 0.000001:
|
||||
t_seg = .25 / freq
|
||||
accel = self.test_accel_per_hz * freq
|
||||
time += t_seg
|
||||
res.append((time, sign * accel, freq))
|
||||
time += t_seg
|
||||
res.append((time, -sign * accel, freq))
|
||||
freq += 2. * t_seg * self.test_hz_per_sec
|
||||
sign = -sign
|
||||
return res
|
||||
def get_max_freq(self):
|
||||
return self.freq_end
|
||||
|
||||
class SweepingVibrationsTestGenerator:
|
||||
def __init__(self, config):
|
||||
self.vibration_generator = VibrationPulseTestGenerator(config)
|
||||
self.sweeping_accel = config.getfloat('sweeping_accel', 400., above=0.)
|
||||
self.sweeping_period = config.getfloat('sweeping_period', 1.2,
|
||||
minval=0.)
|
||||
def prepare_test(self, gcmd):
|
||||
self.vibration_generator.prepare_test(gcmd)
|
||||
self.test_sweeping_accel = gcmd.get_float(
|
||||
"SWEEPING_ACCEL", self.sweeping_accel, above=0.)
|
||||
self.test_sweeping_period = gcmd.get_float(
|
||||
"SWEEPING_PERIOD", self.sweeping_period, minval=0.)
|
||||
def gen_test(self):
|
||||
test_seq = self.vibration_generator.gen_test()
|
||||
accel_fraction = math.sqrt(2.0) * 0.125
|
||||
if self.test_sweeping_period:
|
||||
t_rem = self.test_sweeping_period * accel_fraction
|
||||
sweeping_accel = self.test_sweeping_accel
|
||||
else:
|
||||
t_rem = float('inf')
|
||||
sweeping_accel = 0.
|
||||
res = []
|
||||
last_t = 0.
|
||||
sig = 1.
|
||||
accel_fraction += 0.25
|
||||
for next_t, accel, freq in test_seq:
|
||||
t_seg = next_t - last_t
|
||||
while t_rem <= t_seg:
|
||||
last_t += t_rem
|
||||
res.append((last_t, accel + sweeping_accel * sig, freq))
|
||||
t_seg -= t_rem
|
||||
t_rem = self.test_sweeping_period * accel_fraction
|
||||
accel_fraction = 0.5
|
||||
sig = -sig
|
||||
t_rem -= t_seg
|
||||
res.append((next_t, accel + sweeping_accel * sig, freq))
|
||||
last_t = next_t
|
||||
return res
|
||||
def get_max_freq(self):
|
||||
return self.vibration_generator.get_max_freq()
|
||||
|
||||
class ResonanceTestExecutor:
|
||||
def __init__(self, config):
|
||||
self.printer = config.get_printer()
|
||||
self.gcode = self.printer.lookup_object('gcode')
|
||||
def run_test(self, test_seq, axis, gcmd):
|
||||
reactor = self.printer.get_reactor()
|
||||
toolhead = self.printer.lookup_object('toolhead')
|
||||
X, Y, Z, E = toolhead.get_position()
|
||||
sign = 1.
|
||||
freq = self.freq_start
|
||||
# Override maximum acceleration and acceleration to
|
||||
# deceleration based on the maximum test frequency
|
||||
systime = self.printer.get_reactor().monotonic()
|
||||
systime = reactor.monotonic()
|
||||
toolhead_info = toolhead.get_status(systime)
|
||||
old_max_accel = toolhead_info['max_accel']
|
||||
old_minimum_cruise_ratio = toolhead_info['minimum_cruise_ratio']
|
||||
max_accel = self.freq_end * self.accel_per_hz
|
||||
max_accel = max([abs(a) for _, a, _ in test_seq])
|
||||
self.gcode.run_script_from_command(
|
||||
"SET_VELOCITY_LIMIT ACCEL=%.3f MINIMUM_CRUISE_RATIO=0"
|
||||
% (max_accel,))
|
||||
|
|
@ -90,24 +144,46 @@ class VibrationPulseTest:
|
|||
gcmd.respond_info("Disabled [input_shaper] for resonance testing")
|
||||
else:
|
||||
input_shaper = None
|
||||
gcmd.respond_info("Testing frequency %.0f Hz" % (freq,))
|
||||
while freq <= self.freq_end + 0.000001:
|
||||
t_seg = .25 / freq
|
||||
accel = self.accel_per_hz * freq
|
||||
max_v = accel * t_seg
|
||||
last_v = last_t = last_accel = last_freq = 0.
|
||||
for next_t, accel, freq in test_seq:
|
||||
t_seg = next_t - last_t
|
||||
toolhead.cmd_M204(self.gcode.create_gcode_command(
|
||||
"M204", "M204", {"S": accel}))
|
||||
L = .5 * accel * t_seg**2
|
||||
dX, dY = axis.get_point(L)
|
||||
nX = X + sign * dX
|
||||
nY = Y + sign * dY
|
||||
toolhead.move([nX, nY, Z, E], max_v)
|
||||
toolhead.move([X, Y, Z, E], max_v)
|
||||
sign = -sign
|
||||
old_freq = freq
|
||||
freq += 2. * t_seg * self.hz_per_sec
|
||||
if math.floor(freq) > math.floor(old_freq):
|
||||
"M204", "M204", {"S": abs(accel)}))
|
||||
v = last_v + accel * t_seg
|
||||
abs_v = abs(v)
|
||||
if abs_v < 0.000001:
|
||||
v = abs_v = 0.
|
||||
abs_last_v = abs(last_v)
|
||||
v2 = v * v
|
||||
last_v2 = last_v * last_v
|
||||
half_inv_accel = .5 / accel
|
||||
d = (v2 - last_v2) * half_inv_accel
|
||||
dX, dY = axis.get_point(d)
|
||||
nX = X + dX
|
||||
nY = Y + dY
|
||||
toolhead.limit_next_junction_speed(abs_last_v)
|
||||
if v * last_v < 0:
|
||||
# The move first goes to a complete stop, then changes direction
|
||||
d_decel = -last_v2 * half_inv_accel
|
||||
decel_X, decel_Y = axis.get_point(d_decel)
|
||||
toolhead.move([X + decel_X, Y + decel_Y, Z, E], abs_last_v)
|
||||
toolhead.move([nX, nY, Z, E], abs_v)
|
||||
else:
|
||||
toolhead.move([nX, nY, Z, E], max(abs_v, abs_last_v))
|
||||
if math.floor(freq) > math.floor(last_freq):
|
||||
gcmd.respond_info("Testing frequency %.0f Hz" % (freq,))
|
||||
reactor.pause(reactor.monotonic() + 0.01)
|
||||
X, Y = nX, nY
|
||||
last_t = next_t
|
||||
last_v = v
|
||||
last_accel = accel
|
||||
last_freq = freq
|
||||
if last_v:
|
||||
d_decel = -.5 * last_v2 / old_max_accel
|
||||
decel_X, decel_Y = axis.get_point(d_decel)
|
||||
toolhead.cmd_M204(self.gcode.create_gcode_command(
|
||||
"M204", "M204", {"S": old_max_accel}))
|
||||
toolhead.move([X + decel_X, Y + decel_Y, Z, E], abs(last_v))
|
||||
# Restore the original acceleration values
|
||||
self.gcode.run_script_from_command(
|
||||
"SET_VELOCITY_LIMIT ACCEL=%.3f MINIMUM_CRUISE_RATIO=%.3f"
|
||||
|
|
@ -116,14 +192,13 @@ class VibrationPulseTest:
|
|||
if input_shaper is not None:
|
||||
input_shaper.enable_shaping()
|
||||
gcmd.respond_info("Re-enabled [input_shaper]")
|
||||
def get_max_freq(self):
|
||||
return self.freq_end
|
||||
|
||||
class ResonanceTester:
|
||||
def __init__(self, config):
|
||||
self.printer = config.get_printer()
|
||||
self.move_speed = config.getfloat('move_speed', 50., above=0.)
|
||||
self.test = VibrationPulseTest(config)
|
||||
self.generator = SweepingVibrationsTestGenerator(config)
|
||||
self.executor = ResonanceTestExecutor(config)
|
||||
if not config.get('accel_chip_x', None):
|
||||
self.accel_chip_names = [('xy', config.get('accel_chip').strip())]
|
||||
else:
|
||||
|
|
@ -133,6 +208,8 @@ class ResonanceTester:
|
|||
if self.accel_chip_names[0][1] == self.accel_chip_names[1][1]:
|
||||
self.accel_chip_names = [('xy', self.accel_chip_names[0][1])]
|
||||
self.max_smoothing = config.getfloat('max_smoothing', None, minval=0.05)
|
||||
self.probe_points = config.getlists('probe_points', seps=(',', '\n'),
|
||||
parser=float, count=3)
|
||||
|
||||
self.gcode = self.printer.lookup_object('gcode')
|
||||
self.gcode.register_command("MEASURE_AXES_NOISE",
|
||||
|
|
@ -156,12 +233,9 @@ class ResonanceTester:
|
|||
toolhead = self.printer.lookup_object('toolhead')
|
||||
calibration_data = {axis: None for axis in axes}
|
||||
|
||||
self.test.prepare_test(gcmd)
|
||||
self.generator.prepare_test(gcmd)
|
||||
|
||||
if test_point is not None:
|
||||
test_points = [test_point]
|
||||
else:
|
||||
test_points = self.test.get_start_test_points()
|
||||
test_points = [test_point] if test_point else self.probe_points
|
||||
|
||||
for point in test_points:
|
||||
toolhead.manual_move(point, self.move_speed)
|
||||
|
|
@ -186,7 +260,8 @@ class ResonanceTester:
|
|||
raw_values.append((axis, aclient, chip.name))
|
||||
|
||||
# Generate moves
|
||||
self.test.run_test(axis, gcmd)
|
||||
test_seq = self.generator.gen_test()
|
||||
self.executor.run_test(test_seq, axis, gcmd)
|
||||
for chip_axis, aclient, chip_name in raw_values:
|
||||
aclient.finish_measurements()
|
||||
if raw_name_suffix is not None:
|
||||
|
|
@ -218,7 +293,7 @@ class ResonanceTester:
|
|||
parsed_chips.append(chip)
|
||||
return parsed_chips
|
||||
def _get_max_calibration_freq(self):
|
||||
return 1.5 * self.test.get_max_freq()
|
||||
return 1.5 * self.generator.get_max_freq()
|
||||
cmd_TEST_RESONANCES_help = ("Runs the resonance test for a specifed axis")
|
||||
def cmd_TEST_RESONANCES(self, gcmd):
|
||||
# Parse parameters
|
||||
|
|
|
|||
|
|
@ -48,7 +48,9 @@ class CalibrationData:
|
|||
# Avoid division by zero errors
|
||||
psd /= self.freq_bins + .1
|
||||
# Remove low-frequency noise
|
||||
psd[self.freq_bins < MIN_FREQ] = 0.
|
||||
low_freqs = self.freq_bins < 2. * MIN_FREQ
|
||||
psd[low_freqs] *= self.numpy.exp(
|
||||
-(2. * MIN_FREQ / (self.freq_bins[low_freqs] + .1))**2 + 1.)
|
||||
def get_psd(self, axis='all'):
|
||||
return self._psd_map[axis]
|
||||
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ class RetryHelper:
|
|||
return self.increasing > 1
|
||||
def check_retry(self, z_positions):
|
||||
if self.max_retries == 0:
|
||||
return
|
||||
return "done"
|
||||
error = round(max(z_positions) - min(z_positions),6)
|
||||
self.gcode.respond_info(
|
||||
"Retries: %d/%d %s: %0.6f tolerance: %0.6f" % (
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ class Move:
|
|||
self.delta_v2 = 2.0 * move_d * self.accel
|
||||
self.max_smoothed_v2 = 0.
|
||||
self.smooth_delta_v2 = 2.0 * move_d * toolhead.max_accel_to_decel
|
||||
self.next_junction_v2 = 999999999.9
|
||||
def limit_speed(self, speed, accel):
|
||||
speed2 = speed**2
|
||||
if speed2 < self.max_cruise_v2:
|
||||
|
|
@ -55,6 +56,8 @@ class Move:
|
|||
self.accel = min(self.accel, accel)
|
||||
self.delta_v2 = 2.0 * self.move_d * self.accel
|
||||
self.smooth_delta_v2 = min(self.smooth_delta_v2, self.delta_v2)
|
||||
def limit_next_junction_speed(self, speed):
|
||||
self.next_junction_v2 = min(self.next_junction_v2, speed**2)
|
||||
def move_error(self, msg="Move out of range"):
|
||||
ep = self.end_pos
|
||||
m = "%s: %.3f %.3f %.3f [%.3f]" % (msg, ep[0], ep[1], ep[2], ep[3])
|
||||
|
|
@ -64,9 +67,9 @@ class Move:
|
|||
return
|
||||
# Allow extruder to calculate its maximum junction
|
||||
extruder_v2 = self.toolhead.extruder.calc_junction(prev_move, self)
|
||||
max_start_v2 = min(
|
||||
extruder_v2, self.max_cruise_v2, prev_move.max_cruise_v2,
|
||||
prev_move.max_start_v2 + prev_move.delta_v2)
|
||||
max_start_v2 = min(extruder_v2, self.max_cruise_v2,
|
||||
prev_move.max_cruise_v2, prev_move.next_junction_v2,
|
||||
prev_move.max_start_v2 + prev_move.delta_v2)
|
||||
# Find max velocity using "approximated centripetal velocity"
|
||||
axes_r = self.axes_r
|
||||
prev_axes_r = prev_move.axes_r
|
||||
|
|
@ -462,6 +465,10 @@ class ToolHead:
|
|||
self.commanded_pos[:] = newpos
|
||||
self.kin.set_position(newpos, homing_axes)
|
||||
self.printer.send_event("toolhead:set_position")
|
||||
def limit_next_junction_speed(self, speed):
|
||||
last_move = self.lookahead.get_last()
|
||||
if last_move is not None:
|
||||
last_move.limit_next_junction_speed(speed)
|
||||
def move(self, newpos, speed):
|
||||
move = Move(self, self.commanded_pos, newpos, speed)
|
||||
if not move.move_d:
|
||||
|
|
|
|||
|
|
@ -146,7 +146,7 @@ int picoboot_flash(libusb_device_handle *handle, struct flash_data *image, model
|
|||
}
|
||||
|
||||
fprintf(stderr, "Rebooting device\n");
|
||||
if (model == 2040) {
|
||||
if (model == rp2040) {
|
||||
if (picoboot_reboot(handle, 0, 0, 500)) {
|
||||
return report_error(handle, "reboot");
|
||||
}
|
||||
|
|
|
|||
41
src/Kconfig
41
src/Kconfig
|
|
@ -96,15 +96,19 @@ config WANT_DISPLAYS
|
|||
bool
|
||||
depends on HAVE_GPIO
|
||||
default y
|
||||
config WANT_SENSORS
|
||||
config WANT_THERMOCOUPLE
|
||||
bool
|
||||
depends on HAVE_GPIO_I2C || HAVE_GPIO_SPI
|
||||
depends on HAVE_GPIO_SPI
|
||||
default y
|
||||
config WANT_ADXL345
|
||||
bool
|
||||
depends on HAVE_GPIO_SPI
|
||||
default y
|
||||
config WANT_LIS2DW
|
||||
bool
|
||||
depends on HAVE_GPIO_SPI || HAVE_GPIO_I2C
|
||||
default y
|
||||
config WANT_LDC1612
|
||||
config WANT_MPU9250
|
||||
bool
|
||||
depends on HAVE_GPIO_I2C
|
||||
default y
|
||||
|
|
@ -116,6 +120,14 @@ config WANT_ADS1220
|
|||
bool
|
||||
depends on HAVE_GPIO_SPI
|
||||
default y
|
||||
config WANT_LDC1612
|
||||
bool
|
||||
depends on HAVE_GPIO_I2C
|
||||
default y
|
||||
config WANT_SENSOR_ANGLE
|
||||
bool
|
||||
depends on HAVE_GPIO_SPI
|
||||
default y
|
||||
config WANT_SOFTWARE_I2C
|
||||
bool
|
||||
depends on HAVE_GPIO && HAVE_GPIO_I2C
|
||||
|
|
@ -126,8 +138,8 @@ config WANT_SOFTWARE_SPI
|
|||
default y
|
||||
config NEED_SENSOR_BULK
|
||||
bool
|
||||
depends on WANT_SENSORS || WANT_LIS2DW || WANT_LDC1612 || WANT_HX71X \
|
||||
|| WANT_ADS1220
|
||||
depends on WANT_ADXL345 || WANT_LIS2DW || WANT_MPU9250 \
|
||||
|| WANT_HX71X || WANT_ADS1220 || WANT_LDC1612 || WANT_SENSOR_ANGLE
|
||||
default y
|
||||
menu "Optional features (to reduce code size)"
|
||||
depends on HAVE_LIMITED_CODE_SIZE
|
||||
|
|
@ -137,14 +149,17 @@ config WANT_GPIO_BITBANGING
|
|||
config WANT_DISPLAYS
|
||||
bool "Support LCD devices"
|
||||
depends on HAVE_GPIO
|
||||
config WANT_SENSORS
|
||||
bool "Support external sensor devices"
|
||||
depends on HAVE_GPIO_I2C || HAVE_GPIO_SPI
|
||||
config WANT_THERMOCOUPLE
|
||||
bool "Support thermocouple MAX sensors"
|
||||
depends on HAVE_GPIO_SPI
|
||||
config WANT_ADXL345
|
||||
bool "Support adxl accelerometers"
|
||||
depends on HAVE_GPIO_SPI
|
||||
config WANT_LIS2DW
|
||||
bool "Support lis2dw and lis3dh 3-axis accelerometers"
|
||||
depends on HAVE_GPIO_SPI || HAVE_GPIO_I2C
|
||||
config WANT_LDC1612
|
||||
bool "Support ldc1612 eddy current sensor"
|
||||
config WANT_MPU9250
|
||||
bool "Support MPU accelerometers"
|
||||
depends on HAVE_GPIO_I2C
|
||||
config WANT_HX71X
|
||||
bool "Support HX711 and HX717 ADC chips"
|
||||
|
|
@ -152,6 +167,12 @@ config WANT_HX71X
|
|||
config WANT_ADS1220
|
||||
bool "Support ADS 1220 ADC chip"
|
||||
depends on HAVE_GPIO_SPI
|
||||
config WANT_LDC1612
|
||||
bool "Support ldc1612 eddy current sensor"
|
||||
depends on HAVE_GPIO_I2C
|
||||
config WANT_SENSOR_ANGLE
|
||||
bool "Support angle sensors"
|
||||
depends on HAVE_GPIO_SPI
|
||||
config WANT_SOFTWARE_I2C
|
||||
bool "Support software based I2C \"bit-banging\""
|
||||
depends on HAVE_GPIO && HAVE_GPIO_I2C
|
||||
|
|
|
|||
10
src/Makefile
10
src/Makefile
|
|
@ -14,12 +14,12 @@ src-$(CONFIG_WANT_GPIO_BITBANGING) += buttons.c tmcuart.c neopixel.c \
|
|||
src-$(CONFIG_WANT_DISPLAYS) += lcd_st7920.c lcd_hd44780.c
|
||||
src-$(CONFIG_WANT_SOFTWARE_SPI) += spi_software.c
|
||||
src-$(CONFIG_WANT_SOFTWARE_I2C) += i2c_software.c
|
||||
sensors-src-$(CONFIG_HAVE_GPIO_SPI) := thermocouple.c sensor_adxl345.c \
|
||||
sensor_angle.c
|
||||
sensors-src-$(CONFIG_HAVE_GPIO_I2C) += sensor_mpu9250.c
|
||||
src-$(CONFIG_WANT_SENSORS) += $(sensors-src-y)
|
||||
src-$(CONFIG_WANT_THERMOCOUPLE) += thermocouple.c
|
||||
src-$(CONFIG_WANT_ADXL345) += sensor_adxl345.c
|
||||
src-$(CONFIG_WANT_LIS2DW) += sensor_lis2dw.c
|
||||
src-$(CONFIG_WANT_LDC1612) += sensor_ldc1612.c
|
||||
src-$(CONFIG_WANT_MPU9250) += sensor_mpu9250.c
|
||||
src-$(CONFIG_WANT_HX71X) += sensor_hx71x.c
|
||||
src-$(CONFIG_WANT_ADS1220) += sensor_ads1220.c
|
||||
src-$(CONFIG_WANT_LDC1612) += sensor_ldc1612.c
|
||||
src-$(CONFIG_WANT_SENSOR_ANGLE) += sensor_angle.c
|
||||
src-$(CONFIG_NEED_SENSOR_BULK) += sensor_bulk.c
|
||||
|
|
|
|||
|
|
@ -13,11 +13,20 @@
|
|||
#include "sensor_bulk.h" // sensor_bulk_report
|
||||
#include "spicmds.h" // spidev_transfer
|
||||
|
||||
enum { SA_CHIP_A1333, SA_CHIP_AS5047D, SA_CHIP_TLE5012B, SA_CHIP_MAX };
|
||||
enum {
|
||||
SA_CHIP_A1333,
|
||||
SA_CHIP_AS5047D,
|
||||
SA_CHIP_TLE5012B,
|
||||
SA_CHIP_MT6816,
|
||||
SA_CHIP_MT6826S,
|
||||
SA_CHIP_MAX
|
||||
};
|
||||
|
||||
DECL_ENUMERATION("spi_angle_type", "a1333", SA_CHIP_A1333);
|
||||
DECL_ENUMERATION("spi_angle_type", "as5047d", SA_CHIP_AS5047D);
|
||||
DECL_ENUMERATION("spi_angle_type", "tle5012b", SA_CHIP_TLE5012B);
|
||||
DECL_ENUMERATION("spi_angle_type", "mt6816", SA_CHIP_MT6816);
|
||||
DECL_ENUMERATION("spi_angle_type", "mt6826s", SA_CHIP_MT6826S);
|
||||
|
||||
enum { TCODE_ERROR = 0xff };
|
||||
enum {
|
||||
|
|
@ -131,6 +140,15 @@ a1333_query(struct spi_angle *sa, uint32_t stime)
|
|||
angle_add_data(sa, stime, mtime1, (msg[0] << 9) | (msg[1] << 1));
|
||||
}
|
||||
|
||||
static int bit_parity(uint8_t *msg)
|
||||
{
|
||||
uint_fast8_t parity = msg[0] ^ msg[1];
|
||||
parity ^= parity >> 4;
|
||||
parity ^= parity >> 2;
|
||||
parity ^= parity >> 1;
|
||||
return parity;
|
||||
}
|
||||
|
||||
// as5047d sensor query
|
||||
static void
|
||||
as5047d_query(struct spi_angle *sa, uint32_t stime)
|
||||
|
|
@ -147,10 +165,7 @@ as5047d_query(struct spi_angle *sa, uint32_t stime)
|
|||
msg[0] = 0xC0;
|
||||
msg[1] = 0x00;
|
||||
spidev_transfer(sa->spi, 1, sizeof(msg), msg);
|
||||
uint_fast8_t parity = msg[0] ^ msg[1];
|
||||
parity ^= parity >> 4;
|
||||
parity ^= parity >> 2;
|
||||
parity ^= parity >> 1;
|
||||
uint_fast8_t parity = bit_parity(msg);
|
||||
if (parity & 1)
|
||||
angle_add_error(sa, SE_CRC);
|
||||
else if (msg[0] & 0x40)
|
||||
|
|
@ -159,6 +174,60 @@ as5047d_query(struct spi_angle *sa, uint32_t stime)
|
|||
angle_add_data(sa, stime, mtime2, (msg[0] << 10) | (msg[1] << 2));
|
||||
}
|
||||
|
||||
static void mt6816_query(struct spi_angle *sa, uint32_t stime)
|
||||
{
|
||||
uint8_t msg[3] = {0x83, 0x00, 0x00};
|
||||
uint32_t mtime1 = timer_read_time();
|
||||
spidev_transfer(sa->spi, 1, sizeof(msg), msg);
|
||||
uint32_t mtime2 = timer_read_time();
|
||||
// Data is latched on first sclk edge of response
|
||||
if (mtime2 - mtime1 > MAX_SPI_READ_TIME) {
|
||||
angle_add_error(sa, SE_SPI_TIME);
|
||||
return;
|
||||
}
|
||||
uint_fast8_t parity = bit_parity(&msg[1]);
|
||||
if (parity & 1)
|
||||
angle_add_error(sa, SE_CRC);
|
||||
else if (msg[2] & 0x02)
|
||||
angle_add_error(sa, SE_NO_ANGLE);
|
||||
else
|
||||
angle_add_data(sa, stime, mtime2, (msg[1] << 8) | (msg[2] & 0xfc));
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
crc8_mt(uint8_t crc, uint8_t data)
|
||||
{
|
||||
crc ^= data;
|
||||
int i;
|
||||
for (i = 0; i < 8; i++)
|
||||
crc = crc & 0x80 ? (crc << 1) ^ 0x07 : crc << 1;
|
||||
return crc;
|
||||
}
|
||||
|
||||
static void mt6826s_query(struct spi_angle *sa, uint32_t stime)
|
||||
{
|
||||
uint8_t msg[6] = {0x30, 0x03, 0x00, 0x00, 0x00, 0x00};
|
||||
uint32_t mtime1 = timer_read_time();
|
||||
spidev_transfer(sa->spi, 1, sizeof(msg), msg);
|
||||
uint32_t mtime2 = timer_read_time();
|
||||
// Data is latched on first sclk edge of response
|
||||
if (mtime2 - mtime1 > MAX_SPI_READ_TIME) {
|
||||
angle_add_error(sa, SE_SPI_TIME);
|
||||
return;
|
||||
}
|
||||
uint8_t crc = 0;
|
||||
for (int i = 2; i < 5; i++)
|
||||
crc = crc8_mt(crc, msg[i]);
|
||||
|
||||
if (crc != msg[5])
|
||||
angle_add_error(sa, SE_CRC);
|
||||
else if (msg[4] & 0x02)
|
||||
angle_add_error(sa, SE_NO_ANGLE);
|
||||
else
|
||||
angle_add_data(sa, stime, mtime2, (msg[2] << 8) | msg[3]);
|
||||
}
|
||||
|
||||
|
||||
#define TLE_READ 0x80
|
||||
#define TLE_READ_LATCH (TLE_READ | 0x04)
|
||||
#define TLE_REG_AVAL 0x02
|
||||
|
|
@ -301,6 +370,10 @@ spi_angle_task(void)
|
|||
as5047d_query(sa, stime);
|
||||
else if (chip == SA_CHIP_TLE5012B)
|
||||
tle5012b_query(sa, stime);
|
||||
else if (chip == SA_CHIP_MT6816)
|
||||
mt6816_query(sa, stime);
|
||||
else if (chip == SA_CHIP_MT6826S)
|
||||
mt6826s_query(sa, stime);
|
||||
angle_check_report(sa, oid);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,3 +6,4 @@ CONFIG_WANT_SOFTWARE_SPI=n
|
|||
CONFIG_WANT_LIS2DW=n
|
||||
CONFIG_WANT_HX71X=n
|
||||
CONFIG_WANT_ADS1220=n
|
||||
CONFIG_WANT_SENSOR_ANGLE=n
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue