Marlin firmware user guide for beginners

Starting with Marlin Firmwaresettings-265131_1280

If you built your own 3D printer or if you want to optimize its performance, you will have to put your hands in the firmware. This step can seem very tricky at first glance and put people off from doing it. In this post I will try to explain the basic steps required to run a 3D printer. To show you how simple it can be, we will modify only one file and we will only change configuration options and numbers.


First question: What is firmware?

Firmware is a program which resides on the printer’s motherboard. The firmware is the link between software and hardware, it interprets commands from the G code file and controls the motion accordingly. The firmware configuration is unique to your printer. It knows the properties of the 3D printer, like the dimensions or heating settings. It plays a major role in the quality of the print.

Get the tools:


In this example we will use one of the most common motherboards in the RepRap DIY 3D printer world. That is the Arduino Mega 2560 and the RAMPS 1.4 Shield that goes over it. Marlin firmware is compatible with a lot of motherboards and the following explanations apply with a little variation.


Get the Marlin firmware: and click on the Download Zip button. Unzip the folder on your computer.

Arduino IDE

You will need a software to communicate with the board of your 3D printer to install the firmware. This is the Arduino IDE. It is an integrated development environment to program for the Arduino microcontroller. It is standard in many projects such as 3D printers.

Choose the version specific to your operating system to download.

Install Arduino IDE and start the application.

Select your hardware:

You will have to select the Arduino board that you use. Tools menu / Board / Arduino Mega 2560

Arduino board choice

First programming rule: comments

Sometimes we need help and comments to understand the intent of the programmer, but we don’t want the computer to get confused by these human comments so we use separators. In Arduino IDE the separator between computer language and comments is a double slash //, it works for every line. The compiler will not look after this separator. This is the only programming rule that we need to understand to configure the firmware properly. Sometimes we will activate some options by removing the comments and some other times we will comment-out options to deactivate them. Not to say that you might find useful information in the comments close to the parameter you need to edit.

Ramps 1.4 option

Before the attacking the configuration, if you use a RAMPS 1.4 or 1.3, you have first to edit one line in the pins.h file.

Search for the following text : “#define RAMPS_V_1_3” and remove the comments character “//” at the beginning of the line to activate it.

Save the file.


Open the file Configuration.h in the Marlin folder.


General Settings

Set the communication speed:

Using the Arduino IDE to edit the configuration.h file, search for #define BAUDRATE (ctrl+F)

Set the communication speed in baud to:


#define BAUDRATE 250000


You can keep the other speed in comments, just remember this: //#define BAUDRATE 115200

This defines the communication speed between the electronic board and the computer. There are two speeds commonly used by 3D printing software, the 250000 and 115200 baud rate. If one doesn’t work with your hardware or software, try the other one.

Select the motherboard

Above the line: #define MOTHERBOARD you will see a list of different motherboards. You just have to find your configuration among the list and use the appropriate number. For example a RAMPS 1.3 / 1.4 (Power outputs: Extruder, Fan, Bed) will be configured:


#define MOTHERBOARD 33


*It doesn’t matter if you don’t use a fan or heat bed for now.


Defines the number of extruders

If you use more than one extruders you can write it there. However we will not go into details about multiple extruders in this post.


#define EXTRUDERS 1

Thermal Settings

Temperature sensor choice

Among the list (in configuration.h), choose the thermistor number that you use for each of the hot ends and for the heat bed. If you pick the wrong number, you may have an inaccurate temperature reading but you can still do temperature control and be able to print correctly.


#define TEMP_SENSOR_0 1

#define TEMP_SENSOR_1 0

#define TEMP_SENSOR_2 0



TEMP_SENSOR_0 is used by the first hot end and TEMP_SENSOR_BED is connected to the heat bed. If you don’t use a sensor, use 0 to disable it.


Minimum temperature

Use a minimum temperature different than 0 to check if the thermistor is working. This security will prevent the controller from heating the hot end at max power indefinitely. This is important. It should already be set by default


#define HEATER_0_MINTEMP 5

#define HEATER_1_MINTEMP 5

#define HEATER_2_MINTEMP 5

#define BED_MINTEMP 5

*units are in °Celcius

Maximum temperature

Depending on your hardware material your hot end will have a specific maximum temperature resistance. This security will prevent the temperature from going over it. For example a J-Head extruder may use a PTFE tube to guide the filament in the hot zone which can be damaged over 240°C. Notice the controller can overshoot the target temperature by a couple of °C, it is better to keep a security margin here.


#define HEATER_0_MAXTEMP 230

#define HEATER_1_MAXTEMP 230

#define HEATER_2_MAXTEMP 230

#define BED_MAXTEMP 120

PID temperature controller.

This is an advanced option which needs to be tuned later. For now you can use the default options.

Prevent dangerous extrusion:

These settings are set by default.

For a security reason you may want to prevent the extrusion if the temperature of the hot end is under the melting point of the material. You don’t want to push the extruder over solid material and risk breaking it.




*Note that you can override this protection by sending a M302 command with the host software.

If there is a mistake in the code like a dot position for example, you would want to prevent a very long extrusion command.




Here you can set the values for the minimum temperature:



Mechanical settings

End Stops

End stops are switches that trigger before an axis reaches its limit. In other words: It will prevent the printer from trying to move out of its own frame. End stops are also used by the printer as a reference position. It will move each axis in a specific direction until it reaches an end stop, this is the home of the printer.

Pull-ups resistances

It is a good practice to use a pull-up or pull-down circuit for a basic switch. To keep it simple the pull-ups resistance are needed if you directly connect a mechanical endswitch between the signal and ground pins.

Fortunately there is already a pull-up resistor integrated in Arduino that can be activated by the software.

#define ENDSTOPPULLUPS // Comment this out (using // at the start of the line) to disable the endstop pull-up resistors


The Marlin firmware allows one to configure each limit switch individually. You can use multiple end stop types on the same printer.










Invert endswitch logic

Some limit switches are normally closed (NC) and turn off when triggered and some are normally open (NO) and turn on when triggered. Ideally the limit switches would be normally on and turn current off when triggered. The printer would interpret the same signal if the end stop is hit as if the end stop is broken or disconnected.


NO = true

NC = false


const bool X_MIN_ENDSTOP_INVERTING = false;

const bool Y_MIN_ENDSTOP_INVERTING = false;

const bool Z_MIN_ENDSTOP_INVERTING = false;

const bool X_MAX_ENDSTOP_INVERTING = false;

const bool Y_MAX_ENDSTOP_INVERTING = false;

const bool Z_MAX_ENDSTOP_INVERTING = false;

Use three or six end stops?

Under normal circumstance the printer would always know its position according to the home reference position and never move out of its maximum envelope. In this case three endstops would be enough. While running it is possible the 3D printer loses its position because of a collision or skipped steps. In this case the printer can eventually move out of its normal envelope and cause damage. Using end stops at each end of each axis would prevent such situations.

Uncomment the following lines to disable all max or all min end stops.




Invert stepper motor direction

There is only way to know if the stepper motor direction is correct and it is to try it. I would wait until the configuration is completed, compiled and sent to the controller before you try. You can come back here after.

  1. Position the printer axis at the center of each axis.

  2. Keep your finger close to the stop button.

  3. Send a command to move the X axis a little amount like +1 or +10 mm

  4. If the printer moves in the other direction, you will have to reverse the axis direction.

  5. Repeat for each X Y Z axis

To inspect the extruder you would need to heat the hot end to the extrusion temperature, otherwise you can temporarily disable the EXTRUDE_MINTEMP protection. Be sure to perform the test without the filament loaded. Send extrusion command of 10 mm and check the motor rotation direction.

You can invert the stepper motor direction if it was wired the wrong way. It doesn’t make a difference if you invert the stepper motor wiring or if you invert it in the code. *Remember to power off the printer before unplugging or replugging the stepper motors.


#define INVERT_X_DIR false

#define INVERT_Y_DIR true

#define INVERT_Z_DIR true

#define INVERT_E0_DIR true

#define INVERT_E1_DIR true

#define INVERT_E2_DIR false

Set home direction

Here we set the home direction when the home button is pressed. It tells the printer which direction it should go to reach the end stop and get its reference position.


#define X_HOME_DIR -1

#define Y_HOME_DIR -1

#define Z_HOME_DIR 1


The Z axis is the one which will get the printing surface very close to the nozzle. It needs to be very precise and very quick to trigger otherwise there will be a collision between the nozzle and the surface. I prefer to send the print surface to home in the max direction and come back closer when the printer knows where to stop.

Allow the printer to go beyond the end stops limits

If you use optical end stops for instance you can position the end stops at the center of the moving area. You can tell the printer to move over the end stop signal. I never use it. If you placed end stops at the end of each axis, then keep these options set to true.


Don’t go over the minimum limit:


#define min_software_endstops true


Don’t go beyond the maximum limit


#define max_software_endstops true

Printer area

Here we can tell the firmware what the limits are of the travel zones. The travel distance is not calibrated yet and the practical distance will be different than the calculated distance. For now it is better to reduce the travel distance a bit and come back later when it is calibrated.


#define X_MAX_POS 190

#define X_MIN_POS 0

#define Y_MAX_POS 190

#define Y_MIN_POS 0

#define Z_MAX_POS 190

#define Z_MIN_POS 0

Movement settings

Define the number of axis

It is the total number of axis (3) plus the number of extruders (1).


#define NUM_AXIS 4


Homing feed rate

This is the moving speed of the axis when homing in [mm/min]. Oftentimes in Marlin, speed or acceleration are expressed in [mm/s] or [mm/s2] but the feed is expressed in [mm/min].


#define HOMING_FEEDRATE {50*60, 50*60, 4*60}

Axis steps per unit

The stepper motor receives step by step moving command from the controller. The controller needs to know the steps/mm ratio to send the appropriate steps to reach the required distance. How many steps are needed to move an axis by 1 mm?


Belts and pulley (usually xy axis):

steps_per_mm = (motor_steps_per_rev * driver_microstep) /
(belt_pitch * pulley_number_of_teeth)

lead screw (z axis)
steps_per_mm = (motor_steps_per_rev * driver_microstep) / thread_pitch


Direct drive extruder:

e_steps_per_mm = (motor_steps_per_rev * driver_microstep) /
(hob_effective_diameter * pi)

 See the example of bowden extruder

Extruder with gear reduction:

e_steps_per_mm = (motor_steps_per_rev * driver_microstep) *
(big_gear_teeth / small_gear_teeth) / (hob_effective_diameter * pi)


#define DEFAULT_AXIS_STEPS_PER_UNIT   {80,80,200.0*8/3,760}

Send the firmware to the 3D Printer

In Arduino IDE, save the modification done to Configuration.h

Verify the code

If everything is fine, Arduino should say “Done compiling” otherwise you will get one or more error messages. If this happens, there is usually a mention about the line of the error. Check your code for a comments error //, dots or other special characters that may have been mistyped.

Once it is compiled properly you can connect the Arduino board to the computer with the USB cable.

Select the proper port, Tools menu / Serial Port / <port number>

Upload the compiled code to the Arduino

Now your printer is ready to move. It’s alive!!!

Just one more thing. You need to try the stepper motor direction as mentioned above. You will need to use a host software connected to the 3D printer. The instructions to use this software will be explained in another post, for now I will stick to the basic guidelines. You can find more info on Pronterface here:

You can also use Repetier which has an awesome G code viewer:

To test the motor direction, connect the printer to the computer with the USB cable.

  1. Position the printer axis manually at the center of each axis.

  2. Power up the printer

  3. Open a host software like Pronterface or Repetier

  4. Click to connect the host to the printer

  5. Keep your finger close to the stop button of the motherboard (just in case).

  6. Send a command to move X axis a little amount like +1 or +10 mm

  7. If the printer moves in the other direction, you will have to reverse the axis direction.

  8. Repeat for each X Y Z axis

To inspect the extruder you will need to heat the hot end to the extrusion temperature, otherwise you can disable the protection by sending the M302 command. Be sure to perform the test without the filament loaded. Send the extrusion command of 10 mm and check the motor rotation direction.


You can invert the stepper motor direction if it was wired the wrong way, it doesn’t make a difference if you invert the stepper motor wiring or if you invert it in the code. *Remember to power off the printer before unplugging or replugging the stepper motors.


#define INVERT_X_DIR false

#define INVERT_Y_DIR true

#define INVERT_Z_DIR true

#define INVERT_E0_DIR true

#define INVERT_E1_DIR true

#define INVERT_E2_DIR false

Next Step

This concludes the configuration. I hope you successfully got your 3D printer to move properly. The next step you will have to go through before printing accurately is the calibration. You can get more details from Triffid Hunter’s Calibration Guide.

I hope you liked this article and if you did, please let me know by clicking on the sharing buttons below.

What is your biggest difficulty with 3D printing?

Tell us more about your biggest issue with 3d printing. What problem would you like to solve? What would you like to read more about? I will use this information to write the next article topic. Thanks for sharing.

Your Name (optional)

Your Email (optional)

Your Message

What do you think?

21 thoughts on “Marlin firmware user guide for beginners

  • Chris

    I am using optical sensors but I cant get them to show up in pronterface. Is there a way to set up Marlin for optical sensors? Also I have a thermocouple on the heat bed instead of a thermistor how do I set it up in Marlin? Thanks for any help.

    • Frans van Heel

      I own a Velleman K8200. On my controllerboard i had to bridge the +5v & the GND above the X-endstop connector by soldering a thin wire between these solder ponts to make optical endstops to work.
      This enables the +5v of the optical endstops.
      This is for my board and could be different for other boards.

  • archy

    Hey Great set up guide. thanks for your work!

    Im looking for some way to add additional temperature control to marlin and cant seem to find any posts about it.

    For example, I am using the Rambo board which has 4 thermister inputs. 1 for the bed, 2 for dual extruders, and Id like the 4th to control the temperature of the box I built to hold my printer.

    my heat bed and extruders use PID control, but the fourth would ideally be bang bang style since the output pin with switch an AC relay, turning on and off power to an AC heater.

    any direction you could point me in to get this working would be helpful!


    • Normand Post author

      Sorry to tell you that but marlin is not designed to manage more than 2 heaters. All the extruders have the same pid settings and the bed have another set of settings. I’m afraid you would have to develop your own solution for this project.
      The rambo board has 4 thermistor inputs build-in and 3 outputs. For the fourth output I recommend you to use a solid state relay because the bang-bang switching will use the 100 000 cycles of a mechanical relay pretty fast.
      Good luck


    So I am an extremely novice programmer…probably comparable to your average pre-schooler…and I’ve been tasked with building our companies 3D printer. I’m nearly complete…i think…but keep getting this error when uploading:

    ultralcd.cpp: In function ‘void lcd_goto_menu(void (*) (), uint32_t, bool)’:
    ultralcd.cpp:195: error: ‘encoder’ was not declared in this scope

    I’m normally good at following directions, but not when I don’t have any….
    Please help

    • Normand Post author

      It seams related to your lcd screen.

      What I would do in your position is to use a utility like winmerge or to compare the difference between your firmware folder and a fresh downloaded one unmodified. Every modification you made will then be highlighted.
      Check if it compile without lcd option.
      Check the lcd type you use and ask more info from the supplier.

      It is difficult to find a solution with theses limited details and the amount of lcd display on the market.

  • Josh

    If I do not want to use the heaters or some of the end stops, can I just comment them out and will the program still run and machine still work how I want it to? Lets say I comment out the heatbed because I want to test some machine parameters, if I comment it and click run will it work?

    • archy

      You shouldn’t have to comment any of these out. If you never send the machine a set point for the bed temperature, it will never turn on. If you don’t have a heater plugged in to your board, it wouldn’t matter either way. Your slicer software should have a checkbox for heated bed. If you uncheck it, the slicer will never put temp set lines in your Gcode.

      I would suggest putting in the effort to get at least one endstop on each axis. This is so you can run the homing command and locate your print head at 0. I use one endstop at the min position (0), and dont have any endstops plugged in for the max position. I don’t comment anything about the max endstops out in my configuration.h file.

  • doug

    I found the guide to be helpful to me, I’m building a laser engraver with mostly scraps of hardware I’ve disassembled through the years, I did buy the laser diode/driver, and the Arduino 2560 with RAMPS 1.4 and Pololu drivers. Getting it all to work has been educational. Yesterday I was setting up the end stop on the X axis, and with no power to the machine, manually moved the axis screw to center the axis, and in the corner of my eye saw that the LED on the Arduino board was flashing. (no power connected when I did this) I understand that turning a stepper motor will create electric current, so I stopped what I was doing, and tried to move the axis with the Marlin firmware in the Arduino. Now the motor makes a squealing noise, but doesn’t move, unless I give it commands to move it in very small increments. I’ve tried the motor on the driver for the Y axis, and it moves, swapped out the A4988 driver for a new one, and still get no real movement on the X axis. Have I ruined my Arduino? The RAMPS board? Is there a test to determine what’s going on?

    • archy

      I wouldn’t expect this to destroy your board. Are you sure it worked before this incident?

      Remove the endstop you were working with and start over.

      Test the Y axis pololu with both the X and Y motors, then move the Y axis pololu to the place of the X axis pololu and test with both the X and Y axis motor (do not unplug motors or drivers while they are powered). Make sure the current limiting trimpot on the X axis pololu (and the second pololu you swapped out with) isn’t set too low. Make sure the jumper pins for setting microstepping are set the same for X and Y pololu locations (all shorted = 1/16th microstepping). Make sure axis steps per mm are correct for X and Y in marlin configuration.h

      just some guesses…

      • doug

        Thanks for the reply! Yes, it had been working prior to moving the axis manually. I tried moving parts around to see what results would be, moved the driver from the y axis position on the RAMPS board to the x position, and plugged the y axis motor to the plug for the x axis, and the y axis motor does the same thing that the x axis motor had been doing. It just makes a squealing noise, and no movement. So I’ve either ruined the RAMPS board, or the Arduino. I wonder if there’s a test to determine which, so I don’t end up buying one of each.

        • archy

          swap pololu and motor back to Y position and make sure everything still works there.

          disconnect motor from leadscrew and make sure it isn’t just the leadscrew/carriage binding.

          What software are you using to send the commands to the board? make sure speed hasn’t gotten changed for the X axis. If the speed is set too high or two low, the motor will just squeal. Make sure the software sending the commands isn’t overriding axis steps per mm for x axis. Re-flash marlin firmware and make sure steps per mm are still identical for X and Y. If number of steps per mm are way off, it is equivalent to commanding a speed that is too high or too low.

          are you powering the arduino board from the +-12 V for the ramps board? it is actually rather easy to burn out the voltage regulator on the arduino…especially if the endstops were wired incorrectly, it is easy to dead short +V to -V and burn out the regulator. The arduino board would still be usable, you would just have to power through the USB connector, or supply 5V from some other power supply. I believe this has to do with the D1 diode on the ramps board.

          try making sure you are supplying power to the arduino through only the USB connector, and supplying the ramps with a separate 12V supply.


          (actually tough to sort out the real details of D1, but with some trial and error I was able to sort out that my regulator was definitely fried. I could then only supply power from USB, or hard wire a 5V supply in, which is what I ended up doing, so I could disconnect from the PC during a job.)

          • doug

            Pololu and motor are back on Y and working like they did before, I went through my configuration.h file to see what I’ve got in the firmware, and I think I found what I did. Your clue about motor running too slow or too fast got me looking, and I’m going to have to understand more about microstepping and how the signals are understood from my firmware. My X axis is a screw drive, but the Y is a belt drive. X has 1260 steps/mm and my Y has 12 steps/mm. I had tried to make them match up so that a centimeter of travel on the X is the same distance as the Y axis.
            It is being quite the learning experience. This is my first Arduino project, so it’s learning about hardware, software, firmware. I appreciate your help! I’m happy to say that both X and Y are moving smoothly now!

  • Jonathan

    Well, everything looks fine except for one error. Please understand I’m probably not even a novice at programming.
    Under fastio.h, at the bottom of the page, I’m getting an error called “#error “unknown CPU” .” It seems that the ‘if’ and ‘elif’ statements aren’t proving true, with the last statement “#else” pointing to the statement “#error “unknown CPU” .”
    Don’t know what to do; help would be greatly appreciated!