Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Manual bed leveling + mesh bed leveling #1619

Merged

Conversation

epatel
Copy link
Contributor

@epatel epatel commented Mar 16, 2015

Here is a manual way to configure a bed leveling combined with a bed level solution using a mesh.
I happend to buy a non-finished RigidBot BIG which was not too great, after shipping and been misshandled by the previous owner. The structure was solid though and I have re-build most of it using a RAMPS 1.4 board + 128x64 LCD board. But the bed wasn't flat, I even tried to use a sheet of glas and compensate with that.

I have previously experimented to add an option in the menu for doing a bed leveling without servos etc. This on a smaller Huxley. So I added that and I started to experiment with the GRID auto bed leveling in Marlin. But after a while I started to understand that the bed leveling in Marlin is only based on a plane which still require a flat bed. Not enough for this big non-flat bed. The GRID wasn't using a mesh. So I built that, a mesh based bed leveling. One obstacle I realized was long lines needs to be split on mesh boundaries. I wrote most code in a "simulator" to get the logic right and have tested it all day. The mesh calculations are basically a bi-linear calculation from the mesh edges, maybe not perfect.

Enable in Configuration.h, both MANUAL_BED_LEVELING and MESH_BED_LEVELING. I have separated them so one might use them for other things in the future (maybe?).

The bed level option is added last in the Prepare menu. When selecting it the hotend will travel to all points and one use the encoder to move it up/down. Move it down until the usual paper thickness from the bed and press the encoder to "enter" that value, keep doing that until all points have been entered. The mesh can be saved in the EEPROM so storing them is good. A G28 homing will show if the mesh is active or not. If it does not travel to the first measure point (for sync position with mesh) the mesh is not active.

This is what I get when measuring the bed I have (using 5x5 points) Pretty bad bed huh?

2.00  2.10  2.10  2.05  2.00 
2.25  2.25  2.24  2.20  2.15 
2.35  2.34  2.40  2.35  2.35 
2.05  2.15  2.25  2.25  2.25 
1.75  1.95  2.15  2.15  2.15 

But with this method I have been able to print pretty much all over the bed. The bed is BIG, at least 360x290 print area with some to spare. The width of the reptiles print is over 200mm and without this it would have been impossible.

img_2432
img_2434

This image explain the bi-linear calculation pretty good. (from http://www.dspguide.com/ch23/7.htm)

bilinear

#if defined(MESH_BED_LEVELING)
EEPROM_WRITE_VAR(i, mbl.active);
EEPROM_WRITE_VAR(i, mbl.z_values);
#endif // MESH_BED_LEVELING
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When we change the EEPROM layout we must always write something. If the option is disabled then you should write reasonable default values in the same place where you would have written the real values. You should also bump the EEPROM version number up by 1.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, ok I see now. Though I see some other options do not do that, but most do. Maybe one should add a length check when reading to read defaults if storage length has changed?
@thinkyhead would that be an improvement? adding a length check?

@thinkyhead
Copy link
Member

This concept has been discussed somewhat. The thing is, it's not a good idea to curve the whole object to compensate for an uneven bed. Instead, it might be better to compensate by extruding more material where the bed is lower, and less where the bed is higher, and gradually (over the first mm or so) reduce the compensation (whether by extrusion or following a mesh) to a point where it is completely flat (so you're left only with global planar compensation). In this way the object may have a slightly warped bottom, but the rest of the model will be nice and flat.

@emartinez167
Copy link
Contributor

Wouldn't it make more sense to print a removable variable height raft like
the ones already used to prevent warping to compensate for the curved bed
and then print the object on top of it?
On Mon, 16 Mar 2015 at 13:40 Scott Lahteine notifications@github.com
wrote:

This concept has been discussed somewhat. The thing is, it's not a good
idea to curve the whole object to compensate for an uneven bed. Instead, it
might be better to compensate by extruding more material where the bed is
lower, and less where the bed is higher, and gradually (over the first mm
or so) reduce the compensation (whether by extrusion or following a mesh)
to a point where it is completely flat. In this way the object may have a
slightly warped bottom, but the rest of the model will be nice and flat.


Reply to this email directly or view it on GitHub
#1619 (comment)
.

@thinkyhead
Copy link
Member

@emartinez167 I'm inclined to prefer the tried and true simplest methods too. While it's obviously possible to add this kind of software-based compensation, truly your bed should not be so warped that it should be required. And if it is, then it might be better to fix the bed than to rely on a software solution. Adhesion will not be optimal with an uneven bed, regardless of compensation.

@alexborro
Copy link
Contributor

@epatel Your idea is Awesome!! I'm thinking something similar for months, but could not have any idea how to interpolate the lines between probed points.

But what @thinkyhead came up with is important, we cannot apply this compensation for the hole print; otherwise the print top surface will be curved.

I have tried extruding more material on lower spots and it works pretty good!!!

What if we tried that: Using the traditional Bed Leveling to compensate a skewed bed and your algorithm to extrude more material in lower spots??

Cheers.

Alex.

@nophead
Copy link
Contributor

nophead commented Mar 16, 2015

If you are printing lots of small objects then it is better to compensate
all the layers so each object is close to correct top and bottom. If you are
printing one large object it is perhaps better to just compensate the
bottom layers, but you get a distorted object anyway. If you want to print
accurate large objects you need a flat bed.

On 16 March 2015 at 13:30, alexborro notifications@github.com wrote:

@epatel https://github.com/epatel Your idea is Awesome!! I'm thinking
something similar for months, but could not have any idea how to
interpolate the lines between probed points.

But what @thinkyhead https://github.com/thinkyhead came up with is
important, we cannot apply this compensation for the hole print; otherwise
the print top surface will be curved.

I have tried extruding more material on lower spots and it works pretty
good!!!

What if we tried that: Using the traditional Bed Leveling to compensate a
skewed bed and your algorithm to extrude more material in lower spots??

Cheers.

Alex.

Reply to this email directly or view it on GitHub
#1619 (comment)
.

@maverikou
Copy link
Contributor

This sounds exactly like what the non-linear bed leveling code does in PR #1586.

@epatel
Copy link
Contributor Author

epatel commented Mar 16, 2015

I am happy to see so many comments! I imagined this could be a little off the chart :)

I actually did some thinking before implementing this. But for me I do not print mission critical objects and I think the normal warping that occur has a much larger effect than this. As a measurement, because the size of the bed does not came through in the pics above, the worst diff on the plate is 2.40-1.75=0.65 which sounds pretty bad. Very difficult to print with that, but it is really an error less than 0.325% as the distance between the points its over 200 mm.

@thinkyhead @emartinez167 Interesting ideas. Not sure where that solution should live, rafts etc? a slicer? guess one need to analyze first layer to place the raft in the right place, or make a raft over the whole bed (which in my case would take a considerate time). About adhesion, I included the images to show that I actually got pretty good adhesion (considering the circumstances). The 12 reptiles has a skirt around 20 cm wide and the 5 40x10 calibration parts a skirt about 30 cm wide and adhesion seem to be "enough", this with a 0.25 layer height. I am happy! :)

@nophead Yes it all depends on how accurate one want the objects. I totally agree that a flat bed is better!

@maverikou Cool didn't know that! :) But I don't see that you split the lines if they cross a grid boundary? In my code I do it in the mesh_plan_buffer_line(). Also need to look into how you interpolate, I believe there are better ways than the bi-linear calculations I do. 3D splines would be best, but... :-S not this week.

I will try to write up some instructions and demos how it works and should be used.

I am preparing a ~20h print. Will maybe try that this weekend. Will be very interesting. I am hopeful :)

@thinkyhead
Copy link
Member

@epatel The idea of compensating just during the first few layers is pretty sound, and the math is straightforward. You just start by applying compensation at 100% and reduce it by 10% each layer, then at 0% you turn off compensation and go back to the normal planner. The compensation could be applied by increasing the flow, and/or by adjusting the Z position, depending on how extreme it is. For some objects and bed surfaces, a raft may always be desirable, but that's a slicer option. Bed compensation like this will also improve the experience with rafts, if they are used.

@epatel
Copy link
Contributor Author

epatel commented Mar 17, 2015

@thinkyhead Ah, think I understand. Partly Marlin, partly slicer. Maybe need some output to display/serial about how many layers are needed before compensation has been reduced to 0 (and some way to identify when a new layer ends/begins, guess there can be something like that already in Marlin).

@thinkyhead
Copy link
Member

@epatel Yeah, you're right that counting layers isn't the best way. Better to just reduce from 100% down to 0% over something like 0.6mm.

@boelle
Copy link
Contributor

boelle commented Mar 19, 2015

i would just replace the bed with a perfect flat one

also how much code does this take up? i mean @ErikZalm said that the core of marlin should be able to fit on a 644 based system...

i think the ultimaker was mentioned....

@epatel
Copy link
Contributor Author

epatel commented Mar 19, 2015

@boelle Not enabled it does not add anything. But the full implementation of this looks to counts in at 6442 bytes. I am also reworking the border split function to be a little bit shorter (looks like it will shave off 416 bytes, need to test that it works first). Only the mesh calculus, that I think also can be used somewhere in the AUTO_BED_LEVELING algorithm counts in at only 4506 bytes. Enabling ENABLE_AUTO_BED_LEVELING adds 27176 bytes, yes it does more things but it also adds quite some vector3d things etc.

The implementation I have here is only useful with a display. With a little work I think it could be used with a auto leveling procedure but I don't have that setup so hard for me to add and test.

Below are some different compiles to compare with.

Development plain
Sketch uses 55 332 bytes (21%) of program storage space. Maximum is 258 048 bytes.
Global variables use 3 020 bytes (36%) of dynamic memory, leaving 5 172 bytes for local variables. Maximum is 8 192 bytes

Development with ENABLE_AUTO_BED_LEVELING
Sketch uses 82 508 bytes (31%) of program storage space. Maximum is 258 048 bytes.
Global variables use 3 164 bytes (38%) of dynamic memory, leaving 5 028 bytes for local variables. Maximum is 8 192 bytes.

Mesh code DISABLED
Sketch uses 55 332 bytes (21%) of program storage space. Maximum is 258 048 bytes.
Global variables use 3 020 bytes (36%) of dynamic memory, leaving 5 172 bytes for local variables. Maximum is 8 192 bytes

Mesh code only Mesh enabled
Sketch uses 59 838 bytes (23%) of program storage space. Maximum is 258 048 bytes.
Global variables use 3 057 bytes (37%) of dynamic memory, leaving 5 135 bytes for local variables. Maximum is 8 192 bytes.

Mesh code Mesh + Display enabled (no LCD enabled though)
Sketch uses 59 838 bytes (23%) of program storage space. Maximum is 258 048 bytes.
Global variables use 3 057 bytes (37%) of dynamic memory, leaving 5 135 bytes for local variables. Maximum is 8 192 bytes.

Mesh code DISABLED + Display (enabled REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER)
Sketch uses 124 862 bytes (48%) of program storage space. Maximum is 258 048 bytes.
Global variables use 5 035 bytes (61%) of dynamic memory, leaving 3 157 bytes for local variables. Maximum is 8 192 bytes.

Mesh code Mesh + Display enabled (enabled REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER)
Sketch uses 131 304 bytes (50%) of program storage space. Maximum is 258 048 bytes.
Global variables use 5 075 bytes (61%) of dynamic memory, leaving 3 117 bytes for local variables. Maximum is 8 192 bytes

@alexborro
Copy link
Contributor

@epatel , do you have Skype? If yes, add me: alexborro
I think we can help each other developing this..

Cheers.

Alex.

@thinkyhead
Copy link
Member

I like this generally, especially as it's encapsulated in a class. I could see doing more of that throughout Marlin to group features together better.

@epatel
Copy link
Contributor Author

epatel commented Mar 21, 2015

Just added a G29 command to use this mesh leveling feature without a display.

G29 S0 will show the measured mesh points.
G29 S1 will initiate a mesh probing sequence. It will first travel to the first point and then wait there. Now one can move Z down with your preferred printer software until it touches the bed.
G29 S2 will store the Z position and travel to the next probe position. Repeat until done.

@boelle With this I think it's now possible to have mesh bed leveling even on a limited system as a 644.

I might mention that I have mounted an opto end for the Z axis so traveling though it doesn't strain anything extra.

@boelle
Copy link
Contributor

boelle commented Mar 21, 2015

@epatel oki, @thinkyhead is the main coder so i will give him the honour of hitting merge

@thinkyhead
Copy link
Member

I'm definitely feeling the need to write up a documentation page specifically for G29 since it has so many different methods now. If people read older comments and documentation of G29 online they are bound to get confused.

In the meantime, I should merge this and get it in for testing.

thinkyhead added a commit that referenced this pull request Mar 21, 2015
@thinkyhead thinkyhead merged commit 9b639b4 into MarlinFirmware:Development Mar 21, 2015
@lrpirlet
Copy link
Contributor

There is another aspect that I have never seen discussed yet, that give the same effect than the base note... I have a Prusa i3.
I have an issue with the bed to hot-end distance. The distance is independent from the position of the Y coordinate. The distance is proportional to the position of the X coordinate. I have integrated Roxy g29 code in my (old 1.0.0) firmware. Using 5 by 5 grid, it is quite clear that the distance between the hot-end and the bed is following a curve where the extreme points on the X axis are about 0.1 lower than the middle point on the X axle...
NO, the bed is flat. I turned the glass 90 degrees and I got the same pattern...
No, the smooth rods are NOT bended. I rotated both X rods, one at the time, in 3 steps of about 60 degrees... the pattern does NOT change...
Now, looking at the architecture of the machine, the hot-end, the extruder an the motor are all on the same side of the plane containing both rods... Yes there is a torque that changes the distance of the hot-end to the bed... I proved it using a pendulum (made of a length of wood) pinched in the extruder... In that configuration, the map generated shows a constant distance (well, I mean within the 6 sigma variation) for all 25 probed points...
The solution would be to have a balanced extruder/hot-end over the X axis. The workaround would be to have some software correction that could compensate that variable distance...

Would that "mesh bed leveling" code help???

P.S. without pendulum G29 code shows

20:50:22.839 : Bed Height Topography:
20:50:22.839 : +0.03416 +0.03191 +0.05216 +0.03691 --0.12084
20:50:22.839 : +0.01716 +0.04241 +0.05241 +0.01866 --0.15809
20:50:22.839 : +0.04591 +0.00991 +0.06291 +0.02641 --0.14759
20:50:22.855 : +0.01866 +0.05416 +0.04641 +0.01491 --0.16109
20:50:22.855 : +0.01791 +0.04991 +0.06341 +0.03091 --0.13959
20:50:22.855 : 
20:50:22.855 : planeNormal x: -0.00 y: 0.00 z: 1.00
20:50:22.855 : 
20:50:22.855 : Bed Level Correction Matrix:
20:50:22.855 : 1.000000 0.000000 0.000938
20:50:22.855 : 0.000000 1.000000 -0.000012
20:50:22.855 : -0.000938 0.000012 1.000000

WITH pendulum G29 code shows

21:07:50.335 : Bed Height Topography:
21:07:50.335 : +0.06647 +0.01847 +0.00422 --0.01903 --0.07703
21:07:50.351 : +0.06747 +0.02622 --0.00653 --0.02978 --0.08203
21:07:50.351 : +0.07897 +0.03747 +0.01272 --0.02728 --0.10928
21:07:50.351 : +0.08222 +0.03772 +0.00922 --0.02928 --0.10628
21:07:50.366 : +0.08447 +0.04222 +0.01297 --0.01778 --0.07653
21:07:50.366 : 
21:07:50.366 : planeNormal x: -0.00 y: -0.00 z: 1.00
21:07:50.366 : 
21:07:50.366 : Bed Level Correction Matrix:
21:07:50.366 : 1.000000 0.000000 0.001025
21:07:50.366 : 0.000000 1.000000 0.000066
21:07:50.366 : -0.001025 -0.000066 1.000000
21:07:55.686 : ok

@nophead
Copy link
Contributor

nophead commented Mar 23, 2015

If your carriage rotates around the X axis then you will also get a Y
offset at the nozzle tip. This is why I centred the weight over a
horizontal axis when I designed Mendel90, rather than following the herd to
having a vertical X axis, which is easier to print.

On 23 March 2015 at 21:22, lrpirlet notifications@github.com wrote:

There is another aspect that I have never seen discussed yet, that give
the same effect than the base note... I have a Prusa i3.
I have an issue with the bed to hot-end distance. The distance is
independent from the position of the Y coordinate. The distance is
proportional to the position of the X coordinate. I have integrated Roxy
g29 code in my (old 1.0.0) firmware. Using 5 by 5 grid, it is quite clear
that the distance between the hot-end and the bed is following a curve
where the extreme points on the X axis are about 0.1 lower than the middle
point on the X axle...
NO, the bed is flat. I turned the glass 90 degrees and I got the same
pattern...
No, the smooth rods are NOT bended. I rotated both X rods, one at the
time, in 3 steps of about 60 degrees... the pattern does NOT change...
Now, looking at the architecture of the machine, the hot-end, the extruder
an the motor are all on the same side of the plane containing both rods...
Yes there is a torque that changes the distance of the hot-end to the
bed... I proved it using a pendulum (made of a length of wood) pinched in
the extruder... In that configuration, the map generated shows a constant
distance (well, I mean within the 6 sigma variation) for all 25 probed
points...
The solution would be to have a balanced extruder/hot-end over the X axis.
The workaround would be to have some software correction that could
compensate that variable distance...

Would that "mesh bed leveling" code help???

P.S. without pendulum G29 code shows
20:50:22.839 : Bed Height Topography:
20:50:22.839 : +0.03416 +0.03191 +0.05216 +0.03691 --0.12084
20:50:22.839 : +0.01716 +0.04241 +0.05241 +0.01866 --0.15809
20:50:22.839 : +0.04591 +0.00991 +0.06291 +0.02641 --0.14759
20:50:22.855 : +0.01866 +0.05416 +0.04641 +0.01491 --0.16109
20:50:22.855 : +0.01791 +0.04991 +0.06341 +0.03091 --0.13959
20:50:22.855 :
20:50:22.855 : planeNormal x: -0.00 y: 0.00 z: 1.00
20:50:22.855 :
20:50:22.855 : Bed Level Correction Matrix:
20:50:22.855 : 1.000000 0.000000 0.000938
20:50:22.855 : 0.000000 1.000000 -0.000012
20:50:22.855 : -0.000938 0.000012 1.000000
WITH pendulum G29 code shows
21:07:50.335 : Bed Height Topography:
21:07:50.335 : +0.06647 +0.01847 +0.00422 --0.01903 --0.07703
21:07:50.351 : +0.06747 +0.02622 --0.00653 --0.02978 --0.08203
21:07:50.351 : +0.07897 +0.03747 +0.01272 --0.02728 --0.10928
21:07:50.351 : +0.08222 +0.03772 +0.00922 --0.02928 --0.10628
21:07:50.366 : +0.08447 +0.04222 +0.01297 --0.01778 --0.07653
21:07:50.366 :
21:07:50.366 : planeNormal x: -0.00 y: -0.00 z: 1.00
21:07:50.366 :
21:07:50.366 : Bed Level Correction Matrix:
21:07:50.366 : 1.000000 0.000000 0.001025
21:07:50.366 : 0.000000 1.000000 0.000066
21:07:50.366 : -0.001025 -0.000066 1.000000
21:07:55.686 : ok

Reply to this email directly or view it on GitHub
#1619 (comment)
.

@lrpirlet
Copy link
Contributor

I aggree with you.
However, I would like to be able to print several parts rather tahn using a small part of the bed. So the Y variation would be small...

Another consequence would be resonnance at some speed/patern leading to skipped motor steps ( the motor weight is well above the rotation point located somewhere in between the 2 rods.).

BTW, I was playing with the idea to desing an "horizontal" X carriage like in the prusa i2. I guess this would be a nice (funny) hybrid...
Thing is: I only can play during the W.E.

@epatel
Copy link
Contributor Author

epatel commented Mar 23, 2015

Yes, I think there are many weird effects that can be caused from the design of the printer too. i.e. the 8mm rods that are so common do actually bend when put to stress. I have an old original Sells Mendel which I have been experimenting on and the X axis rods definitely bend when the X carriage is in the middle and less at the ends. I have been using a dial gauge to measure this. Printing still works if I put down a 0.3 first layer. I'd like to remove this all together by either use 10mm rods or some aluminum profile.

If this mesh thing helps? Maybe. Hard to say. I'll try to write up some instructions when I get some free time.

I never got around to do the 20hour print this weekend. Needed to take care off some other private things first. Next weekend maybe.

This is what I want to print first http://www.thingiverse.com/thing:657156
..and this looks like a fun project too :) http://www.thingiverse.com/thing:450512
Bigger plate enables crazier projects :)

@thinkyhead
Copy link
Member

The mesh bed leveling would actually do some good things in the case of a truly flat bed but a situation where rods bend, or other stresses cause the carriage to shift. Hmm…

@shampine1
Copy link

I've got a printer that has a completely flat bed, but the gantry has some sag in it (no surprise for a 15" cube work area!). Adjusting the bed to minimize the motion error is pretty good, but not "less than half a layer" good. I think this would be just the thing to make it move properly!

There are two things that would be really nice to have on this function:
An offset dimension from the hotends to a proximity sensor
An automated probing function using a proximity sensor

If someone could point me at where this code lives, I could take a look to see if my feeble programming skills could be useful in addressing this.

@adamfilip
Copy link

Im testing out the manual mesh levelling. is there a way to enter the values into Marlin or via GCode prior to a print job. im trying to avoid it being saved via EEPROM

@epatel
Copy link
Contributor Author

epatel commented Dec 22, 2015

@adamfilip I think I added that in a later commit, setting the sample points manually.

See G29 S3 and G29 S4 here
https://github.com/epatel/Marlin/blob/75f9fb50c4002f6d4ba0345f5594cbac1fab1fa6/Documentation/MeshBedLeveling.md

Not sure they have made it to the release branch yet...here is the original commit
epatel@75f9fb5

You might need to run through a sample sequence (and/or save to EEPROM) to enable it.

@dushyantahuja
Copy link

First of all - thanks for the great feature - it works like a charm. Just wanted to check if there is a way to modify 1 point in the grid manually? I think, while leveling I left a little extra space between the extruder and the bed on one of the points. Is there some way I can simply change the value in the EEPROM directly.

@brainscan
Copy link

G29 S3 Xnn Ynn Zn.nn
There are more detailed instructions if you look in the wiki

Sent from my iPhone

On 25 Dec 2015, at 04:58, Dushyant Ahuja notifications@github.com wrote:

First of all - thanks for the great feature - it works like a charm. Just wanted to check if there is a way to modify 1 point in the grid manually? I think, while leveling I left a little extra space between the extruder and the bed on one of the points. Is there some way I can simply change the value in the EEPROM directly.


Reply to this email directly or view it on GitHub.

@adamfilip
Copy link

How do you know what X & Y each point is set-to?
If i wanted to choose alter specific point. I wouldnt know what XY location that point was at

A

@brainscan
Copy link

Either use G29 or M501 to show the mesh points and then alter the z value to whatever you want.

Sent from my iPhone

On 25 Dec 2015, at 18:32, adamfilip notifications@github.com wrote:

How do you know what X & Y each point is set too.?
If i wanted to choose alter specific point. I wouldnt know what XY location that point was at

A


Reply to this email directly or view it on GitHub.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.