j-be / AutoBim

A bed tramming utility for OctoPrint using ABL
Other
29 stars 3 forks source link

[FR] LEVEL_CORNERS_USE_PROBE #3

Closed Guilouz closed 2 years ago

Guilouz commented 3 years ago

What do you think about this :

Add a option to level the bed corners using a probe. Instead of using the nozzle to paper and ajust the screws, it will probe the first corner (or the center) and save the z position. Then will go to the next corner to check if is within tolerance range. If is in tolerance, will go to next corner. If is not, will leave the probe deployed waiting the user to raise the bed until the probe is trigered. When all corners are within tolerance, will present an option to execute bed leveling.

This is how the option #define LEVEL_CORNERS_USE_PROBE works in Marlin.

Just a button to run this functionnality like when clicking on 'Level Corner' on printer's screen when this option is enabled in Marlin.

j-be commented 3 years ago

Thank you very much for pointing my attention to that. I honestly didn't think Marlin does it that differently, than the video link in README shows. So I never checked what it actually does. Interesting approach...

I'm not sure if this all is possible purely via GCode, especially the "detect if probe triggers" part. Do you have any insight on that? Could you maybe try it out? If not, that would mean you need to interact with the plugin more, as it cannot automatically move to next corner, as it doesn't know when. That would be a no-go for me - I want to be able to do everything on the printer without interacting with OctoPrint.

On the bright side: It would remove the need for M117, as one can visually see when the probe triggers, so that would improve support on those sh***y new Creality LCDs, which would be great.

I hope I find some to look into it this weekend. In any case (purely by GCode or not), I'd be happy to add it as alternative approach if I get it to work somehow, and, if it turns out to be more user-freindly, faster, or more accurate, even make it the default.

Guilouz commented 3 years ago

Yes there is no GCode for that (like G35 and Tramming Assistant who is different), it's hard coded.

If _LEVEL_CORNERS_USEPROBE is disabled : When go in Level Corner on LCD screen, you can choose each corners to use paper to adjust them manually

If _LEVEL_CORNERS_USEPROBE is enabled : When go in Level Corner on LCD screen, the process is running. It's very precise and very practical because you just have to raise the bed until the pin of the bltouch is retracted.

This is a part of the code in Marlin :

if ENABLED(LEVEL_CORNERS_USE_PROBE)

define VALIDATE_POINT(X, Y, STR) static_assert(Probe::build_time::can_reach((X), (Y)), \

"LEVEL_CORNERS_INSET_LFRB " STR " inset is not reachable with the default NOZZLE_TO_PROBE offset and PROBING_MARGIN.")

VALIDATE_POINT(lf.x, Y_CENTER, "left"); VALIDATE_POINT(X_CENTER, lf.y, "front"); VALIDATE_POINT(rb.x, Y_CENTER, "right"); VALIDATE_POINT(X_CENTER, rb.y, "back");

ifndef PAGE_CONTAINS

#define PAGE_CONTAINS(...) true

endif

void _lcd_draw_probing() { if (!ui.should_draw()) return;

TERN_(HAS_MARLINUI_U8GLIB, ui.set_font(FONT_MENU)); // Set up the font for extra info

MenuItem_static::draw(0, GET_TEXT(MSG_PROBING_MESH), SS_INVERT); // "Probing Mesh" heading

uint8_t cy = TERN(TFT_COLOR_UI, 3, LCD_HEIGHT - 1), y = LCD_ROW_Y(cy);

// Display # of good points found vs total needed
if (PAGE_CONTAINS(y - (MENU_FONT_HEIGHT), y)) {
  SETCURSOR(TERN(TFT_COLOR_UI, 2, 0), cy);
  lcd_put_u8str_P(GET_TEXT(MSG_LEVEL_CORNERS_GOOD_POINTS));
  IF_ENABLED(TFT_COLOR_UI, lcd_moveto(12, cy));
  lcd_put_u8str(GOOD_POINTS_TO_STR(good_points));
  lcd_put_wchar('/');
  lcd_put_u8str(GOOD_POINTS_TO_STR(nr_edge_points));
}

--cy;
y -= MENU_FONT_HEIGHT;

// Display the Last Z value
if (PAGE_CONTAINS(y - (MENU_FONT_HEIGHT), y)) {
  SETCURSOR(TERN(TFT_COLOR_UI, 2, 0), cy);
  lcd_put_u8str_P(GET_TEXT(MSG_LEVEL_CORNERS_LAST_Z));
  IF_ENABLED(TFT_COLOR_UI, lcd_moveto(12, 2));
  lcd_put_u8str(LAST_Z_TO_STR(last_z));
}

}

void _lcd_draw_raise() { if (!ui.should_draw()) return; MenuItem_confirm::select_screen( GET_TEXT(MSG_BUTTON_DONE), GET_TEXT(MSG_BUTTON_SKIP) , []{ corner_probing_done = true; wait_for_probe = false; } , []{ wait_for_probe = false; } , GET_TEXT(MSG_LEVEL_CORNERS_RAISE) , (const char*)nullptr, NUL_STR ); }

void _lcd_draw_level_prompt() { if (!ui.should_draw()) return; MenuItem_confirm::confirm_screen( []{ queue.inject_P(TERN(HAS_LEVELING, PSTR("G29N"), G28_STR)); ui.return_to_status(); } , []{ ui.goto_previous_screen_no_defer(); } , GET_TEXT(MSG_LEVEL_CORNERS_IN_RANGE) , (const char*)nullptr, PSTR("?") ); }

bool _lcd_level_bed_corners_probe(bool verify=false) { if (verify) do_blocking_move_to_z(current_position.z + LEVEL_CORNERS_ZHOP); // do clearance if needed TERN(BLTOUCH_SLOW_MODE, bltouch.deploy()); // Deploy in LOW SPEED MODE on every probe action do_blocking_move_to_z(last_z - LEVEL_CORNERS_PROBE_TOLERANCE, MMM_TO_MMS(Z_PROBE_SPEED_SLOW)); // Move down to lower tolerance if (TEST(endstops.trigger_state(), TERN(Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN, Z_MIN, Z_MIN_PROBE))) { // check if probe triggered endstops.hit_on_purpose(); set_current_from_steppers_for_axis(Z_AXIS); sync_planposition(); TERN(BLTOUCH_SLOW_MODE, bltouch.stow()); // Stow in LOW SPEED MODE on every trigger // Triggered outside tolerance range? if (ABS(current_position.z - last_z) > LEVEL_CORNERS_PROBE_TOLERANCE) { last_z = current_position.z; // Above tolerance. Set a new Z for subsequent corners. good_points = 0; // ...and start over } return true; // probe triggered } do_blocking_move_to_z(last_z); // go back to tolerance middle point before raise return false; // probe not triggered }

bool _lcd_level_bed_corners_raise() { bool probe_triggered = false; corner_probing_done = false; wait_for_probe = true; ui.goto_screen(_lcd_draw_raise); // show raise screen ui.set_selection(true); while (wait_for_probe && !probe_triggered) { // loop while waiting to bed raise and probe trigger probe_triggered = PROBE_TRIGGERED(); if (probe_triggered) { endstops.hit_onpurpose(); TERN(LEVEL_CORNERS_AUDIOFEEDBACK, ui.buzz(200, 600)); } idle(); } TERN(BLTOUCH_SLOW_MODE, bltouch.stow()); ui.goto_screen(_lcd_draw_probing); return (probe_triggered); }

void _lcd_test_corners() { bed_corner = TERN(LEVEL_CENTER_TOO, center_index, 0); last_z = LEVEL_CORNERS_HEIGHT; endstops.enable_z_probe(true); good_points = 0; ui.goto_screen(_lcd_draw_probing); do { ui.refresh(LCDVIEW_REDRAW_NOW); _lcd_draw_probing(); // update screen with # of good points do_blocking_move_to_z(current_position.z + LEVEL_CORNERS_Z_HOP); // clearance

  _lcd_level_bed_corners_get_next_position();         // Select next corner coordinates
  current_position -= probe.offset_xy;                // Account for probe offsets
  do_blocking_move_to_xy(current_position);           // Goto corner

  if (!_lcd_level_bed_corners_probe()) {              // Probe down to tolerance
    if (_lcd_level_bed_corners_raise()) {             // Prompt user to raise bed if needed
      #if ENABLED(LEVEL_CORNERS_VERIFY_RAISED)        // Verify
        while (!_lcd_level_bed_corners_probe(true)) { // Loop while corner verified
          if (!_lcd_level_bed_corners_raise()) {      // Prompt user to raise bed if needed
            if (corner_probing_done) return;          // Done was selected
            break;                                    // Skip was selected
          }
        }
      #endif
    }
    else if (corner_probing_done)                     // Done was selected
      return;
  }

  if (bed_corner != center_index) good_points++; // ignore center
  if (++bed_corner > 3) bed_corner = 0;

} while (good_points < nr_edge_points); // loop until all points within tolerance

ui.goto_screen(_lcd_draw_level_prompt); // prompt for bed leveling
ui.set_selection(true);

}

else // !LEVEL_CORNERS_USE_PROBE

static inline void _lcd_goto_next_corner() { line_to_z(LEVEL_CORNERS_Z_HOP);

// Select next corner coordinates
_lcd_level_bed_corners_get_next_position();

line_to_current_position(manual_feedrate_mm_s.x);
line_to_z(LEVEL_CORNERS_HEIGHT);
if (++bed_corner >= available_points) bed_corner = 0;

}

endif // !LEVEL_CORNERS_USE_PROBE

j-be commented 3 years ago

Ok, so I all I can do is:

Any suggestions on what ??? should look like? Is there anything (anything at all) in OctoPrint's Terminal when the probe retracts? I cannot currently check...

If not, dialog on OctoPrint maybe? Hardcoded timeout (i.e. just wait 5 seconds, how long can it take)?

Guilouz commented 3 years ago

if ENABLED(LEVEL_BED_CORNERS)

define LEVEL_CORNERS_INSET_LFRB { 40, 40, 40, 40 } // (mm) Left, Front, Right, Back insets

define LEVEL_CORNERS_HEIGHT 0.0 // (mm) Z height of nozzle at leveling points

define LEVEL_CORNERS_Z_HOP 4.0 // (mm) Z height of nozzle between leveling points

//#define LEVEL_CENTER_TOO // Move to the center after the last corner

define LEVEL_CORNERS_USE_PROBE

if ENABLED(LEVEL_CORNERS_USE_PROBE)

#define LEVEL_CORNERS_PROBE_TOLERANCE 0.1
#define LEVEL_CORNERS_VERIFY_RAISED   // After adjustment triggers the probe, re-probe to verify
//#define LEVEL_CORNERS_AUDIO_FEEDBACK

endif

/**

In fact the process probe the 4 points first (or 5 if LEVEL_CENTER_TOO is enabled), it keeps the highest value of them to adjust others in tolerance defined by LEVEL_CORNERS_PROBE_TOLERANCE. If tolerance is good it goes to the next point if not it ask to user to move up the corner of the bed until the probe retracts or to skip this point, and it can also do another probe to see if tolerance is good when LEVEL_CORNERS_VERIFY_RAISED is enabled

The goal is to have all 4 corners within the defined tolerance.

There is no info in Terminal during the process

Here a video of the process : https://www.youtube.com/watch?v=FMbsn1hwxnU

j-be commented 3 years ago

I'm not sure anymore I understand what you are getting at.

If you are just telling me the feature exists: Understood, I like the approach they are using. I already recommend to check the feature out as one of the first thing in README - I just never did, because it doesn't seem to work on Marlin 2.0.7.2 and I'd rather not switch to bugfix.

If you are just telling me to replicate the feature in my plugin: I would, but I don't think it is possible. In OctoPrint, I only can communicate with the printer using GCodes as far as I know. I can replicate everything up until this point (i.e. second 40 of your video where the user needs to turn the knob). But in order to do so I need to use M401 - Deploy Probe (seems to be the only way to deploy the probe without moving the printhead) - and if the probe is triggered after a M401 it seems to go into error state. So I do not consider that to by an option. And even if it would be fine, I get no response on console, so I'm stuck there.

Of course Marlin can easily do it in code: it is nothing more than a G30 without Z axis movement. If you know a way to replicate the behavior using only GCodes let me know, and I am happy to implement it.

On a different note: Please stop copy and pasting hunks of codes in comments. Try to link it - you can even highlight code hunks using link parameters like e.g. https://github.com/MarlinFirmware/Configurations/blob/62338c884318e91c4fc139402dfbb6ccc1ccfa46/config/default/Configuration.h#L1508-L1521 (notice the L1508-1521 at the end of the link). That makes sure I can more easily read through it as I have syntax highlighting and all that sweet stuff. It also allows me to more easily check out the code in VSCode because I know where to find it.

If you absolutely must copy-and-paste it, please make sure to properly escape it using backticks as described here.

j-be commented 2 years ago

Closing due to inactivity.