Traumflug / Teacup_Firmware

Firmware for RepRap and other 3D printers
http://forums.reprap.org/read.php?147
GNU General Public License v2.0
312 stars 199 forks source link

Dynamic bed leveling #299

Closed phord closed 6 years ago

phord commented 6 years ago

After some discussion on #288 (and after many years of thinking "it should be easy"), I've implemented dynamic bed leveling based on 3-point bed plane registration. It works nicely in my tests so far. I pushed the basic change to the bed-leveling branch. It needs a little tidying up, but the basic functionality is there. Just add this to your printer.h to try it:

#define BED_LEVELING

Note, this is not automatic z-probe sampling. It's a somewhat manual process. Here's what you do:

  1. Start with a bed that's not level
  2. Home the printer's axes (important)
  3. Raise or lower the Z position using G1 commands until it's just touching the bed
  4. Send a registration command: G29 S1
  5. Move to another location on the bed, some distance from the first point and repeat steps 3 and 4
  6. Move to a third location on the bed and repeat the registration

After three points are registered the leveling will be active. You can save the three points in a gcode script to be entered again in the future. Use G29 S0 to see the registration status.

G29 S0
Bed leveling status: active (3) positions registered
  1: G29 S1 X20.000 Y20.000 Z-0.300
  2: G29 S1 X220.000 Y120.000 Z-1.700
  3: G29 S1 X120.000 Y220.000 Z-0.700
ok

It's no good to register three colinear points. Make sure the three points you choose are not in a straight line. The idea is to make a big triangle on your print bed. A good starting point maybe is (20,20), (150, 80), and (80, 150).

This three-point leveling works by assuming your bed is actually flat, even if it's not level. If your bed is warped, this method won't work for you. We'll need to implement mesh-mapping for that.

Traumflug commented 6 years ago

Nice work!

To avoid this gets lost, it should get forwarded to experimental / master. If needed, with an additional switch in Configtool, distributed to all printer.h templates and with the above text copied into the RepRap wiki.

Yes, some additional work, but having features available to everybody is the point of open source, isn't it?

phord commented 6 years ago

@Traumflug Yes, that's my next step. I'll finish it up this weekend.

phord commented 6 years ago

Some of the changes for this were tiny and I didn't want to crowd them inside #ifdefs. So even without this feature enabled the change costs 110 bytes of Program and 48 bytes of Data.

Before:

ATmega sizes               '168   '328(P)   '644(P)     '1280
Program:  22058 bytes      154%       72%       35%       18%
   Data:   1267 bytes      124%       62%       31%       16%
 EEPROM:     32 bytes        4%        2%        2%        1%

After:

ATmega sizes               '168   '328(P)   '644(P)     '1280
Program:  22168 bytes      155%       73%       35%       18%
   Data:   1315 bytes      129%       65%       33%       17%
 EEPROM:     32 bytes        4%        2%        2%        1%
phord commented 6 years ago

Didn't push to experimental yet. I noticed a bug causes bad Z-movement when resetting the bed leveling to new values. It's bad for beds.

phord commented 6 years ago

This is now on experimental.

I simplified the operational part of this. All of the position structures which are in um reflect the "logical" position on the printer. The ones which are in steps reflect the "actual" position on the printer. When converting from um to steps, we apply the desired bed-leveling-offset at the given position to get a correct z-value in steps. Similarly when converting from steps to um, we subtract the same offset.

One weird case is in dda_new_startposition(). We may want to set the startposition as the "actual" position if we are homing the Z-axis, but we want to set the "logical" position in other cases, such as E92. Now it takes a flag to decide which action to take.