Marlin: Sanity Check for Mesh Bed Leveling systems...

Created on 2 Jul 2017  路  34Comments  路  Source: MarlinFirmware/Marlin

I'm seeing a lot of people trying to use the various Mesh Bed Leveling systems and they have

#define MIN_SOFTWARE_ENDSTOPS

turned on. For Mesh Bed Leveling systems, it might make sense to caution them this will hurt the bed leveling system's performance. Turning this on will keep the nozzle from tracking the bed if a mesh point is negative. It maybe, we should still allow them to enable this option but just not enforce it on the Z-Axis when a Mesh Bed Leveling system is active.

Thoughts and opinions are welcome...

Calibration Discussion

Most helpful comment

We're trying to move a lot of the description & "how to use/setup" stuff out of the bloated configuration files and into the Wiki.

I'm a late comer. I'm sure I must have missed the no doubt extended conversation where you all agreed to this. But I feel compelled to say:

That sounds like a crazy idea. Who wants to toggle between a wiki and a header to get set up. On top of that, when something changes, the natural place for the dev to document it is where the change occurs. There's not a chance the two will stay in sync. Surely a smarter move would be to use doxygen and gen the docco from the source and comments? Otherwise you're just making it demotivational for the lazy human dev.

Have you tried to configure samba or apache lately? It's not a perfect comparison, but their config is 99% comment. It is a GoodThingTM.

Comments are not bloat. They are information.

Any contributions would be much appreciated.

I bet! On account of nobody really thinks this is a good use of their time.

All 34 comments

I agree - do not enforce MIN_SOFTWARE_ENDSTOPS on the Z axis when bed leveling is active.

I'm not aware of a generally useable method of guaranteeing the head won't crash into the bed. The closest I've seen is a few systems where the nozzle is the probe/endstop.

The only method I've been able to come up with is to add yet another configuration item something like Z_PRINT_MINIMUM and check that instead of the software endstop.

Rather than yet another config option, why not relax MIN_SOFTWARE_ENDSTOPS on the Z-axis when BL is active only up (down) to Z_PROBE_OFFSET_RANGE_MIN (which is already set by the user theoretically to the lowest possible distance). This will at least prevent digging into the bed more than this many steps and if we add a sufficent comment in Configuration.h to explain this use during BL, the user can be more maticulous about selecting an appropriate value just below their lowest point on the bed.

what if the sensor can move beyond the edge of the bed? you want something to
keep from breaking the machine (I recently broke my Z motor mount because the
bottom Z stop wasn't working)

what if the sensor can move beyond the edge of the bed?

I don't follow. How is that relevant ? If MIN_SOFTWARE_ENDSTOPS is active today, bed leveling may not be able to correct for bed contour. The proposal is to change it so when bed leveling is active:

(min Z point when MIN_SOFTWARE_ENDSTOP is enabled) = (G28 homing Z value) + Z_PROBE_OFFSET_RANGE_MIN

This potentially extends the lowest Z travel point to just below the bed (if the user sets Z_PROBE_OFFSET_RANGE_MIN appropriately), but would prevent Z stepper from driving nozzle into bed indefinitely.

On Sun, 2 Jul 2017, Dave Johnson wrote:

If MIN_SOFTWARE_ENDSTOPS is active today, bed leveling may not be able to
correct for bed contour.

it may not be able to correct for bed contour, but it tries really hard to avoid
breaking the machine

The proposal is to change it so:
>

MIN_SOFTWARE_ENDSTOP = (G28 homing Z value) - Z_PROBE_OFFSET_RANGE_MIN

When bed leveling is active. This potentially extends the lowest Z travel point to just below the bed (if the user sets Z_PROBE_OFFSET_RANGE_MIN appropriately.

allowing the software endstop to be defined to go a limited amount negative is
reasonable, allowing it to go a lot negative 'just in case' is not.

how far is too much is impossible to know in a generic way. So allowing
min_software_endstop to be defined as a negative value is ok, but the default
should be not to go below Z=0

How about making the Z min check value something that is created/updated whenever a bed leveling system is active.

Maybe we could do this:

  1. Set the Z_MIN check to the lowest point in the active bed leveling mesh/grid.
  2. G29 would always update the Z_MIN check value.
  3. Anything that loads or modifies a mesh/grid would also have to update the Z_MIN check value.

The linear and 3 point systems could be a problem.


~I've gotten a couple of requests for a mechanism to keep the nozzle within the printable area. Basically a more restrictive version of software endstops.~

~Rather than muddy up this thread I've opened another issue.~
~Keep nozzle within printable/active area #7218~

Rather than muddy up this thread I've opened another issue.

I think it is ok to muddy up this thread... And really... Not letting the nozzle go below Z=0.000 is an attempt to keep the nozzle within the printable area. It just doesn't really describe what is going on in a Mesh Bed Leveling scenario.

I've had a couple of requests for a mechanism to constrain the nozzle to within the printable area.

Since Marlin is also being used for some CNC machines I'm thinking "active area" is a better description than "printable area".

My vision for such a system is:

  1. Similar to software endstops but user configurable.
  2. Would be used by all bed leveling systems on Cartesian robots to define the active/printable area. Deltas already have a bed/travel radius and a printable radius
  3. Required if using a bed leveling system (one source of truth)
    4) G28, G29, park, ... would be able to disable/ignore the system.
    5) Be integrated into the planner (remove checks being done in multiple places now).

The Z minimum check suffers from the same issues as above.

Maybe we could do this:

  1. Set the Z_MIN check to the lowest point in the active bed leveling mesh/grid.
  2. G29 would always update the Z_MIN check value.
  3. Anything that loads or modifies a mesh/grid would also have to update the Z_MIN check value.

Here's my first pass at wording for configuration.h

///////////////////////////////////////////////////
////////  Travel and Active limits  ///////////////
////////       Cartesian only       ///////////////
///////////////////////////////////////////////////

/**
 *  Travel limits define the area that the nozzle/tool can reach.
 *  Active limits define the area where the nozzle/tool will be active.
 *    On a printer this is the printable area.  On a CNC machine this 
 *    is the area that the machining can take place.
 *
 *  The travel limits must be defined so that the front left 
 *  corner of the active area is X = 0 , Y = 0.
 */

// Travel limits after homing (units are in mm) 
#define X_MIN_POS -50  // if homing in the - direction, G28 sets X position to this value after homing
#define Y_MIN_POS -70  // if homing in the - direction, G28 sets Y position to this value after homing
#define Z_MIN_POS 0    // if homing in the - direction, G28 sets Z position to this value after homing
#define X_MAX_POS 330  // if homing in the + direction, G28 sets X position to this value after homing
#define Y_MAX_POS 280  // if homing in the + direction, G28 sets Y position to this value after homing
#define Z_MAX_POS 430  // if homing in the + direction, G28 sets Z position to this value after homing

// Active limits
// 
//      X_MIN_ACTIVE 0              
//      Y_MIN_ACTIVE 0
//      Z_MIN_ACTIVE   set by Marlin to 1mm lower than the lowest point in the mesh/grid
#define X_MAX_ACTIVE X_MAX_POS - 10  //modify to suit your robot
#define Y_MAX_ACTIVE Y_MAX_POS - 10  //modify to suit your robot
#define Z_MAX_ACTIVE Z_MAX_POS - 10  //modify to suit your robot

I think this makes a lot of sense.

But shouldn't the X, Y and Z_MIN_ACTIVE be settable numbers? If I know my glass is pretty flat... I might set a hard limit of Z_MIN_ACTIVE to -1mm Probably, even a 'crash' of that much isn't going to do much damage. And if the the G29 updates the value to a little bit less (actually more since I'm talking about a negative number) I would get even less force on the nozzle when it crashes.

I think your suggestions deserve some more investigation. And probably... They wouldn't be very hard to implement and might actually simplify the code.

By definition the front left corner of the active area is X = 0, Y = 0.

The travel limits would have to be set so as to make this true.

Hmmmm.... In the general case.... It seems like we should envision a solution that handles anything. For example... Delta's have the center of the bed at (0,0,0) And usually Cartesian printers have the left front corner at (0,0,0) but that isn't always the case.

Would there be any harm (or complexity for the user to setup and understand what needs to be done) by relaxing that constraint? We could also add sanity checks that made sure the active area was always within the min and max position area. If a user got confused and put in bogus numbers, that would catch it before any harm was done...

I have a printer where the bed sensor is a couple inches behind the nozzle, so I
really want the nozzle to be able to be moved to y=-40 or so to sense the front
of the bed, and limit it's testing to not go beyond about Y=150 or I end up
testing where the sensor will miss the bed entirely. I don't want it to keep
going negative Z just because it's probing too far back.

If this is prevented via some other mechanism, I apologize.

By definition the front left corner of the active area is X = 0, Y = 0.

In 3PBL, LBL, BBL, and presumably UBL, there is a concept of Z-offset for the probe, whereby the nozzle will never go below this point (which the user is familiar with).

@Roxy-3D - it seems it would be trivial to detect when a point on a mesh level grid detects a point that is lower than the homing Z value, so as long as probe Z offset is set correctly (M851) UBL could report a warning in the terminal + on the feedback line of LCD with "Probe point lower than endstop detected!" so the user can then increase the value accordingly ?

I agree the last thing anyone ever wants by default is metal hitting metal. Better to have users unable to get a perfect first layer than to have them gouge their bed. As long as the warning is clear and there is googleable documentation that explains what to do when the warning occurs, it would solve the problem, no ?

One thing that I'm finding odd, is there is no probe offzet in BBL if PROBE_MANUAL is set, yet with #define Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN I actually use my probe for homing, so it's frustrating I can't user M851 to adjust overall mesh offset (mesh captured by hand, because my probe doesn't get perfect results in upper right corner, and probe can't reach left 1" of the 6" bed)

UBL could report a warning in the terminal + on the feedback line of LCD with "Probe point lower than endstop detected!" so the user can then increase the value accordingly ?

Good thinking! Soon UBL will be running without either a serial console or an LCD Panel. But still... What you said is true. It would be very good to do this.

Ah yes, the world according to Bob ... or as my oldest daughter says "Why is everyone else crazy?"

Making it fit my printer is semi-easy. Making it general is harder but well worth the effort.

@davidelang - I've set my travel limits so X=0 & Y=0 is the front left corner of my printable area. I then use the following to tell UBL the extends of my print area:

#define UBL_MESH_MIN_X 0        
#define UBL_MESH_MAX_X 300
#define UBL_MESH_MIN_Y 0
#define UBL_MESH_MAX_Y 375

There's also this for MESH_BED_LEVELING

    #define MESH_MIN_X
    #define MESH_MAX_X
    #define MESH_MIN_Y
    #define MESH_MAX_Y

I'm not sure if this also sets the printable limits or just the autoprobe limits.

#if ENABLED(AUTO_BED_LEVELING_LINEAR) || ENABLED(AUTO_BED_LEVELING_BILINEAR)
  // Set the boundaries for probing (where the probe can reach).
  #define LEFT_PROBE_BED_POSITION 15
  #define RIGHT_PROBE_BED_POSITION 170
  #define FRONT_PROBE_BED_POSITION 20
  #define BACK_PROBE_BED_POSITION 170

Barging in with some unsolicited, idle, thoughts...

It seems to me that most issues can be solved by explicitly defining the meaning if the words used. With a lot of words. Personally, I find the whole setup thing very obtuse.

I would have expected that something called an end stop would define the absolute limit of travel in that direction. Possibly even causing the machine to halt with an error.

At some stage it became apparent to a developer that, at least for the z min stop, that this was very hard to set within +- .005mm and so this particular situation became an exception.

It seems to me that the z min end stop, as it is used now, should be renamed to 'Z-KNOWN-LOCATION' then the z min end stop can relative to this, and be changed in software. Then software end stops would work as expected. In this scenario you may even have an actual z min end stop as well.

Now we should define the limits of movement of the head, the dimensions of the bed, and the offset of the bed within the space accessible to the head. Understanding this, it should be a simple matter to describe the location of any probe relative to the head, and the software will know where it can probe.

(A quick aside... Roxy mentioned somewhere that the probing routine should take care of the [i]type[/i] of probe. Nothing else should need to know. I can see no practical difference in the outcome of a manual probe and an automated one. Including testing your ability to get your 'feel' consistent by trying a repeatability test.)

It is not currently clear to me from the documentation what offsets take precedence. And, further, these things appear to be configured in wildly different places in the config header.

It it what it is, and this is not a rant, just idle observations. But I'd really like to see either more words about this in the comments in the config file, or a good description online.

'Z-KNOWN-LOCATION' has merits.

This one may be little too long: 馃槈 Z_KNOWN_LOCATION_AS_DEFINED_BY_TRAVEL_LIMITS_IN_RESPONSE_TO_Z-MIN_ENDSTOP_TRIGGERING_IF_HOMING_IN_THE_NEGATIVE_DIRECTION_ELSE_Z-MAX_ENDSTOP_TRIGGERING_IF_HOMING_IN_THE_POSITIVE_DIRECTION


We're trying to move a lot of the description & "how to use/setup" stuff out of the bloated configuration files and into the Wiki.

We have a long way to go. Any contributions would be much appreciated.

We're trying to move a lot of the description & "how to use/setup" stuff out of the bloated configuration files and into the Wiki.

I'm a late comer. I'm sure I must have missed the no doubt extended conversation where you all agreed to this. But I feel compelled to say:

That sounds like a crazy idea. Who wants to toggle between a wiki and a header to get set up. On top of that, when something changes, the natural place for the dev to document it is where the change occurs. There's not a chance the two will stay in sync. Surely a smarter move would be to use doxygen and gen the docco from the source and comments? Otherwise you're just making it demotivational for the lazy human dev.

Have you tried to configure samba or apache lately? It's not a perfect comparison, but their config is 99% comment. It is a GoodThingTM.

Comments are not bloat. They are information.

Any contributions would be much appreciated.

I bet! On account of nobody really thinks this is a good use of their time.

What would happen if those user with a proximity sensor would rem the following line

#if ENABLED(MIN_SOFTWARE_ENDSTOPS)
NOLESS(target[X_AXIS], soft_endstop_min[X_AXIS]);
NOLESS(target[Y_AXIS], soft_endstop_min[Y_AXIS]);
// NOLESS(target[Z_AXIS], soft_endstop_min[Z_AXIS]);

found in "Marlin_main.cpp" as a workaround?

The discussion here seems to be mostly about the Z min, but I was wondering if it also applies to X and Y.
In my case specifically, my X_MIN_POS is set to -20 and my X_PROBE_OFFSET_FROM_EXTRUDER is set to 28. So in theory my 12mm diameter probe should be able to travel almost to the edge of the bed. However once I do G29 P1, it moves my nozzle to X=0 and starts probing, never going farther left. Is this expected?

The nozzle should be free to travel over the entire declared bed. But the G29 P1 won't probe on the edge of the bed where the probe can not get to the points.

Thanks, @Roxy-3D. My question was why the nozzle doesn't travel outside of the declared bed so the probe can reach farther to the left (but still remain fully on the bed). As it stands right now, I have to manually probe a whole column of points that the probe could reach but doesn't.

You can fill them in that way... But you can also just do a G29 P3 to fill in one row at a time.... And then do the G26 to see how correct they are... and a G29 P4 to edit them if necessary. I prefer the later approach. For me, it is much more accurate than manually probing that many points.

Which will probably take half an hour. Or Marlin could do what I described which would take seconds. My question is - why doesn't it? I gave it all the information it needs to know that it's possible with the configured X_MIN_POS=-20.

If Marlin thought it could probe the point... It would have. I haven't looked at your Configuration.h files to see why Marlin doesn't believe that it is possible.

@Roxy-3D you were absolutely right. My bad. By reducing my UBL_MESH_INSET and X_MAX_POS at the same time, the nozzle now travels outside the bed Many thanks for the pointer!

However, even though the probe's edge is only a couple of mm away from the bed's edge, I still get a column of NULL values on the left side of the matrix.

Here are my configuration.h and configuration_adv.h. Would you mind having a look?

Yes... With any (X|Y)_PROBE_OFFSET_FROM_EXTRUDER you will get unprobed mesh points. But invoking the G29 P3 'Smart Fill' command will fill those in with reasonable values.

After you do a G26... You can decide if those filled in values need to be tweaked or not. It is very possible you say "It is almost like the machine probed those locations." But if you do decide to adjust the numbers, the G29 P4 R is so quick to do, it just doesn't matter.

If you were willing to use a much larger inset, the printable bed would be where the probe could reach. But with a 2mm inset... That can't compensate for the 44mm and 28mm offset for X & Y
```cpp

define X_PROBE_OFFSET_FROM_EXTRUDER 28 // X offset: -left +right [of the nozzle]

define Y_PROBE_OFFSET_FROM_EXTRUDER 44 // Y offset: -front +behind [the nozzle]

define Z_PROBE_OFFSET_FROM_EXTRUDER -1.5 // Z offset: -below +above [the nozzle]

```

Thanks for the explanation. I'm not worried about the front of the bed. My probe can't reach that. It can however reach the full width of my bed, so I'm still confused why there are null values on the left side.
So when I did a full fine tuning of the bed I realized that the nozzle travels outside of the bed to the left (to X=-18) to validate points that make no sense. Obviously the probe can't reach those, but it doesn't need to since I can't print there.
Doesn't Marlin expect that the printable area is delineated by the zero coordinates? If so, why does it think it needs mesh points with negative coordinates in X or Y?

Doesn't Marlin expect that the printable area is delineated by the zero coordinates?

No... The nozzle can go anywhere within this 'Print Envelope'. The probe is offset from that, so the probe can not reach the entire print envelope:

// Travel limits after homing (units are in mm)
#define X_MIN_POS 6
#define Y_MIN_POS 3
#define Z_MIN_POS 0
#define X_MAX_POS 207
#define Y_MAX_POS 182
#define Z_MAX_POS 175

Thanks. I guess the cleaner solution to that would be to differentiate between a travel envelope and a print envelope.

For now I can fill in the left row with G29 P3 since it won't be used anyways, but it seems hacky.

Not to derail the intent of this very useful and needed discussion, the reason the probe can't probe off this area is exactly because it's technically an assumption at where the probeable areas are based on the assumed bed location determined from the max xy travel values.

There's been a lot of separate discussions about this recently so it's probably time to seriously consider the need for defining the bed location separate from probable area as it would solve a lot of problems without too mich extra config bloat. See #7268 for more details.

My Read on this and related discussions:
A) axis physical travel limitations
B) nozzle 'T0 tool-point' (x,y,z) zero
C) nozzle 'T0 tool-point' (x,y,z) max
D) z probe (x,y,z) travel limits based from zero

Basing all from zero would lessen users confusion of probe/nozzle/LS position relationships during setup. Leave the offset calculations to the devs.

Does that help to understand our needs?
(And I agree, everyone else is crazy)
HTH

Turning this on will keep the nozzle from tracking the bed if a mesh point is negative.

Incorrect. MIN_SOFTWARE_ENDSTOPS only applies to the high-level cartesian position and doesn't prevent the nozzle moving lower if needed once we get to the planner.

void prepare_move_to_destination() {
  clamp_to_software_endstops(destination);
  . . .
}

I agree - do not enforce MIN_SOFTWARE_ENDSTOPS on the Z axis when bed leveling is active.

So this would have no useful effect.

A solution is still needed to prevent MIN_SOFTWARE_ENDSTOPS from affecting probing moves when prepare_move_to_destination is being used to move the nozzle. And that is:

Set soft_endstops_enabled = false in do_blocking_move_to and restore its prior value afterward.

  void do_blocking_move_to() {
    const bool old_soft_endstops_enabled = soft_endstops_enabled;
    soft_endstops_enabled = false;
    . . .
    soft_endstops_enabled = old_soft_endstops_enabled;
    . . .
  }

Closer examination shows that do_blocking_move_to is not using prepare_move_to_destination for downward moves. So no patch is needed.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

W8KDB picture W8KDB  路  4Comments

heming3501 picture heming3501  路  4Comments

spanner888 picture spanner888  路  4Comments

ahsnuet09 picture ahsnuet09  路  3Comments

Matts-Hub picture Matts-Hub  路  3Comments