Marlin: [FR] G29 multi-probe taking the average

Created on 25 Jan 2017  路  15Comments  路  Source: MarlinFirmware/Marlin

During G29 probing, would it be useful and/or practical to take multiple measurements in each probed location and use the average to create the mesh?

Probes have varying accuracies, and making multiple measurements could help to smooth out any variations. A user definable configuration variable could allow the user to set the number of probes per point to the value of their choosing (with default of 1).

Calibration Feature Request

All 15 comments

This would not be very hard to implement. But there are knowledgeable people that are opposed to even doing a 'Double Bump' and measuring at low speed. I'm a little skeptical that we would get noticeably better results by doing multiple probes at the same point.

With that said... Probably... it would be easiest to just just add the code and actually do it and test the concept rather than discuss it. Maybe hard code the repetition at 5 probes at each location and see what happens??? If you want to do some tests and report on the results, I'll see if I can get a small piece of code done you can Cut & Paste into your Marlin_main.cpp to force this to happen.

Here is what I have to test. I haven't run it yet, but if you can check my logic it would be nice to know if I'm on the right track:

in configuration.h:

// Set the number of times to probe each point.
// The mean of multiple measurements will be used when creating the mesh.
#define ABL_NUM_PROBE_MEASUREMENTS 3

in Marlin_main.cpp:

// Perform multiple probes and use the mean if option is defined
#if defined(ABL_NUM_PROBE_MEASUREMENTS)

    for(uint8_t i = 0; i < ABL_NUM_PROBE_MEASUREMENTS; i++) {
        measured_z += probe_pt(xProbe, yProbe, stow_probe_after_each, verbose_level);
    }

    measured_z /= ABL_NUM_PROBE_MEASUREMENTS;

#else
    measured_z = probe_pt(xProbe, yProbe, stow_probe_after_each, verbose_level);
#endif

Probably needs error handling after each probe, but seems like it should work for a proof of concept?

@Roxy-3D
I'm not against multiple probing and than averaging them, even if i think it will not improve the result, if the probe is subtile at all.
I'm against the current double touch probing for the reasons i explained in https://github.com/MarlinFirmware/Marlin/pull/4455#issue-168307569. This does __NOT!!!__ improve the result.

I tested this code:

// Perform multiple probes and use the mean if option is defined
#if defined(ABL_NUM_PROBE_MEASUREMENTS)
    float measured_z_sum = 0;
    for(uint8_t i = 0; i < ABL_NUM_PROBE_MEASUREMENTS; i++) {
        measured_z_sum += probe_pt(xProbe, yProbe, stow_probe_after_each, verbose_level);
    }

    measured_z = measured_z_sum / ABL_NUM_PROBE_MEASUREMENTS;

#else

        measured_z = probe_pt(xProbe, yProbe, stow_probe_after_each, verbose_level);

#endif

This is an example of the output (my z-offset is -1.9mm)

> G28
< X:102.00 Y:92.00 Z:11.90 E:0.00 Count X: 10200 Y:9200 Z:4760
> G29 V4
< G29 Auto Bed Leveling
< Bed X: 15.000 Y: 15.000 Z: 1.832
< Bed X: 15.000 Y: 15.000 Z: 1.807
< Bed X: 15.000 Y: 15.000 Z: 1.812
< Bed X: 58.000 Y: 15.000 Z: 1.880
< Bed X: 58.000 Y: 15.000 Z: 1.875
< Bed X: 58.000 Y: 15.000 Z: 1.867
< Bed X: 101.000 Y: 15.000 Z: 1.885
< Bed X: 101.000 Y: 15.000 Z: 1.885
< Bed X: 101.000 Y: 15.000 Z: 1.890
< Bed X: 144.000 Y: 15.000 Z: 1.962
< Bed X: 144.000 Y: 15.000 Z: 1.945
< Bed X: 144.000 Y: 15.000 Z: 1.950
< Bed X: 187.000 Y: 15.000 Z: 2.040
< Bed X: 187.000 Y: 15.000 Z: 2.045
< Bed X: 187.000 Y: 15.000 Z: 2.047
< Bed X: 187.000 Y: 53.000 Z: 1.905
< Bed X: 187.000 Y: 53.000 Z: 1.917
< Bed X: 187.000 Y: 53.000 Z: 1.905
< Bed X: 144.000 Y: 53.000 Z: 1.870
< Bed X: 144.000 Y: 53.000 Z: 1.867
< Bed X: 144.000 Y: 53.000 Z: 1.877
< Bed X: 101.000 Y: 53.000 Z: 1.837
< Bed X: 101.000 Y: 53.000 Z: 1.840
< Bed X: 101.000 Y: 53.000 Z: 1.842
< Bed X: 58.000 Y: 53.000 Z: 1.862
< Bed X: 58.000 Y: 53.000 Z: 1.867
< Bed X: 58.000 Y: 53.000 Z: 1.857
< Bed X: 15.000 Y: 53.000 Z: 1.860
< Bed X: 15.000 Y: 53.000 Z: 1.837
< Bed X: 15.000 Y: 53.000 Z: 1.845
< Bed X: 15.000 Y: 91.000 Z: 1.792
< Bed X: 15.000 Y: 91.000 Z: 1.775
< Bed X: 15.000 Y: 91.000 Z: 1.790
< Bed X: 58.000 Y: 91.000 Z: 1.797
< Bed X: 58.000 Y: 91.000 Z: 1.792
< Bed X: 58.000 Y: 91.000 Z: 1.787
< Bed X: 101.000 Y: 91.000 Z: 1.762
< Bed X: 101.000 Y: 91.000 Z: 1.755
< Bed X: 101.000 Y: 91.000 Z: 1.752
< Bed X: 144.000 Y: 91.000 Z: 1.777
< Bed X: 144.000 Y: 91.000 Z: 1.775
< Bed X: 144.000 Y: 91.000 Z: 1.770
< Bed X: 187.000 Y: 91.000 Z: 1.815
< Bed X: 187.000 Y: 91.000 Z: 1.800
< Bed X: 187.000 Y: 91.000 Z: 1.805
< Bed X: 187.000 Y: 129.000 Z: 1.860
< Bed X: 187.000 Y: 129.000 Z: 1.867
< Bed X: 187.000 Y: 129.000 Z: 1.862
< Bed X: 144.000 Y: 129.000 Z: 1.850
< Bed X: 144.000 Y: 129.000 Z: 1.850
< Bed X: 144.000 Y: 129.000 Z: 1.850
< Bed X: 101.000 Y: 129.000 Z: 1.835
< Bed X: 101.000 Y: 129.000 Z: 1.835
< Bed X: 101.000 Y: 129.000 Z: 1.832
< Bed X: 58.000 Y: 129.000 Z: 1.857
< Bed X: 58.000 Y: 129.000 Z: 1.860
< Bed X: 58.000 Y: 129.000 Z: 1.850
< Bed X: 15.000 Y: 129.000 Z: 1.842
< Bed X: 15.000 Y: 129.000 Z: 1.830
< Bed X: 15.000 Y: 129.000 Z: 1.830
< Bed X: 15.000 Y: 167.000 Z: 1.822
< Bed X: 15.000 Y: 167.000 Z: 1.830
< Bed X: 15.000 Y: 167.000 Z: 1.827
< Bed X: 58.000 Y: 167.000 Z: 1.877
< Bed X: 58.000 Y: 167.000 Z: 1.872
< Bed X: 58.000 Y: 167.000 Z: 1.880
< Bed X: 101.000 Y: 167.000 Z: 1.885
< Bed X: 101.000 Y: 167.000 Z: 1.892
< Bed X: 101.000 Y: 167.000 Z: 1.890
< Bed X: 144.000 Y: 167.000 Z: 1.937
< Bed X: 144.000 Y: 167.000 Z: 1.935
< Bed X: 144.000 Y: 167.000 Z: 1.942
< Bed X: 187.000 Y: 167.000 Z: 2.000
< Bed X: 187.000 Y: 167.000 Z: 2.007
< Bed X: 187.000 Y: 167.000 Z: 2.000
< Bilinear Leveling Grid:
<       0     1     2     3     4
<  0 -0.08 -0.03 -0.01 +0.05 +0.14
<  1 -0.05 -0.04 -0.06 -0.03 +0.01
<  2 -0.11 -0.11 -0.14 -0.13 -0.09
<  3 -0.07 -0.04 -0.07 -0.05 -0.04
<  4 -0.07 -0.02 -0.01 +0.04 +0.10
< X:212.00 Y:210.00 Z:11.80 E:0.00 Count X: 21200 Y:21000 Z:4760

In the end I don't think it made an appreciable difference to my bed matrix as my sensor is fairly accurate, with a maximum 0.03mm range across repeated measurements. For people with less accurate sensors it might be useful?

@AnHardt

I'm not against multiple probing and than averaging them, even if i think it will not improve the result, if the probe is subtile at all. I'm against the current double touch probing for the reasons i explained in #4455 (comment). This does NOT!!! improve the result.

I understand the logic of what you say. I guess I have several comments. First, I don't think I've ever seen position lost because of a rapid stop of the first bump. But I can see where it might happen. And I think I agree it is dangerous.

I do like the idea of moving rapidly to a known position close to where the trigger is expected, and then continuing slowly for the actual point probe. Doing the probe this way would be fairly easy and should produce good results.

I don't know if averaging multiple probes is going to be much better than any individual probe, but theoretically it could be.

The simplest way to implement this would be to rename PROBE_DOUBLE_TOUCH to PROBE_TOUCHES, setting this option to the number of probes to do at each point. A flag (PROBE_AVERAGING) would indicate that each set should be averaged instead of taking the last one. Perhaps it would be enabled automatically if PROBE_TOUCHES > 2.

I actually thought PROBE_DOUBLE_TOUCH did exactly what this issue is suggesting: average the results of two complete cycles of our default probe method in order to improve accuracy. But reading #4455, it does not and instead is really using an antiquated method of probing that relies on the requirement to have infinite jerk capability in the Z-axis.

Surely others newer to Marlin must misunderstand the same ?

Shouldn't priority change be made to PROBE_DOUBLE_TOUCH in one of the following ways ?:

  1. Renamed USE_OLD_DOUBLE_TOUCH_PROBING and no code changes
  2. Code changed so PROBE_DOUBLE_TOUCH averages the results of two complete cycles of our default probing method
  3. Rename PROBE_DOUBLE_TOUCH to PROBE_TOUCHES and code changed to use current default probe method implemented in #4455 (@thinkyhead 's suggestion above)
  4. Remove PROBE_DOUBLE_TOUCH entirely (but may incur having to explain to a lot of confused people what I misunderstood, which in the end could be more work than any of the above)

3 seems ideal but if not, then at least 1, because leaving it as-is is a diservice to the users who may not understand the history of this feature and believe that enabling PROBE_DOUBLE_TOUCH is simply a trade off between time probing and impoved accuracy.

@benlye, I'm interested in changing the code to incorporate the multiple probes. However, I cannot find where to insert the code that you have posted. I'm running 1.1.6 of Marlin. I added the following lines of code in line 4830 on marlin_main.cpp but it doesn't seem to do anything. Can you kindly help?

    // Perform multiple probes and use the mean if option is defined
      #if defined(ABL_NUM_PROBE_MEASUREMENTS)
      float measured_z_sum = 0;
          const bool stow_probe_after_each = parser.boolval('E');
      for(uint8_t i = 0; i < ABL_NUM_PROBE_MEASUREMENTS; i++) {
        measured_z_sum += probe_pt(xProbe, yProbe, stow_probe_after_each, verbose_level);
      }
          measured_z = measured_z_sum / ABL_NUM_PROBE_MEASUREMENTS;

      #else
    // Save the previous Z before going to the next point
        measured_z = current_position[Z_AXIS];
      #endif

I cant see where this will fit in now since I think the code has changed quite a bit since it was originally written. I can also not get it to work.

That's really unfortunate as I would really love to implement this to eliminate any errorneous one-off readings that may occur. Even a simple voting algorithm (say, take 3 readings and choose the median) would be way superior to a single reading.

Found this after trying to configure Marlin to do a multiple-average of each point on the bed.

I have noticed once or twice that one of my mesh points is off by more than it should be, so I wanted to take an average of 5 readings at each point and take the mean of 3.

Interesting reading about double touch also - I assumed it was an averaging method, clearly it's not.

I forked from 1.1.6 (my current version) and applied the test code:

https://github.com/CraigMason/Marlin/commit/7af762927bc928f551a7414ffb5063711e4a6dda

Send: G29 V4
Recv: G29 Auto Bed Leveling
Recv: Bed X: 40.000 Y: 51.000 Z: -0.037
Recv: Bed X: 40.000 Y: 51.000 Z: -0.027
Recv: Bed X: 40.000 Y: 51.000 Z: -0.032
Recv: Bed X: 40.000 Y: 51.000 Z: -0.048
Recv: Bed X: 40.000 Y: 51.000 Z: -0.048
Recv: Bed X: 110.000 Y: 51.000 Z: -0.003
Recv: Bed X: 110.000 Y: 51.000 Z: 0.005
Recv: Bed X: 110.000 Y: 51.000 Z: 0.005
Recv: Bed X: 110.000 Y: 51.000 Z: 0.005
Recv: Bed X: 110.000 Y: 51.000 Z: 0.000
Recv: Bed X: 180.000 Y: 51.000 Z: 0.010
Recv: Bed X: 180.000 Y: 51.000 Z: 0.020
Recv: Bed X: 180.000 Y: 51.000 Z: 0.017
Recv: Bed X: 180.000 Y: 51.000 Z: 0.015
Recv: Bed X: 180.000 Y: 51.000 Z: 0.020
Recv: Bed X: 180.000 Y: 115.000 Z: -0.010
Recv: Bed X: 180.000 Y: 115.000 Z: 0.005
Recv: Bed X: 180.000 Y: 115.000 Z: -0.005
Recv: Bed X: 180.000 Y: 115.000 Z: -0.015
Recv: Bed X: 180.000 Y: 115.000 Z: 0.007
Recv: Bed X: 110.000 Y: 115.000 Z: 0.015
Recv: Bed X: 110.000 Y: 115.000 Z: 0.020
Recv: Bed X: 110.000 Y: 115.000 Z: 0.012
Recv: Bed X: 110.000 Y: 115.000 Z: 0.015
Recv: Bed X: 110.000 Y: 115.000 Z: 0.017
Recv: Bed X: 40.000 Y: 115.000 Z: -0.030
Recv: Bed X: 40.000 Y: 115.000 Z: -0.025
Recv: Bed X: 40.000 Y: 115.000 Z: -0.027
Recv: Bed X: 40.000 Y: 115.000 Z: -0.022
Recv: Bed X: 40.000 Y: 115.000 Z: -0.025
Recv: Bed X: 40.000 Y: 179.000 Z: -0.007
Recv: Bed X: 40.000 Y: 179.000 Z: -0.010
Recv: Bed X: 40.000 Y: 179.000 Z: -0.010
Recv: Bed X: 40.000 Y: 179.000 Z: -0.007
Recv: Bed X: 40.000 Y: 179.000 Z: -0.010
Recv: Bed X: 110.000 Y: 179.000 Z: 0.050
Recv: Bed X: 110.000 Y: 179.000 Z: 0.048
Recv: Bed X: 110.000 Y: 179.000 Z: 0.048
Recv: Bed X: 110.000 Y: 179.000 Z: 0.045
Recv: Bed X: 110.000 Y: 179.000 Z: 0.045
Recv: Bed X: 180.000 Y: 179.000 Z: 0.052
Recv: Bed X: 180.000 Y: 179.000 Z: 0.052
Recv: Bed X: 180.000 Y: 179.000 Z: 0.043
Recv: Bed X: 180.000 Y: 179.000 Z: 0.050
Recv: Bed X: 180.000 Y: 179.000 Z: 0.037
Recv: Bilinear Leveling Grid:
Recv:       0      1      2
Recv:  0 -0.039 -0.005 +0.015
Recv:  1 -0.023 +0.016 -0.000
Recv:  2 -0.014 +0.044 +0.056

Multiple probe feature was added in 1.1.7 with https://github.com/MarlinFirmware/Marlin/pull/8705

Great! Thanks, can this issue be closed?

This is amazing! I'll be upgrading to 1.1.8 soon. I had wanted to take the median of 3 readings (so as to discard the occasional outlier) but I guess I will go with the mean of 5 for now.

Was this page helpful?
0 / 5 - 0 ratings