Klipper3d / klipper

Klipper is a 3d-printer firmware
GNU General Public License v3.0
9.36k stars 5.29k forks source link

[FR] Use accelerometer as Z probe #3741

Closed Apsu closed 2 years ago

Apsu commented 3 years ago

Now that Input Shaper and ADXL support has been given heavy attention for the past 6 months or so, it seems like it wouldn't be too difficult to mount the accelerometer to a toolhead and use it for Z probing.

There's been some work on this in the past, from SeeMeCNC and Nicholas Seward. I realize that some piezo approaches exist, but if we could get support added for using the accelerometer as a Z-probe (even in just a test branch), we could spend some time exploring how viable tuning can be for probe repeatability and accuracy.

If it can be done well enough, then you can use it for Input Shaping, probing, and that gives a starting point for doing tilt measurements as well (flying gantry, or 4/5 axis toolhead tramming, or even a second accelerometer on the bed, etc).

KevinOConnor commented 3 years ago

If using probe:z_virtual_endstop then step 2 is not valid and Z_ENDSTOP_CALIBRATE can't be run at all.

Pardon my ignorance, but why?

The Z_ENDSTOP_CALIBRATE command updates the stepper_z position_endstop parameter, but the position_endstop parameter may not be set when using probe:z_virtual_endstop. So, it would not make sense to run the command.

When we first introduced probe:z_virtual_endstop it was necessary to set both stepper_z position_endstop and probe z_offset, and users often would (likely by mistake) not set them to the same value. It caused all sorts of confusion. So, the code was changed to detect the probe:z_virtual_endstop case and automatically set stepper_z position_endstop to probe z_offset in that case (and to forbid the user manually setting position_endstop). This was all before the Z_ENDSTOP_CALIBRATE and PROBE_CALIBRATE commands were added.

It seems (please correct me if I'm wrong) that probe:z_virtual_endstop works as a normal endstop pin, so z_offset of a probe is not taken into account when setting 0 level.

No - there's a special check to internally set the position_endstop to the probe's z_offset in that case.

I must admit it didn't become clear to me from the docs ("z_offset isn't used for anything" part), and for example that relative_reference_index feature seemed quite optional from the docs (rather than being, "you should really use it, unless there is a good reason not to").

Alas, it's more confusing. You really want to set relative_reference_index if the endstop is to be considered the high accuracy sensor. You almost certainly don't want to set it if the probe is to be considered the high accuracy sensor.

Though, I don't really use bed_mesh or probe's so I may be missing something subtle here. Adding to the complication is some users run a bed mesh scan before every print and some rely on scans from months ago.

Well, then I would propose to only support Z_ENDSTOP_CALIBRATE METHOD=AUTOMATIC for ADXL345 (at least, for now) - provided that it really demonstrates sufficient accuracy for different users.

FWIW, might be less confusing to introduce an entirely new command.

code-wise it's really not a lot, so it may make sense to integrate even if there are only a few users.

I haven't done a review of the code, but it seems like it's a useful feature worth adding.

-Kevin

KevinOConnor commented 3 years ago

Thinking about this further, perhaps a simpler way of thinking about this is to distinguish between two different uses of the probe:

  1. Some users use the probe both to level the bed (the nozzle is a consistent distance from the bed at different XY coordinates) and to home the Z (the nozzle is a known distance from the bed).
  2. Other users use the probe to level the bed, but use a Z endstop to set the absolute distance between probe and bed.

Characteristics of the first case are probe:z_virtual_endstop, and/or running a BED_MESH_CALIBRATE, BED_TILT_CALIBRATE, Z_TILT_ADJUST prior to every print.

Characteristics of the second case are using relative_reference_index, and always homing (G28 Z) after bed mesh / bed tilt / z tilt / quad gantry level.

I think the Klipper docs (and tools) could do a better job explaining and distinguishing between the above. It's actually pretty easy to get confused between the two. For example, run Z_TILT_CALIBRATE and print - then the probe z_offset is primarily used - but run Z_TILT_CALIBRATE, G28, and print - then the position_endstop is used. Similarly on a delta, home and you're using the endstops, but run a bed_mesh and then you're likely using the probe..

It's can also be a bit difficult to reason on - for example, what does the position_endstop mean if the bed is tilted or not flat?

-Kevin

Apsu commented 3 years ago

I think the Klipper docs (and tools) could do a better job explaining and distinguishing between the above. It's actually pretty easy to get confused between the two. For example, run Z_TILT_CALIBRATE and print - then the probe z_offset is primarily used - but run Z_TILT_CALIBRATE, G28, and print - then the position_endstop is used. Similarly on a delta, home and you're using the endstops, but run a bed_mesh and then you're likely using the probe..

It's can also be a bit difficult to reason on - for example, what does the position_endstop mean if the bed is tilted or not flat?

I agree this could be better explained, as I had no idea and have used all of these pieces in different combinations before. Accelerometer or not, seems like this exercise might be a good impetus to rework docs a bit to give a clear high-level view of leveling and probing, and what combinations of tools work together towards those goals.

dmbutyugin commented 3 years ago

@KevinOConnor

The Z_ENDSTOP_CALIBRATE command updates the stepper_z position_endstop parameter, but the position_endstop parameter may not be set when using probe:z_virtual_endstop. So, it would not make sense to run the command.

When we first introduced probe:z_virtual_endstop it was necessary to set both stepper_z position_endstop and probe z_offset, and users often would (likely by mistake) not set them to the same value. It caused all sorts of confusion. So, the code was changed to detect the probe:z_virtual_endstop case and automatically set stepper_z position_endstop to probe z_offset in that case (and to forbid the user manually setting position_endstop). This was all before the Z_ENDSTOP_CALIBRATE and PROBE_CALIBRATE commands were added.

Strangely enough, this was not my experience. I was able to add (more like, I was not forced to remove position_endstop parameter when I set probe:z_virtual_endstop), and Z_ENDSTOP_CALIBRATE would adjust position_endstop in this case (see klippy.log attached; granted, it was generated on my adxl345-probe branch, but I didn't make any specific changes to manual Z_ENDSTOP_CALIBRATE or any stepper-related Klipper code). Alas, I was not able to find traces of the code you've mentioned either:

klippy$ grep z_virtual_endstop -l -R .
./extras/probe.py
klippy$ grep get_offsets -l -R .
./extras/bed_mesh.py
./extras/adxl345.py
./extras/probe.py
klippy$ grep probe_offsets -l -R .
./extras/probe.py
klippy$ grep z_offset -l -R .
./extras/delta_calibrate.py
./extras/bed_mesh.py
./extras/adxl345.py
./extras/bed_tilt.py
./extras/bltouch.py
./extras/probe.py
./extras/z_tilt.py

Well, then I would propose to only support Z_ENDSTOP_CALIBRATE METHOD=AUTOMATIC for ADXL345 (at least, for now) - provided that it really demonstrates sufficient accuracy for different users.

FWIW, might be less confusing to introduce an entirely new command.

OK, I've added a new BED_OFFSET_CALIBRATE command. However, right now it does recalculate z endstop offset, so it may be a bit more confusing. But, I am open to suggestions for better names.

Thinking about this further, perhaps a simpler way of thinking about this is to distinguish between two different uses of the probe:

1. Some users use the probe both to level the bed (the nozzle is a consistent distance from the bed at different XY coordinates) and to home the Z (the nozzle is a known distance from the bed).

2. Other users use the probe to level the bed, but use a Z endstop to set the absolute distance between probe and bed.

Characteristics of the first case are probe:z_virtual_endstop, and/or running a BED_MESH_CALIBRATE, BED_TILT_CALIBRATE, Z_TILT_ADJUST prior to every print.

Characteristics of the second case are using relative_reference_index, and always homing (G28 Z) after bed mesh / bed tilt / z tilt / quad gantry level.

This PoV makes a lot of sense, thanks!

It's can also be a bit difficult to reason on - for example, what does the position_endstop mean if the bed is tilted or not flat?

I'd think in this case z endstop simply sets 0 level on Z axis. It would be a user responsibility to make sense of a tilted / non-flat bed using bed mesh or bed tilt. Then the 0 level will have to match - via the z endstop offset - the chosen method to compensate bed defects (e.g. with a bed mesh it should reference the bed mesh "origin").

AlmightyFrog commented 3 years ago

Ok, now I am getting more and more confused about what is a good solution for my use cases:

What i have:

What I want:

My use cases why/when i want to make bed mesh

So if I get it right i shall set

Then for new bed mesh sequence would be:

Is that assumption fine?


@dmbutyugin btw i had some missed probes lately, not sure why but i had the feeling the distance from bed for starting the probe was smaller than the normal disctance used at config. I already had G28 so it should know, that my current z position was below the usual probe height. Do you verify that and in case current Z is smaller first increase distance between bed and nozzle?


Btw: I had to change my hotend, as the old one now completely broke. When doing recalibration everything seemed fine but then i recognized that nozzle was too near at bed for printing. In the end i did need to add offset of about +2mm to make the nozzle not scratch the bed.

My only idea is following: Might be that hotend is now more stable connected to gantry than before, so maybe now it triggers much later only when nozzle is already a little in the soft (buildtak like) bed? But that can't be 2mm for sure... :-/

So don't get me wrong - it is printing now and seems to be level so that is fine, but i did to manually correct this offset.

KevinOConnor commented 3 years ago

I was able to add (more like, I was not forced to remove position_endstop parameter when I set probe:z_virtual_endstop), and Z_ENDSTOP_CALIBRATE would adjust position_endstop

There was a bug fixed recently (commit 89183edb) - that bug prevented the error message. Also, if a position_endstop is in the "save_config" area of the config file, then it wont trigger the error message - and would technically allow Z_ENDSTOP_CALIBRATE to run. However, in all of the above cases, position_endstop from the config is not used - instead the probe's z_offset is used. The code is in stepper.py - look for hasattr(mcu_endstop, "get_position_endstop") - when a probe is used the stepper code obtains the internal position endstop from the probe and not the config.

-Kevin

dmbutyugin commented 3 years ago

@KevinOConnor I see, thanks a lot for the explanation, I missed that part about get_position_endstop.

@AlmightyFrog,

What I want:

* Normal operation only needs G28 before print

* In case anyhting at bed or nozzle changed, perfom bed mesh

Per discussion in this thread, I think you should not be using bed mesh every time something changes. Instead, you should do the following. First, one time do the following:

Then, if the bed changes, and one time in the beginning

Then if you change the nozzle, and one time in the beginning, run

Then, if you switch the hotend, I can imagine that the probe z_offset may change, so

@dmbutyugin btw i had some missed probes lately, not sure why but i had the feeling the distance from bed for starting the probe was smaller than the normal disctance used at config. I already had G28 so it should know, that my current z position was below the usual probe height. Do you verify that and in case current Z is smaller first increase distance between bed and nozzle?

Depends on which command you run. BED_OFFSET_CALIBRATE first sets Z level (if specified in the config). BED_MESH_CALIBRATE also has a parameter for that. PROBE command just probes from the current position, I believe. Also, the problems could be if the Z endstop position is off.

Btw: I had to change my hotend, as the old one now completely broke. When doing recalibration everything seemed fine but then i recognized that nozzle was too near at bed for printing. In the end i did need to add offset of about +2mm to make the nozzle not scratch the bed.

Can you verify the tuning sequence? As per suggestion above.

My only idea is following: Might be that hotend is now more stable connected to gantry than before, so maybe now it triggers much later only when nozzle is already a little in the soft (buildtak like) bed? But that can't be 2mm for sure... :-/

You can try to record acceleration data during probe and post the compressed raw data here (not just the chart), I can take a look (hopefully, it will be visible in the raw data when the nozzle hits the buildplate).

dmbutyugin commented 3 years ago

@AlmightyFrog and one other thing: if you set relative_reference_index to the middle of the bed, then you should set bed_probe_point in [adxl345] section to point to the middle of the bed too. And if you want the probe to maintain the height during the move and between the probe, set horizontal_move_z parameter there too.

AlmightyFrog commented 3 years ago

@dmbutyugin I'll post more verbose information later, but currently am stuck on a point where i guess that is not expected behavior...

  1. When doing PROBE_CALIBRATE it first did probe the bed and then moved away from it for me to do manual paper calibration. It also does not account of adxl345.bed_probe_point

  2. Not sure, but as per source code i guess adxl345.bed_probe_point shall be "x, y". I first had set it to the same index like used in bed mesh (11, as it begins looks like with 0 counting)

  3. Might it be, that while doing BED_MESH_CALIBRATE also the false probes are counted? I had in this one run quite many (first probe, and one after a X move) and bed mash seemed to still take that wrong values over. Please have a deeper look at following log: image

    // probe at 20.000,20.000 is z=-2.665000
    // probe at 20.000,20.000 is z=-0.202500
    // Probe samples exceed tolerance. Retrying...
    // probe at 20.000,20.000 is z=-0.190000
    // probe at 20.000,20.000 is z=-0.182500
    // probe at 20.000,20.000 is z=-0.182500
    // probe at 85.000,20.000 is z=0.122500
    // probe at 85.000,20.000 is z=0.100000
    // probe at 85.000,20.000 is z=0.102500
    // probe at 150.000,20.000 is z=0.270000
    // probe at 150.000,20.000 is z=0.270000
    // probe at 150.000,20.000 is z=0.265000
    // probe at 215.000,20.000 is z=0.487500
    // probe at 215.000,20.000 is z=0.497500
    // probe at 215.000,20.000 is z=0.495000
    // probe at 280.000,20.000 is z=-2.557500
    // probe at 280.000,20.000 is z=-2.842500
    // Probe samples exceed tolerance. Retrying...
    // probe at 280.000,20.000 is z=-3.042500
    // probe at 280.000,20.000 is z=-0.065000
    // Probe samples exceed tolerance. Retrying...
    // probe at 280.000,20.000 is z=-0.052500
    // probe at 280.000,20.000 is z=-0.072500
    // probe at 280.000,20.000 is z=-0.067500
    // probe at 280.000,85.000 is z=-0.032500
    // probe at 280.000,85.000 is z=-0.030000
    // probe at 280.000,85.000 is z=-0.022500
    // probe at 215.000,85.000 is z=-0.007500
    // probe at 215.000,85.000 is z=0.015000
    // probe at 215.000,85.000 is z=0.020000
    // probe at 150.000,85.000 is z=-0.107500
    // probe at 150.000,85.000 is z=-0.110000
    // probe at 150.000,85.000 is z=-0.102500
    // probe at 85.000,85.000 is z=-0.235000
    // probe at 85.000,85.000 is z=-0.235000
    // probe at 85.000,85.000 is z=-0.237500
    // probe at 20.000,85.000 is z=-0.410000
    // probe at 20.000,85.000 is z=-0.407500
    // probe at 20.000,85.000 is z=-0.420000
    // probe at 20.000,150.000 is z=-0.372500
    // probe at 20.000,150.000 is z=-0.382500
    // probe at 20.000,150.000 is z=-0.382500
    // probe at 85.000,150.000 is z=-0.162500
    // probe at 85.000,150.000 is z=-0.135000
    // probe at 85.000,150.000 is z=-0.152500
    // probe at 150.000,150.000 is z=0.020000
    // probe at 150.000,150.000 is z=0.017500
    // probe at 150.000,150.000 is z=0.017500
    // probe at 215.000,150.000 is z=0.092500
    // probe at 215.000,150.000 is z=0.100000
    // probe at 215.000,150.000 is z=0.102500
    // probe at 280.000,150.000 is z=0.040000
    // probe at 280.000,150.000 is z=0.047500
    // probe at 280.000,150.000 is z=0.047500
    // probe at 280.000,215.000 is z=0.115000
    // probe at 280.000,215.000 is z=0.110000
    // probe at 280.000,215.000 is z=0.115000
    // probe at 215.000,215.000 is z=0.262500
    // probe at 215.000,215.000 is z=0.272500
    // probe at 215.000,215.000 is z=0.270000
    // probe at 150.000,215.000 is z=0.172500
    // probe at 150.000,215.000 is z=0.175000
    // probe at 150.000,215.000 is z=0.175000
    // probe at 85.000,215.000 is z=-0.050000
    // probe at 85.000,215.000 is z=-0.037500
    // probe at 85.000,215.000 is z=-0.035000
    // probe at 20.000,215.000 is z=-3.077500
    // probe at 20.000,215.000 is z=-0.682500
    // Probe samples exceed tolerance. Retrying...
    // probe at 20.000,215.000 is z=-3.432500
    // probe at 20.000,215.000 is z=-0.845000
    // Probe samples exceed tolerance. Retrying...
    // probe at 20.000,215.000 is z=-0.842500
    // probe at 20.000,215.000 is z=-0.840000
    // probe at 20.000,215.000 is z=-0.832500
    // probe at 20.000,280.000 is z=-0.875000
    // probe at 20.000,280.000 is z=-0.875000
    // probe at 20.000,280.000 is z=-0.877500
    // probe at 85.000,280.000 is z=-0.340000
    // probe at 85.000,280.000 is z=-0.342500
    // probe at 85.000,280.000 is z=-0.347500
    // probe at 150.000,280.000 is z=-0.052500
    // probe at 150.000,280.000 is z=-0.020000
    // probe at 150.000,280.000 is z=-0.052500
    // probe at 215.000,280.000 is z=-0.020000
    // probe at 215.000,280.000 is z=-0.040000
    // probe at 215.000,280.000 is z=-0.035000
    // probe at 280.000,280.000 is z=-0.307500
    // probe at 280.000,280.000 is z=-0.297500
    // probe at 280.000,280.000 is z=-0.290000
    // Mesh Bed Leveling Complete
    // Bed Mesh state has been saved to profile [default]
    // for the current session.  The SAVE_CONFIG command will
    // update the printer config file and restart the printer.
    ok
    BED_MESH_OUTPUT
    // Mesh Leveling Probed Z positions:
    // -0.200000 0.085000 0.252500 0.477500 -0.085000
    // -0.427500 -0.252500 -0.125000 -0.002500 -0.047500
    // -0.400000 -0.170000 0.000000 0.082500 0.030000
    // -0.857500 -0.055000 0.157500 0.252500 0.097500
    // -0.892500 -0.360000 -0.070000 -0.052500 -0.315000
dmbutyugin commented 3 years ago

@AlmightyFrog

1. When doing PROBE_CALIBRATE it first did probe the bed and then moved away from it for me to do manual paper calibration. It also does not account of adxl345.bed_probe_point

PROBE_CALIBRATE is the standard command (I didn't change it), so indeed it does not take adxl345.bed_probe_point into account. It might be that the ADXL345 API and config will have to be changed later to be less confusing. For now it is just the experimental setup, so please pardon the potential inconsistencies between different commands. So you need to manually move the probe where you want to run PROBE_CALIBRATE.

BTW, the probe Z offset calibration using PROBE_CALIBRATE is described in more details here. I would advice you to run the probe calibration and bed offset calibration at the same point as pointed to by relative_reference_index parameter.

2. Not sure, but as per source code i guess adxl345.bed_probe_point shall be "x, y". I first had set it to the same index like used in bed mesh (11, as it begins looks like with 0 counting)

Yes, bed_probe_point is in 'x, y' format.

3. Might it be, that while doing BED_MESH_CALIBRATE also the false probes are counted? I had in this one run quite many (first probe, and one after a X move) and bed mash seemed to still take that wrong values over.

No, that should not be the case. If you look at the output of

BED_MESH_OUTPUT
// Mesh Leveling Probed Z positions:
// -0.200000 0.085000 0.252500 0.477500 -0.085000
// -0.427500 -0.252500 -0.125000 -0.002500 -0.047500
// -0.400000 -0.170000 0.000000 0.082500 0.030000
// -0.857500 -0.055000 0.157500 0.252500 0.097500
// -0.892500 -0.360000 -0.070000 -0.052500 -0.315000

The you see, it doesn't have all those false large -2, -3 (or their positive equivalents) values. In fact, the middle of the bed is at 0.000 (due to relative_reference_index set correctly to the middle of the bed). And the pic seems to be OK too, no? It is hard to tell the minimum, but it is from somewhere around -1, and you had the following 'good' probes:

// probe at 20.000,280.000 is z=-0.875000
// probe at 20.000,280.000 is z=-0.875000
// probe at 20.000,280.000 is z=-0.877500

and up to ~0.5, and you had the following probe:

// probe at 215.000,20.000 is z=0.487500
// probe at 215.000,20.000 is z=0.497500
// probe at 215.000,20.000 is z=0.495000

So, all in all, everything seems to make sense?

dmbutyugin commented 3 years ago

I wanted to share my latest progress on using the ADXL345 as a probe.

First, I made some HW changes to my Ender 3:

Then I also (re-)enabled stealthchop mode for Z stepper. This allowed me to drop the tap threshold to 5000 and the probing speed to 10 mm/sec, improving the reliability and repeatability of the probing. The final config (the relevant parts) looks like this:

[stepper_z]
position_max: 250
position_min: -4

[tmc2208 stepper_z]
uart_pin: P1.8
interpolate: True
run_current: 0.40
hold_current: 0.20
stealthchop_threshold: 30

[printer]
kinematics: cartesian
max_z_velocity: 15
max_z_accel: 200

[adxl345 hotend]
cs_pin: P0.26
spi_bus: ssp1
axes_map: -x,-z,-y
tap_thresh: 5000
int_pin: int2
probe_pin: P1.0
sample_retract_dist: 5.0
samples: 5
samples_result: average
samples_tolerance: 0.01
samples_tolerance_retries: 20
speed: 10
bed_probe_point: 92,125
horizontal_move_z: 10
z_offset: -0.130

[bed_mesh]
speed: 100
horizontal_move_z: 10
mesh_min: 20,50
mesh_max: 200, 200
probe_count: 6,5
relative_reference_index: 14

[endstop_phase]

Note that I bumped samples_tolerance_retries quite a bit to 20 just to make sure that the probing will succeed. I think that samples = 5 is a good choice for this probe, because the chances of getting bogus measurements are really low then. With samples = 3 the chances are higher, at least.

Another note is about z_offset of the probe. I first used PROBE_CALIBRATE and paper test, and I was getting -0.09..-0.11 z_offset for the probe. Then I noticed that this is very close to the thickness of the paper sheet I was using (I checked its thickness with a micrometer, which turned out to be 0.1mm). @AlmightyFrog, I wonder, which z_offset did you get? And can it be that ADXL345 really has a very low z_offset of its own? If yes, then z_offset only needs to account for subsequent thermal expansion.

AlmightyFrog commented 3 years ago

@dmbutyugin sorry for long delay. Not sure what your sequence was. But doing PROBE_CALIBRATE

PROBE_CALIBRATE
// probe at 200.000,200.000 is z=0.310000
// probe at 200.000,200.000 is z=0.310000
// probe at 200.000,200.000 is z=0.590000
// Probe samples exceed tolerance. Retrying...
// probe at 200.000,200.000 is z=-0.407500
// probe at 200.000,200.000 is z=-0.422500
// probe at 200.000,200.000 is z=0.752500
// Probe samples exceed tolerance. Retrying...
// probe at 200.000,200.000 is z=0.110000
// probe at 200.000,200.000 is z=-0.207500
// Probe samples exceed tolerance. Retrying...
// probe at 200.000,200.000 is z=0.790000
// probe at 200.000,200.000 is z=-0.417500
!! Probe samples exceed samples_tolerance

Not sure why, maybe distance is to small. Probe accuracy and bed mesh leveling itself seems to still work properly.

PROBE_ACCURACY PROBE_SPEED=25
// PROBE_ACCURACY at X:200.000 Y:200.000 Z:15.112 (samples=10 retract=5.000 speed=25.0 lift_speed=20.0)
// probe at 200.000,200.000 is z=-0.457500
// probe at 200.000,200.000 is z=-0.457500
// probe at 200.000,200.000 is z=-0.450000
// probe at 200.000,200.000 is z=-0.460000
// probe at 200.000,200.000 is z=-0.457500
// probe at 200.000,200.000 is z=-0.452500
// probe at 200.000,200.000 is z=-0.450000
// probe at 200.000,200.000 is z=-0.452500
// probe at 200.000,200.000 is z=-0.450000
// probe at 200.000,200.000 is z=-0.462500
// probe accuracy results: maximum -0.450000, minimum -0.462500, range 0.012500, average -0.455000, median -0.455000, standard deviation 0.004330

Note: I btw in the meantime changed to a glass bed. Measurement is reproducible and seems to be fine.

// Mesh Leveling Probed Z positions:
// -0.605000 -0.355000 -0.137500 0.047500 0.137500
// -0.502500 -0.230000 -0.045000 0.130000 0.195000
// -0.440000 -0.207500 0.000000 0.152500 0.195000
// -0.432500 -0.202500 -0.037500 0.120000 0.150000
// -0.505000 -0.312500 -0.147500 -0.020000 -0.017500
Mesh X,Y: 13,13
Search Height: 15
Mesh Average: -0.09
Mesh Range: min=-0.6050 max=0.2013

Currently I use z_offset = -0.400 with great success. My stepper_z position_endstop is set to -2.0

AlmightyFrog commented 3 years ago

@dmbutyugin Any new progress/experience from your side?

For myself i can sadly not tell anything new due to lack of time and having clogging issues with my big printer. To formulate it differently: I have a perfectly fine bed slinger printer which just lacks a little stability of bed and bed ad heasion. To formulate it postitive: I am thinking of upgrading that printer also with ADXL, and as there is nothing there yet, i could use that opportunity for doing high level documentation and simple guide how to implement it step by step. Might not be the post used setup, but should be pretty much average. It has a SKR 1.3 board init and as @Apsu said that might be a problem cause of pins available. I use st7920 display on it so following pins are already used:

[display]
lcd_type: st7920
cs_pin: P1.19
sclk_pin: P1.20
sid_pin: P1.18
encoder_pins: ^P3.26, ^P3.25
click_pin: ^!P0.28

[output_pin beeper]
pin: P1.30
pwm: True
value: 0
shutdown_value: 0
cycle_time: 0.001
scale: 1000

But besides that anything should be mostly usable/repurposable. Here is pinout of the board and schematics: https://raw.githubusercontent.com/bigtreetech/BIGTREETECH-SKR-V1.3/master/BTT%20SKR%20V1.3/hardware/SKR-V1.3-pinout.jpg

https://github.com/bigtreetech/BIGTREETECH-SKR-V1.3/blob/master/BTT%20SKR%20V1.3/hardware/SKR-V1.3-SCH.pdf

As I only use single extruder at that printer and only one Z stepper (planetary gearad, belt driven axis, hard synchronized with steel rod) there would be E1 port totally unused. Using available pins there I'd get access to E1SPI including using E1-RX (P1.1) as CS pin for one ADXL as there is no 2208 stepper connected. Second ADXL i can use some unused endstop pin i guess.

Does that sound fine or any better/more clear idea?


Having second thought, maybe it would be easier to connect directly to RPI as i guess that is more universal also for other people to use in the end.

Following Measuring Resonances documentation, do you @dmbutyugin and @apsu have already "defined" a common easy layout for using two ADXL boards? I'd suggest to use SPI0_CE1_N (pin 26) additionaly as CS for the second board. For ease of plug and play I'd also move 3V3 (pin 1) to pin 17 and GND (pin 6) to pin 20 or pin 25 so that i can use a normal 10 pin dual row connector to with one plug interface both sensors.

Does that seem like the right way to do for you?


@dmbutyugin To avoid getting this thread to a chatty discussion, do you btw use IRC or Discord? Could improve to keep this thread more facts based for easier reading by others afterwards.

dmbutyugin commented 3 years ago

@AlmightyFrog Thanks, I cannot say I made significant further progress on this matter. I have been using ADXL345 as a Z probe for some time already, and I am pretty happy with it. I used it on a bunch of occasions to re-calibrate the bed offset, and I used the following process: heat up the bed to the working temperature, and the hotend to the printing temperature - 60 degrees (so it'll be 150 C for 210 C prints) to prevent filament oozing from the hotend, and then re-calibrate the offset. That allows me to account for the thermal expansion for the most part, and so I only use probe z_offset: -0.09 to account for the remaining hotend expansion for the 60 degrees temp difference.

I guess we now need to write the docs :) I'll look into that, but again, it would be great to have more folks testing it and sharing their feedback.

For the 2 accelerometers config: I don't think there is a very well established wiring schema. Unfortunately, it is not possible to connect 2 adxl345 to the same SPI bus (so SPI0_CE1_N pin won't work). But it would seem that many RPi models (with 40 pin header) have 2 SPI interfaces. So I guess one can be connected to SPI0 bus and another one - to the SPI1 bus. And configured something like

[adxl345 honted]
cs_pin: rpi:None
spi_bus: spidev0.0
....

[adxl345 bed]
cs_pin: rpi:None
spi_bus: spidev1.0
...

I personally connect 1 adxl345 to the RPi (bed) and 1 adxl345 to the SKR 1.4 board (which has dedicated SPI header) I use on the Ender 3 pro. The latter is used on the hotend, and since it's connected to the printer board, it was easy enough to wire the int pin to the one of the available board pins, no optocoupler needed.

As for your idea to use E1; ADXL345 doesn't work (without HW modification) if there are other devices on the same SPI bus, so if you have some stepper motor drivers on that board that use SPI, such a setup won't work.

@dmbutyugin To avoid getting this thread to a chatty discussion, do you btw use IRC or Discord? Could improve to keep this thread more facts based for easier reading by others afterwards.

I infrequently happen to join the now official Discord Klipper server.

xkuyax commented 3 years ago

@dmbutyugin is there an issue/comment in here which explains how to properly set it up? Id like to give it a try on my V0, which has no probe, i haven't followed this thread, and im not keen on reading all 60 comments :D

AlmightyFrog commented 3 years ago

@xkuyax Not sure what your starting point is, but if you don't already use an ADXL345 I'd first suggest to follow https://www.klipper3d.org/Measuring_Resonances.html to get the basic hardware setup running and being able to verify it. You can do this of cause on original Klipper branch.

Once you have done that, check out latest specific development branch mentioned in https://github.com/KevinOConnor/klipper/issues/3741#issuecomment-759105616 and perform there the basic checkup. If that show some promising results, you might have a look at https://github.com/KevinOConnor/klipper/issues/3741#issuecomment-765739539 also.

Whatever points you struggle or have questions, please note down so we can use that for writing docs.

AlmightyFrog commented 3 years ago

I guess we now need to write the docs :) I'll look into that, but again, it would be great to have more folks testing it and sharing their feedback.

I am waiting for new cables and further ADXL boards coming in. I'll then like said before try to perform the whole sequence of installing it to my bed slinger. I hope that till then rotation_distance is not yet enforced and i can still use steps_per_mm so that there are not two big changes at the same time. In that process I will try to note down kind of the steps I did in a similar but not that extensive manner like you did in Measuring Resonances docs here in a comment. If you've prepared something before I get to this, of cause I am a happy early adoptor to test it out! ;)

For the 2 accelerometers config: I don't think there is a very well established wiring schema. Unfortunately, it is not possible to connect 2 adxl345 to the same SPI bus (so SPI0_CE1_N pin won't work). But it would seem that many RPi models (with 40 pin header) have 2 SPI interfaces.

Thanks for clarification, that would have cost me much time of frustration and cable creation. Would you mind to tell me, why you can't share one SPI bus. Is it then to slow to interleaved query the data from both sensors in given time?

dmbutyugin commented 3 years ago

@xkuyax

@dmbutyugin is there an issue/comment in here which explains how to properly set it up? Id like to give it a try on my V0, which has no probe, i haven't followed this thread, and im not keen on reading all 60 comments :D

You can start with this comment. A few notes/comments that came after that posting:

@AlmightyFrog

I am waiting for new cables and further ADXL boards coming in. I'll then like said before try to perform the whole sequence of installing it to my bed slinger. I hope that till then rotation_distance is not yet enforced and i can still use steps_per_mm so that there are not two big changes at the same time.

Aha, OK, sounds good.

Thanks for clarification, that would have cost me much time of frustration and cable creation. Would you mind to tell me, why you can't share one SPI bus. Is it then to slow to interleaved query the data from both sensors in given time?

No, it's because ADXL345 implements both SPI and I2C protocols using pretty much the same set of pins. So, when the RPi talks to a different SPI chip, this might be interpreted by ADXL345 as an I2C communication instead, and it will mess the SPI transfers. There is a way to do a HW modification of ADXL345 to prevent this (soldering some diodes if I'm not mistaken), but honestly connecting each ADXL345 to a separate hardware SPI bus is just way simpler.

xkuyax commented 3 years ago

@dmbutyugin thanks for the info! My Z Axis isn't mounted onto an coupler, instead its installed like this image (with the motor being connected to the leadscrew via an belt + pulley, the leadscrew is fixed into an bearing block) do you think that is going to be an problem?

I tried connecting the ADXL onto the SKR Mini E3 v1.2 SPI Header, but if i do that, the board doesn't boot anymore... (should this in theory work?) Im using a 24->5V/5A psu for the pi (where the adxl is connected) so connecting Int1 to an pin on the skr should work or?

xkuyax commented 3 years ago

@dmbutyugin Hey, i just hooked my hardware, i get the following error (latest git) NameError: global name 'name' is not defined Internal error during connect: global name 'name' is not defined https://pastebin.com/nb1W5JgK

Could it be that the latest line should be self.name instead name?

gcode.register_mux_command("ACCELEROMETER_QUERY", "CHIP", self.name,
                                   self.cmd_ACCELEROMETER_QUERY,
                                   desc=self.cmd_ACCELEROMETER_QUERY_help)
        gcode.register_mux_command("READ_ADXL345", "CHIP", name,

Edit: I changed those 2 to use self.name and i got it running. Homing and getting values works fine, but if i set SET_ADXL345 REG=0x2E VAL=0x40 and do QUERY_PROBE it always reports Triggered (if i invert it to !PC14 on the skr mini i just get the inverse, ^PC14 didnt work either) im using an skr mini with int2 as my interrupt pin, connected to the probe pin (just a normal input pin)

dmbutyugin commented 3 years ago

@xkuyax

@dmbutyugin Hey, i just hooked my hardware, i get the following error (latest git) NameError: global name 'name' is not defined Internal error during connect: global name 'name' is not defined https://pastebin.com/nb1W5JgK

Could it be that the latest line should be self.name instead name?

Yes, that was a merge mistake on my part, it should be fixed now, thanks.

@dmbutyugin thanks for the info! My Z Axis isn't mounted onto an coupler, instead its installed like this (with the motor being connected to the leadscrew via an belt + pulley, the leadscrew is fixed into an bearing block) do you think that is going to be an problem?

The coupler isn't really required, just adds a bit of safety. But I would advice getting a backlash-free nut, if you don't have one already. At least for me, the default Z nut on Ender 3 pro was giving issues, because the leadscrew would occasionally give in to backlash, and that would cause the spurious triggering.

I tried connecting the ADXL onto the SKR Mini E3 v1.2 SPI Header, but if i do that, the board doesn't boot anymore... (should this in theory work?)

It seems that the SPI bus on SKR Mini is shared with the SD card. Then I guess not? (Cause ADXL345 does not work well if there are other devices on the same SPI bus).

Im using a 24->5V/5A psu for the pi (where the adxl is connected) so connecting Int1 to an pin on the skr should work or?

As long as the ground of the built-in SKR Mini step-down converter and the one you use to power the RPi, it should work. But I don't know your wiring to give definitive answers.

Homing and getting values works fine, but if i set SET_ADXL345 REG=0x2E VAL=0x40 and do QUERY_PROBE it always reports Triggered (if i invert it to !PC14 on the skr mini i just get the inverse, ^PC14 didnt work either) im using an skr mini with int2 as my interrupt pin, connected to the probe pin (just a normal input pin)

You don't need to invert the pin. If you get the always triggered situation, it is likely that you've set too low tap_tresh value, which makes the ADXL345 trigger from the ambient noise (e.g. from the fans). You can still run

QUERY_PROBE
SET_ADXL345 CHIP=hotend REG=0x2E VAL=0x40
ACCELEROMETER_MEASURE CHIP=hotend
QUERY_PROBE
ACCELEROMETER_MEASURE CHIP=hotend

sequence, and then look at the generated file using graph_accelerometer.py script to see if there are any outliers on the chart that are above tap_thresh acceleration.

AlmightyFrog commented 3 years ago

Ok, took quite some time but my ADXL345 arrived. Just threw one so far onto my bed slinger following the steps i supposed at https://github.com/KevinOConnor/klipper/issues/3741#issuecomment-780686355 for @xkuyax to follow. Looked promising so far, but then when it came to bed mesh leveling i ran it several times and got really bad repeatability. Sometims it workes quite promising, sometimes there is one or two really bad values per point, sometimes it does not make sense at all and it crashes hard into bed. I removed the glass to not break it and now probe directly on the aluminum base plate. so that could destroy my nozzle, but should be good enough for making defined trigger point.

@dmbutyugin, any suggestions how to best work on sensitivity? Which values would be good to start with from your guess/experience? Tapthresh = 4000 till 6000 seemed to be good choices as per graph, but it was hard to get balance. also speed is an issue, as it accelerates too fast if initial height difference between bed and nozzle is to big so it already triggers in mid air.

Ah maybe I should mention, that it is a belt only printer, whereas all axis are driven by planetary geard nema17 motors and the both sides of z axis are synchronized hard with a steel rod. That should at least rule out any errors with regards to lead screws as they are not existing.

AlmightyFrog commented 3 years ago

Seems like it's just not working for my bed slinger sadly. I have the strong feeling, that the way this printer accelerates z axis plays a big role. so i had to turn down acceleration from 40 to 10 to reduce early triggerings in mid air while tap thresh is already 5000. If I then also reduce probe height from 5 to 3 mm then it works quite reproducable - at least at PROBE_ACCURACY. But as soon as travel from BED_MESH_CALIBRATE comes in, it sometimes triggers early seemingly just when it moved to new location where probe shall continue (i know exact same problem from my corexy also when i was using piezo).

May we get a parameter for

Also what might be good would be an easier way to play with tap thresh and speed - is there a way to add tap thresh to e.g. PROBE_ACCURACY command or even better as separate command?

dmbutyugin commented 3 years ago

@AlmightyFrog Which motor drivers are you using? I wonder if the axis is not moving consistently? Also, maybe you should try reducing the probing speed instead of reducing acceleration. I also wonder if the adxl345 location plays a role? I.e. depending on the mounting location, maybe the nozzle doesn't transmit enough acceleration from the hit into the sensor?

As for the command to set tap threshold etc., I'll add something.

A bit of update from my side: I recently tried adxl345 as a probe with a spring steel PEI-coated sheet. Unfortunately, I wasn't able to get it working well so far. If I set similar parameters to what I use for glass bed, it does not trigger sometimes. It would seem that the steel sheet is just not heavy enough and less rigid than glass (plus, PEI coating may be playing a role) and sometimes the nozzle just isn't hitting the sheet hard enough to trigger the tap on adxl345. When that happens, I can hear the difference between the successful probing attempt: when the probing is successful, there is some noticeable sound of a hit, but when it is unsuccessful, the nozzle 'crashes' into the steel sheet without any sound really. So it is not really a problem of adxl345 not triggering, but rather that it really had no chance to trigger. Then, if I increase the probing speed, it start to trigger mid-air. If I increase the tap_threshold, then it won't trigger once in a while. So it gets into a vicious cycle of increasing the probing speed and the tap_threshold.

For glass it actually works pretty well. My relevant parameters are: tap_threshold = 4000, probe speed = 7, max_z_accel = 200, sample_retract_dist = 5. I also set samples = 5, samples_tolerance = 0.01 and samples_tolerance_retries just a high number (like, 20-25, but with a glass, it makes 3-4 retries in a single point worst case). The Z axis is driven by the leadscrew though. And Z axis is using tmc driver in stealthchop mode.

ReprapRyn commented 3 years ago

May we get a parameter for

  • delay before probe after mesh move to reduce early trigger issue.
  • probe acceleration config

on my Piezo sensors, I have to add a pause gcode in my [probe] sections as well as a #samples_tolerance and samples_tolerance_retries to get over the occasional weirdness in a sensor. I would assume since Accelerometers are also sensitive to being triggered prematurely we would need this as well.

github-actions[bot] commented 3 years ago

Hello,

It looks like there hasn't been any recent updates on this Klipper github issue. If you created this issue and no longer consider it open, then please login to github and close the issue. Otherwise, if there is no further activity on this thread then it will be automatically closed in a few days.

Best regards,

~ Your friendly GitIssueBot

PS: I'm just an automated script, not a human being.

davidjericho commented 3 years ago

@dmbutyugin have you made any further progress on this? This is genuinely interesting me for a range of reasons, and would love to know if this still considered viable.

dmbutyugin commented 3 years ago

@davidjericho For me, it works well for glass bed. Unfortunately, not for PEI steel sheet. It might be worth integrating if it works at least for some surfaces. But I'd think we need more testing and successful usages before we can integrate it. So if you want to test it, please do.

FWIW, I've added some delay between the probing attempts in the hope to minimize the false premature triggering of the adxl345. I realized that I completely forgot to add TAPTHRESH parameter to PROBE* command(s), so I'll do that in the nearest future to simplify the tuning.

tobyfu commented 3 years ago

I have had some success after a lot of fiddling my printer is a prusa style bed slinger with a tooling plate on standoffs at 3 points which would be super rigid except the carriage plate under them tends to flex if pressure is applied to the X extreme ends of the bed, as a result when probing at those ends it will fail to trigger or vary in accuracy, lowering the tap threshold could help but then it tends to trigger the moment the probe starts. It would work better if there were a way to ignore the trigger until after it begins descending but I understand that isn't possible with how things work currently.

So where I have settled at is probing a smaller grid than I would usually do so that it avoids the failures and inaccuracies and the projects the rest of the bed, which works only because my bed is quite flat.

I am quite keen to see this integrated though as I think it will work particularly well on more suitable machines and I intend to use it as it means I can remove the bulk of the piezo orion module I'm using and I will probably just use it for bed_tilt. Also I really like the BED_OFFSET_CALIBRATE command I didn't have a seperate Z endstop set up before but I added one to make this easier and I find I prefer it this way.

On the bed surfaces I do use a magnetic sheet and pei powder coated spring steel, I don't have glass to make the comparison but from my experience here it seems like it's more important that the bed is rigidly mounted.

I added the activate_gcode bit from probe.py to the adxl endstop in my local copy so I could try a couple of things as I thought potentially backlash on my leadscrews was causing the early trigger and wanted to add a little hop prior to each probe to get it out of the way, it didn't seem to make a difference though.

btw the latest merge from master seems to have broken probing in your branch so I am using the prior commit

psrowser commented 3 years ago

I've been following this eagerly. Ive thought about using an accelerometer for this. Since learning that SeemeCnc once did it. As someone that barely knows python and new to klipper. I appreciate you sharing your findings.

dmbutyugin commented 3 years ago

btw the latest merge from master seems to have broken probing in your branch so I am using the prior commit

Thanks, I believe that should be fixed. Unfortunately, I had some problems with adxl345 wiring lately, so I could not test it too much.

BTW, I've also added a command SET_ACCEL_PROBE CHIP=... TAP_THRESH=... which can override the tap_thresh sensitivity at runtime, e.g. SET_ACCEL_PROBE CHIP=hotend TAP_THRESH=6000. Hopefully, that will make tuning easier.

github-actions[bot] commented 3 years ago

Hello,

It looks like there hasn't been any recent updates on this Klipper github issue. If you created this issue and no longer consider it open, then please login to github and close the issue. Otherwise, if there is no further activity on this thread then it will be automatically closed in a few days.

Best regards,

~ Your friendly GitIssueBot

PS: I'm just an automated script, not a human being.

tobyfu commented 3 years ago

I'm still using this though just for Z tilt and Z endstop calibration, would really like to see it get to the point it can be added to the master branch

zenturacp commented 3 years ago

Ll

github-actions[bot] commented 3 years ago

Hello,

It looks like there hasn't been any recent updates on this Klipper github issue. If you created this issue and no longer consider it open, then please login to github and close the issue. Otherwise, if there is no further activity on this thread then it will be automatically closed in a few days.

Best regards,

~ Your friendly GitIssueBot

PS: I'm just an automated script, not a human being.

dmbutyugin commented 3 years ago

@tobyfu, or anybody else, if you have successfully calibrated the adxl345 as a probe and are using it like that - please share your experiences. The most importantly - how did you run the calibration (according to the mini-guide in this ticket, or using your own process), what worked well and what were the problems. Please also report what kind of bed surfaces you found working, and what kind of kinematics (and Z axis configuration) your printer has, which stepper drivers are used for Z axis, and other helpful information.

I think the current state of the feature is that code-wise, it is totally merge-able, but the documentation is lacking. I could pull the first version of the documentation and the tuning guide from the comments in this issue, but I think we lack enough confirmation that the tuning procedure really works for more than a couple of folks.

github-actions[bot] commented 3 years ago

Hello,

It looks like there hasn't been any recent updates on this Klipper github issue. If you created this issue and no longer consider it open, then please login to github and close the issue. Otherwise, if there is no further activity on this thread then it will be automatically closed in a few days.

Best regards,

~ Your friendly GitIssueBot

PS: I'm just an automated script, not a human being.

Yury-MonZon commented 3 years ago

Any updates on this? How reliable is it?

github-actions[bot] commented 2 years ago

Hello,

It looks like there hasn't been any recent updates on this Klipper github issue. If you created this issue and no longer consider it open, then please login to github and close the issue. Otherwise, if there is no further activity on this thread then it will be automatically closed in a few days.

Best regards,

~ Your friendly GitIssueBot

PS: I'm just an automated script, not a human being.

ogland commented 2 years ago

I'm totally stoked about this! Any progress?

JiMcNulty commented 2 years ago

@dmbutyugin Amazing work! Would be really cool, too bad it didn't got more attention

I believe that It didn't work on PEI because like you said, its soft, but also the toolhead itself has some give, not so stiff and together they "absorb" the tap and round the graph

But this give can help! Did you see any tilt readings (different axis)? it might be enough to combine them both

Also, is there a more sensitive accelerator that is small low power and relatively low cost? how is the LIS3DSH compared to the adxl345? Or maybe combine it when an angle sensor?

dmbutyugin commented 2 years ago

@the-cobbler

ADXL345 does not have a tilt sensor. But I'm not sure if there would be any sufficient tilt to detect in the first place: I imagine it would be maybe a few degrees max. And LIS3DSH is unsupported by Klipper.

It is too bad that it didn't receive a lot of attention and user base. But I think that happens for a reason. After this attempt, I personally got BLTouch, and was happily using them ever since. I think the main troubles with adxl345 as a Z probe are:

  1. Requires that the nozzle is clean from any remnants of the filament from the previous prints. Otherwise, that sticking filament will soften the impact and adxl345 won't trigger. TBH, that's the biggest blocker for me: I oftentimes forget to clean the nozzle; and it is generally a lot of bother.
  2. "Z-Probe" failure mode: if it does not trigger, it does not trigger. Most (all?) other probes, even if they have repeatability issues, will trigger eventually (e.g. BLTouch, switch-based probes, piezo sensors, inductive and capacitive sensors probably), and then it is possible to just discard the wrong measurement. In this case, it does not trigger, and homing or bed meshing process stops with error; besides this can cause significant damage.
  3. Noise-to-signal ratio: the spikes of acceleration are not very high vs the average noise level when the Z axis operates (and this is even with stealthChop on Z axis enabled, which might be a bad idea (#4977). Increasing probing speed increases acceleration spikes, but also increases the noise, so in general it is not helpful. This leads to occasional probing errors.
  4. Apparently does not work for all surfaces. Maybe PEI sheet gives in, or maybe it's just that the glass has bigger mass, and so it resists the impact more, slowing the toolhead more abruptly.

But I understand that in some situations this probing sensor might be beneficial vs others (e.g. in some heated chambers). So, I will update my branch for further testing if others want to after (#4931), if that gives some good results.

JiMcNulty commented 2 years ago

@dmbutyugin Thanks for replying! I understand, its not robust enough But I do Like the concept, as I have toasty enclosure, bltouch does not hold up, inductive as well Only the klicky give some comfort But this solution will be much better, easier and lighter

Check out this sensor, it has an accel and a gyroscope that will detect the tilt, all we need is the 0.5 degrees detection

https://www.adafruit.com/product/1714 https://www.adafruit.com/product/4569 - built-in tap detection

This will give the full picture of what's happening (It can also help with a lot of other problems like side crashing and a nozzle that touches the print because of wrap for example) It may also really improve the input shaping calibration and technically can tell you what is the position of the nozzle at any given point, enabling you to detect missing steps or uncalibrated steps (not sure, need to understand the accuracy)

Sineos commented 2 years ago

https://github.com/adafruit/Adafruit_CircuitPython_ADXL34x/blob/main/examples/adxl34x_tap_detection_test.py Standard ADXL345 seems to have a dedicated "tap detection" as well

JiMcNulty commented 2 years ago

https://github.com/adafruit/Adafruit_CircuitPython_ADXL34x/blob/main/examples/adxl34x_tap_detection_test.py Standard ADXL345 seems to have a dedicated "tap detection" as well

It does, but its about sensitivity and cross checking with another sensor (gyro) that increase the overall resolution Anyway, its just suggestion :)

dmbutyugin commented 2 years ago

Yep, the current ADXL345-as-Z-probe implementation uses tap detection. The problem is indeed that during Z axis movements, there are lots of spiky noises that can be detected as tap events. It is the balance between too low and too high sensitivity that is hard to achieve. Perhaps there are sensors with more sophisticated tap event detection, but I don't know about them (and it is still unclear if that would help).

@the-cobbler I looked at the specs a bit, and the gyroscopes detect angular velocity (rotation) only, rather than the angular position. So, I'm still worried that the speed of tilting will be insufficient to detect a tap event from the operational noise. It would be a pity to spend considerable amount of time to program the communication protocol with such a device only to learn that it is useless.

JiMcNulty commented 2 years ago

Yep, the current ADXL345-as-Z-probe implementation uses tap detection. The problem is indeed that during Z axis movements, there are lots of spiky noises that can be detected as tap events. It is the balance between too low and too high sensitivity that is hard to achieve. Perhaps there are sensors with more sophisticated tap event detection, but I don't know about them (and it is still unclear if that would help).

@the-cobbler I looked at the specs a bit, and the gyroscopes detect angular velocity (rotation) only, rather than the angular position. So, I'm still worried that the speed of tilting will be insufficient to detect a tap event from the operational noise. It would be a pity to spend considerable amount of time to program the communication protocol with such a device only to learn that it is useless.

True. I will try to find another sensor that will have our requirements. Just another thought, it will be less cool but still cool: We can put the accel with tap detection on the bed itself (with a mount, away from the heat) , that will reduce most if not all of the noise because the bed is not moving while descending

ogland commented 2 years ago

@the-cobbler my bed is moving while ascending for homing.

JiMcNulty commented 2 years ago

@the-cobbler my bed is moving while ascending for homing.

Sorry, only had the voron 2 in mind In that case it wouldn't work, but the tilt detection will still work

@dmbutyugin I don't know if its already in klipper, and i'm surprised I didn't find any python packages for it, but you can get an angle from the adxl345 with less then 1 degree accuracy

The theory: https://www.analog.com/en/app-notes/an-1057.html

Some old code that can help: http://wizmoz.blogspot.com/2013/01/simple-accelerometer-data-conversion-to.html?_sm_au_=iVVrPJjs44Sjbntq

Another example: https://wiki.dfrobot.com/How_to_Use_a_Three-Axis_Accelerometer_for_Tilt_Sensing

There is also a nice read here (there is also some angle calc code): https://www.best-microcontroller-projects.com/adxl345.html

It says something that I think not everyone is aware of, because I saw people mounting the sensor in different positions. He basically says that the way the adxl345 is positioned can affect its measurements accuracy

Why not ±90°? Why can't the ADXL345 accelerometer indicate ±90°?

If you run the program below you will see that the accelerometer is extremely good at indicating tilt at low angles (on a flat surface) to about 70°, but does not reach ±90°. In fact it can't seem to reach that magic number ±90°! At first, I thought there was something wrong with the accelerometer since no one seems to talk about this. Why should it not be possible to measure all angles?

If you think about holding a piece of wood - the maximum force on it is when you hold it horizontally. The more you point it upwards, to the vertical position, the less gravity can affect it, hence - the accelerometer becomes less sensitive.

So it turns out that the sensitivity of the accelerometer decreases with increasing angle and follows a near sinusoidal response, and accuracy decreases the closer you get to ±90° of tilt.

"The sensor is a polysilicon surface-micromachined structure built on top of a silicon wafer. Polysilicon springs suspend the structure over the surface of the wafer and provide a resistance against forces due to applied acceleration." [datasheet] You can imagine the sensor as a beam suspended on springs, with the capacitance between the beam and the support base giving the acceleration measurement. When the beam is perpendicular to the acceleration field small tilt changes will have a large effect as gravity acts over a larger area.

As the beam tilts vertically, the sensor becomes less sensitive (interacting with the gravity vector less) until, at full vertical orientation, it can not return a reading since the gravity vector has no effect on the beam.

What do you think? is there hope?

dewi-ny-je commented 2 years ago

@dmbutyugin

Yep, the current ADXL345-as-Z-probe implementation uses tap detection. The problem is indeed that during Z axis movements, there are lots of spiky noises that can be detected as tap events. It is the balance between too low and too high sensitivity that is hard to achieve. Perhaps there are sensors with more sophisticated tap event detection, but I don't know about them (and it is still unclear if that would help).

You could integrate the readings and stop when the offset between expected position and actual position crosses a threshold. It makes the process much more resistant to noise.

Use the initial "constant speed" motion as baseline and detect the offset compared to that. No need of absolute calibration.

Any bed or gantry has enough give to tolerate such a solution based on offsets.