MarlinFirmware / Marlin

Marlin is an optimized firmware for RepRap 3D printers based on the Arduino platform. Many commercial 3D printers come with Marlin installed. Check with your vendor if you need source code for your specific machine.
https://marlinfw.org
GNU General Public License v3.0
16.3k stars 19.25k forks source link

[FR] Adaptive Mesh Leveling Marlin Cura - Workaround #26204

Open KhalidKhattak opened 1 year ago

KhalidKhattak commented 1 year ago

Is your feature request related to a problem? Please describe.

I was able to have Adaptive mesh levelling working in Cura with Marlin Firmware. Details are below, however i need someone to help me addition of Purge line near the bounding box. I have very little experience in Python Coding. Following is the workaround for adaptive mesh bed levelling: Adaptive Mesh Levelling Cura Marlin Firmware This is a tested python script to be used in Cura for Adaptive Bed Mesh levelling in Marlin Firmware 3D printers. This script get the bounding box of items on the Cura Bed and apply the mesh bed levelling with offset of 6mm. The G29 must be present in Start Gcode portion of Cura. This G29 is replaced by the G29 LFRB with values of the calculated bounding box. This can be changed in by Editing the python file. a- copy the the attached Python file and place in in Script folder of Cura. C:\Users\Administrator\AppData\Roaming\cura\5.4\scripts b- In your Start Gcode G29 must be placed after G28. c- In Cura MENU select Extensions---Post Processing---Modify Gcode and then select from Drop Down Menu the script with name Leveling Mesh Optimizer , the spacing value 10mm doesnt have any effect and reserve for future use. d- Now add your parts to be 3d printed and save the file... In the file you will find G29 L15.275 R190.000 F15.275 B180.000 the values infront of LRFB are calculated bounding box with 6mm skirt offset.

Are you looking for hardware support?

No response

Describe the feature you want

   #Copy the following script in a text file with the name of LevelingMeshOptimizer.py

`import re

from ..Script import Script

class LevelingMeshOptimizer(Script): def getSettingDataString(self): return """{ "name": "Leveling Mesh Optimizer", "key": "LevelingMeshOptimizer", "metadata": {}, "version": 2, "settings": { "spacing": { "label": "Spacing", "description": "How far apart to space the probe points within the mesh", "unit": "mm", "type": "float", "default_value": 10 } } }"""

##  Calculates and fills in the bounds of the first layer.
#   \param data A list of lines of GCODE representing the entire print.
#   \return A similar list, with the bounds of the mesh filled in.
def execute(self, data: [str]) -> [str]:
    _DATA_START_GCODE = 1
    _DATA_LAYER_0 = 2

    # Calculate bounds of first layer
    bounds = self.findBounds(data[_DATA_LAYER_0])

    # Fill in bounds in start GCODE
    data[_DATA_START_GCODE] = self.fillBounds(data[_DATA_START_GCODE], bounds)

    return data

##  Finds the minimum and maximum X and Y coordinates in a GCODE layer.
#   \param data A block of GCODE representing the layer.
#   \return A dict such that [X|Y][min|max] resolves to a float
def findBounds(self, data: str) -> {str: {str: float}}:
    bounds = {
        "X": {"min": float("inf"), "max": float("-inf")},
        "Y": {"min": float("inf"), "max": float("-inf")},
    }

    for line in data.split("\n"):
        # Get coordinates on this line
        for match in re.findall(r"([XY])([\d.]+)\s", line):
            # Get axis letter
            axis = match[0]

            # Skip axes we don't care about
            if axis not in bounds:
                continue

            # Parse parameter value
            value = float(match[1])

            # Update bounds
            bounds[axis]["min"] = min(bounds[axis]["min"], value+6)
            bounds[axis]["max"] = max(bounds[axis]["max"], value+6)

    return bounds

##  Replaces the G29 command in the start GCODE so that the bounds are filled in.
#   \param data The entire start GCODE block.
#   \return The same GCODE but with the bounds of the mesh filled in.
def fillBounds(self, data: str, bounds: {str: {str: float}}) -> str:
    # Fill in the level command template
    # new_cmd = "G29 L%.3f R%.3f F%.3f B%.3f \n G0 X1 Y1; Leveling mesh defined by LevelingMeshOptimizer" % (
    new_cmd = "G29 L%.3f R%.3f F%.3f B%.3f \n G0 X1 Y1; Leveling mesh defined by LevelingMeshOptimizer" % (
       bounds["X"]["min"], min([190,bounds["X"]["max"]]),
        bounds["Y"]["min"], min([180,bounds["Y"]["max"]]),

)

    # Replace G29 command in GCODE
    return re.sub(r"^G29 .*$", new_cmd, data, flags=re.MULTILINE)`

Additional context

No response

KhalidKhattak commented 1 year ago

https://www.youtube.com/watch?v=QksjSpTgaGU

KhalidKhattak commented 1 year ago

https://github.com/KhalidKhattak/Adaptive-Mesh-Levelling-Cura