Marlin is the most widely used open-source firmware in 3D printing. It powers millions of printers around the world — from the classic Ender-3 to high-end CoreXY machines — and has been maintained by an active community since 2011. If your printer is not running Klipper, it is almost certainly running Marlin.
This guide covers Marlin 2.x (current stable: 2.1.2.7) — the generational leap that added native 32-bit board support, a much cleaner code architecture, and features that simply did not exist in Marlin 1.x. You will see, step by step, how to configure it from scratch for any printer, no matter your experience level.
If you want to jump straight to a specific section, use the index below.
Configuring Marlin 2.x from scratch
The parameters in this guide are ordered as they appear in the Marlin configuration files. Follow the order and you will not miss anything important. If you need more detail on a specific feature, the full reference is available at marlin.3dwork.io.
- Configuring Marlin 2.x from scratch
- What is Marlin and why Marlin 2.x?
- Prepare your own Marlin to customise it
- Additional Marlin function tweaks
- Marlin logo (SHOW_BOOTSCREEN)
- Communication ports (SERIAL_PORT and SERIAL_PORT_2)
- Communication speed (BAUDRATE)
- Mainboard or electronics (MOTHERBOARD)
- Your machine name (CUSTOM_MACHINE_NAME)
- Number of extruders (EXTRUDERS)
- Filament diameter (DEFAULT_NOMINAL_FILAMENT_DIA)
- Prusa multi-material kit (PRUSA_MMU2)
- Temperature sensors (TEMP_SENSORS)
- Temperature limiters (MINTEMP & MAXTEMP)
- PID Tuning (extruders)
- PID Bed Tuning (heated bed)
- Cold extrusion (PREVENT_COLD_EXTRUSION)
- Extrusion length (PREVENT_LENGTHY_EXTRUDE)
- Thermal protection (THERMAL_PROTECTION)
- Mechanical parameters (CoreXY kinematics)
- Available endstops (USE_XMIN_PLUG & USE_XMAX_PLUG)
- Endstop logic (ENDSTOP_INVERTING)
- Configuring drivers (DRIVER_TYPE)
- Steps configuration (DEFAULT_AXIS_STEPS_PER_UNIT)
- Auto-bed levelling probe position (NOZZLE_TO_PROBE_OFFSET)
- Levelling travel speed (XY_PROBE_SPEED)
- Invert motor direction (INVERT_X_DIR)
- Print volume (X_BED_SIZE & Y_BED_SIZE)
- Movement limits (MIN_POS & MAX_POS)
- Movement restrictions (MIN_SOFTWARE_ENDSTOPS)
- EEPROM storage (EEPROM_SETTINGS)
- ABS/PLA preheat (PREHEAT)
- Menu language (LCD_LANGUAGE)
- SD Card support (SDSUPPORT)
- Slim menus (SLIM_LCD_MENUS)
- Display type (LCD / Controller Selection)
- Bed levelling (BED_LEVELING)
- EXTRA: Useful Marlin tricks
- Final compilation of Marlin with VSCode + PlatformIO + Auto Build Marlin
- Uploading Marlin to your printer
- Final remarks
What is Marlin and why Marlin 2.x?

Marlin is an open-source firmware for FDM 3D printers, developed since 2011 from Erik van der Zalm’s original project. It controls every aspect of the printer: axis movement, temperatures, bed levelling, extrusion, screen… everything. It is the industry standard: Creality, Elegoo, Artillery, Sovol and most Chinese manufacturers use it as the base for their machines.
Marlin 2.x was the definitive generational leap. The key improvements over Marlin 1.x:
- Native 32-bit board support (STM32, LPC1768/LPC1769, SAM): modern boards like SKR, BTT Octopus and Creality 4.2.x require Marlin 2.x. Marlin 1.x is AVR-only (Mega 2560).
- Input Shaping (MPC/FTDI/ZV): software resonance compensation similar to Klipper, reducing ghosting at high print speeds.
- Model Predictive Control (MPC): more accurate and stable temperature control than traditional PID, especially useful for high-temperature hotends.
- ABL improvements: Unified Bed Leveling (UBL) with high-resolution mesh, Bilinear, and support for modern probes (BLTouch, CR Touch, inductive, capacitive).
- Filament Runout, Power Loss Recovery, Filament Width Sensor: reliability features that in 1.x were experimental or non-existent.
- Multi-extruder and colour mixing: improved support for multi-material toolheads.
Configuring Marlin only requires knowing your printer well (extruder type, thermistor, print volume, electronics) and the patience to edit the configuration files. You do not need to know how to program. The following sections cover the full process.
If you want to go deeper into what Marlin can do, we recommend our full Marlin guide at marlin.3dwork.io, with detailed documentation of every parameter and feature.
Prepare your own Marlin to customise it
In this guide we will explain the steps to generate your own Marlin for commercial printers, or for any printer with an official preconfiguration. You can also use it by downloading the latest stable version from the Marlin repository and customising it by hand, although it is normally advisable to start from a preconfiguration of a similar machine.
There are several options to obtain our Marlin firmware, ordered from fastest to most flexible:
- Official precompiled firmware — MarlinBuilds: the Marlin team itself publishes compiled binaries for more than 80 brands based on its official preconfigurations. The fastest option if your machine is among the supported ones.
- Using our Marlin Auto Builder with Marlin sources and preconfigurations: we automatically compile firmware for more than 100 manufacturers and 421 printer/electronics combinations, in English and Spanish. Check whether yours is included.
- Using Marlin sources and preconfigurations directly from GitHub: the most flexible method, and the only one that lets you customise the firmware with your own modifications. It also applies if your manufacturer has its own fork.
Official precompiled firmware — MarlinBuilds (recommended if your machine is supported)
Since 2024, the Marlin team itself publishes precompiled binaries for the vast majority of commercial printers in the official MarlinBuilds repository. These binaries are generated directly from the preconfigurations in the Configurations repository, guaranteeing that they match the official configuration of each machine 100%.
If your printer is among the supported ones, this is the fastest option: download the binary, copy it to the SD card and you are done. No compilation needed.
- Official repository: https://github.com/MarlinFirmware/MarlinBuilds
- More than 80 brands and hundreds of supported models (Creality, Prusa, Elegoo, Artillery, Sovol, Tevo, Geeetech, Two Trees, Qidi, Kingroon, etc.).
- To find your binary: navigate
builds/→ brand → model → download the.binor.hexfile suitable for your electronics. - Inside each model you will find subfolders with variants depending on the electronics or probes installed (for example, for an Ender-3 V2:
CrealityV422/,CrealityV427/,CrealityV427-BLTouch/…).
Important notice: MarlinBuilds binaries are generated from Marlin’s unmodified preconfigurations. If you have made changes to your machine (a different ABL probe, different driver, etc.) you will need to compile your own firmware with those changes, following the procedure in the next sections.
3Dwork automated procedure using Marlin sources and preconfigurations
We have built an automation that automatically compiles Marlin firmware for more than 100 manufacturers and 421 combinations of printers and electronics, using the official Marlin sources and preconfigurations. Firmwares are available in two languages: English (EN) and Spanish (ES), each with its own download link.
You can find the full list of supported machines, with a direct download link for each combination and language, in our build status document: BUILD_STATUS — Full list of firmwares compiled by 3Dwork.
The table below shows the list of supported machines. If you would like us to add more, you can contact us through our 3Dwork Spanish Telegram group or our English channel.
Manual procedure using Marlin sources and preconfigurations
This is the process we always recommend. Although it can be technically tricky at times, it gives you full control over your machine and over the firmware options, tuned to your taste.
The first thing you have to do is prepare the environment to compile the firmware (and edit it, obviously). Just three steps, so let’s get to it:
Downloading Marlin firmware
From your browser, go to Marlin’s official GitHub:
https://github.com/MarlinFirmware/Marlin
Once on the page, download the Marlin code as follows:


The next step, if you have a commercial printer, is to download the configuration presets from https://github.com/MarlinFirmware/Configurations following the same process as in the previous step.

Now that you have the Marlin files on your computer you need to unzip them. Ideally, do not place the Marlin folder deep inside many nested folders, and avoid symbols or accents in folder names, since they can cause compilation errors.
We will combine stable Marlin with our machine’s preconfiguration
- Open Windows File Explorer and navigate to the folder where you downloaded and unzipped the Marlin repository.
- Once there, open another file explorer window with the contents of the preconfigurations repository.
- You will find two Marlin preconfiguration files for your printer. In the example image we use an Ender 3 with the SKR MINI v2 preconfigurations (the folder to look for is highlighted in the blue box in the screenshot below):

- Copy the files inside the preconfiguration folder (red box in the previous screenshot) and paste them (replacing the existing ones) into the «…\Marlin» folder where you unzipped the Marlin repository.
Marlin is now ready to compile.
Installing the software required to edit and compile Marlin
The next step is to install the required software. Download and install the following programs:
- Python: https://www.python.org/downloads/ you can also download it from the Microsoft Store, which in some cases performs a cleaner install
- Git: https://git-scm.com/
- Visual Studio Code: https://code.visualstudio.com/ A pesar de que parezca que Python y Git no se usan en ningún paso, son requerimientos de Visual Studio Code para este tutorial
- Once both programs are installed, install the PlatformIO plugin in Visual Studio Code by following these steps:
- Click on the squares icon in the left-hand menu.
- In the search box, type «PlatformIO».
- Click the green Install button.

Compiling our Marlin
Once you have the Marlin files in place and the required software installed correctly, it is time to compile it to generate the file we will use on the printer:
- Once this is done, open Visual Studio Code, click on the two-documents icon in the left-hand menu, and then on the blue «Add Folder» button.

- Find the location of your Marlin repository and click Add:

We advise against placing your Marlin sources inside many nested directories, as it can cause issues.
Ideally, place it at the root of one of your drives, e.g. C:/Marlin.
- In Visual Studio Code, select the platformio.ini file in the Marlin workspace you just added.
- Editamos la línea «default_envs» y sustituimos » megaatmega2560 » por el adecuado para nuestra placa/impresora, haciendo scroll en el documento encontrarás diferentes placas diversas placas, localiza la tuya y sustituye «megaatmega2560» por la correspondiente

- Next, if you want to change the basic configuration of your printer (because you have modified it, or to improve some setting), expand the Marlin folder and the two configuration files will appear. You can find information about the basic Marlin options at this link in the official documentation, or explained in a more “approachable” way in this Marlin guide.

- Once the desired tweaks are done, click the compile button, located at the bottom left of the window and shaped like a tick «✓».

- Once the code has compiled, go to «…\Marlin\.pio\build\xxxx» where you will find a file called «firmware.bin» or similar, depending on the requirements of your electronics.
- Copy this file to the root of an empty SD card, or follow the appropriate procedure for your electronics.
- Eject the SD card from the computer.
- Power off the printer (disconnect USB and power if both are plugged in).
- Wait around 30 seconds.
- Insert the SD card with the new firmware.
- Power on the printer. After a few seconds you will see it installing the new firmware, and shortly after it will boot with your new Marlin installed.
Updating Marlin to a new version
Many users find it complicated to update their own compiled version to a new one. Here are some tips to make the process easier.
- Download the new Marlin version, as we explained: here we will download the new Marlin version either from the release link in its documentation or from its GitHub.

Download Marlin from the documentation

Download Marlin from GitHub. Make sure to select the correct branch in the top-left corner.
- Once downloaded and unzipped, add that folder to your VSC project alongside the previous version.

- Now that we have both directories in our project, we just need to use the built-in VSC compare tool to compare the Marlin configuration files.
- platformio.ini: the file where you will essentially find the env for your electronics.
- Marlin/configuration.h: the file where you normally enable features and configure the printer/electronics/extensions.
- Marlin/configuration_adv.h: similar to the previous one, but with certain advanced features.
- To compare two files, from the side panel with the project structure (Explorer), right-click on the file from the old version and select Select for Compare from the context menu.

- Then do the same with the file from the new version, this time choosing Compare with Selected. A new screen with the diff between them will appear.
- At the top of the screenshot below you will see the name and folder of the files being compared.
- In the middle you will see how changes are highlighted: the first block (red) shows what is not in the destination; the centre (red/green) shows changes on both sides — the one you normally use to spot tweaks; and the bottom (green) shows what is in the new file but not in the old one.

- Once all changes have been applied, just load the new project in PlatformIO as explained at the start of the guide and compile, fixing any errors that appear — they tend to be quite descriptive.
Final tips
- If you are going to update a printer and do not have the original Marlin files, and you have changed the configuration, we recommend running M503 from a terminal client like Pronterface and saving the output. These are the EEPROM values, very useful to set in your new firmware.
- Remember that, after flashing the firmware, it is advisable to load the factory EEPROM values. You can do it via terminal with M502 followed by M500, or from the screen in Marlin mode with Configuration/Restore followed by Configuration/Save EEPROM… along with M503, which lists the EEPROM values so you can make sure they are correct.
- En las placas actuales se genera un firmware.bin que se copia en la SD, en estos casos si el proceso de actualización se hizo de forma correcta este fichero queda renombrado a .CUR. Así que para comprobar si el proceso fue de forma correcta extrae la SD después de realizar el proceso de actualización y comprueba desde tu ordenador que el .BIN cambió a .CUR
- On other (typically older 8-bit) boards, the firmware is «burned» directly onto the board, so it must be connected via USB. In some cases USB programming can cause issues, so you can go to the location of the compiled binary (usually a .hex file in these cases) and upload it with tools specific to your printer. Slicers like PrusaSlicer or Cura can also do this step fairly easily.
Additional Marlin function tweaks
As we mentioned before, there are two main files that manage all the configuration of Marlin 2.0.x. Many more changes and modifications are possible, but they are not necessary for our current purpose (menu modifications, logos, etc.).
Comencemos a editar el archivo Configuration.h con el editor que hayamos escogido (en mi caso Sublime) y seguiremos por orden las opciones más comunes. Este archivo contiene las configuraciones principales de hardware, idiomas y controladores, así como las características y componentes más habituales de la impresora.
Active options (or those active by default) appear in white, and disabled ones in dark grey. To enable an option, remove the two «//» slashes in front of the parameter. To disable it, add them back. If you are a programmer, you will already be familiar with this approach.
If we leave any parameter out (there are countless printers), please mention it in the comments at the end of the article. We will keep expanding the guide little by little, making it useful to more users.
Marlin logo (SHOW_BOOTSCREEN)
This is the Marlin logo that appears when the firmware boots. It is active by default; we can disable it if we wish. It is not essential to configure Marlin 2, but disabling it can free up some memory if you are tight.
You can also use your own custom logo or image, but we will cover that at the end of this guide in the «Useful Marlin tricks» section.
// Show the Marlin bootscreen on startup. ** ENABLE FOR PRODUCTION **
#define SHOW_BOOTSCREEN
Communication ports (SERIAL_PORT and SERIAL_PORT_2)
These are the communication ports of the electronics. You should not modify the first one unless you have exotic electronics. I leave the second one disabled because I use an MKS Gen v1.4.
If your board were an SKR V1.4 or SKR V1.4 Turbo, you should enable SERIAL_PORT_2 and set it to -1 (as it is by default). For the SKR GTR V1.0, set SERIAL_PORT to -1 and SERIAL_PORT_2 to 3.
These are the boards I am most familiar with. For others, you will need to search the values online — it should not take you long to find them.
/**
* Select the serial port on the board to use for communication with the host.
* This allows the connection of wireless adapters (for instance) to non-default port pins.
* Serial port -1 is the USB emulated serial port, if available.
* Note: The first serial port (-1 or 0) will always be used by the Arduino bootloader.
*
* :[-1, 0, 1, 2, 3, 4, 5, 6, 7]
*/
#define SERIAL_PORT 0
/**
* Select a secondary serial port on the board to use for communication with the host.
* :[-1, 0, 1, 2, 3, 4, 5, 6, 7]
*/
//#define SERIAL_PORT_2 -1
Communication speed (BAUDRATE)
The speed at which the computer talks to the printer. The default is 250000, so we leave it as is.
If you have communication issues with the printer, you can lower this value to try to fix them.
/**
* This setting determines the communication speed of the printer.
*
* 250000 works in most cases, but you might try a lower speed if
* you commonly experience drop-outs during host printing.
* You may try up to 1000000 to speed up SD file transfer.
*
* :[2400, 9600, 19200, 38400, 57600, 115200, 250000, 500000, 1000000]
*/
#define BAUDRATE 250000
Mainboard or electronics (MOTHERBOARD)
A critical parameter. Here we select the electronics installed in the printer. Since there are many, we need to find ours and the value to put in.
You have a list of supported electronics in the «boards.h» file. You will find it at the following path inside the Marlin firmware: \Marlin\src\core\boards.h
In my case, my printer uses an MKS Gen v1.4. That is why I write «BOARD_MKS_GEN_13», as you can see in the example. Use the one that matches your board.
// Choose the name from boards.h that matches your setup
#ifndef MOTHERBOARD
#define MOTHERBOARD BOARD_MKS_GEN_13
#endif
Your machine name (CUSTOM_MACHINE_NAME)
This one is easy: the name you want for your printer. It comes disabled by default, hence the two “//” slashes before the #define.
Remove the two slashes and leave the configuration like this:
// Name displayed in the LCD "Ready" message and Info menu
#define CUSTOM_MACHINE_NAME "Pulsar X1 PRO"
Number of extruders (EXTRUDERS)
Here we configure the number of extruders on the printer. The default value is 1, since most printers only have one. If that is not your case, enter the correct number.
// This defines the number of extruders
// :[1, 2, 3, 4, 5, 6, 7, 8]
#define EXTRUDERS 1
Filament diameter (DEFAULT_NOMINAL_FILAMENT_DIA)
Here we select the filament diameter used by the printer. The default is 3.0, which is odd because most current printers use 1.75 mm. It is important to change it.
// Generally expected filament diameter (1.75, 2.85, 3.0, ...). Used for Volumetric, Filament Width Sensor, etc. #define DEFAULT_NOMINAL_FILAMENT_DIA 1.75
Prusa multi-material kit (PRUSA_MMU2)
Enable this if you have installed the original Josef Prusa multi-material kit on your printer, or some Chinese clone available on the market. If not, leave it as is, with the two slashes in front.
/** * Prusa Multi-Material Unit v2 * * Requires NOZZLE_PARK_FEATURE to park print head in case MMU unit fails. * Requires EXTRUDERS = 5 * * For additional configuration see Configuration_adv.h */ //#define PRUSA_MMU2
Temperature sensors (TEMP_SENSORS)
In this section of Marlin we define the temperature sensors present in the printer. Version 2.0.7.2 added support for more extruders (up to 11) and includes a sensor for the chamber.
As you can see, there are loads of them, and the listing appears right in the code. If you do not have info on yours, search Google: some other user with the same printer has probably documented it.
Only TEMP_SENSOR_0 is configured by default, with value “1”. In my case, I need to set it to “5”.
Como tengo cama calefactable (para mejorar la adherencia y evitar problemas de Warping, configuro TEMP_SENSOR_BED con el valor 1. El resto lo dejo a 0, ya que no tengo más extrusores ni habitáculo caliente (Chamber Temp).
/** * --NORMAL IS 4.7kohm PULLUP!-- 1kohm pullup can be used on hotend sensor, using correct resistor and table * * Temperature sensors available: * * -5 : PT100 / PT1000 with MAX31865 (only for sensors 0-1) * -3 : thermocouple with MAX31855 (only for sensors 0-1) * -2 : thermocouple with MAX6675 (only for sensors 0-1) * -4 : thermocouple with AD8495 * -1 : thermocouple with AD595 * 0 : not used * 1 : 100k thermistor - best choice for EPCOS 100k (4.7k pullup) * 331 : (3.3V scaled thermistor 1 table) * 2 : 200k thermistor - ATC Semitec 204GT-2 (4.7k pullup) * 3 : Mendel-parts thermistor (4.7k pullup) * 4 : 10k thermistor !! do not use it for a hotend. It gives bad resolution at high temp. !! * 5 : 100K thermistor - ATC Semitec 104GT-2/104NT-4-R025H42G (Used in ParCan & J-Head) (4.7k pullup) * 501 : 100K Zonestar (Tronxy X3A) Thermistor * 512 : 100k RPW-Ultra hotend thermistor (4.7k pullup) * 6 : 100k EPCOS - Not as accurate as table 1 (created using a fluke thermocouple) (4.7k pullup) * 7 : 100k Honeywell thermistor 135-104LAG-J01 (4.7k pullup) * 71 : 100k Honeywell thermistor 135-104LAF-J01 (4.7k pullup) * 8 : 100k 0603 SMD Vishay NTCS0603E3104FXT (4.7k pullup) * 9 : 100k GE Sensing AL03006-58.2K-97-G1 (4.7k pullup) * 10 : 100k RS thermistor 198-961 (4.7k pullup) * 11 : 100k beta 3950 1% thermistor (4.7k pullup) * 12 : 100k 0603 SMD Vishay NTCS0603E3104FXT (4.7k pullup) (calibrated for Makibox hot bed) * 13 : 100k Hisens 3950 1% up to 300°C for hotend "Simple ONE " & "Hotend "All In ONE" * 15 : 100k thermistor calibration for JGAurora A5 hotend * 18 : ATC Semitec 204GT-2 (4.7k pullup) Dagoma.Fr - MKS_Base_DKU001327 * 20 : Pt100 with circuit in the Ultimainboard V2.x * 201 : Pt100 with circuit in Overlord, similar to Ultimainboard V2.x * 60 : 100k Maker's Tool Works Kapton Bed Thermistor beta=3950 * 61 : 100k Formbot / Vivedino 3950 350C thermistor 4.7k pullup * 66 : 4.7M High Temperature thermistor from Dyze Design * 67 : 450C thermistor from SliceEngineering * 70 : the 100K thermistor found in the bq Hephestos 2 * 75 : 100k Generic Silicon Heat Pad with NTC 100K MGB18-104F39050L32 thermistor * 99 : 100k thermistor with a 10K pull-up resistor (found on some Wanhao i3 machines) * * 1k ohm pullup tables - This is atypical, and requires changing out the 4.7k pullup for 1k. * (but gives greater accuracy and more stable PID) * 51 : 100k thermistor - EPCOS (1k pullup) * 52 : 200k thermistor - ATC Semitec 204GT-2 (1k pullup) * 55 : 100k thermistor - ATC Semitec 104GT-2 (Used in ParCan & J-Head) (1k pullup) * * 1047 : Pt1000 with 4k7 pullup * 1010 : Pt1000 with 1k pullup (non standard) * 147 : Pt100 with 4k7 pullup * 110 : Pt100 with 1k pullup (non standard) * * 1000 : Custom - Specify parameters in Configuration_adv.h * * Use these for Testing or Development purposes. NEVER for production machine. * 998 : Dummy Table that ALWAYS reads 25°C or the temperature defined below. * 999 : Dummy Table that ALWAYS reads 100°C or the temperature defined below. */ #define TEMP_SENSOR_0 5 #define TEMP_SENSOR_1 0 #define TEMP_SENSOR_2 0 #define TEMP_SENSOR_3 0 #define TEMP_SENSOR_4 0 #define TEMP_SENSOR_5 0 #define TEMP_SENSOR_6 0 #define TEMP_SENSOR_7 0 #define TEMP_SENSOR_BED 1 #define TEMP_SENSOR_PROBE 1 #define TEMP_SENSOR_CHAMBER 0
Temperature limiters (MINTEMP & MAXTEMP)
Configuring these parameters in Marlin 2 is very important: they control the maximum and minimum temperatures of the printer.
We define valid ranges for each sensor. If any sensor falls below or exceeds that temperature, Marlin shows an error on the display and disables the hotend and the heated bed.
In my case I usually set the extruders to 5 °C (minimum) and 265 °C (maximum). If an extruder or the bed cannot reach 5 °C, we can assume the thermistor is not properly installed or is physically damaged.
It also protects us if the maximum temperature is accidentally exceeded — crucial for your safety and that of your home.
// Below this temperature the heater will be switched off // because it probably indicates a broken thermistor wire. #define HEATER_0_MINTEMP 5 #define HEATER_1_MINTEMP 5 #define HEATER_2_MINTEMP 5 #define HEATER_3_MINTEMP 5 #define HEATER_4_MINTEMP 5 #define HEATER_5_MINTEMP 5 #define HEATER_6_MINTEMP 5 #define HEATER_7_MINTEMP 5 #define BED_MINTEMP 5 // Above this temperature the heater will be switched off. // This can protect components from overheating, but NOT from shorts and failures. // (Use MINTEMP for thermistor short/failure protection.) #define HEATER_0_MAXTEMP 265 #define HEATER_1_MAXTEMP 265 #define HEATER_2_MAXTEMP 265 #define HEATER_3_MAXTEMP 265 #define HEATER_4_MAXTEMP 265 #define HEATER_5_MAXTEMP 265 #define HEATER_6_MAXTEMP 265 #define HEATER_7_MAXTEMP 265 #define BED_MAXTEMP 120
PID Tuning (extruders)
This section controls the algorithm in charge of managing the temperature of the extruders and the heated bed.
We could dive deeper into how it works, but this is not the right article for that. If you are interested in PID Tuning, we recommend taking a look at the REPRAP article on PID Tuning.
Some default values are provided for several of the best-known printers. Since my printer does not match any of them, I have simply added my own values.
#if ENABLED(PIDTEMP)
//#define PID_EDIT_MENU // Add PID editing to the "Advanced Settings" menu. (~700 bytes of PROGMEM)
//#define PID_AUTOTUNE_MENU // Add PID auto-tuning to the "Advanced Settings" menu. (~250 bytes of PROGMEM)
//#define PID_PARAMS_PER_HOTEND // Uses separate PID parameters for each extruder (useful for mismatched extruders)
// Set/get with gcode: M301 E[extruder number, 0-2]
#if ENABLED(PID_PARAMS_PER_HOTEND)
// Specify between 1 and HOTENDS values per array.
// If fewer than EXTRUDER values are provided, the last element will be repeated.
#define DEFAULT_Kp_LIST { 22.20, 22.20 }
#define DEFAULT_Ki_LIST { 1.08, 1.08 }
#define DEFAULT_Kd_LIST { 114.00, 114.00 }
#else
#define DEFAULT_Kp 20.3
#define DEFAULT_Ki 1.43
#define DEFAULT_Kd 71.84
#endif
#endif // PIDTEMP
To obtain the values for your printer you can either look them up online or calculate them with a Marlin built-in function called PID Autotune.
Para ello, conecta tu impresora a Repetier/Simplify3D o cualquier otro software que te permita utilizar comandos Gcode. Una vez conectado, envía el comando M303 E0 S200 C8 y comenzará el proceso.
After heating and cooling the hotend 8 times, the process will finish and show the following information. Just take the Kp, Ki and Kd values and enter them in your firmware in the DEFAULT_Kp, DEFAULT_Ki and DEFAULT_Kd fields.
bias: 92 d: 92 min: 196.56 max: 203.75
Ku: 32.59 Tu: 54.92
Clasic PID
Kp: 19.56
Ki: 0.71
Kd: 134.26
PID Autotune finished ! Place the Kp, Ki and Kd constants in the configuration.h
PID Bed Tuning (heated bed)
Same as before, but for the heated bed. In the current firmware it is disabled by default. If you have a heated bed, you must uncomment the #define PIDTEMPBED option as you will see in my configuration.
You can also obtain the bed values with a Marlin built-in function. Run it with the G-code command M303 E-1 C8 S90.
//=========================================================================== //====================== PID > Bed Temperature Control ====================== //=========================================================================== /** * PID Bed Heating * * If this option is enabled set PID constants below. * If this option is disabled, bang-bang will be used and BED_LIMIT_SWITCHING will enable hysteresis. * * The PID frequency will be the same as the extruder PWM. * If PID_dT is the default, and correct for the hardware/configuration, that means 7.689Hz, * which is fine for driving a square wave into a resistive load and does not significantly * impact FET heating. This also works fine on a Fotek SSR-10DA Solid State Relay into a 250W * heater. If your configuration is significantly different than this and you don't understand * the issues involved, don't use bed PID until someone else verifies that your hardware works. */ #define PIDTEMPBED //#define BED_LIMIT_SWITCHING /** * Max Bed Power * Applies to all forms of bed control (PID, bang-bang, and bang-bang with hysteresis). * When set to any value below 255, enables a form of PWM to the bed that acts like a divider * so don't use it unless you are OK with PWM on your bed. (See the comment on enabling PIDTEMPBED) */ #define MAX_BED_POWER 255 // limits duty cycle to bed; 255=full current if ENABLED(PIDTEMPBED) //#define MIN_BED_POWER 0 //#define PID_BED_DEBUG // Sends debug data to the serial port. //120V 250W silicone heater into 4mm borosilicate (MendelMax 1.5+) //from FOPDT model - kp=.39 Tp=405 Tdead=66, Tc set to 79.2, aggressive factor of .15 (vs .1, 1, 10) #define DEFAULT_bedKp 347.77 #define DEFAULT_bedKi 48.46 #define DEFAULT_bedKd 623.90 //120V 250W silicone heater into 4mm borosilicate (MendelMax 1.5+) //from pidautotune //#define DEFAULT_bedKp 97.1 //#define DEFAULT_bedKi 1.41 //#define DEFAULT_bedKd 1675.16 // FIND YOUR OWN: "M303 E-1 C8 S90" to run autotune on the bed at 90 degreesC for 8 cycles. #endif // PIDTEMPBED
Even so, there are times when enabling PIDTEMPBED is counterproductive. As a starting point, I recommend not enabling it.
Cold extrusion (PREVENT_COLD_EXTRUSION)
Both options manage cold extrusion in Marlin. As we all know, it is not advisable to extrude filament if the hotend is not heated.
The PREVENT_COLD_EXTRUSION option will simply prevent us from extruding material if the hotend has not reached the minimum defined temperature.
We can configure the minimum temperature at which Marlin will be allowed to extrude with the EXTRUDE_MINTEMP parameter. Both come enabled by default, so there is nothing to worry about.
Even so, I thought it was important to mention so that you know it exists.
/** * Prevent extrusion if the temperature is below EXTRUDE_MINTEMP. * Add M302 to set the minimum extrusion temperature and/or turn * cold extrusion prevention on and off. * * *** IT IS HIGHLY RECOMMENDED TO LEAVE THIS OPTION ENABLED! *** */ #define PREVENT_COLD_EXTRUSION #define EXTRUDE_MINTEMP 170
Extrusion length (PREVENT_LENGTHY_EXTRUDE)
As the comments indicate, this prevents extruding filament beyond the configured distance. It means Marlin will only allow you to extrude a maximum of 200mm in a single G-code command.
If you need to extrude more than 200 mm in a single command (for example, when loading filament from the display with a Bowden extruder), you should change the EXTRUDE_MAXLENGTH parameter to a higher value. Both come enabled by default in Marlin 2.
If that is not your case, leave it as is. I, for example, load filament by hand, so I do not need to modify it, but it is always good to know.
/** * Prevent a single extrusion longer than EXTRUDE_MAXLENGTH. * Note: For Bowden Extruders make this large enough to allow load/unload. */ #define PREVENT_LENGTHY_EXTRUDE #define EXTRUDE_MAXLENGTH 200
Thermal protection (THERMAL_PROTECTION)
These three parameters enable the additional thermal protection that Marlin 2.0.x offers to prevent damage to the printer. They should always be enabled; in fact they are enabled by default in Marlin 2, so we will not touch them.
/** * Thermal Protection provides additional protection to your printer from damage * and fire. Marlin always includes safe min and max temperature ranges which * protect against a broken or disconnected thermistor wire. * * The issue: If a thermistor falls out, it will report the much lower * temperature of the air in the room, and the the firmware will keep * the heater on. * * If you get "Thermal Runaway" or "Heating failed" errors the * details can be tuned in Configuration_adv.h */ #define THERMAL_PROTECTION_HOTENDS // Enable thermal protection for all extruders #define THERMAL_PROTECTION_BED // Enable thermal protection for the heated bed #define THERMAL_PROTECTION_CHAMBER // Enable thermal protection for the heated chamber
Mechanical parameters (CoreXY kinematics)
There are printers on the market with very different kinematics: Cartesian, delta, tripteron, CoreXY (and its variants), etc. The truth is they could fill a whole article on their own.
If your printer uses CoreXY kinematics or any of its variants, you must enable the corresponding parameter. Since I have a Cartesian setup, I leave everything disabled, as you can see.
//=========================================================================== //============================= Mechanical Settings ========================= //=========================================================================== // @section machine // Enable one of the options below for CoreXY, CoreXZ, or CoreYZ kinematics, // either in the usual order or reversed //#define COREXY //#define COREXZ //#define COREYZ //#define COREYX //#define COREZX //#define COREZY //#define MARKFORGED_XY // MarkForged. See https://reprap.org/forum/read.php?152,504042
Available endstops (USE_XMIN_PLUG & USE_XMAX_PLUG)
Here we tell Marlin which endstops are wired to the board. The usual setup is three endstops for the minimum travels (home stops); that way Marlin determines the initial position (0) of all axes when HOMING.
Extra sensors can also be installed for maximum travels. They prevent the machine from moving further than necessary. They are not essential, but they are a good option to keep every contingency under control.
In my case, I have two mechanical endstops on the X axis (extruder) and the Y axis (bed), plus a Z probe. So I only leave the minimum endstops enabled in the firmware, as you can see for yourself in the lines below.
// Specify here all the endstop connectors that are connected to any endstop or probe. // Almost all printers will be using one per axis. Probes will use one or more of the // extra connectors. Leave undefined any used for non-endstop and non-probe purposes. #define USE_XMIN_PLUG #define USE_YMIN_PLUG #define USE_ZMIN_PLUG //#define USE_XMAX_PLUG //#define USE_YMAX_PLUG //#define USE_ZMAX_PLUG
Endstop logic (ENDSTOP_INVERTING)
Depending on the type of sensor or endstop you use, the logic will be different. It is no big mystery: leave them all at FALSE. If any of them does not work, change the logic here (set it to TRUE). In my case I had to set X and Y to TRUE, as you can see.
// Mechanical endstop with COM to ground and NC to Signal uses "false" here (most common setup). #define X_MIN_ENDSTOP_INVERTING true // Set to true to invert the logic of the endstop. #define Y_MIN_ENDSTOP_INVERTING true // Set to true to invert the logic of the endstop. #define Z_MIN_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop. #define X_MAX_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop. #define Y_MAX_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop. #define Z_MAX_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop. #define Z_MIN_PROBE_ENDSTOP_INVERTING false // Set to true to invert the logic of the probe.
Configuring drivers (DRIVER_TYPE)
Configuring Marlin 2 with the drivers you have is a must. Do not worry: it is a simple process.
You will see that all options are disabled by default. Enable the ones matching the drivers installed on your board.
My printer has three motors for the three axes (X, Y, Z) and a single motor for the extruder, so I enable the relevant options. The first extruder is always called E0, as you can see.
Beyond enabling the option, you also need to indicate which driver you have installed. In my case, with DRV8825, I have told the compiler and that is it.
In the comments you can see all the driver types supported by Marlin 2: find yours and copy it exactly as it appears.
/** * Stepper Drivers * * These settings allow Marlin to tune stepper driver timing and enable advanced options for * stepper drivers that support them. You may also override timing options in Configuration_adv.h. * * A4988 is assumed for unspecified drivers. * * Options: A4988, A5984, DRV8825, LV8729, L6470, L6474, POWERSTEP01, * TB6560, TB6600, TMC2100, * TMC2130, TMC2130_STANDALONE, TMC2160, TMC2160_STANDALONE, * TMC2208, TMC2208_STANDALONE, TMC2209, TMC2209_STANDALONE, * TMC26X, TMC26X_STANDALONE, TMC2660, TMC2660_STANDALONE, * TMC5130, TMC5130_STANDALONE, TMC5160, TMC5160_STANDALONE * :['A4988', 'A5984', 'DRV8825', 'LV8729', 'L6470', 'L6474', 'POWERSTEP01', 'TB6560', 'TB6600', 'TMC2100', 'TMC2130', 'TMC2130_STANDALONE', 'TMC2160', 'TMC2160_STANDALONE', 'TMC2208', 'TMC2208_STANDALONE', 'TMC2209', 'TMC2209_STANDALONE', 'TMC26X', 'TMC26X_STANDALONE', 'TMC2660', 'TMC2660_STANDALONE', 'TMC5130', 'TMC5130_STANDALONE', 'TMC5160', 'TMC5160_STANDALONE'] */ #define X_DRIVER_TYPE DRV8825 #define Y_DRIVER_TYPE DRV8825 #define Z_DRIVER_TYPE DRV8825 //#define X2_DRIVER_TYPE A4988 //#define Y2_DRIVER_TYPE A4988 //#define Z2_DRIVER_TYPE A4988 //#define Z3_DRIVER_TYPE A4988 #define E0_DRIVER_TYPE DRV8825 //#define E1_DRIVER_TYPE A4988 //#define E2_DRIVER_TYPE A4988 //#define E3_DRIVER_TYPE A4988 //#define E4_DRIVER_TYPE A4988 //#define E5_DRIVER_TYPE A4988 //#define E6_DRIVER_TYPE A4988 //#define E7_DRIVER_TYPE A4988
Steps configuration (DEFAULT_AXIS_STEPS_PER_UNIT)
In this section we tell the printer how many steps are executed per unit of movement. Units can be either millimetres or inches.
If you are going to use inches, you must enable INCH_MODE_SUPPORT. We do not enable it because we work in millimetres and we enter the steps for each axis and the extruder.
You need to know the values to enter. The safe option is to take them from an existing firmware for your printer.
Another option is to search online (some user will have published them), check forums, ask the manufacturer or, as a last resort, calculate them yourself as you can see in this video.
/**
* Default Axis Steps Per Unit (steps/mm)
* Override with M92
* X, Y, Z, E0 [, E1[, E2...]]
*/
#define DEFAULT_AXIS_STEPS_PER_UNIT { 160, 160, 800, 803 }
Auto-bed levelling probe position (NOZZLE_TO_PROBE_OFFSET)
If you use an auto-bed-levelling probe (as I do), you have to tell the firmware the probe position relative to the nozzle. The probe will always be offset from the nozzle, and we define this offset as coordinates in millimetres.
My probe is 37 mm to the right of the hotend and 2 mm further back. The configuration would look like this:
/**
* Nozzle-to-Probe offsets { X, Y, Z }
*
* - Use a caliper or ruler to measure the distance from the tip of
* the Nozzle to the center-point of the Probe in the X and Y axes.
* - For the Z offset use your best known value and adjust at runtime.
* - Probe Offsets can be tuned at runtime with 'M851', LCD menus, babystepping, etc.
*
* Assuming the typical work area orientation:
* - Probe to RIGHT of the Nozzle has a Positive X offset
* - Probe to LEFT of the Nozzle has a Negative X offset
* - Probe in BACK of the Nozzle has a Positive Y offset
* - Probe in FRONT of the Nozzle has a Negative Y offset
*
* Some examples:
* #define NOZZLE_TO_PROBE_OFFSET { 10, 10, -1 } // Example "1"
* #define NOZZLE_TO_PROBE_OFFSET {-10, 5, -1 } // Example "2"
* #define NOZZLE_TO_PROBE_OFFSET { 5, -5, -1 } // Example "3"
* #define NOZZLE_TO_PROBE_OFFSET {-15,-10, -1 } // Example "4"
*
* +-- BACK ---+
* | [+] |
* L | 1 | R <-- Example "1" (right+, back+)
* E | 2 | I <-- Example "2" ( left-, back+)
* F |[-] N [+]| G <-- Nozzle
* T | 3 | H <-- Example "3" (right+, front-)
* | 4 | T <-- Example "4" ( left-, front-)
* | [-] |
* O-- FRONT --+
*/
#define NOZZLE_TO_PROBE_OFFSET { 37, -2, 0 }
Levelling travel speed (XY_PROBE_SPEED)
This defines the speed at which Marlin 2 moves the auto-bed-levelling probe between two measurement points. The default is 133*60 mm/min; you can leave it as is or raise it, at your discretion.
// X and Y axis travel speed (mm/min) between probes #define XY_PROBE_SPEED (133*60)
Invert motor direction (INVERT_X_DIR)
We modify these parameters if, when homing or printing, any motor turns in the wrong direction. They all come at FALSE by default. In my case I had to invert the direction of the bed (Y axis), as you can see below.
Another option is to flip the motor connector cable: whichever is more comfortable for you.
// Invert the stepper direction. Change (or reverse the motor connector) if an axis goes the wrong way. #define INVERT_X_DIR false #define INVERT_Y_DIR true #define INVERT_Z_DIR false
Print volume (X_BED_SIZE & Y_BED_SIZE)
Here we set the exact dimensions of the print volume (bed). My printer has a 285 mm x 206 mm bed, so the configuration would look like this:
// The size of the print bed #define X_BED_SIZE 285 #define Y_BED_SIZE 206
Movement limits (MIN_POS & MAX_POS)
Once the bed dimensions are set, we configure the minimum and maximum movement limits in Marlin 2.
By default, Marlin sets minimums to 0, which we should not modify since it is the HOME. For the maximums, Marlin uses the bed dimensions on X and Y directly (which we had already configured in the previous parameter).
To finish, on the Z axis we need to add the maximum print height of the machine. In my case I can print around 296 mm, so I enter that value.
// Travel limits (mm) after homing, corresponding to endstop positions. #define X_MIN_POS 0 #define Y_MIN_POS 0 #define Z_MIN_POS 0 #define X_MAX_POS X_BED_SIZE #define Y_MAX_POS Y_BED_SIZE #define Z_MAX_POS 296
Movement restrictions (MIN_SOFTWARE_ENDSTOPS)
For safety reasons, and to avoid damaging the components, Marlin 2 is configured by default so that we cannot exceed the minimum limits. When an endstop or probe is reached, it will not let the motor advance any further, not even manually.
Even so, like many other things in Marlin 2.0.x, you can disable that limit if you wish. It is an option I DO NOT RECOMMEND, but I wanted to mention it so you know it exists.
I personally tend to remove the limit on the Z axis, but as I mentioned, unless you really know what you are doing, it is best to leave the default firmware values.
// Min software endstops constrain movement within minimum coordinate bounds #define MIN_SOFTWARE_ENDSTOPS #if ENABLED(MIN_SOFTWARE_ENDSTOPS) #define MIN_SOFTWARE_ENDSTOP_X #define MIN_SOFTWARE_ENDSTOP_Y #define MIN_SOFTWARE_ENDSTOP_Z #endif
EEPROM storage (EEPROM_SETTINGS)
Marlin lets you change the printer configuration from the display itself and save the changes to the EEPROM.
If you want that option available, enable this parameter in your firmware.
#define EEPROM_SETTINGS // Persistent storage with M500 and M501
ABS/PLA preheat (PREHEAT)
As you will have seen if you have tinkered with your printer, Marlin offers two initial options to preheat the printer before printing. You can configure the temperatures available for ABS and PLA filaments, though you could add more if you wanted.
It is very handy, because the default temperatures can be improved. I personally use these configurations:
// Preheat Constants #define PREHEAT_1_LABEL "PLA" #define PREHEAT_1_TEMP_HOTEND 200 #define PREHEAT_1_TEMP_BED 60 #define PREHEAT_1_FAN_SPEED 0 // Value from 0 to 255 #define PREHEAT_2_LABEL "ABS" #define PREHEAT_2_TEMP_HOTEND 250 #define PREHEAT_2_TEMP_BED 100 #define PREHEAT_2_FAN_SPEED 0 // Value from 0 to 255
Menu language (LCD_LANGUAGE)
The language that will appear in all the menus of the Marlin 2 firmware (display). The one I prefer is Spanish, so that is the one I have selected. By default it comes in English; you will probably want to change it.
/**
* LCD LANGUAGE
*
* Select the language to display on the LCD. These languages are available:
*
* en, an, bg, ca, cz, da, de, el, el_gr, es, eu, fi, fr, gl, hr, it, jp_kana,
* ko_KR, nl, pl, pt, pt_br, ru, sk, tr, uk, vi, zh_CN, zh_TW, test
*
* :{ 'en':'English', 'an':'Aragonese', 'bg':'Bulgarian', 'ca':'Catalan', 'cz':'Czech', 'da':'Danish', 'de':'German', 'el':'Greek', 'el_gr':'Greek (Greece)', 'es':'Spanish', 'eu':'Basque-Euskera', 'fi':'Finnish', 'fr':'French', 'gl':'Galician', 'hr':'Croatian', 'it':'Italian', 'jp_kana':'Japanese', 'ko_KR':'Korean (South Korea)', 'nl':'Dutch', 'pl':'Polish', 'pt':'Portuguese', 'pt_br':'Portuguese (Brazilian)', 'ru':'Russian', 'sk':'Slovak', 'tr':'Turkish', 'uk':'Ukrainian', 'vi':'Vietnamese', 'zh_CN':'Chinese (Simplified)', 'zh_TW':'Chinese (Traditional)', 'test':'TEST' }
*/
#define LCD_LANGUAGE es
Accents on HD44780 character displays: if you have a basic 20×4 or 16×2 LCD (the most common blue or green displays), in order for Spanish accents (á, é, í, ó, ú, ñ) to display correctly you also need to define the appropriate charset:
#define DISPLAY_CHARSET_HD44780 WESTERN
The available values are JAPANESE (more common on Asian displays), WESTERN (European accents) and CYRILLIC (Cyrillic/Russian). If you do not know which one your display uses, compile with LCD_LANGUAGE test and check on the display itself which character set looks correct.
Multi-language with hot-swap (graphical displays)
On graphical displays with enough memory (128×64 DOGLCD such as RepRapDiscount Full Graphic, or TFTs with Marlin emulation enabled) it is possible to compile the firmware with several simultaneous languages and hot-swap between them using the G-code M414, with no need to recompile.
To enable it, define the additional languages in Configuration.h:
#define LCD_LANGUAGE es // idioma principal — español #define LCD_LANGUAGE_2 en // segundo idioma — inglés #define LCD_LANGUAGE_3 de // tercer idioma — alemán (opcional)
Once the firmware is installed, switch languages from the serial console or a startup script:
M414 S0 ; idioma 1 -> español (LCD_LANGUAGE) M414 S1 ; idioma 2 -> inglés (LCD_LANGUAGE_2) M414 S2 ; idioma 3 -> alemán (LCD_LANGUAGE_3)
Multi-language is not available on basic HD44780 displays due to controller memory limitations. If your display does not support it, define only LCD_LANGUAGE with your desired language and recompile.
SD Card support (SDSUPPORT)
Enabling this option is practically essential. It lets you load files directly from an SD card.
Believe it or not, it is disabled by default. You will need to enable it, as in my configuration.
/** * SD CARD * * SD Card support is disabled by default. If your controller has an SD slot, * you must uncomment the following option or it won't work. * */ #define SDSUPPORT
Slim menus (SLIM_LCD_MENUS)
Marlin lets you navigate through endless menus on the display, to a point that becomes overwhelming (at least for me).
Many of these parameters should be set in the firmware itself, with no need to tweak them «on the fly».
To trim the menus, Marlin offers the SLIM_LCD_MENUS parameter. It not only simplifies the menus, it also saves a non-trivial amount of memory. We recommend enabling this option.
/** * LCD Menu Items * * Disable all menus and only display the Status Screen, or * just remove some extraneous menu items to recover space. */ //#define NO_LCD_MENUS #define SLIM_LCD_MENUS
Display type (LCD / Controller Selection)

Finally, we reach the display configuration. If we take a look at the Configuration.h file we will see that there are countless displays.
It may look complicated, but you only need to find the description of your LCD and uncomment the corresponding line.
There are text-based displays, graphical LCDs, OLEDs and a few more. I have a graphical one called MKS MINI 12864 (photo above); to enable it I have uncommented the following line.
If you cannot find your display name, use the Windows «Find» feature: it is the quickest and simplest option.
// // MKS MINI12864 with graphic controller and SD support // https://reprap.org/wiki/MKS_MINI_12864 // #define MKS_MINI_12864
One detail to keep in mind: in some cases (like mine) you need external libraries to compile the firmware with support for your display. This is the case of the MKS MINI12864, which requires searching and installing the libraries manually.
If you try to compile, Marlin will throw an error indicating which library you need. In my case, for example, it asks for the U8glib library. Let’s look at the error:
sketch\src\HAL\HAL_AVR\u8g_com_HAL_AVR_sw_spi.cpp:65:10: fatal error: U8glib.h:
No such file or directory
The fix is simple: go to Tools -> Manage Libraries… and click. In the search box, type U8glib and press ENTER.
The available online libraries for this search will appear; we will see that ours, «U8glib by Oliver», is at the bottom. Click INSTALL and you are done.
Lastly, the display contrast did not convince me: it looked a bit dark at first, so I decided to change it.
You can change the contrast (making the display lighter or darker) from the display itself, but I prefer to fix it in the firmware: I am not going to touch it again, and if I reset the EEPROM I will not need to configure it again.
To do this I had to edit a file called «pins_RAMPS.h» at \Marlin\src\pins\ramps\. Once edited, we add the line #define LCD_CONTRAST 150 as shown in the lines below:
#elif ENABLED(MINIPANEL) #define BEEPER_PIN 42 // not connected to a pin #define LCD_BACKLIGHT_PIN 65 // backlight LED on A11/D65 #define DOGLCD_A0 44 #define DOGLCD_CS 66 // GLCD features // Uncomment screen orientation //#define LCD_SCREEN_ROT_90 //#define LCD_SCREEN_ROT_180 //#define LCD_SCREEN_ROT_270 #define BTN_EN1 40 #define BTN_EN2 63 #define BTN_ENC 59 #define SD_DETECT_PIN 49 #define KILL_PIN 64 #define LCD_CONTRAST 150
Bed levelling (BED_LEVELING)
There are several methods and features in Marlin 2 to help with auto bed levelling. They come disabled by default in the firmware, so we need to enable them to use them.
Explaining each one would deserve a full article, so I will just show you how to level the bed in two different ways. The first one if you do not have a probe installed, and the second one if you do.
To start, in both cases, we must uncomment the AUTO_BED_LEVELING_BILINEAR feature and then RESTORE_LEVELING_AFTER_G28, so they remain enabled in the firmware.
/** * Choose one of the options below to enable G29 Bed Leveling. The parameters * and behavior of G29 will change depending on your selection. * * If using a Probe for Z Homing, enable Z_SAFE_HOMING also! * * - AUTO_BED_LEVELING_3POINT * Probe 3 arbitrary points on the bed (that aren't collinear) * You specify the XY coordinates of all 3 points. * The result is a single tilted plane. Best for a flat bed. * * - AUTO_BED_LEVELING_LINEAR * Probe several points in a grid. * You specify the rectangle and the density of sample points. * The result is a single tilted plane. Best for a flat bed. * * - AUTO_BED_LEVELING_BILINEAR * Probe several points in a grid. * You specify the rectangle and the density of sample points. * The result is a mesh, best for large or uneven beds. * * - AUTO_BED_LEVELING_UBL (Unified Bed Leveling) * A comprehensive bed leveling system combining the features and benefits * of other systems. UBL also includes integrated Mesh Generation, Mesh * Validation and Mesh Editing systems. * * - MESH_BED_LEVELING * Probe a grid manually * The result is a mesh, suitable for large or uneven beds. (See BILINEAR.) * For machines without a probe, Mesh Bed Leveling provides a method to perform * leveling in steps so you can manually adjust the Z height at each grid-point. * With an LCD controller the process is guided step-by-step. */ //#define AUTO_BED_LEVELING_3POINT //#define AUTO_BED_LEVELING_LINEAR #define AUTO_BED_LEVELING_BILINEAR //#define AUTO_BED_LEVELING_UBL //#define MESH_BED_LEVELING /** * Normally G28 leaves leveling disabled on completion. Enable * this option to have G28 restore the prior leveling state. */ #define RESTORE_LEVELING_AFTER_G28
This way, our probe will lower at several points and create a virtual mesh with the different heights. And since I always like to home at the centre of the bed, I enable the Z_SAFE_HOMING option.
#define Z_SAFE_HOMING #if ENABLED(Z_SAFE_HOMING) #define Z_SAFE_HOMING_X_POINT ((X_BED_SIZE) / 2) // X point for Z homing when homing all axes (G28). #define Z_SAFE_HOMING_Y_POINT ((Y_BED_SIZE) / 2) // Y point for Z homing when homing all axes (G28). #endif
Once all this is configured, only apply the option you need for your firmware: option 1 without a probe, or option 2 with a probe. Enabling both is not necessary and can cause issues or compilation errors. Let’s go for it…
Option 1: Configuration without probe (4 corners)
This is the configuration we apply when we do not have a probe on our toolhead. First, we tell Marlin 2 that we are going to do the levelling without a probe.
/** * The "Manual Probe" provides a means to do "Auto" Bed Leveling without a probe. * Use G29 repeatedly, adjusting the Z height at each point with movement commands * or (with LCD_BED_LEVELING) the LCD controller. */ #define PROBE_MANUALLY //#define MANUAL_PROBE_START_Z 0.2
Next we indicate how many probe points we want for our manual levelling, so we modify the GRID_MAX_POINTS parameters. To level the four corners we need four points, so we will leave the configuration like this.
// Set the number of grid points per dimension. #define GRID_MAX_POINTS_X 2 #define GRID_MAX_POINTS_Y GRID_MAX_POINTS_X
Last but not least, we will enable LCD_BED_LEVELING and LEVEL_BED_CORNERS. This will add the corresponding menus on the display.
/** * Add a bed leveling sub-menu for ABL or MBL. * Include a guided procedure if manual probing is enabled. */ #define LCD_BED_LEVELING #if ENABLED(LCD_BED_LEVELING) #define MESH_EDIT_Z_STEP 0.025 // (mm) Step size while manually probing Z axis. #define LCD_PROBE_Z_RANGE 4 // (mm) Z Range centered on Z_MIN_POS for LCD Z adjustment //#define MESH_EDIT_MENU // Add a menu to edit mesh points #endif // Add a menu item to move between bed corners for manual bed adjustment #define LEVEL_BED_CORNERS
Option 2: Configuration with probe (BABYSTEPPING)
This is the configuration I use on my printer with a probe on the toolhead. In my case I use an IR probe, but it applies to any type of probe (inductive, capacitive, IR, etc.).
If you have a BLTouch, I do recommend looking for a specific manual, since Marlin has dedicated features for it.
On 3DWork we have a full article on how to configure it: Installing and configuring BLTouch / 3DTouch in Marlin 2.0.x (MKS Gen, SKR, Anet A8, RAMPS)
Back to the configuration: the first thing is to tell Marlin that we have a fixed auto-bed-levelling probe. To do this we edit the following line:
/** * A Fix-Mounted Probe either doesn't deploy or needs manual deployment. * (e.g., an inductive probe or a nozzle-based probe-switch.) */ #define FIX_MOUNTED_PROBE
Then we configure how many probe points we want the probed levelling to use, so we modify the GRID_MAX_POINTS parameters.
I usually do 9 probe points before each print, so I leave the defaults, which are 3 per axis (3 x 3 = 9).
// Set the number of grid points per dimension. #define GRID_MAX_POINTS_X 3 #define GRID_MAX_POINTS_Y GRID_MAX_POINTS_X
Then we will edit a new file called configuration_adv.h. It differs from the first one in that it offers more detailed options, add-ons and experimental or in-development features (such as BABYSTEPPING).

On my printer I use a levelling feature in Marlin 2 called BABYSTEPPING. This feature lets you use a piece of paper to calibrate the height of the levelling probe at the centre of the bed only once.
After that, the printer will probe 9 points automatically at the start of each print. That way I do not have to go corner by corner to calibrate the bed.
It is disabled by default, so we enable BABYSTEPPING as shown below:
/** * Babystepping enables movement of the axes by tiny increments without changing * the current position values. This feature is used primarily to adjust the Z * axis in the first layer of a print in real-time. * * Warning: Does not respect endstops! */ #define BABYSTEPPING #if ENABLED(BABYSTEPPING) //#define INTEGRATED_BABYSTEPPING // EXPERIMENTAL integration of babystepping into the Stepper ISR //#define BABYSTEP_WITHOUT_HOMING #define BABYSTEP_ALWAYS_AVAILABLE // Allow babystepping at all times (not just during movement). //#define BABYSTEP_XY // Also enable X/Y Babystepping. Not supported on DELTA! #define BABYSTEP_INVERT_Z false // Change if Z babysteps should go the other way //#define BABYSTEP_MILLIMETER_UNITS // Specify BABYSTEP_MULTIPLICATOR_(XY|Z) in mm instead of micro-steps #define BABYSTEP_MULTIPLICATOR_Z 20 // (steps or mm) Steps or millimeter distance for each Z babystep #define BABYSTEP_MULTIPLICATOR_XY 1 // (steps or mm) Steps or millimeter distance for each XY babystep #define DOUBLECLICK_FOR_Z_BABYSTEPPING // Double-click on the Status Screen for Z Babystepping. #if ENABLED(DOUBLECLICK_FOR_Z_BABYSTEPPING) #define DOUBLECLICK_MAX_INTERVAL 1250 // Maximum interval between clicks, in milliseconds. // Note: Extra time may be added to mitigate controller latency. //#define MOVE_Z_WHEN_IDLE // Jump to the move Z menu on doubleclick when printer is idle. #if ENABLED(MOVE_Z_WHEN_IDLE) #define MOVE_Z_IDLE_MULTIPLICATOR 1 // Multiply 1mm by this factor for the move step size. #endif #endif //#define BABYSTEP_DISPLAY_TOTAL // Display total babysteps since last G28 #define BABYSTEP_ZPROBE_OFFSET // Combine M851 Z and Babystepping #if ENABLED(BABYSTEP_ZPROBE_OFFSET) //#define BABYSTEP_HOTEND_Z_OFFSET // For multiple hotends, babystep relative Z offsets #define BABYSTEP_ZPROBE_GFX_OVERLAY // Enable graphical overlay on Z-offset editor #endif #endif
EXTRA: Useful Marlin tricks
Visualise your mesh in 3D

Since Marlin 2.0.x it is possible to generate 3D meshes of the print surface without needing OctoPrint or any of its plugins.
Marlin generates a file you can edit and load into OpenSCAD to visualise the mesh at any time. You can read the full article here: Visualise your 3D bed mesh with Marlin 2.x (no OctoPrint)
Install games in Marlin

Another fun Marlin trick is enabling a set of hidden games inside the firmware. You need a graphical LCD and to tweak a couple of parameters.
You have the full article here: Enabling hidden games in Marlin 2.0.x for your 3D printer
Custom logo in Marlin

Since version 1.1.0 of the Marlin firmware it is relatively easy to add custom logos to the Marlin firmware. As you would expect, you need a graphical LCD, a logo, and to prepare the image.
You will need to tweak some parameters inside the firmware. Read the full article here: Create your own custom boot logo in Marlin 2.0.x
Final compilation of Marlin with VSCode + PlatformIO + Auto Build Marlin

We have reached the point where we compile the firmware. From Marlin 2.x onwards, the standard build method is Visual Studio Code + PlatformIO + Auto Build Marlin: it works the same on 8- and 32-bit boards, detects your electronics automatically and saves you from editing platformio.ini by hand.
If you do not yet have the environment ready, check the Manual procedure section of this same guide, where we explain how to install Python, Git, VSCode and the required extensions.
Auto Build Marlin: the official Marlin team extension
Auto Build Marlin is the official Marlin team extension for Visual Studio Code. It is the piece that makes compilation really comfortable: it automatically detects the board defined in MOTHERBOARD inside Configuration.h and shows you the available environments. You no longer need to find and edit default_envs in platformio.ini by hand.
- Install it from the VSCode marketplace by searching for Auto Build Marlin (publisher: MarlinFirmware) or from its page: marketplace.visualstudio.com/items?itemName=MarlinFirmware.auto-build
- Automatic board detection: it only shows environments compatible with your
MOTHERBOARD, without touchingplatformio.ini. - Direct buttons in the side panel: Build, Upload, Clean and Debug.
- Configuration Editor (alpha): a visual editor for
Configuration.handConfiguration_adv.h. Right-click either of the two files and choose Open With… → Config Editor to search and toggle options without touching the code directly.
Steps to compile
- Open Visual Studio Code and load your Marlin folder (File → Open Folder).
- Verify that in
Marlin/Configuration.hthe#define MOTHERBOARDdirective matches your electronics. Adjust it if needed. - Click the Auto Build Marlin icon in the VSCode side menu (Marlin logo). In the panel you will see the detected environments for your board.
- Press Build on the relevant environment and wait for the compilation to finish. The binary appears in
.pio/build/<env>/firmware.bin(or.hexon 8-bit boards). - Copy the generated file to the SD card (32-bit boards) or upload it via USB with Upload (8-bit boards with a bootloader).
If you would rather not use Auto Build Marlin, you can compile directly with PlatformIO by pressing the ✓ (Build) icon in the blue status bar at the bottom of VSCode, after setting default_envs in platformio.ini to the correct value for your electronics.
Uploading Marlin to your printer
The process depends on the type of electronics:
- 32-bit boards (SKR, BTT, Creality 4.2.x, MKS Robin, etc.): copy the generated
firmware.binto the root of an empty SD card, insert it into the printer while powered off, and turn it on. After a few seconds it boots with the new firmware. If all went well, the file is renamed to.CURon the SD (a sign that the update was applied correctly). - 8-bit boards (Mega 2560, RAMPS, MKS GEN, etc.): connect the printer to the computer via USB and use the Upload button in Auto Build Marlin or PlatformIO. If VSCode does not detect the port, make sure you have the board drivers installed and that Cura/PrusaSlicer are not open (they can lock the COM port). As an alternative, you can upload the generated
.hexfrom Cura or PrusaSlicer (both integrate a firmware updater).
After updating it is highly advisable to reset the EEPROM by sending M502 followed by M500 (or from the screen: Configuration → Restore and then Configuration → Save EEPROM). This way you make sure you do not carry over incompatible values from the previous firmware.
Final remarks
We hope this Configuring Marlin 2.x from scratch guide has been helpful. As we said at the start, it does not aim to be an exhaustive manual — just a simple introduction using my current printer as an example.
The idea is to keep expanding the article little by little. It is possible that you run into something unexpected while configuring Marlin 2.0.x for your printer.
If so, we would appreciate it if you shared it with us in the comments or on our Telegram channel.
Lastly, if there is any typo in the article, we apologise in advance. Configuring Marlin 2.0.x is fairly time-consuming (which is not the same as difficult).
It is quite possible that we missed a parameter (nothing easier than correcting it in a later edit). Do not hesitate to let us know in the comments.
As always, we leave you with some other interesting 3DWork articles:
- Post-processing 3D-printed (FDM) parts with SLA resin — is it possible?
- Advanced supports in Simplify3D: 6 essential tricks to improve your supports
- Wall-E: build your own replica with Raspberry Pi, Arduino and 3D printing
- Easily create lithophanes with your 3D printer at 3DWork.io
- Simplify3D manual: everything you need to know to get started
- The STL format is dead, long live the 3MF format
- Making fully realistic eyes with your 3D printer is possible
- What is ChiTuBox and where to download the software?
- Guide to convert G-code files to STL





























Thank you so much for putting this together. Im just a hobbyist and this article really helped explain Marlin better for me. I found it very informative and detailed. I look forward to learning more as I go and it’s thanks to people such as yourself, that I’m able to do these projects.
El enlace a tu Marlin Builder no funciona. ¿Cómo puedo acceder? Suena bastante interesante.
El Marlin Builder se ha discontinuado dada la complejidad de mantenerlo funcionando… en su lugar como puedes ver en la guia tenemos un auto builder y proximamente el propio Marlin tendra algo similar.