Friday Facts 4: How to Marlin Polargraph

Assuming you have two stepper motors, two limit switches, some timing belt, a 3D printer control board, and a hobby servo then you have everything you need to make a wall hanging plotter of your own that will work with Makelangelo Software. Read on for firmware configuration.

All the changes described herein have been applied to the fork of Marlin we maintain on Github. Make sure you are working with the branch called 2.1.x-polargraph which should match this blog post. You can modify this setup for your custom board. Many people have successfully built RAMPS+mega derivatives and shared their success stories in the Discord channel.

You’ll need to open the firmware in an Integrated Development Environment like Visual Studio Code and install the PlatformIO plugin.

The main files we’ll touch are Marlin\Configuration.h and Marlin\Configuration_adv.h. First I will show the line to find and then explain what is changed and why.



This sets the type of brain board you are using. The full list can be found in Marlin\src\pins\pins.h. In my case I change BOARD_RAMPS_14_EFB to BOARD_RUMBA.

#define CUSTOM_MACHINE_NAME "3D Printer"

Change 3D Printer to Polargraph. It’s aesthetic and non-essential.

#define EXTRUDERS 1

Polargraphs have no extruders. Change 1 to 0.

//#define POLARGRAPH

I remove the // part in front of # so that it becomes defined.


Makleangelo uses 1m belts. The pen holder adds a small amount to that and so my length for both belts is 1035. Correct belt length is essential to getting square drawings. While this is the default number in Marlin, you may have to change it – especially if you are making a huge machine.


100mm (radius of pen holder) – 14.466 (curved part of belt over pulley) – 50 (straight part of belt from switch to pulley) = 35.53400. That’s how a 1m belt becomes a hypoteneuse of 1035.

For Makelangelo huge 2035 worked great on 2m belt. From this I conclude that (the length of the pen holder arms) – (the part of the belt lost inside the motor mount) = +35mm. If you make a custom pen holder or different motor mounts your 35 will change.

  #define X_MAX_PIN       35
  #define Y_MAX_PIN       34

These are the digital pins that are connected to your limit switches, uses for homing. When homing the machine will move the pen down and the counterweights up until the weights touch the switches. That is the maximum reach of each belt, and thus the max limit switch. For most boards, including RAMPS, you can ignore these lines so long as your switches are wired to x max and y max, respectively. These are here because RUMBA usage for polargraph predates Marlin adoption and Marlin needed to be made backward compatible for all existing customers.


I disable using minimum limit switch by adding // at the start of these lines.

//#define USE_XMAX_PLUG
//#define USE_YMAX_PLUG
//#define USE_ZMAX_PLUG

I enable using maximum limit switch by removing the // at the start of these lines.

#define X_MAX_ENDSTOP_INVERTING true // Set to true to invert the logic of the endstop.
#define Y_MAX_ENDSTOP_INVERTING true // Set to true to invert the logic of the endstop.
#define Z_MAX_ENDSTOP_INVERTING true // Set to true to invert the logic of the endstop.

I have switches wired to go LOW when they are clicked. If you have it the opposite then you’ll want to leave these set to false.

#define E0_DRIVER_TYPE A4988

There is no E0 Driver and the sanity checks in Marlin will get mad if this is defined. Put another // at the start of the line.

#define X_DRIVER_TYPE  A4988
#define Y_DRIVER_TYPE  A4988

If you are using something other than an A4988 stepper driver for your motor… this is where you’d list it.

#define DEFAULT_AXIS_STEPS_PER_UNIT   { 80, 80, 400, 500 }

There are only three axies of motion on this system, so we have to change it from { 80, 80, 400, 500 } to { 80, 80, 80 }. That assumes 200 step-per-turn motors and a 20 tooth GT2 pulley at 1/16 microstepping. (200*16) / (20*2)=80. Adjust your numbers accordingly. a 400-step motor would be 160 for the first two. The third is not really important because we don’t use a third stepper motor. Marlin won’t let me set two axies so it dangles on the end there like a vestigial tail.

#define DEFAULT_MAX_FEEDRATE          { 300, 300, 5, 25 }

I have changed these to { 90*60, 90*60, 90*60 }. Experiment with this number and see what kind of speeds you can get!

#define DEFAULT_MAX_ACCELERATION      { 3000, 3000, 100, 10000 }

I set mine to { 40*60, 40*60, 40*60 }. Another area I encourage you to experiment.

//#define CLASSIC_JERK

I don’t remember why I had to remove the // part but I did to appease the sanity checks.

#define INVERT_X_DIR false

By default Makelangelos are built with the left motor physically wired backwards so that “pull in” and “push out” was the same for both. So I have to change false to true. Discord user CaptFuture pointed out if you are building a DIY machine be aware mixing the wiring and the inversion might make some motors behave backwards.

//#define NO_MOTION_BEFORE_HOMING // Inhibit movement until all axes have been homed.
//#define HOME_AFTER_DEACTIVATE   // Require rehoming after steppers are deactivated.

I removed // from both. Safety third, right after chainsaws and LSD.

#define X_HOME_DIR -1
#define Y_HOME_DIR -1
#define Z_HOME_DIR -1

I changed these to 1 so that it homes to the maximum limits.

#define X_BED_SIZE 200
#define Y_BED_SIZE 200

Here I set the X_BED_SIZE to the width of a Makelangelo. The width is measured from one motor shaft center to the other motor shaft center. Makelangelo 5 is 650mm. For the Makelangelo height I used 1000mm (1m). More on this in a minute. Note: this number cannot be an odd number.

#define X_MIN_POS (-X_BED_SIZE/2)
#define Y_MIN_POS (-Y_BED_SIZE/2)

The bottom-left corner of the drawing area would then be – X_BED_SIZE/2 and -Y_BED_SIZE/2, or -325 and -500, respectively.

#define X_MAX_POS (X_BED_SIZE/2)
#define Y_MAX_POS (Y_BED_SIZE/2)

The top-right corner of the drawing area would then be X_BED_SIZE/2 and Y_BED_SIZE/2, or 325 and 500, respectively.

//#define BED_CENTER_AT_0_0

I removed the //. You can tell from the math that it should be true.

//#define MANUAL_X_HOME_POS 0
//#define MANUAL_Y_HOME_POS 0

First I remove the //. Then the MANUAL_Y_HOME_POS is equal to -482.65. I get that number from

Y_MAX_POS - ( sqrt( sq(POLARGRAPH_MAX_BELT_LEN) - sq(X_BED_SIZE/2) ) )

Remember using the triangle adjacent and the opposite to get the hypoteneuse? well here we use the opposite (machine bed size) and the hypoteneuse (the belt length) to get the adjacent, and then adjust by the Y_MAX_POS.

Image courtesy of Discord user PO

Note that the final value has to be inside the allowable drawing area of the machine – you can’t home to a spot that’s outside the printable area. That means the -Y_BED_SIZE/2 has to be a larger negative number than the MANUAL_Y_HOME_POS. With my settings -Y_BED_SIZE/2 is -500 and everything is fine.


remove the //. EEPROM_SETTINGS will allow you to tweak some firmware settings like acceleration and steps/mm from the LCD panel and then save them to the printer’s (very tiny) memory. Worth it!

//#define SDSUPPORT

If you have an SD card slot, remove the //.

//#define NUM_SERVOS 3

I set this to 1. As Jack Black said, one’s all you need.


Remove the //. This keeps the servo from jittering when not being used, which makes for a more pleasant sounding machine. It is reactivated every time it is used, don’t worry.


#define AXIS_RELATIVE_MODES { false, false, false, false }

Change to { false, false, false } because there are three axies and zero extruders. Keeps the sanity check happy.

#define MICROSTEP_MODES { 16, 16, 16, 16, 16, 16 } // [1,2,4,8,16]

Change to { 16, 16, 16 } to keep the sanity check happy. Same reason. This is where you’d set your microstepping values.

#define MANUAL_FEEDRATE { 50*60, 50*60, 4*60, 2*60 }

I changed to { 50*60, 50*60, 4*60 }. Three axis! THREE.

#define G0_FEEDRATE 3000 // (mm/min)

I changed the number to 12000. What can I say? I like to go fast.

LCD panels

Discord member Headly pointed out that there’s no mention of LCD control panels. Search Configuration.h for “LCD / Controller Selection” and then start reading. There are many choices from which to choose. For Makelangelo I use


If your Makelangelo has no LCD panel you must DISABLE this feature. When the robot is told to change pens (Gcode M0) it will wait for the user to click the dial. With no dial and no LCD, the user will be confused while the robot patiently waits forever.

While the previous Makelangelo-firmware talked at 57600 Baud, Marlin defaults to 250000. If you connect the app to your firmware and nothing is “heard” from the robot then the app and the robot are on two different baud rates.

Discord member Mesut asked about the minimum temperature settings in Marlin. There is no extruder so minimum temp settings are ignored by Marlin.

Help! Every G0 move goes to center!

Most motherboards that run Marlin have a small amount of EEPROM memory that needs to be initialized once to hold tweakable settings like top speed and machine dimensions. By default they are all zero, which makes math fail in the firmware and sends the pen holder to 0,0 on every move.

If you have an LCD panel connected to your machine the firmware should request a firmware reset at startup.

Another way is to connect over serial and send two commands: Reinitialize your EEPROM with an M502 factory reset, then save your EEPROM changes with an M500. Recheck that your machine width and height is not zero with an M503.


If you are building a custom machine, be aware that there are more settings to check. The DEFAULT_AXIS_STEPS_PER_UNIT is calculated this way:

( motor total steps per turn * microstepping ) / ( pulley pitch circumference )

Makelangelo uses 200 steps-per-turn motors and 16 microsteps. The pulleys are 20 tooth GT2 pulleys, or 40mm pitch circumference. That means our math is 200 * 16 / 20 or 80 steps per unit.

Be sure to check that your microstepping switches/jumpers match your math!

Final thoughts

After all these changes you should be able to upload the firmware and start running your polargraph drawing robot. Take it in small steps – try homing your machine with no belts on and then touch the switches to see if it behaves. Also check the pulleys turn the correct direction before putting the belts on.

By default Makelangelo software uses a servo position of 90 (middle of the range) for pen up and 40 for pen down. Keep that in mind when you install the servo horn (the finger thing that lifts).

If you have any trouble with this, please join me and other polagraph fans on the Discord channel. It may be you’re doing something exotic; maybe this document needs a refresh; or you just want to find people with similar tastes. Join us!

Further Reading

The Marlin Configuration guide online

You can find more serial commands at


Makelangelo software 7.26.0 beta

This Makelangelo software 7.26.0 beta release brings several changes that should improve drawings and quality of life. It is a pre-release for the very brave. If you do try it then please come to our Discord, introduce yourself, and tell us about the experience so we can make it better.

All new firmware

Before Marginally Clever Robots was even conceived I was learning to move motors with Arduino. As time went on 3D printers arrived and the Marlin firmware in my Prusa printers got really really good. So good, in fact, that I make a fork of the Marlin code and taught it to run a Makelangelo 5 robot. It is smoother, faster, and it means going forward I will have more time to do the things Marginally Clever Robots is good at.

Firmware update tool for Windows

Built into the Makelangelo app is a new firmware update tool. Your robot must be on and connected via USB cable. The app should not be connected to the robot yet.

  • avrDude path: is the location of the windows tool that uploads the .hex file to your robot. A copy has been included in this release. If you have Arduino software installed it will try to use that instead.
  • *.hex file: is the file to upload. This release includes a file called firmware-2021-09-10.hex.
  • Port: is the COM port your robot appears on when USB connected.
  • Refresh: will update the COM port list if you add/remove a robot.
  • Start: will initiate the upload process. It can take up to 2 minutes.

Sending code to the robot

The correct way to send a file to the robot is to use Makelangelo > Save to File/SD card. Save the *.gcode file to your SD card (included with the robot) and run your code from the robot.

Quality of Life

I want to separate the “make art” part of the app from the “drive robot” part of the app. You will find new top level menu items for all art stuff, and the right hand panel is for driving-only.

They are as follows:

  • Makelangelo > New: start over
  • Makelangelo > Open File: open an image file and begin converting it to lines.
  • Generate Art: The name hasn’t changed, only the location. The artwork does not “stack” – a new creation will replace the old one.
  • Art Pipeline: This might be renamed later to “tools”. It includes things like scaling, flipping, and the Simplify and Reorder actions. Until now every image loaded automatically ran simplify and reorder, even if you were not done experimenting with your image conversion. Now you must do it explicitly. Take note of your estimated drawing time, it will often drop by large amounts!

Final thoughts

This release does not respond to connect + drive commands. It tries to connect, does not recognize the new firmware, and then never unlocks the driving buttons. At this time I want to gauge your feelings about the new firmware and the quality of life changes.

The tool works in Windows only. It should make life easier for 99% of the artists out there. The firmware upload tool is only designed for the Makelangelo 5 robot.

This version of the Makelangelo Software app is written for Java 15. Get Java SE 15 here.

For the rest of you… please come to our Discord, introduce yourself, and we’ll figure it out together!


Makelangelo update!

Makelangelo firmware has been updated to v9.1.0.

  • If I run a Makelangelo 5 from the LCD panel and tell it to go home, it will often go to a position high on the left side. This was the symptom of an off-by-two problem in the EEPROM, which has been fixed.
  • Added Dynamic Acceleration: accelerate more slowly at the bottom and in the corners to avoid swinging from the pen holder and get better quality drawings
  • Improved LCD menu options with a toggle up/down command, a status menu, and more responsive dial behavior.

Makelangelo software has been updated to 7.21.0.

  • Better DXF and SVG handling
  • candy-cane coloring of line segments to show more of what’s going on in the mind of the robot
  • better time estimates
  • at the end of a Makelangelo 5 drawing, move the pen away from the image.

These two must be updated together. For help with updating the firmware, please see our pictoral guide.


Makelangelo software 7.8.0, Makelangelo firmware 7.0.0

Makelangelo software 7.8.0 brings friendlier CPU usage, new generators, DXF export for your CNC machine, and a host of bug fixes.  Did you know there are now over 2500 Makelangelo robots around the world? Awesome!