Klipper3d / klipper

Klipper is a 3d-printer firmware
GNU General Public License v3.0
9.02k stars 5.19k 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).

Apsu commented 3 years ago

SeeMeCNC is still selling their accelerometer probe toolhead, FWIW: https://www.seemecnc.com/products/he280-hotend-with-accelerometer-probe

klipper-gitissuebot commented 3 years ago

Hi @Apsu,

It did not look like there was a Klipper log file attached to this ticket. The log file has been engineered to answer common questions the Klipper developers have about the software and its environment (software version, hardware type, configuration, event timing, and hundreds of other questions).

Unfortunately, too many people have opened tickets without providing the log. That consumes developer time; time that would be better spent enhancing the software. If this ticket references an event that has occurred while running the software then the Klipper log must be attached to this ticket. Otherwise, this ticket will be automatically closed in a few days.

For information on obtaining the Klipper log file see: https://github.com/KevinOConnor/klipper/blob/master/docs/Contact.md

The log can still be attached to this ticket - just add a comment and attach the log to that comment.

Best regards, ~ Your friendly GitIssueBot

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

dmbutyugin commented 3 years ago

Hmm, interesting! In principle, it is not completely out of question: adxl345 supports tap detection, which can be used for this purpose. In this case, ADXL345 must be connected to the MCU board of the printer, and that MCU must have SPI support (to be more precise, to the board that controls Z axis/es). And an additional wire is needed that would go to the Z endstop pin (though this is not a problem really).

What I'm concerned a bit is if it can really reasonably detect the 'homing' event. From its specs, the minimum tap acceleration it can detect is ~600 mm/s^2. I'm not sure what is the order of magnitude of acceleration the toolhead experiences if it hits the print bed with the nozzle, for instance. And unlike other types of sensors (mechanical, optical, piezo, servo bl touch), setting the incorrect scale may have a catastrophic failure mode: the nozzle will crash into the bed without being detected and the printer will keep pushing the nozzle, which can damage the bed, the toolhead, and other parts of the printer. Like, piezo sensor or mechanical endstop will eventually detect the crash even if they are offset, but accelerometer won't, if the scale of a tap is off.

On the positive side, it can be a really useful probing sensor if proves to work well. It can be used for homing and bed meshing. Like, Smart Effector has a piezo sensor and it probes with the hotend nozzle itself, and it probes the surface of the bed, so there are no issues with sensor offset or sensor sensing the metal under the glass/etc. However, Smart Effector only works for delta printers.

Apsu commented 3 years ago

Hmm, interesting! In principle, it is not completely out of question: adxl345 supports tap detection, which can be used for this purpose. In this case, ADXL345 must be connected to the MCU board of the printer, and that MCU must have SPI support (to be more precise, to the board that controls Z axis/es). And an additional wire is needed that would go to the Z endstop pin (though this is not a problem really).

What I'm concerned a bit is if it can really reasonably detect the 'homing' event. From its specs, the minimum tap acceleration it can detect is ~600 mm/s^2. I'm not sure what is the order of magnitude of acceleration the toolhead experiences if it hits the print bed with the nozzle, for instance.

Yeah, I considered this functionality and it's interesting, but I was actually thinking that you could just use the existing code added for input shaping to query the sensor value data stream on the SBC side instead of MCU, allowing you to do analysis the ADXL doesn't have baked in already.

For example, if you know the homing speed being requested, you can likely use that in conjunction with an impulse equation (Force dTime = mass dVelocity) to set an expected range of acceleration spike, then configure a threshold based on it.

And unlike other types of sensors (mechanical, optical, piezo, servo bl touch), setting the incorrect scale may have a catastrophic failure mode: the nozzle will crash into the bed without being detected and the printer will keep pushing the nozzle, which can damage the bed, the toolhead, and other parts of the printer. Like, piezo sensor or mechanical endstop will eventually detect the crash even if they are offset, but accelerometer won't, if the scale of a tap is off.

This is certainly true that misconfiguration can cause a failure that leads to damaging parts, but I disagree it's different than other sensors. It's possible to misconfigure, miswire, or mount incorrectly pretty much all those other types, leading to potential damage.

On the positive side, it can be a really useful probing sensor if proves to work well. It can be used for homing and bed meshing. Like, Smart Effector has a piezo sensor and it probes with the hotend nozzle itself, and it probes the surface of the bed, so there are no issues with sensor offset or sensor sensing the metal under the glass/etc. However, Smart Effector only works for delta printers.

Yes indeed, I agree strongly, and since I am personally working towards a simultaneous parallel 5-axis design, I would already like to make use of tilt/orientation detection of accelerometers to tram the toolhead vs the bed, and this seems like a good first step in that direction. More general purpose functionality out of accelerometers the better!

dmbutyugin commented 3 years ago

Yeah, I considered this functionality and it's interesting, but I was actually thinking that you could just use the existing code added for input shaping to query the sensor value data stream on the SBC side instead of MCU, allowing you to do analysis the ADXL doesn't have baked in already.

I'm not sure I fully understand the proposal. But at any rate, homing endstop must be connected to the MCU that controls the respective stepper; this is by the current Klipper design and may not be very feasible to change. Also, querying accelerometer data and processing it would have higher latency (probably?).

For example, if you know the homing speed being requested, you can likely use that in conjunction with an impulse equation (Force dTime = mass dVelocity) to set an expected range of acceleration spike, then configure a threshold based on it.

That would define the lower limit for the detection threshold. But we are interested in detecting toolhead hitting the bed (deceleration), and in that case neither dTime nor dVelocity is not really known.

And unlike other types of sensors (mechanical, optical, piezo, servo bl touch), setting the incorrect scale may have a catastrophic failure mode: the nozzle will crash into the bed without being detected and the printer will keep pushing the nozzle, which can damage the bed, the toolhead, and other parts of the printer. Like, piezo sensor or mechanical endstop will eventually detect the crash even if they are offset, but accelerometer won't, if the scale of a tap is off.

This is certainly true that misconfiguration can cause a failure that leads to damaging parts, but I disagree it's different than other sensors. It's possible to misconfigure, miswire, or mount incorrectly pretty much all those other types, leading to potential damage.

In principle, yes, but due care can minimize the chances of things going wrong. Like, misconfigured piezo will still detect the nozzle hitting the bed, just a bit later (but before any damage is caused). For the mechanical switch, one can test when (and if) it triggers by manually moving Z axis with the motors turned off. With the accelerometer, safe testing process needs yet to be defined. It is similar to sensorless homing with the difference that the latter is usually done only on X and Y axes, and there failure to detect homing event would typically cause less damage.

Yes indeed, I agree strongly, and since I am personally working towards a simultaneous parallel 5-axis design, I would already like to make use of tilt/orientation detection of accelerometers to tram the toolhead vs the bed, and this seems like a good first step in that direction. More general purpose functionality out of accelerometers the better!

If the accelerometer can work as a Z 'probe', then all the related functionality should become available.

Apsu commented 3 years ago

Fair point about the endstop requirement. I wasn't certain that was the case.

My thinking on the impulse equation was that we know dVelocity will be homing speed, since we're going from homing to stopped. That leaves dTime, and it's not easy to derive analytically, but on this point and your other points about likelihood of risks, I suspect there's a way to empirically calibrate it in a safe way.

For example, using Zmax comes to mind. Starting off with a relatively 'safe' speed, and move towards Z+ until you get a spike above bare minimum. Measure the spike duration, repeat, derive threshold and window duration from it, reverse for Zmin to probe bed.

I'm sure there's other clever ideas too, but I can see this as a safer way to calibrate, much like sensorless homing as you mentioned.

Apsu commented 3 years ago

Looking through the data sheet the tap detection seems really good, actually. It's relatively granular to set the threshold and window/duration, and you can even restrict the axes to detect in. Finding lots of example Arduino builds using values as high as 2-3G for threshold with 20-50ms windows and it's easy to detect taps with fingers. This seems viable, as long as a safe calibration method can be derived.

dmbutyugin commented 3 years ago

@Apsu, OK, so I've put together a branch which adds Z probe functionality to ADXL345. Use it at your own risk. Similarly to sensorless homing, ADXL345 may fail to trigger if the sensitivity is set too low, and Z axis motor(s) are typically powerful enough (due to high reduction ratio) to cause some damage to the printer if they don't stop at the right time. I also suspect that if a noisy stepper driver is used for Z axis (and not TMC stepper driver or other reasonably silent drivers), it is possible that you may not be able to get stable result with it.

Now here are my thoughts about how to try to experiment with it.

First, ADXL345 must be connected to the printer MCU (the one controlling Z axis motors if there are many MCUs), and either int1 or int2 pin must be wired to some pin on the MCU that can work as an endstop pin (theoretically, only int1/2 pin must be connected to the printer MCU, however that has some chance of working only if the same power source is used for both printer and the RPi, and given the associated dangers of doing something wrong, e.g. if buck converter for RPi is connected inappropriately, I wouldn't recommend it). I recommend to keep Z endstop connected for initial experiments; so only connect ADXL345 in a 'probe' mode.

Then, the initial configuration must be set, e.g.

[adxl345 hotend]
cs_pin: ...
spi_bus: ...
axes_map: ...
probe_pin: ...
int_pin: int1  # or int2
tap_thresh: 5000
tap_dur: 0.01
speed: 20
z_offset: -0.2
# If the probe triggers prematurely, this should allow to
# detect this and run a few attempts to get good measurements
samples: 5
sample_retract_dist: 5.0
samples_result: median
samples_tolerance: 0.05
samples_tolerance_retries: 3

[stepper_z]
position_min: -0.5  # must allow hotend nozzle to 'hit' bed everywhere
homing_speed: 20
second_homing_speed: 20

[printer]
max_z_velocity: 25

Do not forget to increase the maximum z velocity, and also increase the z homing speed (at least, for now).

First of all, in [adxl345] the parameter axes_map must be set correctly (this is used to subtract G acceleration). Once its set, restart the printer and issue a command ACCELEROMETER_QUERY CHIP=hotend (if adxl345 has no name, juts ACCELEROMETER_QUERY command should be used). It should return some small values, e.g.

Send: ACCELEROMETER_QUERY CHIP=hotend
Recv: // adxl345 values (x, y, z): 627.625600, -0.000000, -235.359600

If it returns 2 big values (in the order of 7000-12000), or 1 very big number (15000-25000), it means that axes_map is not configured correctly; correct it before proceeding further.

Next, we need to figure the right tap_thresh value. Home the printer, move the toolhead to a place where Z homing using the normal Z endstop can be done (e.g. at X=0,Y=0), Z must be 5-10 mm, and then run the following commands:

ACCELEROMETER_MEASURE CHIP=hotend
G28 Z
ACCELEROMETER_MEASURE CHIP=hotend

Wait for homing to complete before running the second ACCELEROMETER_MEASURE... command. This will write the raw accelerometer measurements during homing. You can plot them on RPi using the command (copy the CSV file name from the output of ACCELEROMETER_MEASURE command)

~/klippy-env/bin/python ~/klipper/scripts/graph_accelerometer.py /tmp/adxl345-2021...csv -r -o /tmp/homing.png

It will look like this (approximately): homing

So the accelerometer happily picks up the various noises, for example from stepper driver (I'm using TMC2208 on Z axis in spreadcycle mode). The tap_tresh must be above that noise with some safety margin. For example, I ended up using tap_thresh=6500 on my printer. Note that tap_thresh value does not need to be very precise - it is anyway heavily rounded for ADXL sensor. BTW, one can also see a homing event on the chart where a spike is (when the printer abruptly stops Z axis when Z endstop is triggered). Restart the printer once the good tap_thresh value is set.

Now we can test if the wiring of the probe endstop works. Fortunately, ADXL345 can work as a probe and measure acceleration data simultaneously. Move the toolhead a bit above the bed, maybe 5-10 cm. Run the following commands:

QUERY_PROBE ; should report 'open'
SET_ADXL345 CHIP=hotend REG=0x2E VAL=0x40
ACCELEROMETER_MEASURE CHIP=hotend
QUERY_PROBE ; should still report 'open'

Now hit the hotend nozzle with your finger (e.g. nail) or some small metal tool. Run QUERY_PROBE command again. Now it should report TRIGGERED. If not, try hitting harder. If it still doesn't work, the wiring (or pin configuration) may be wrong. To finish with this, run ACCELEROMETER_MEASURE CHIP=hotend again, this will write the acceleration data from your attempt. You can plot it with graph_accelerometer.py to see the amplitude of acceleration the adxl345 experienced when you hit the nozzle (though in real probing the amplitude may be different).

Then, we need to figure the right probe speed parameter. This one is admittedly tricky. My thoughts are as follows. In my measurements (on Ender 3 pro with a DD extruder and a glass bed) it seems that when the nozzle hits the bed, the 'hit' event takes ~1-2 msec to occur: probe_accuracy_2 Note that this is also indicative that the default tap_dur: 0.01 is good enough guess for most cases.

In general velocity = accel dt. For accel amplitude, we want it to be at least 2 tap_thresh. So for example if tap_thresh = 6500, velocity = 6500 2 0.001 = 13 or 6500 2 0.002 = 26. So, in this case I'd say the probing speed should be roughly in the range of 15-25 mm/sec.

For testing, I suggest to start with higher value and reduce it if proves to be safe. Make sure that max_z_velocity is sufficiently high, move the toolhead to the location where probing can be done and then run the following commands:

ACCELEROMETER_MEASURE CHIP=hotend
PROBE_ACCURACY PROBE_SPEED=25
ACCELEROMETER_MEASURE CHIP=hotend

If probe is triggered and everything goes well, the results can be plotted using the same command (with the right filename):

~/klippy-env/bin/python ~/klipper/scripts/graph_accelerometer.py /tmp/adxl345-2021...csv -r -o /tmp/probing.png

For example: probe_accuracy_1 If the acceleration of the 'taps' is high enough, then maybe PROBE_SPEED can be reduced. I still think that it should be at least 15 mm/sec, but YMMV. If the acceleration is insufficient, the velocity should be increased instead. The final value can be stored in [adxl345] section as speed parameter. Then homing speeds can be returned to normal.

However, if you really want to use ADXL345 as Z endstop too, you can do so by setting

[stepper_z]
endstop_pin: probe:z_virtual_endstop
position_min: -0.5  # must allow hotend nozzle to 'hit' bed everywhere
# both speeds must be equal to `speed` in `[probe]` section
homing_speed: 20
second_homing_speed: 20

and define the section

[safe_z_home]
home_xy_position: 100,100 # Change coordinates to the center of your print bed
speed: 50
z_hop: 10                 # Move up 10mm
z_hop_speed: 5

You will also need to configure the Z offset of the probe.

My experience. I ended up using probing speed 16 mm/sec and tap_thresh = 6500 mm/sec^2. I tested it on Ender 3 Pro with a DD extruder only with a glass bed, not the steel PEI sheet, for instance. I suspect that if the bed cover is too soft, it may work poorly for this purpose. Also I would suggest to clean up the nozzle from the remaining strings of filament if anything is left from printing. The probe accuracy I usually achieve:

Send: PROBE_ACCURACY
Recv: // PROBE_ACCURACY at X:100.000 Y:100.000 Z:20.000 (samples=10 retract=5.000 speed=15.0 lift_speed=15.0)
Recv: // probe at 100.000,100.000 is z=-0.313750
Recv: // probe at 100.000,100.000 is z=-0.320000
Recv: // probe at 100.000,100.000 is z=-0.315625
Recv: // probe at 100.000,100.000 is z=-0.313750
Recv: // probe at 100.000,100.000 is z=-0.313125
Recv: // probe at 100.000,100.000 is z=-0.312500
Recv: // probe at 100.000,100.000 is z=-0.309375
Recv: // probe at 100.000,100.000 is z=-0.311250
Recv: // probe at 100.000,100.000 is z=-0.310000
Recv: // probe at 100.000,100.000 is z=-0.309375
Recv: // probe accuracy results: maximum -0.309375, minimum -0.320000, range 0.010625, average -0.312875, median -0.312813, standard deviation 0.003090

@Arksine, in your experience, how good or bad such a probe is? I was also able to build a bed mesh with this 'probe', not sure if it makes sense though

#*# [bed_mesh default]
#*# version = 1
#*# points =
#*#       -0.148750, -0.087500, -0.108125, -0.090625, -0.183125, -0.228750
#*#       -0.143750, -0.078125, -0.109375, -0.099375, -0.195625, -0.251875
#*#       -0.166250, -0.098125, -0.122500, -0.110625, -0.196875, -0.243125
#*#       -0.150625, -0.083750, -0.113750, -0.100625, -0.188750, -0.236250
#*#       -0.156250, -0.098125, -0.127500, -0.117500, -0.211875, -0.265000
#*# tension = 0.2
#*# min_x = 20.0
#*# algo = lagrange
#*# y_count = 5
#*# mesh_y_pps = 2
#*# min_y = 50.0
#*# x_count = 6
#*# max_y = 200.0
#*# mesh_x_pps = 2
#*# max_x = 200.0
Apsu commented 3 years ago

Wow, this is phenomenal work! I didn't expect you to get so far so fast. Your final probing graphs and repeatability measurements seem to show extremely consistent results, that's very promising!

I will definitely check out the branch and test it as soon as I can. I look forward to seeing input from others who I know are interested in this, as I'm sure we can streamline the calibration process a bit and most likely improve safety with enough clever folks looking at it.

Thanks for all your work so far, this is awesome.

dmbutyugin commented 3 years ago

Wow, this is phenomenal work! I didn't expect you to get so far so fast. Your final probing graphs and repeatability measurements seem to show extremely consistent results, that's very promising!

Note that across probing the bed, the amplitude of peaks did vary quite a bit (sometimes they are below 10K mm/sec^2, so that threshold 6500 mm/sec^2 is pretty tight at 16 mm/sec probing speed). Repeatability is usually that though (within 0.01 mm) if the sensor triggers at the right time. So if the Z axis doesn't move evenly, it may trigger prematurely. For example, I figured that my lead screw was a bit misaligned and was causing some uneven movement and sensor triggering :) After I aligned it it works more reliable. Also in initial experiments when I set insufficient sensitivity the printer bent the X carriage slightly, so it had a bit of play on X profile.

Apsu commented 3 years ago

Note that across probing the bed, the amplitude of peaks did vary quite a bit (sometimes they are below 10K mm/sec^2, so that threshold 6500 mm/sec^2 is pretty tight at 16 mm/sec probing speed). Repeatability is usually that though (within 0.01 mm) if the sensor triggers at the right time. So if the Z axis doesn't move evenly, it may trigger prematurely. For example, I figured that my lead screw was a bit misaligned and was causing some uneven movement and sensor triggering :) After I aligned it it works more reliable. Also in initial experiments when I set insufficient sensitivity the printer bent the X carriage slightly, so it had a bit of play on X profile.

That's an interesting point all on its own. In theory this gives some insight into gantry dynamics and rigidity, by graphing accelerometer measurements from the toolhead during various moves, such that problems that might be hard to see like you had can be discovered.

Arksine commented 3 years ago

This is nice! The range looks good for the PROBE_ACCURACY command. It depends on the Z step distance but a range of .01 is generally acceptable. With regard to the mesh, the deviation across the mesh looks normal for a bed at room temperature. What doesn't look normal is the entire mesh is offset in the negative direction. If you are homing at (100, 100), the Z value in the mesh should be near zero at that location. Looking at the profile, the closet value to (100,100) in the mesh is Z=-.1225.

What this suggests to me is that the probe might be triggering lower during the mesh calibration than it did during the homing operation. Could it be due to a change in probing speed?

dmbutyugin commented 3 years ago

The bed mesh was built at room temperature, and I used the normal Z endstop for homing, with its own offset set by a paper sheet method (before all these adxl345 tests happened). I did a paper probe calibration at 100,100 I believe though. I didn't use adxl345 for homing much (I just tested that it works in principle). So the bed mesh being offset in general is possible, I guess, due to some misalignment between different offsets (which I don't claim I got right from the first attempt).

Arksine commented 3 years ago

Ah, that explains it. If you homed using an endstop then its just a difference in the z_offset. In that situation you can use the relative_reference_index option in [bed_mesh] to have it override the z_offset.

AlmightyFrog commented 3 years ago

@dmbutyugin first of all thank you very much for (maybe) making my secret wish come true to be able to use homing and probing with ADXL. By the way I did test around lately much with piezos and let me tell you: to get perfect trigger condition is at least printers where Z Axis moves during homing can be a nightmare. I did many times crash nozzle into the bed, so the fail safe argument you pointed out before for other methods than ADXL seem to be not too strong for me.

First, ADXL345 must be connected to the printer MCU (the one controlling Z axis motors if there are many MCUs), and either int1 or int2 pin must be wired to some pin on the MCU that can work as an endstop pin (theoretically, only int1/2 pin must be connected to the printer MCU, however that has some chance of working only if the same power source is used for both printer and the RPi, and given the associated dangers of doing something wrong, e.g. if buck converter for RPi is connected inappropriately, I wouldn't recommend it). I recommend to keep Z endstop connected for initial experiments; so only connect ADXL345 in a 'probe' mode.

Q1: Ok, this means I could just use my current setup which uses ADXL at RPI for input shaper calibration and I just need to add the interrupt pin connection?

Q2: If i change the ADXL to MCU, can i still use it as before for input shaper calibration with all the graphs and so on? I am asking as I am playing around with different print head configurations and there it might make a difference if it is e.g. direct extrude with heavy motor, remote extruder or just bowden setup.

Q3: Is there any performance downside connecting ADXL to MCU insteat of RPI? I (mostly) use SKR 1.3 boards so they should be reasonably fast enough, but one printer still runs on RAMPS.

Apsu commented 3 years ago

@dmbutyugin Was just looking into how to wire this thing to an SKR 1.3, for example, and it's turning out to be quite difficult. The I2C pins are all repurposed for critical things, and one of the two SPI buses is the SD card. The other being for motor drivers, of course. You could hijack one of the slots if using UART drivers, but the pins are hidden if using all 5 drivers, and it's just a mess.

So looking at your statement:

theoretically, only int1/2 pin must be connected to the printer MCU, however that has some chance of working only if the same power source is used for both printer and the RPi, and given the associated dangers of doing something wrong, e.g. if buck converter for RPi is connected inappropriately, I wouldn't recommend it

This has me thinking that maybe the MCU agnostic way to do this is hook to the rPi the same as for Input Shaper, but use an optocoupler for the interrupt signal pin, to avoid mismatched power supply concerns. Something like image

for a convenient breakout board with easy optoisolation could let you run everything on the pi.

Thoughts?

dmbutyugin commented 3 years ago

Optocoupler should certainly work, and it is an easy and safe way to attach the adxl int pin to the printer MCU (int1/2 pin as + and gnd pin as -).

Q1: Ok, this means I could just use my current setup which uses ADXL at RPI for input shaper calibration and I just need to add the interrupt pin connection?

If you figure galvanic isolation between the RPi and MCU, then yes (e.g. with an optocoupler).

Q2: If i change the ADXL to MCU, can i still use it as before for input shaper calibration with all the graphs and so on? I am asking as I am playing around with different print head configurations and there it might make a difference if it is e.g. direct extrude with heavy motor, remote extruder or just bowden setup.

Yes, if adxl345 is connected to the mcu, it can still be used for measuring resonances and such.

Q3: Is there any performance downside connecting ADXL to MCU insteat of RPI? I (mostly) use SKR 1.3 boards so they should be reasonably fast enough, but one printer still runs on RAMPS.

On some slow boards, maybe. I think SKR 1.3 should work just fine, not sure about RAMPS though.

mental405 commented 3 years ago

If this pans out, it might be good for deltas as an alternative to FSR's

AlmightyFrog commented 3 years ago

I just want to point out, that error messages might be misleading. It was complaining Error: Option 'int_pin' is not valid in section 'adxl345' but for real i only missed to add probe_pin (besides removal of old deprecated probe section).

AlmightyFrog commented 3 years ago

Ok, I am some steps further, but now can't continue.

If I restart, QUERY_PROBE says open always. Then when i execute step SET_ADXL345 CHIP=hotend REG=0x2E VAL=0x40 it directly shows triggered always.

Btw when it comes to pullup - what is the right setting: with or without?

Another strange finding is, that my numbers in initial measure tests are way off in comparison to @dmbutyugin shown values. This is my noise floor without any movement: noise

Here you can see it when i move X, Y and Z (don't mind Z not showing up, it is so smooth that there is no spike as you can see from about 25s till end): noise-while-x-y-z

A graph of homing ( i always have forced X, Y, Z order where it lifts Z first to not crash nozzle into bed clips) seems fine: homing

BTW as my values are about factor 10 higher than yours, also query in stillstand varies a lot:

ACCELEROMETER_QUERY
// adxl345 values (x, y, z): -5256.364400, 3687.300400, -18279.595600
ok
ACCELEROMETER_QUERY
// adxl345 values (x, y, z): -941.438400, 2981.221600, -18122.689200
ok
dmbutyugin commented 3 years ago

I just want to point out, that error messages might be misleading. It was complaining Error: Option 'int_pin' is not valid in section 'adxl345' but for real i only missed to add probe_pin (besides removal of old deprecated probe section).

That's because the probe functionality (along with all additional parameters) is enabled only if probe_pin parameter is set. At least, that's how it is for now. I may change it in the future, but I'm not sure yet how to change that best.

So, are you sure you've set axes_map correctly? I think your z axis has the wrong sign (and so you get ~-18K (== 2 * 9800) instead of close to zero).

Then when i execute step SET_ADXL345 CHIP=hotend REG=0x2E VAL=0x40 it directly shows triggered always.

Wrong axes_map may also affect this behaviour.

Then, if your noise level is ~5-7K, you probably need to increase the threshold to 7-10K.

Btw when it comes to pullup - what is the right setting: with or without?

I think you don't need any pullup or pulldown, since accelerometer already pulls it down on low.

Here you can see it when i move X, Y and Z (don't mind Z not showing up, it is so smooth that there is no spike as you can see from about 25s till end):

In general, that's bad because it actually needs to be noticeable. Are you sure you have increased the homing speed (and the max speed for z axis)? Edit: or did you mean just the regular axes move? If the latter, it's fine. You just need to look at the homing graph.

dmbutyugin commented 3 years ago

If this pans out, it might be good for deltas as an alternative to FSR's

In principle, yes, though for delta printers there's also smart effector available. It works pretty well as the Z probe (assuming the default sensitivity is fine for the printer).

AlmightyFrog commented 3 years ago

So, are you sure you've set axes_map correctly? I think your z axis has the wrong sign (and so you get ~-18K (== 2 * 9800) instead of close to zero). Pretty sure as it is basically same config I use for input shaper calibration. I have axes_map: z,y,x set in config. Silkscreen is as following:

  • X arrow on silkscreen points for real Z Axis downwards
  • Y arrow on silkscreen points for real Y Axis in direction of min
  • Z arrow on silkscreen points for real X Axis, but direction i can't tell

Then, if your noise level is ~5-7K, you probably need to increase the threshold to 7-10K. Currently I use tap_thresh: 50000, I changed it to 10k and now it is always open.

BTW high noise on this ADXL might be as I have had a issue with capacitor on that specific pcb.

Just for completeness here a G28 run g28 Whereas at about 13s it was X axis home, about 15s it was Y axis home and about 23s it was Z axis home (endstop switch). Please not that this is a CoreXY Printer so the behavior seemed fine for me, as probe is mounted on head and gantry did not move during z home. Of cause in the following picture for failed probe where nozzle crashes into bed I'd have expected something.

Here you can see it when i move X, Y and Z (don't mind Z not showing up, it is so smooth that there is no spike as you can see from about 25s till end):

In general, that's bad because it actually needs to be noticeable. Are you sure you have increased the homing speed (and the max speed for z axis)? Edit: or did you mean just the regular axes move? If the latter, it's fine. You just need to look at the homing graph. The graph was only axis move but same is also at probing. Here you see the graph when nozzle crashes into bed: probefailed I honestly can't tell you when exactly it was, but i guess about 10 seconds in or so. Values in cfg are adxl345.speed = stepper_z.homing_speed = stepper_z.second_homing_speed = 20. I did same with 40 and same results.

Might it be, that the ADXL is just "too tightly" mounted at the carriage that there is too less movement possible?

dmbutyugin commented 3 years ago

So, are you sure you've set axes_map correctly? I think your z axis has the wrong sign (and so you get ~-18K (== 2 * 9800) instead of close to zero).

Pretty sure as it is basically same config I use for input shaper calibration. I have axes_map: z,y,x set in config.

No, that's not good enough that the config is the same. Input shaper calibration doesn't care about the axes_map, it can be whatever and shaper calibration will still work just as well. In the main branch the axes_map is only for your own convenience (for charts), it doesn't serve any real purpose for the shaper calibration.

Then, sorry, I did not fully understand your explanation about chip orientation, but as a random guess, try to invert the sign for z printer axis as axes_map: z,y,-x and see if that helps.

BTW high noise on this ADXL might be as I have had a issue with capacitor on that specific pcb.

I'm not sure which capacitor your are talking about and how it would affect the measurements? Note that the adxl - board connection for accelerometer data is digital. Maybe the fans are noisy? Anyway, tap_threshold around 7000 could be a start.

Please not that this is a CoreXY Printer so the behavior seemed fine for me, as probe is mounted on head and gantry did not move during z home.

So, you have the bed moving in Z direction (and not, say, the XY portal)? I'm not sure what the best setup is in this case. I mean, should the accelerometer be mounted on the toolhead or on the bed. If you choose the toolhead,

Might it be, that the ADXL is just "too tightly" mounted at the carriage that there is too less movement possible?

then it should actually be mounted tightly, so that its movements follow the movements of the toolhead exactly (and hopefully it can pick any 'echo' from the hit). In my tests, the adxl345 triggers the interrupt even if I pinch the motionless hotend with my finger. So there's certainly some hope. Though the charts with crashing the bed don't show anything, which is strange and surprising. Is it possible that the file is wrong (from a different measurement)?

AlmightyFrog commented 3 years ago

I moved sensor to bed, changed axis accordingly and now have had at least two successful probe runs. Tap threshold 12k is on the edge of working. Sadly i have no trace of it:

PROBE_ACCURACY at X:200.000 Y:200.000 Z:12.648 (samples=10 retract=5.000 speed=25.0 lift_speed=40.0)
probe at 200.000,200.000 is z=-2.435000
probe at 200.000,200.000 is z=-2.437500
probe at 200.000,200.000 is z=-2.442500
probe at 200.000,200.000 is z=-2.437500
probe at 200.000,200.000 is z=-2.440000
probe at 200.000,200.000 is z=-2.442500
probe at 200.000,200.000 is z=-2.440000
probe at 200.000,200.000 is z=-2.445000
probe at 200.000,200.000 is z=-2.437500
probe at 200.000,200.000 is z=-2.437500
probe accuracy results: maximum -2.435000, minimum -2.445000, range 0.010000, average -2.439500, median -2.438750, standard deviation 0.002915

PROBE_ACCURACY at X:200.000 Y:200.000 Z:2.563 (samples=10 retract=5.000 speed=25.0 lift_speed=40.0)
probe at 200.000,200.000 is z=-2.440000
probe at 200.000,200.000 is z=-2.440000
probe at 200.000,200.000 is z=-2.440000
probe at 200.000,200.000 is z=-2.440000
probe at 200.000,200.000 is z=-2.440000
probe at 200.000,200.000 is z=-2.440000
probe at 200.000,200.000 is z=-2.445000
probe at 200.000,200.000 is z=-2.442500
probe at 200.000,200.000 is z=-2.435000
probe at 200.000,200.000 is z=-2.442500
probe accuracy results: maximum -2.435000, minimum -2.445000, range 0.010000, average -2.440500, median -2.440000, standard deviation 0.002449

But before and after i had massive issues with triggering to early or not at all.

I'm not sure which capacitor your are talking about and how it would affect the measurements? Note that the adxl - board connection for accelerometer data is digital. Maybe the fans are noisy? Anyway, tap_threshold around 7000 could be a start.

It might not make sense to continue with the ADXL board i have here. Tantal capacitor which should smooth input voltage was soldered wrong way in and got burning hot. Now I use the board without it but that of cause should result in worse measurement accuracy. Of cause you read out signal digital, but in case the adc within the chip is not getting stable voltage it might cause measurement deviations. This means for me i have to stop here, find another board or wait till another is shipped and then only i can continue.

If this pans out, it might be good for deltas as an alternative to FSR's

In principle, yes, though for delta printers there's also smart effector available. It works pretty well as the Z probe (assuming the default sensitivity is fine for the printer).

What would be the way you expect to best work on a delta. On the effector itself or on the (rigid mounted) bed?

dmbutyugin commented 3 years ago

I see, yes, if the voltage regulator is busted due to capacitor, then yes, I presume it can work incorrectly. You can also try the MEASURE_AXES_NOISE command, which in my case gives the following results:

Send: MEASURE_AXES_NOISE
Recv: // Axes noise for xy-axis accelerometer: 82.637596 (x), 133.620911 (y), 135.221446 (z)

But I imagine it will be much larger in your case. In that case, the sensor is faulty and needs to be replaced.

What would be the way you expect to best work on a delta. On the effector itself or on the (rigid mounted) bed?

It is generally a good question where to mount the accelerometer for probing. I think the effector is the best place to mount it for delta. And even in other kinematicsl it might make more sense to mount it on the hotend, even if the bed is moving for Z homing/probing instead. Otherwise, the probing amplitude of acceleration may depend on the probing point within the bed (and so it may be too low in the farthest corners of the bed), which would defeat the purpose. At least if the accelerometer is mounted on the hotend, the amplitude of the vibrations it experiences will be more consistent and predictable and much less depend on the probing location. Even though you had more success setting up the probe on the bed; but maybe your current probe is not very representative. Anyway, it would be very interesting to see other results and experiences; I think only the practice can tell.

dmbutyugin commented 3 years ago

BTW, I made the adxl345 to self-calibrate its freefall acceleration offset, so it will no longer depend on the correct axes_map parameter. And now other adxl345s (besides the one that is used as a probe) can be (again) connected on-demand. Also if the probe was disconnected and then reconnected, one can run ACCEL_PROBE_CALIBRATE to force the probing to be re-calibrated.

AlmightyFrog commented 3 years ago

BTW, I made the adxl345 to self-calibrate its freefall acceleration offset, so it will no longer depend on the correct axes_map parameter.

Interesting Idea. Didn't think it through, but maybe think of, whether you also want to have X and Y auto detection for resonance calibration. Trivial as you only need to G0 one axis to see what moved, and from my current point of view useless, but at least then you'd get the direction of acceleration if that is of any worth.

And now other adxl345s (besides the one that is used as a probe) can be (again) connected on-demand.

So I guess that is only for bed slingers relevant, as I got from texts before that otherwise best idea is to mount for common printers (like CoreXY/H-Bot and Delta) there you anyhow connect one for all axis to the hotend. Any other printer style I didn't think of? For documentation purposes i guess it is worth to point stuff like that out then.

I just found another ADXL board which seems to work fine, so I'll continue tests this weekend at least with the CoreXY, maybe a bed slinger also. My delta is physically too unstable to get any use of tests out there. So if anyone here has a delta, I'd be happy to hear about test results.

dmbutyugin commented 3 years ago

Interesting Idea. Didn't think it through, but maybe think of, whether you also want to have X and Y auto detection for resonance calibration.

Actually, there is no need for that. Resonance measurement script knows which axis it tests. And then it is a good idea to measure vibrations on all axes, because, say, movements on Y axis can excite resonances on Z axis (e.g. on bed slinger). Such resonances can, of course, affect the quality of the prints and should be reduced, but then they'll be on Z axis and not Y.

And now other adxl345s (besides the one that is used as a probe) can be (again) connected on-demand.

So I guess that is only for bed slingers relevant, as I got from texts before that otherwise best idea is to mount for common printers ... to the hotend.

Yes, though I think by now more common printers are bed slingers :) Not sure about the distribution among Klipper users though. Anyway, since input shaping is only applied for the motion in XY plane, accelerometer(s) should be mounted somewhere on the axes that are moving within XY plane. For bed slinger and CoreXZ, 2 are needed (or 1 needs to be re-mounted), and for CoreXY and Delta one on the hotend is sufficient. But it is indeed interesting to test what is the best place to mount the accelerometer for Z probing. Also note that one can configure a separate adxl345 in printer.cfg just for probing, independent of [resonance_tester], e.g.

[adxl345 hotend]
...

[resonance_tester]
accel_chip: adxl345 hotend
...

[adxl345 bed]
probe_pin: ...
z_offset: ...
...
AlmightyFrog commented 3 years ago

I've updated to latest code (5a28a14bcba105c9b387938d586fb5e25741387d) and swapped the broken ADXL board by another one from same buy batch (just corrected the tantal capacitor to the correct polarity before applying power for first time) and it seems to work much better.

// Axes noise for xy-axis accelerometer: 28.440713 (x), 33.333971 (y), 21.261850 (z) <-- non relevant note on the side, your text it says "xy-axis" but also z is there.

Idle noise is way reduced, in following graph you can see it sitting just idle with turning the part cooler fan on between about 6,5 and 13s: IdleFan

I was not sure if using tap_thresh=2000 would be fine, so i chose tap_thresh=4000 to be safe in klipper config.

Probe accuracy tests seem fine

// PROBE_ACCURACY at X:150.000 Y:150.000 Z:2.112 (samples=10 retract=5.000 speed=25.0 lift_speed=40.0)
// probe at 150.000,150.000 is z=-2.885000
// probe at 150.000,150.000 is z=-2.882500
// probe at 150.000,150.000 is z=-2.890000
// probe at 150.000,150.000 is z=-2.887500
// probe at 150.000,150.000 is z=-2.882500
// probe at 150.000,150.000 is z=-2.890000
// probe at 150.000,150.000 is z=-2.887500
// probe at 150.000,150.000 is z=-2.920000
// probe at 150.000,150.000 is z=-2.887500
// probe at 150.000,150.000 is z=-2.885000
// probe accuracy results: maximum -2.882500, minimum -2.920000, range 0.037500, average -2.889750, median -2.887500, standard deviation 0.010395

ProbeAccuracy


But doing BedMesh for test gave me mixed feelings. As my previous piezo leveling was sometimes unreliable for one measurement of a point i just set count to 5. I know this log is quite long, but it shows some strange difference in reliability to previous probe accuracy:

BED_MESH_CALIBRATE
// probe at 20.000,20.000 is z=-2.360000
// probe at 20.000,20.000 is z=-2.355000
// probe at 20.000,20.000 is z=-2.357500
// probe at 20.000,20.000 is z=-2.350000
// probe at 20.000,20.000 is z=-2.355000
// probe at 85.000,20.000 is z=-2.435000
// probe at 85.000,20.000 is z=-2.442500
// probe at 85.000,20.000 is z=-2.455000
// probe at 85.000,20.000 is z=-2.455000
// probe at 85.000,20.000 is z=-2.457500
// probe at 150.000,20.000 is z=-1.532500
// probe at 150.000,20.000 is z=-1.545000
// probe at 150.000,20.000 is z=-1.555000
// probe at 150.000,20.000 is z=-1.597500
// Probe samples exceed tolerance. Retrying...
// probe at 150.000,20.000 is z=-1.565000
// probe at 150.000,20.000 is z=-1.557500
// probe at 150.000,20.000 is z=-1.595000
// probe at 150.000,20.000 is z=-1.555000
// probe at 150.000,20.000 is z=-1.550000
// probe at 215.000,20.000 is z=-2.757500
// probe at 215.000,20.000 is z=-2.727500
// probe at 215.000,20.000 is z=-2.725000
// probe at 215.000,20.000 is z=-2.727500
// probe at 215.000,20.000 is z=-2.720000
// probe at 280.000,20.000 is z=-2.975000
// probe at 280.000,20.000 is z=-3.000000
// probe at 280.000,20.000 is z=-3.002500
// probe at 280.000,20.000 is z=-2.990000
// probe at 280.000,20.000 is z=-2.977500
// probe at 280.000,85.000 is z=-2.847500
// probe at 280.000,85.000 is z=-2.847500
// probe at 280.000,85.000 is z=-2.847500
// probe at 280.000,85.000 is z=-2.852500
// probe at 280.000,85.000 is z=-2.847500
// probe at 215.000,85.000 is z=-2.585000
// probe at 215.000,85.000 is z=-2.577500
// probe at 215.000,85.000 is z=-2.580000
// probe at 215.000,85.000 is z=-2.582500
// probe at 215.000,85.000 is z=-2.585000
// probe at 150.000,85.000 is z=-2.427500
// probe at 150.000,85.000 is z=-2.477500
// probe at 150.000,85.000 is z=-2.480000
// Probe samples exceed tolerance. Retrying...
// probe at 150.000,85.000 is z=-2.485000
// probe at 150.000,85.000 is z=-2.475000
// probe at 150.000,85.000 is z=-2.430000
// Probe samples exceed tolerance. Retrying...
// probe at 150.000,85.000 is z=-2.487500
// probe at 150.000,85.000 is z=-2.485000
// probe at 150.000,85.000 is z=-2.480000
// probe at 150.000,85.000 is z=-2.480000
// probe at 150.000,85.000 is z=-2.490000
// probe at 85.000,85.000 is z=-2.262500
// probe at 85.000,85.000 is z=-2.260000
// probe at 85.000,85.000 is z=-2.272500
// probe at 85.000,85.000 is z=-2.272500
// probe at 85.000,85.000 is z=-2.272500
// probe at 20.000,85.000 is z=-2.147500
// probe at 20.000,85.000 is z=-2.152500
// probe at 20.000,85.000 is z=-2.152500
// probe at 20.000,85.000 is z=-2.150000
// probe at 20.000,85.000 is z=-2.152500
// probe at 20.000,150.000 is z=-2.132500
// probe at 20.000,150.000 is z=-2.127500
// probe at 20.000,150.000 is z=-2.127500
// probe at 20.000,150.000 is z=-2.127500
// probe at 20.000,150.000 is z=-2.130000
// probe at 85.000,150.000 is z=-2.235000
// probe at 85.000,150.000 is z=-2.240000
// probe at 85.000,150.000 is z=-2.247500
// probe at 85.000,150.000 is z=-2.235000
// probe at 85.000,150.000 is z=-2.237500
// probe at 150.000,150.000 is z=-2.407500
// probe at 150.000,150.000 is z=-2.415000
// probe at 150.000,150.000 is z=-2.372500
// probe at 150.000,150.000 is z=-2.417500
// probe at 150.000,150.000 is z=-2.372500
// probe at 215.000,150.000 is z=-2.525000
// probe at 215.000,150.000 is z=-2.520000
// probe at 215.000,150.000 is z=-2.520000
// probe at 215.000,150.000 is z=-2.520000
// probe at 215.000,150.000 is z=-2.525000
// probe at 280.000,150.000 is z=-2.795000
// probe at 280.000,150.000 is z=-2.787500
// probe at 280.000,150.000 is z=-2.795000
// probe at 280.000,150.000 is z=-2.792500
// probe at 280.000,150.000 is z=-2.787500
// probe at 280.000,215.000 is z=-2.772500
// probe at 280.000,215.000 is z=-2.770000
// probe at 280.000,215.000 is z=-2.770000
// probe at 280.000,215.000 is z=-2.775000
// probe at 280.000,215.000 is z=-2.767500
// probe at 215.000,215.000 is z=-2.472500
// probe at 215.000,215.000 is z=-2.477500
// probe at 215.000,215.000 is z=-2.490000
// probe at 215.000,215.000 is z=-2.490000
// probe at 215.000,215.000 is z=-2.492500
// probe at 150.000,215.000 is z=-2.375000
// probe at 150.000,215.000 is z=-2.385000
// probe at 150.000,215.000 is z=-2.385000
// probe at 150.000,215.000 is z=-2.347500
// probe at 150.000,215.000 is z=-2.345000
// probe at 85.000,215.000 is z=-2.237500
// probe at 85.000,215.000 is z=-2.215000
// probe at 85.000,215.000 is z=-2.237500
// probe at 85.000,215.000 is z=-2.220000
// probe at 85.000,215.000 is z=-2.237500
// probe at 20.000,215.000 is z=-2.225000
// probe at 20.000,215.000 is z=-2.215000
// probe at 20.000,215.000 is z=-2.217500
// probe at 20.000,215.000 is z=-2.212500
// probe at 20.000,215.000 is z=-2.215000
// probe at 20.000,280.000 is z=-2.190000
// probe at 20.000,280.000 is z=-2.187500
// probe at 20.000,280.000 is z=-2.185000
// probe at 20.000,280.000 is z=-2.192500
// probe at 20.000,280.000 is z=-2.187500
// probe at 85.000,280.000 is z=-2.277500
// probe at 85.000,280.000 is z=-2.275000
// probe at 85.000,280.000 is z=-2.277500
// probe at 85.000,280.000 is z=-2.275000
// probe at 85.000,280.000 is z=-2.277500
// probe at 150.000,280.000 is z=-2.377500
// probe at 150.000,280.000 is z=-2.410000
// probe at 150.000,280.000 is z=-2.410000
// probe at 150.000,280.000 is z=-2.430000
// Probe samples exceed tolerance. Retrying...
// probe at 150.000,280.000 is z=-2.417500
// probe at 150.000,280.000 is z=-2.427500
// probe at 150.000,280.000 is z=-2.387500
// probe at 150.000,280.000 is z=-2.390000
// probe at 150.000,280.000 is z=-2.387500
// probe at 215.000,280.000 is z=-2.535000
// probe at 215.000,280.000 is z=-2.515000
// probe at 215.000,280.000 is z=-2.515000
// probe at 215.000,280.000 is z=-2.540000
// probe at 215.000,280.000 is z=-2.535000
// probe at 280.000,280.000 is z=-2.865000
// probe at 280.000,280.000 is z=-2.862500
// probe at 280.000,280.000 is z=-2.852500
// probe at 280.000,280.000 is z=-2.865000
// probe at 280.000,280.000 is z=-2.852500
// Mesh Bed Leveling Complete

This is mesh config

[bed_mesh]
speed: 60
horizontal_move_z: 3
mesh_min: 20,20
mesh_max: 280,280
probe_count: 5,5

Graph just for completeness, but seems to be useless: BedMesh-cut3

Btw another run later with horizontal_move_z:15 did fail quite early but repeatible 3 times at least:

// probe at 20.000,20.000 is z=-2.347500
// probe at 20.000,20.000 is z=-2.352500
// probe at 20.000,20.000 is z=-2.345000
// probe at 20.000,20.000 is z=-2.357500
// probe at 20.000,20.000 is z=-2.380000
// probe at 85.000,20.000 is z=-2.440000
// probe at 85.000,20.000 is z=-2.437500
// probe at 85.000,20.000 is z=-2.440000
// probe at 85.000,20.000 is z=-2.435000
// probe at 85.000,20.000 is z=-2.435000
// probe at 150.000,20.000 is z=-1.520000
// probe at 150.000,20.000 is z=-1.557500
// probe at 150.000,20.000 is z=-1.545000
// probe at 150.000,20.000 is z=-1.540000
// probe at 150.000,20.000 is z=-1.565000
// probe at 215.000,20.000 is z=-2.747500
// probe at 215.000,20.000 is z=-2.727500
// probe at 215.000,20.000 is z=-2.720000
// probe at 215.000,20.000 is z=-2.722500
// probe at 215.000,20.000 is z=-2.725000
// probe at 280.000,20.000 is z=-3.005000
// probe at 280.000,20.000 is z=-2.992500
// probe at 280.000,20.000 is z=-3.012500
// probe at 280.000,20.000 is z=-3.007500
// probe at 280.000,20.000 is z=-3.002500
// probe at 280.000,85.000 is z=-2.840000
// probe at 280.000,85.000 is z=-2.847500
// probe at 280.000,85.000 is z=-2.837500
// probe at 280.000,85.000 is z=-2.840000
// probe at 280.000,85.000 is z=-2.847500
// probe at 215.000,85.000 is z=-2.572500
// probe at 215.000,85.000 is z=-2.587500
// probe at 215.000,85.000 is z=-2.587500
// probe at 215.000,85.000 is z=-2.587500
// probe at 215.000,85.000 is z=-2.572500
// probe at 150.000,85.000 is z=-2.460000
// probe at 150.000,85.000 is z=-2.470000
// probe at 150.000,85.000 is z=-2.472500
// probe at 150.000,85.000 is z=-2.410000
// Probe samples exceed tolerance. Retrying...
// probe at 150.000,85.000 is z=-2.482500
// probe at 150.000,85.000 is z=-2.415000
// Probe samples exceed tolerance. Retrying...
// probe at 150.000,85.000 is z=-2.420000
// probe at 150.000,85.000 is z=-2.472500
// Probe samples exceed tolerance. Retrying...
// probe at 150.000,85.000 is z=-2.465000
// probe at 150.000,85.000 is z=-2.412500
!! Probe samples exceed samples_tolerance
ok

Strangely if i probe accuracy at that exact location it seems fine:

// PROBE_ACCURACY at X:150.000 Y:85.000 Z:2.518 (samples=10 retract=5.000 speed=25.0 lift_speed=40.0)
// probe at 150.000,85.000 is z=-2.485000
// probe at 150.000,85.000 is z=-2.445000
// probe at 150.000,85.000 is z=-2.430000
// probe at 150.000,85.000 is z=-2.442500
// probe at 150.000,85.000 is z=-2.432500
// probe at 150.000,85.000 is z=-2.490000
// probe at 150.000,85.000 is z=-2.435000
// probe at 150.000,85.000 is z=-2.487500
// probe at 150.000,85.000 is z=-2.442500
// probe at 150.000,85.000 is z=-2.437500
// probe accuracy results: maximum -2.430000, minimum -2.490000, range 0.060000, average -2.452750, median -2.442500, standard deviation 0.023196

No clue what is going wrong here... maybe do we need more wait time between bed mesh probing what i also needed for piezo for everything calm down? But there it was only necessary after an X or Y move to wait about 800ms before start Z movements. Do you have any idea @dmbutyugin?


One further note to clarify beforehand results a little when it came to G28 measurements. It seems just like "crash" (sensorless homing) in order X,Y,Z there X + Y is quite hard whereas Z is not noticable. G28 If you compare it with Z only it is obvious: G28-Z 100000 is way bigger than 2000 as you can see! ;)


So all in all i have mixed feelings. Using probe accuracy it seems fine, but if i would not trust bed mesh with it. As I didn't find any settings for probe speed itself at bed mesh config part, i do not know how fast it probes for real.

dmbutyugin commented 3 years ago

A few comments:

The latter means that if a probing speed is set relatively high, min z is set very conservatively, and Z acceleration is low, the probe (nozzle) will decelerate a lot by the time it hits the bed. So I can suggest to try either setting min Z to a lower value (e.g. if it was at -3, set it to -10), or increase max Z axis acceleration.

As I didn't find any settings for probe speed itself at bed mesh config part, i do not know how fast it probes for real.

Bed mesh uses the speed from the probe section AFAICT. You could also separately try to reduce the probe speed to, say, 20 mm/sec and see if that affects the precision or not.

So you could try that and see if that helps the bed mesh generation or not. In either case, could you post a klippy.log after your attempts, and could you also generate accelerometer raw data during mesh generation (and probe accuracy measurements for comparison), and pack them and post here?

BTW, after some more testing on my side, it seems that I need to get an anti-backlash Z nut for my Ender 3 and run tests with it. It seems that the Z nut that comes by default has some backlash (or play) that can manifest itself in spurious acceleration of the Z axis and falsely trigger the accelerometer. I'll try to get the anti-backlash version early next week.

dmbutyugin commented 3 years ago

After using the adxl345 as a probe (and also as an endstop) for a while, I realized that the biggest pain point for me is the necessity to clear the nozzle from the filament residue after the previous print. Failing to do so usually leaves some blob or string of filament on the nozzle, which impairs the probing and homing and leads to homing failures. So, in my opinion the best use of adxl345 as a probe is for bed meshing and to setup the offset of the nozzle from the normal Z endstop. This also allows to use [endstop_phase] to increase the reliability of Z endstop switch triggering. To support that, I added an ability for Z_ENDSTOP_CALIBRATE command to use probe measurements to adjust the Z endstop automatically in the last commit. For the reference, here are the relevant parts config that seem to work in my case:

[stepper_z]
endstop_pin: ^P1.27  # Actual z endstop pin

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

[endstop_phase]

[adxl345 hotend]
cs_pin: P0.26  # SKR 1.4 SPI CS pin
spi_bus: ssp1  # SRK 1.4 SPI bus
axes_map: -x,-z,-y
tap_thresh: 7000
int_pin: int2
probe_pin: P1.0  # SKR pin where adxl345 is connected as a probe
sample_retract_dist: 5.0
samples: 5
samples_result: median
samples_tolerance: 0.025
samples_tolerance_retries: 20
speed: 15
# For Z endstop adjustments
z_endstop_probe_point: 10,40
horizontal_move_z: 10

[bed_mesh]
speed: 100
horizontal_move_z: 10
mesh_min: 20,50
mesh_max: 200, 200
probe_count: 6,5
# no fade and/or set relative_reference_index

So, I think the normal workflow to use adxl345 as a probe is as follows. Once do the following:

  1. Tune adxl345 such that it reliably triggers when probing.
  2. Run PROBE_CALIBRATE to adjust z_offset of the adxl345 probe using paper method, and then SAVE_CONFIG

Then, each time a bed is changed (e.g. glass is swapped for steel sheet, etc.) or some recalibration is needed, run the following:

  1. Run Z_ENDSTOP_CALIBRATE to use adxl345 to re-adjust z endstop position, and then SAVE_CONFIG.
  2. Run BED_MESH_CALIBRATE to rebuild the bed mesh, and then save a new bed mesh profile.

@Arksine, I've made the Z_ENDSTOP_CALIBRATE work for the probes in general (code), and it does seem to work with adxl345, but I may have messed it for some cases, so does it look reasonable in your opinion (e.g. perhaps I should have disabled the bed mesh or used kinematic position)? And another question is, is such a feature useful in general for other types of probes? It makes another paper test not needed, especially if the bed is changed or something like that. The similar effect could be achieved simply by rebuilding a bed mesh via BED_MESH_CALIBRATE. But I am thinking about usecases such as swapping between the known bed surfaces, or when swapping a nozzle, when full bed remeshing isn't necessary, and some time can be saved using just Z_ENDSTOP_CALIBRATE (and sometimes PROBE_CALIBRATE, e.g. if a nozzle is swapped with a more conventional probe).

Arksine commented 3 years ago

I think the endstop calibrate code looks good. Users with probes offset on X and Y will need to keep in mind that the actual calibration is being done at the z_endstop_probe_point + the probe's X and Y offsets, as that will be the location actually probed. It shouldn't be necessary to disable bed_mesh since you are commanding the toolhead directly, and retrieving the toolhead's position should be adequate.

In addition to adxl345 this kind of calibration would probably be reliable for a BLTouch or a Piezo style probe. It likely wouldn't be reliable for inductive or capacitive probes, as the type of material and thickness of the adhesive surface would play a role in what the final offset should be.

dmbutyugin commented 3 years ago

@Arksine, thanks!

Users with probes offset on X and Y will need to keep in mind that the actual calibration is being done at the z_endstop_probe_point + the probe's X and Y offsets, as that will be the location actually probed.

That's an excellent point I completely forgot about with adxl345 probe which has 0 offset. I suppose it would be better to simply adjust the probing location such that really the probe is probing z_endstop_probe_point.

In addition to adxl345 this kind of calibration would probably be reliable for a BLTouch or a Piezo style probe. It likely wouldn't be reliable for inductive or capacitive probes, as the type of material and thickness of the adhesive surface would play a role in what the final offset should be.

Hmm, well, if PROBE_CALIBRATE is executed on the same point z_endstop_probe_point, it wouldn't be an issue? (though it is not guaranteed right now) Because PROBE_CALIBRATE exactly determines the z_offset for the probe against the nozzle at the given location. Or am I missing something?

Arksine commented 3 years ago

Hmm, well, if PROBE_CALIBRATE is executed on the same point z_endstop_probe_point, it wouldn't be an issue? (though it is not guaranteed right now) Because PROBE_CALIBRATE exactly determines the z_offset for the probe against the nozzle at the given location. Or am I missing something?

Unlike the adxl345 and BLTouch, the z_offset won't be consistent between build surfaces for inductive probes. For an extreme example, lets assume you have a MIC6 aluminum bed, and you did your initial Z Endstop calibration (paper test) and PROBE_CALIBRATE against this surface. Then you add a spring steel sheet to the bed. The probe will trigger much higher due to the iron content of the spring steel sheet.

dmbutyugin commented 3 years ago

Agreed. However, in your example the user would normally need to run PROBE_CALIBRATE upon adding a spring steel sheet (cause otherwise the probe results will be useless, if I understand correctly), then run manual Z_ENDSTOP_CALIBRATE to update the z endstop offset. Now in case of the new code they would still need to run manual PROBE_CALIBRATE, and then automatic Z_ENDSTOP_CALIBRATE, still saving about half of the time. So, automatic Z_ENDSTOP_CALIBRATE wouldn't be a complete waste in this case either, I guess?

Arksine commented 3 years ago

Ah, now that I think about it you are correct. I was thinking that PROBE_CALIBRATE required a properly calibrated Z endstop, but this does not appear to be the case. So indeed a user should be able to run PROBE_CALIBRATE then run your automatic Z_ENDSTOP_CALIBRATE to adjust the position.

AlmightyFrog commented 3 years ago

@dmbutyugin, i pulled your latest changes in branch, but have issues klipper claiming that parameters z_endstop_probe_point and horizontal_move_z in section adxl345 would not be valid.

Is there anything further i need to do beyond git pull & service klipper restart? I also restarted the whole RPI of cause - still not detected.

What about z_offset, which section is it to be in? I use the process you tell (level once, then use endstop only) since a year or so and it works fine for me. That's the same way I plan to use the adxl probing in future. The offset for the probe might be different to 0 btw: for piezo leveling when it triggered nozzle was already "a little" (let's say 0.1-0.2mm) "within" the bed. so to compensate that i played around with endstop position after bed mesh after fiddling around with manual z endstop offset during print (like babystepping) to find out what's the best squish for first layer. If we could define a clean sequence which is clear for everybody (including me) to understand and to follow which does not involve that manual manipulating z endstop offset that would be perfect.

dmbutyugin commented 3 years ago

@AlmightyFrog thanks, which commit are you on? It works on my RPi, so it is likely some problem with updating the Klipper.

z_offset should go into [adxl345] section.

For the sequence, try using the proposed sequence. However, I can also see that the paper test is only an approximation, and some baby-stepping might be due. Then we probably would want to understand where to put the offset from baby stepping (I suppose into probe offset really).

AlmightyFrog commented 3 years ago

@AlmightyFrog thanks, which commit are you on? It works on my RPi, so it is likely some problem with updating the Klipper.

z_offset should go into [adxl345] section.

Using d1fcc82be5b4b2d260ca1942b1fab576e0f318cd. Now it works... not sure what what i did do wrong.

[adxl345]
axes_map = z,y,x
cs_pin = rpi:None
probe_pin = ^P1.26
int_pin = int1
tap_thresh = 4000
tap_dur = 0.01
z_offset = -0.2
samples = 3
sample_retract_dist = 5.0
samples_result = median
samples_tolerance = 0.05
samples_tolerance_retries = 3
speed = 20

[endstop_phase]

[resonance_tester]
accel_chip = adxl345
probe_points = 
        100,100,20

[input_shaper]
shaper_type_x = 3hump_ei
shaper_freq_x = 76.0
shaper_type_y = 2hump_ei
shaper_freq_y = 43.6

[printer]
kinematics = corexy
max_velocity = 500
max_accel = 7000
max_accel_to_decel = 7000
max_z_velocity = 25
max_z_accel = 200

[bed_mesh]
speed = 100
horizontal_move_z = 15
mesh_min = 20,20
mesh_max = 280,280
probe_count = 5,5

[bed_mesh default]
version = 1
points = 
        -1.065000, -0.927500, -0.945000, -0.890000, -1.010000
        -0.907500, -0.842500, -0.870000, -0.842500, -0.960000
        -0.915000, -0.872500, -0.867500, -0.855000, -0.957500
        -0.917500, -0.900000, -0.870000, -0.852500, -0.967500
        -0.962500, -0.935000, -0.922500, -0.930000, -1.075000
x_count = 5
y_count = 5
mesh_x_pps = 2
mesh_y_pps = 2
algo = lagrange
tension = 0.2
min_x = 20.0
max_x = 280.0
min_y = 20.0
max_y = 280.0
=======================

This is my current config. Would be nice oif you could have a look if config looks as expected. `z_offset´ is -0.2, as i did need to set z_offset during printing to about 0.150 i might set it to -0.05 in future and try bed mesh again.


I also did a `SHAPER_CALIBRATE´ again, which now shows (for my eyes) way different values as before. Before it told me to best use

[input_shaper]
shaper_type_x = 2hump_ei
shaper_freq_x = 71.5
shaper_type_y = 2hump_ei
shaper_freq_y = 37.5

now i ran it several times, and it came mostly same out like e.g.

// Calculating the best input shaper parameters for x axis
// Fitted shaper 'zv' frequency = 86.8 Hz (vibrations = 40.5%, smoothing ~= 0.027)
// Fitted shaper 'mzv' frequency = 60.6 Hz (vibrations = 21.0%, smoothing ~= 0.055)
// Fitted shaper 'ei' frequency = 81.6 Hz (vibrations = 20.6%, smoothing ~= 0.048)
// Fitted shaper '2hump_ei' frequency = 76.2 Hz (vibrations = 11.8%, smoothing ~= 0.093)
// Fitted shaper '3hump_ei' frequency = 74.6 Hz (vibrations = 8.0%, smoothing ~= 0.147)
// Recommended shaper_type_x = 3hump_ei, shaper_freq_x = 74.6 Hz
// Shaper calibration data written to /tmp/calibration_data_x_20210118_210858.csv file
// Calculating the best input shaper parameters for y axis
// Fitted shaper 'zv' frequency = 52.0 Hz (vibrations = 41.2%, smoothing ~= 0.063)
// Fitted shaper 'mzv' frequency = 33.2 Hz (vibrations = 20.8%, smoothing ~= 0.185)
// Fitted shaper 'ei' frequency = 46.0 Hz (vibrations = 20.5%, smoothing ~= 0.152)
// Fitted shaper '2hump_ei' frequency = 44.0 Hz (vibrations = 12.1%, smoothing ~= 0.279)
// Fitted shaper '3hump_ei' frequency = 55.0 Hz (vibrations = 10.9%, smoothing ~= 0.271)
// Recommended shaper_type_y = 3hump_ei, shaper_freq_y = 55.0 Hz
// Calculating the best input shaper parameters for x axis
// Fitted shaper 'zv' frequency = 88.4 Hz (vibrations = 41.9%, smoothing ~= 0.026)
// Fitted shaper 'mzv' frequency = 61.8 Hz (vibrations = 22.0%, smoothing ~= 0.053)
// Fitted shaper 'ei' frequency = 82.0 Hz (vibrations = 21.5%, smoothing ~= 0.048)
// Fitted shaper '2hump_ei' frequency = 77.4 Hz (vibrations = 12.8%, smoothing ~= 0.090)
// Fitted shaper '3hump_ei' frequency = 75.8 Hz (vibrations = 8.8%, smoothing ~= 0.143)
// Recommended shaper_type_x = 3hump_ei, shaper_freq_x = 75.8 Hz
// Shaper calibration data written to /tmp/calibration_data_x_20210118_212150.csv file
// Calculating the best input shaper parameters for y axis
// Fitted shaper 'zv' frequency = 48.4 Hz (vibrations = 43.9%, smoothing ~= 0.072)
// Fitted shaper 'mzv' frequency = 34.0 Hz (vibrations = 23.5%, smoothing ~= 0.176)
// Fitted shaper 'ei' frequency = 44.6 Hz (vibrations = 23.0%, smoothing ~= 0.162)
// Fitted shaper '2hump_ei' frequency = 43.8 Hz (vibrations = 14.1%, smoothing ~= 0.281)
// Fitted shaper '3hump_ei' frequency = 54.2 Hz (vibrations = 12.7%, smoothing ~= 0.279)
// Recommended shaper_type_y = 2hump_ei, shaper_freq_y = 43.8 Hz
// Calculating the best input shaper parameters for x axis
// Fitted shaper 'zv' frequency = 91.2 Hz (vibrations = 45.2%, smoothing ~= 0.025)
// Fitted shaper 'mzv' frequency = 61.8 Hz (vibrations = 23.9%, smoothing ~= 0.053)
// Fitted shaper 'ei' frequency = 82.6 Hz (vibrations = 24.0%, smoothing ~= 0.047)
// Fitted shaper '2hump_ei' frequency = 77.6 Hz (vibrations = 14.5%, smoothing ~= 0.090)
// Fitted shaper '3hump_ei' frequency = 75.8 Hz (vibrations = 9.9%, smoothing ~= 0.143)
// Recommended shaper_type_x = 3hump_ei, shaper_freq_x = 75.8 Hz
// Shaper calibration data written to /tmp/calibration_data_x_20210118_212915.csv file
// Calculating the best input shaper parameters for y axis
// Fitted shaper 'zv' frequency = 51.0 Hz (vibrations = 41.3%, smoothing ~= 0.065)
// Fitted shaper 'mzv' frequency = 33.2 Hz (vibrations = 21.5%, smoothing ~= 0.185)
// Fitted shaper 'ei' frequency = 46.0 Hz (vibrations = 21.0%, smoothing ~= 0.152)
// Fitted shaper '2hump_ei' frequency = 44.4 Hz (vibrations = 12.7%, smoothing ~= 0.274)
// Fitted shaper '3hump_ei' frequency = 54.8 Hz (vibrations = 11.2%, smoothing ~= 0.273)
// Recommended shaper_type_y = 3hump_ei, shaper_freq_y = 54.8 Hz
// Calculating the best input shaper parameters for x axis
// Fitted shaper 'zv' frequency = 89.0 Hz (vibrations = 40.8%, smoothing ~= 0.026)
// Fitted shaper 'mzv' frequency = 61.6 Hz (vibrations = 21.2%, smoothing ~= 0.054)
// Fitted shaper 'ei' frequency = 81.8 Hz (vibrations = 20.4%, smoothing ~= 0.048)
// Fitted shaper '2hump_ei' frequency = 77.4 Hz (vibrations = 12.2%, smoothing ~= 0.090)
// Fitted shaper '3hump_ei' frequency = 75.6 Hz (vibrations = 8.3%, smoothing ~= 0.143)
// Recommended shaper_type_x = 3hump_ei, shaper_freq_x = 75.6 Hz
// Shaper calibration data written to /tmp/calibration_data_x_20210118_214030.csv file
// Calculating the best input shaper parameters for y axis
// Fitted shaper 'zv' frequency = 48.2 Hz (vibrations = 46.7%, smoothing ~= 0.072)
// Fitted shaper 'mzv' frequency = 34.2 Hz (vibrations = 25.4%, smoothing ~= 0.174)
// Fitted shaper 'ei' frequency = 44.6 Hz (vibrations = 25.5%, smoothing ~= 0.162)
// Fitted shaper '2hump_ei' frequency = 43.8 Hz (vibrations = 15.8%, smoothing ~= 0.281)
// Fitted shaper '3hump_ei' frequency = 54.4 Hz (vibrations = 13.9%, smoothing ~= 0.277)
// Recommended shaper_type_y = 3hump_ei, shaper_freq_y = 54.4 Hz
// Calculating the best input shaper parameters for x axis
// Fitted shaper 'zv' frequency = 90.8 Hz (vibrations = 41.2%, smoothing ~= 0.025)
// Fitted shaper 'mzv' frequency = 61.2 Hz (vibrations = 21.2%, smoothing ~= 0.054)
// Fitted shaper 'ei' frequency = 82.0 Hz (vibrations = 20.5%, smoothing ~= 0.048)
// Fitted shaper '2hump_ei' frequency = 77.6 Hz (vibrations = 12.2%, smoothing ~= 0.090)
// Fitted shaper '3hump_ei' frequency = 76.0 Hz (vibrations = 8.3%, smoothing ~= 0.142)
// Recommended shaper_type_x = 3hump_ei, shaper_freq_x = 76.0 Hz
// Shaper calibration data written to /tmp/calibration_data_x_20210118_214925.csv file
// Calculating the best input shaper parameters for y axis
// Fitted shaper 'zv' frequency = 47.4 Hz (vibrations = 45.9%, smoothing ~= 0.074)
// Fitted shaper 'mzv' frequency = 34.2 Hz (vibrations = 24.9%, smoothing ~= 0.174)
// Fitted shaper 'ei' frequency = 44.6 Hz (vibrations = 25.0%, smoothing ~= 0.162)
// Fitted shaper '2hump_ei' frequency = 43.6 Hz (vibrations = 15.3%, smoothing ~= 0.284)
// Fitted shaper '3hump_ei' frequency = 54.0 Hz (vibrations = 13.8%, smoothing ~= 0.281)
// Recommended shaper_type_y = 2hump_ei, shaper_freq_y = 43.6 Hz

Didn't really change anything at the printer at all - therefore i am wondering whether the new value range is fine or not. Maybe it comes from my ADXL now not being that noisy anymore. Does it seem proper for you?

I executed deactivated shaper values and executed TEST_RESONANCES for X and Y to get following graph:

$ ~/klipper/scripts/calibrate_shaper.py /tmp/resonances_x_*.csv -o /tmp/shaper_calibrate_x.png
Fitted shaper 'zv' frequency = 90.0 Hz (vibrations = 40.6%, smoothing ~= 0.025)
Fitted shaper 'mzv' frequency = 61.2 Hz (vibrations = 21.0%, smoothing ~= 0.054)
Fitted shaper 'ei' frequency = 82.0 Hz (vibrations = 20.2%, smoothing ~= 0.048)
Fitted shaper '2hump_ei' frequency = 77.6 Hz (vibrations = 12.0%, smoothing ~= 0.090)
Fitted shaper '3hump_ei' frequency = 75.4 Hz (vibrations = 8.1%, smoothing ~= 0.144)
Recommended shaper is 3hump_ei @ 75.4 Hz

shaper_calibrate_x

$ ~/klipper/scripts/calibrate_shaper.py /tmp/resonances_y_*.csv -o /tmp/shaper_calibrate_y.png
Fitted shaper 'zv' frequency = 49.8 Hz (vibrations = 46.0%, smoothing ~= 0.068)
Fitted shaper 'mzv' frequency = 34.0 Hz (vibrations = 24.6%, smoothing ~= 0.176)
Fitted shaper 'ei' frequency = 45.2 Hz (vibrations = 24.8%, smoothing ~= 0.158)
Fitted shaper '2hump_ei' frequency = 43.8 Hz (vibrations = 15.1%, smoothing ~= 0.281)
Fitted shaper '3hump_ei' frequency = 54.4 Hz (vibrations = 13.5%, smoothing ~= 0.277)
Recommended shaper is 3hump_ei @ 54.4 Hz

shaper_calibrate_y


For the sequence, try using the proposed sequence. However, I can also see that the paper test is only an approximation, and some baby-stepping might be due. Then we probably would want to understand where to put the offset from baby stepping (I suppose into probe offset really).

Did try it three times now bed mesh and start first layer test print and it looks always pretty much same good. Didn't though yet verify the edges of the bed yet - but as my bed is anyhow not perfect flat as long as it sticks it's fine for me.

Imho people should definitylly start play with probe speed. to fast and it might crash to hard in your bed or press it a little down before trigger. Too small and you get random probe errors while bed mesh. E.g. doing probe accuracy 15 was pretty fine for me, but in real world i had to go to at least 20.

dmbutyugin commented 3 years ago

@AlmightyFrog Thanks for the tests!

So I take it you are using optocoupler or something similar to keep adxl345 connected to the RPi? Overall, the config looks good, IMHO. Ideally, for z_offset you can try using PROBE_CALIBRATE (e.g. in the middle of the bed), it first tries to probe the bed, and then uses paper manual method to determine the z_offset. Later you can adjust the z_offset value based on how you had to baby-step your prints: simply subtract the Z offset you set with SET_GCODE_OFFSET from z_offset value. Then after z_offset value is set, you can simply run Z_ENDSTOP_CALIBRATE command in the same location where PROBE_CALIBRATE was executed. I'm thinking that, ideally, it should be possible to generate different z endstop offsets for different bed temperatures (and the same goes for bed mesh).

Didn't really change anything at the printer at all - therefore i am wondering whether the new value range is fine or not. Maybe it comes from my ADXL now not being that noisy anymore. Does it seem proper for you?

If you ran the input shaper autocalibration script relatively long ago, there were recently some changes to its algorithm. Now it recommends the shaper parameters that usually give better tradeoffs between smoothing and remaining vibrations. Basically, now it recommends parameters that may increase ringing tiny bit, but smoothing should be reduced, sometimes considerably. Then I wouldn't be surprised about the changes in the suggested parameters. Looking at your charts, the newly recommended values seem OK.

Did try it three times now bed mesh and start first layer test print and it looks always pretty much same good. Didn't though yet verify the edges of the bed yet - but as my bed is anyhow not perfect flat as long as it sticks it's fine for me.

Well, that's good news! I don't think the accelerometer would fail for edges specifically.

Imho people should definitylly start play with probe speed. to fast and it might crash to hard in your bed or press it a little down before trigger. Too small and you get random probe errors while bed mesh. E.g. doing probe accuracy 15 was pretty fine for me, but in real world i had to go to at least 20.

Yep, I think speed setting is a bit trial and error here. Overall, I think the speed should be somewhere in the range 15-25.

AlmightyFrog commented 3 years ago

@AlmightyFrog Thanks for the tests!

My pleasure! And thank you for implementing this and having patience to read all that long comments @dmbutyugin. I'd also continue on my bed slinger, but am pretty sure bed is too unstable there. Similar applies to my delta which is afaik a Geetech G2S Pro and way to flexible most likely for ADXL probing.

So I take it you are using optocoupler or something similar to keep adxl345 connected to the RPi? Not exactly, I do currently have any pins connected to RPI but the interrupt pin which goes straight to SKR 1.3. Cause as I got it from @Apsu told in a beginning comment the SPI pins are hard to access I didn't continue checking whether I can directly connect it to it. Also I fear that maybe the ADXL data stream (while performing measurements) could put high peak loads in SKR.

Please explain me why exactly you think octocopler is relevant. As for my understanding while both boards are powered by the same voltage source it should be fine. And as far as i got the ADXL board is powered by 5V but has a 3V regulator onboard so that is also directly compatible with SKR. Right?

Overall, the config looks good, IMHO. Ideally, for z_offset you can try using PROBE_CALIBRATE (e.g. in the middle of the bed), it first tries to probe the bed, and then uses paper manual method to determine the z_offset. Later you can adjust the z_offset value based on how you had to baby-step your prints: simply subtract the Z offset you set with SET_GCODE_OFFSET from z_offset value. Then after z_offset value is set, you can simply run Z_ENDSTOP_CALIBRATE command in the same location where PROBE_CALIBRATE was executed. I'm thinking that, ideally, it should be possible to generate different z endstop offsets for different bed temperatures (and the same goes for bed mesh).

I am gonna try this next time possible.

Didn't really change anything at the printer at all - therefore i am wondering whether the new value range is fine or not. Maybe it comes from my ADXL now not being that noisy anymore. Does it seem proper for you?

If you ran the input shaper autocalibration script relatively long ago, there were recently some changes to its algorithm. Now it recommends the shaper parameters that usually give better tradeoffs between smoothing and remaining vibrations. Basically, now it recommends parameters that may increase ringing tiny bit, but smoothing should be reduced, sometimes considerably. Then I wouldn't be surprised about the changes in the suggested parameters. Looking at your charts, the newly recommended values seem OK.

Yeah I ran it as soon as the branch was official merged into mainline as far as i remember and since then only updated now to your experimental Z Probe branch. So then everything is fine and there is no regression.

Did try it three times now bed mesh and start first layer test print and it looks always pretty much same good. Didn't though yet verify the edges of the bed yet - but as my bed is anyhow not perfect flat as long as it sticks it's fine for me.

Well, that's good news! I don't think the accelerometer would fail for edges specifically.

Ah i forgot to mention cause it is trivial/useless, but i had quite some time problems getting my bed level at all on one point. Due to bad adheasion direct on glass plate i went back to original build plate came with my TronXY X5S and that is not flat and flexible. So if anyone sees a picture as following, just add another binder clip at the peak of your measurement and it is fine. The good thing about probing was, that i executed it 5 times and the result was always pretty much the same: bed-mesh

Imho people should definitylly start play with probe speed. to fast and it might crash to hard in your bed or press it a little down before trigger. Too small and you get random probe errors while bed mesh. E.g. doing probe accuracy 15 was pretty fine for me, but in real world i had to go to at least 20.

Yep, I think speed setting is a bit trial and error here. Overall, I think the speed should be somewhere in the range 15-25.

Seems like good recommendation to also write down in docs later. For delta we'll still have to see as soon as someone with a printer like that shows up and does perform tests.

KevinOConnor commented 3 years ago

After using the adxl345 as a probe (and also as an endstop)

Very impressive! Looks like it could be a very useful feature.

I can provide some of my high-level thoughts.

To support that, I added an ability for Z_ENDSTOP_CALIBRATE command to use probe measurements to adjust the Z endstop automatically

At a high-level, the main goal of all the homing/probing code is so that, during a print, when a user commands the nozzle to a particular Z position (eg, G1 Z10), that the nozzle be exactly that distance from the bed (eg, 10mm).

Unfortunately, there are no off-the-shelf sensors that directly support that. Every sensor must be calibrated prior to use. All real-world sensors have a z_offset of some kind.

It seems odd to me that we'd calibrate the Z endstop sensor using the probe sensor, as that would introduce additional errors. That is, any error in the calibration or the measurement of the probe would then add to the error of the Z endstop calibration. It would seem more accurate to me to perform the "paper test" directly when calibrating the Z endstop.

If I understand the scenario correctly, you have a probe that's sometimes accurate (when the nozzle is clean), but sometimes has an unknown (but static) offset (when there's filament on the nozzle). So, I'm guessing you want to use a physical endstop and use bed_mesh with relative_reference_index in the normal case? (As that config doesn't require the probe to have a static z_offset.)

It sounds like you also have a less common case where the bed height is physically changed and you'd like to use a procedure to clean the nozzle (to get an accurate probe z_offset), followed by an automated update of the z endstop position? If that is the case, then I wonder if a z endstop calibration is the appropriate action - perhaps it would be better to perform a bed_mesh translation or a SET_GCODE_OFFSET update instead?

-Kevin

dmbutyugin commented 3 years ago

Thanks for the feedback, Kevin!

Very impressive! Looks like it could be a very useful feature.

So, here there are ultimately 2 independent, however related features: adxl345 as a probe, and z endstop / probe offset calibration, which might work for other probes as well. Which one did you mean?

If I understand the scenario correctly, you have a probe that's sometimes accurate (when the nozzle is clean), but sometimes has an unknown (but static) offset (when there's filament on the nozzle). So, I'm guessing you want to use a physical endstop and use bed_mesh with relative_reference_index in the normal case? (As that config doesn't require the probe to have a static z_offset.)

In my experience, if there is some filament residue on the nozzle, that residue works as a shock absorber, and the adxl345 fails to trigger (because the shock acceleration is much smaller and is smoothed over longer time). This is different from, say, SmartEffector, which still triggers, but less repeatably and has a different offset then. But anyway, yes, I think it makes a lot of sense to use a physical endstop and use bed_mesh with relative_reference_index (for the peace of mind), and make sure to clean the nozzle prior to any probing (which then happens less frequently, and it is less of a bother).

At a high-level, the main goal of all the homing/probing code is so that, during a print, when a user commands the nozzle to a particular Z position (eg, G1 Z10), that the nozzle be exactly that distance from the bed (eg, 10mm).

Unfortunately, there are no off-the-shelf sensors that directly support that. Every sensor must be calibrated prior to use. All real-world sensors have a z_offset of some kind.

Yes, certainly. However, when I followed the Bed Mesh guide (for the first time, admittedly), I stumbled upon this part:

Prior to Mesh Calibration you will need to be sure that your Probe’s Z-Offset is calibrated. If using an endstop for Z homing it will need to be calibrated as well. See Probe_Calibrate and Z_ENDSTOP_CALIBRATE in Manual_Level for more information.

So, essentially the first steps of calibration are:

  1. Calibrate the probe z_offset using the paper method (`PROBE_CALIBRATE')
  2. Calibrate the Z endstop position using the paper method (Z_ENDSTOP_CALIBRATE)
  3. Build bed mesh automatically (BED_MESH_CALIBRATE)
  4. ....

Afterwards, adjust for any inaccuracies (e.g. for temperature compensation, etc.) using SET_GCODE_OFFSET.

Now, if the probe is used as a virtual z endstop, it becomes clear that the steps 1 and 2 will produce essentially the same results (because the probe triggers exactly at the same point where the endstop triggers, so they'll have exactly the same offset from the nozzle), within the probe repeatability bounds, of course. But the latter doesn't play a role: if the probe is not repeatable enough, then re-running the step 1 or 2 will give a different result anyway.

So, if the probe is used as a virtual z endstop, manual step 2 can be omitted - all the data is available from the step 1. So why force a user to do a useless work when they can save half of their manual work time?

Now if the printer has a separate physical z endstop, it is necessary to run the probing at the point where the user would normally run Z_ENDSTOP_CALIBRATE, and then calculate z_endstop_new = z_endstop_old - probe_z + z_offset (probe). Running an automatic probe instead of manual paper method is way faster, in my opinion. So this is how I came across the idea for Z_ENDSTOP_CALIBRATE METHOD=AUTOMATIC, which runs the probing automatically, and then calculates the new z endstop position. My claim (if I'm not mistaken, that is) is that the result of the sequence of steps PROBE_CALIBRATE, Z_ENDSTOP_CALIBRATE METHOD=AUTOMATIC will be the same as the steps PROBE_CALIBRATE, Z_ENDSTOP_CALIBRATE METHOD=MANUAL, with fewer manual work. And it seems that some users would want that (e.g. FR #3803).

... That is, any error in the calibration or the measurement of the probe would then add to the error of the Z endstop calibration. It would seem more accurate to me to perform the "paper test" directly when calibrating the Z endstop.

In principle, I agree with that, however I would point out that: 1) probe calibration and Z endstop calibration are the same paper calibration method essentially, and 2) we are not amplifying the error by doing that, but simply copying the error into Z endstop value (OK, to be more precise, it can get up to 2x the error of the probing in the worst case). You may argue that the endstop may be more accurate (especially if endstop_phase is calibrated for it), but ultimately the probe must be accurate enough for bed meshing (that's why people usually get a probe), which directly affects the first layer. Then why wouldn't it be accurate enough for endstop calibration? Even if some error was introduced into the Z endstop offset, subsequent bed meshing would eliminate that systematic error (and instead the random error is introduced within the probe repeatability). It might make sense to keep the default Z_ENDSTOP_CALIBRATE method manual, and only run the automatic endstop calibration if the user explicitly requests that (Z_ENDSTOP_CALIBRATE METHOD=AUTOMATIC), understanding the potential accuracy caveats of this method.

Also it could make sense to even add a few more convenience methods like Z_ENDSTOP_BABYSTEP_SAVE and/or Z_PROBE_OFFSET_BABYSTEP_SAVE or something alike, which would allow the user to run a print, additionally do some Z axis babystepping to get the perfect first layer, and then save the Z offset into either Z probe offset or Z endstop offset (instead of doing that manually with the potential of +/- errors). BTW, this isn't implemented yet.

Then, depending on what type of changes the user is making to their printer, it may be possible to further optimize the workflow and save even more time:

Note that neither of the scenarios above exclude the potential need for some baby-stepping of the first layer, but that's typical for any change (and paper test of Z endstop won't change that), however the additional convenience functions may simplify that too.

Of course, if a nozzle is changed on a printer with BLTouch, or the bed surface on a printer with an inductive sensor (as Arksine pointed out), then z_offset of the probe still needs to be calibrated. However, half of the manual efforts can still be saved.

dmbutyugin commented 3 years ago

@AlmightyFrog

Please explain me why exactly you think octocopler is relevant. As for my understanding while both boards are powered by the same voltage source it should be fine. And as far as i got the ADXL board is powered by 5V but has a 3V regulator onboard so that is also directly compatible with SKR. Right?

That's right. No, you just asked to check your config, and I saw probe_pin = ^P1.26. I think that pullup is neither necessary, nor makes sense for adxl345 interrupt pin. It is already pulled low by adxl345 when inactive, and it makes it high. Though now that I think about it, in your setup adxl345 is powered by 3.3V, and depending on your printer board, it may require 5V high (though usually the board power internal logic by 3.3V and so high level is at around 3.3V; also pulling up the pin of the chip powered with 3.3V to 5V would be, well, strange).

Yeah I ran it as soon as the branch was official merged into mainline as far as i remember and since then only updated now to your experimental Z Probe branch. So then everything is fine and there is no regression.

Yep, should all be good.

Yep, I think speed setting is a bit trial and error here. Overall, I think the speed should be somewhere in the range 15-25.

Seems like good recommendation to also write down in docs later. For delta we'll still have to see as soon as someone with a printer like that shows up and does perform tests.

Well, writing docs will come later after some more testing, I suppose. And then the range may need to be adjusted.

Though there was some excitement about this feature, but when it comes to real tests, there are fewer volunteers it seems :) It might still be possible to merge the feature at some point with the appropriate 'Here be dragons' warnings.

Apsu commented 3 years ago

I do still want to and intend to test your branch, and make use of this feature if it can be made robust enough. I've been sidetracked by work and a redesign on my current machine build. Hoping I'll have it moving by next weekend and can try your code out. I'm also working on a custom kinematic solution in Klipper for this new build at the same time lol

KevinOConnor commented 3 years ago

So, here there are ultimately 2 independent, however related features: adxl345 as a probe, and z endstop / probe offset calibration, which might work for other probes as well. Which one did you mean?

Getting the adxl345 working as a probe is very impressive! (Other features may also be impressive, but that's what I meant in the above context.)

Now, if the probe is used as a virtual z endstop, it becomes clear that the steps 1 and 2 will produce essentially the same results

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

Now if the printer has a separate physical z endstop, it is necessary to run the probing at the point where the user would normally run Z_ENDSTOP_CALIBRATE, and then calculate z_endstop_new = z_endstop_old - probe_z + z_offset (probe).

Running with two Z sensors (probe and a z endstop) is a less common configuration and it leads to a lot of confusion. This is an area where I think the Klipper docs could be improved upon. (Namely to make it clear that most users do not want to run with two Z sensors.)

The current valid use cases of two Z sensors that I know of are:

  1. The Z endstop is the main sensor. The probe is used for bed_mesh, z_tilt, and/or quad_gantry_level, but it is effectively done in such a way that the probe's z_offset isn't used for anything. (For example, by using relative_reference_index in bed_mesh; homing immediately after a Z_TILT_ADJUST/QUAD_GANTRY_LEVEL.) This methodology works well for probes that don't have a consistent z_offset across sessions (eg, due to temperature drift). The Z endstop in this setup is used as the high accuracy sensor.
  2. The probe is the main sensor. In this setup, the Z endstop is used as a means of safely retracting the head from the bed. A bed_mesh, bed_tilt, or z_tilt is always run before a print, so effectively the Z position_endstop is never used in practice. In this setup, the probe is used as the high accuracy sensor.

It sounds like you're saying you have a different use case. I can say from seeing various trouble reports over the years that using two Z sensors causes lots of confusion. (Again the Klipper docs could be improved.) Either the printing process has to be expertly constructed, or both sensors have to have extreme accuracy. Get it wrong and a casual user just gets confusing results.

My claim (if I'm not mistaken, that is) is that the result of the sequence of steps PROBE_CALIBRATE, Z_ENDSTOP_CALIBRATE METHOD=AUTOMATIC will be the same as the steps PROBE_CALIBRATE, Z_ENDSTOP_CALIBRATE METHOD=MANUAL, with fewer manual work. And it seems that some users would want that (e.g. FR #3803).

If you calibrate "probe" via "paper test", and then calibrate "endstop" from "probe" from "paper test" - that's surely going to have more error than calibrating "endstop" from "paper test". I understand you're getting good results with the adxl345, but most probes are actually pretty unreliable. They often exhibit large temperature drift, have a "location bias", are just plain noisy, and/or measure to a point not directly under the nozzle. Maybe that changes in the future with adxl345, but I'd definitely not recommend anyone assume a common off the shelf probe is accurate enough to calibrate another sensor.

Also it could make sense to even add a few more convenience methods like Z_ENDSTOP_BABYSTEP_SAVE and/or Z_PROBE_OFFSET_BABYSTEP_SAVE or something alike

I'm not really sure what you're suggesting here. I agree we could improve the Klipper docs and tools. I can say, at a high-level, that getting a good Z calibration is hard - there are so many different printers, methods, sensors, etc. That said, my own experience is that print quality goes up dramatically if one can identify the common sources of error (eg, temperature drift, sensor error) and come up with a repeatable process that limits those errors. So, identifying and facilitating a high-quality procedure would be my target.

Cheers, -Kevin

AlmightyFrog commented 3 years ago
  • If a nozzle is changed on the printer with a piezo probe like SmartEffector, or with ADXL345 probe, then the probe offset won't change (I would assume, at least), so the step 1 can be skipped, step 2 performed automatically, and bed re-meshing can likely be skipped as well. I assume this is oftentimes needed by many users.

I can confirm that in this use case there is no need to perform any offset corrections. That is pretty much how i used my piezo probe so far. I only remeshed from time to time, cause my bed (330x330) is akward bend and seems to tend to change from time to time a little maybe i.e. by temperature and/or me separating print from bed with scraper.

  • If a bed surface is changed (e.g. glass is changed for steel pei sheet) on a printer with BLTouch, piezo (SmartEffector) or ADXL345 probe, then probe z_offset didn't change as well, so the step 1 can be skipped, and step 2 performed automatically. Then if a bed is already known, its profile can be loaded, and that'll be it. I do not know how frequently this is needed, I must admit, but there's probably a group of users (myself included) who could benefit from that too.

Same here, i only did to remesh so far in this case with my piezo disk and fsr. But maybe I don't need the highest precission here and therefore was fine so far without calibrating probe again though the bed might be e.g. more squishy now and trigger minimal later. In the end i guess if there would be a auto mode which works good enough it would be a no brainer to anyhow execute it.

In general it would be of casue also interesting (in case probe is reliable enough) to have besides bed mesh regulary and use probe as z endstop to also do automatical bed tilt, but that is not in scope of this FR.

That's right. No, you just asked to check your config, and I saw probe_pin = ^P1.26. I think that pullup is neither necessary, nor makes sense for adxl345 interrupt pin. It is already pulled low by adxl345 when inactive, and it makes it high. Though now that I think about it, in your setup adxl345 is powered by 3.3V, and depending on your printer board, it may require 5V high (though usually the board power internal logic by 3.3V and so high level is at around 3.3V; also pulling up the pin of the chip powered with 3.3V to 5V would be, well, strange).

Yeah that came from the time i guess where i was tinkering around to get it to run properly with my broken ADXL board still on. I shall remove that pullup.

I'm also working on a custom kinematic solution in Klipper for this new build at the same time

@Apsu: Offtopic i know, but what kind of kinematics?

Running with two Z sensors (probe and a z endstop) is a less common configuration and it leads to a lot of confusion.

That might be, but i use it at my two main printers and eventually want to use it also on my delta some day. It is not only about precission but also about piece of mind and reliability cause i trust a ordinary switch more to not fail on me than any kind of probe. So for the seldom case where i need the probe (bed mesh at nozzle change or when bed seems off/differently warped) i can stay happily besdes the printer ready to M112.

Issues with piezo and fsr having nozzle crash/scratch in bed were rare, but existent.

Apsu commented 3 years ago

@Apsu: Offtopic i know, but what kind of kinematics?

@AlmightyFrog 3-axis fully parallel differential drive. I'm building a single-belted gantry, but could apply for multi-belted as well (e.g. CoreXYZ). Hit me up on discord to chat further.

dmbutyugin commented 3 years ago

@KevinOConnor, thanks! Well, I am nowhere near being an expert in actual use of probes, so please excuse some dumb questions. Actually, here are a couple more:

Now, if the probe is used as a virtual z endstop, it becomes clear that the steps 1 and 2 will produce essentially the same results

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? In fact, it seems that maybe calibrating the probe offset isn't necessary, but calibrating the z endstop offset is. Otherwise, if, say, BLTouch is used and it has 2mm offset to the nozzle, it means that it will trigger when the nozzle is 2mm above the bed. 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. So in that case, nozzle 0 level will be 2 mm above the bed.

The current valid use cases of two Z sensors that I know of are:

1. The Z endstop is the main sensor.  The probe is used for bed_mesh, z_tilt, and/or quad_gantry_level, but it is effectively done in such a way that the probe's z_offset isn't used for anything.  (For example, by using `relative_reference_index` in bed_mesh; homing immediately after a `Z_TILT_ADJUST`/`QUAD_GANTRY_LEVEL`.)  This methodology works well for probes that don't have a consistent z_offset across sessions (eg, due to temperature drift).  The Z endstop in this setup is used as the high accuracy sensor.

Thanks, this is enlightening. 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"). I wonder if DELTA_CALIBRATE also falls into that bucket (I mean, cases where probe offset isn't used for anything)?

2. The probe is the main sensor.  In this setup, the Z endstop is used as a means of safely retracting the head from the bed.  A bed_mesh, bed_tilt, or z_tilt is always run before a print, so effectively the Z position_endstop is never used in practice.  In this setup, the probe is used as the high accuracy sensor.

It sounds like you're saying you have a different use case.

Yes. It is like 2.b: The probe is used as the high accuracy sensor (hopefully that'll be true if confirmed by other people), but which is a bit too much bother to use every single time for every homing. It is, however, easy enough to use every time a user may suspect that some change to the printer has happened (e.g. printing with a new temperature, nozzle, bed surface, in the enclosure, etc.). So in practice, Z endstop is used for homing (and calibrated endstop_phase ensures sufficient repeatability of Z sensor).

If you calibrate "probe" via "paper test", and then calibrate "endstop" from "probe" from "paper test" - that's surely going to have more error than calibrating "endstop" from "paper test". I understand you're getting good results with the adxl345, but most probes are actually pretty unreliable. They often exhibit large temperature drift, have a "location bias", are just plain noisy, and/or measure to a point not directly under the nozzle. Maybe that changes in the future with adxl345, but I'd definitely not recommend anyone assume a common off the shelf probe is accurate enough to calibrate another sensor.

I see. 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.

... I can say from seeing various trouble reports over the years that using two Z sensors causes lots of confusion. (Again the Klipper docs could be improved.) Either the printing process has to be expertly constructed, or both sensors have to have extreme accuracy. Get it wrong and a casual user just gets confusing results.

I see. I guess if we see more success reports for adxl345 and decide to integrate this functionality into Klipper, then the tuning guide could be written specifically for the ADXL345 explaining the shortcomings of its use and how to best avoid them, including the simultaneous use of Z endstop and the probe. In case of ADXL345, at least some confusion patterns can be avoided. And TBH, code-wise it's really not a lot, so it may make sense to integrate even if there are only a few users.

In terms of accuracy that can be achieved (this is where I typically calibrate the probe and z endstop offset):

Recv: // PROBE_ACCURACY at X:10.000 Y:40.000 Z:5.071 (samples=10 retract=5.000 speed=15.0 lift_speed=15.0)
Recv: // probe at 10.000,40.000 is z=0.071500
Recv: // probe at 10.000,40.000 is z=0.070875
Recv: // probe at 10.000,40.000 is z=0.072125
Recv: // probe at 10.000,40.000 is z=0.077125
Recv: // probe at 10.000,40.000 is z=0.070250
Recv: // probe at 10.000,40.000 is z=0.073375
Recv: // probe at 10.000,40.000 is z=0.072125
Recv: // probe at 10.000,40.000 is z=0.070250
Recv: // probe at 10.000,40.000 is z=0.071500
Recv: // probe at 10.000,40.000 is z=0.070250
Recv: // probe accuracy results: maximum 0.077125, minimum 0.070250, range 0.006875, average 0.071937, median 0.071500, standard deviation 0.001977

It seems that precision can vary across the bed:

Recv: // PROBE_ACCURACY at X:100.000 Y:100.000 Z:5.300 (samples=10 retract=5.000 speed=15.0 lift_speed=15.0)
Recv: // probe at 100.000,100.000 is z=0.299000
Recv: // probe at 100.000,100.000 is z=0.289625
Recv: // probe at 100.000,100.000 is z=0.271500
Recv: // probe at 100.000,100.000 is z=0.299000
Recv: // probe at 100.000,100.000 is z=0.302125
Recv: // probe at 100.000,100.000 is z=0.305250
Recv: // probe at 100.000,100.000 is z=0.298375
Recv: // probe at 100.000,100.000 is z=0.290250
Recv: // probe at 100.000,100.000 is z=0.270875
Recv: // probe at 100.000,100.000 is z=0.301500
Recv: // probe accuracy results: maximum 0.305250, minimum 0.270875, range 0.034375, average 0.292750, median 0.298687, standard deviation 0.011733

however, reducing speed seems to help:

Recv: // PROBE_ACCURACY at X:100.000 Y:100.000 Z:5.315 (samples=10 retract=5.000 speed=10.0 lift_speed=15.0)
Recv: // probe at 100.000,100.000 is z=0.314625
Recv: // probe at 100.000,100.000 is z=0.313375
Recv: // probe at 100.000,100.000 is z=0.314000
Recv: // probe at 100.000,100.000 is z=0.315875
Recv: // probe at 100.000,100.000 is z=0.312750
Recv: // probe at 100.000,100.000 is z=0.314000
Recv: // probe at 100.000,100.000 is z=0.312125
Recv: // probe at 100.000,100.000 is z=0.312750
Recv: // probe at 100.000,100.000 is z=0.312125
Recv: // probe at 100.000,100.000 is z=0.314625
Recv: // probe accuracy results: maximum 0.315875, minimum 0.312125, range 0.003750, average 0.313625, median 0.313687, standard deviation 0.001159

which probably means that the bed near the center vibrates more and longer after the nozzle hits it, but reducing the speed reduces that effect.

Note that the precision above is close to the theoretical precision that can be achieved with adxl345: 15 mm/sec / 3200 Hz ~= 0.0047 mm, and 10 mm/sec / 3200 Hz ~= 0.0031mm.