Robot Arm Tutorials

Friday Facts 19: Marlin for Robot Arms

Today I’m going to show you how to set up Marlin firmware – the code in the robot brain – for your board so it thinks it is a robot arm and I will be using the Sixi 3 as my example. When we’re done we’ll have a 6 axis machine ready to receive gcode from apps like Robot Overlord.

Building a custom robot arm is easier if one uses common hardware. Thanks to the popularity of 3D printers it is now super easy to get stepper motors, limit switches, and MCUs that drive five, six, or even more motors. Marlin takes away all the headache and lets anyone talk to a robot with gcode, the standard language of CNC machines like 3D printers, mills, and lathes.

The major steps are:

  1. Fork Marlin
  2. Customize it
  3. Flash your board
  4. Test it

Fork Marlin

To “fork” is to make a special copy. it’s special because it includes a feature to update your copy with changes to the original. When the Marlin developers improve something, you can press a button and get all their updates.

The code for Marlin is available at https://github.com/MarlinFirmware/. I have a fork for robot arm Sixi 3 already started. You can get that fork as well right here: https://github.com/MarginallyClever/Marlin/

Make sure that (1) the branch is set to sixi3, then (2) click the code button and then (3) Open with Github Desktop or Download Zip. If it’s a ZIP you’ll have to unpack it somewhere like Documents/Github/Marlin.

Customize Marlin

Here’s a list of lines in Configuration.h that I’ve changed. The bold parts are unchanged so you can use that to search the file. The stepper motors in Marlin are named – internally only – as X, Y, Z, I, J, K.

#define STRING_CONFIG_H_AUTHOR “(Marginally Clever, Sixi3)”

#define MOTHERBOARD BOARD_RUMBA

#define CUSTOM_MACHINE_NAME “Sixi 3 robot arm”

#define EXTRUDERS 0

Because it’s a RUMBA board I also had to redefine a few of the pin settings. Normally all supported boards are defined in Marlin/src/pins/*.

#define I_STEP_PIN                         23
#define I_DIR_PIN                          22
#define I_ENABLE_PIN                       24
#define J_STEP_PIN                         26
#define J_DIR_PIN                          25
#define J_ENABLE_PIN                       27
#define K_STEP_PIN                         29
#define K_DIR_PIN                          28
#define K_ENABLE_PIN                       39

#undef Y_MAX_PIN
#undef Z_MIN_PIN
#undef Z_MAX_PIN

#define I_MIN_PIN                           34
#define J_MIN_PIN                           33
#define K_MIN_PIN                           32

The type of driver and the external name of each motor is next.

#define X_DRIVER_TYPE  A4988
#define Y_DRIVER_TYPE  A4988
#define Z_DRIVER_TYPE  A4988
//#define X2_DRIVER_TYPE A4988
//#define Y2_DRIVER_TYPE A4988
//#define Z2_DRIVER_TYPE A4988
//#define Z3_DRIVER_TYPE A4988
//#define Z4_DRIVER_TYPE A4988
#define I_DRIVER_TYPE  A4988
#define J_DRIVER_TYPE  A4988
#define K_DRIVER_TYPE  A4988

...

#ifdef I_DRIVER_TYPE
  #define AXIS4_NAME 'U' // :['A', 'B', 'C', 'U', 'V', 'W']
  #define AXIS4_ROTATES
#endif
#ifdef J_DRIVER_TYPE
  #define AXIS5_NAME 'V' // :['B', 'C', 'U', 'V', 'W']
  #define AXIS5_ROTATES
#endif
#ifdef K_DRIVER_TYPE
  #define AXIS6_NAME 'W' // :['C', 'U', 'V', 'W']
  #define AXIS6_ROTATES
#endif

Limit switches are tricky because the original Sixi 3 still doesn’t have them. (The plan is a new PCB that has always-on sensors). For Sixi 3 only, I have to trick the sensor code. When the robot turns on it will believe it has already homed, no matter where it is. A better robot with switches would call G28 to find home, and then the invert would depend on the type of switch (normally open vs normally closed) and I don’t remember what plug does.

#define USE_XMIN_PLUG
#define USE_YMIN_PLUG
#define USE_ZMIN_PLUG
#define USE_IMIN_PLUG
#define USE_JMIN_PLUG
#define USE_KMIN_PLUG

...

#define X_MIN_ENDSTOP_INVERTING false 
#define Y_MIN_ENDSTOP_INVERTING false 
#define Z_MIN_ENDSTOP_INVERTING false 
#define I_MIN_ENDSTOP_INVERTING false 
#define J_MIN_ENDSTOP_INVERTING false 
#define K_MIN_ENDSTOP_INVERTING false 
#define X_MAX_ENDSTOP_INVERTING true 
#define Y_MAX_ENDSTOP_INVERTING true 
#define Z_MAX_ENDSTOP_INVERTING true 
#define I_MAX_ENDSTOP_INVERTING false 
#define J_MAX_ENDSTOP_INVERTING false 
#define K_MAX_ENDSTOP_INVERTING false 

Motors also need gearbox and speed settings. Sixi 3 has a 70:1 harmonic gearbox and then a further pulley reduction in each unit. Since each motor does 200 steps per turn, that makes 105 steps per degree!

#define DEFAULT_AXIS_STEPS_PER_UNIT   { 105, 105, 105, 105, 105, 105 }

105 steps per degree * 5 deg/s = 525 steps per second. Impressive for such tiny NEMA17 motors. It might not be fast but it works and it’s affordable. Cheap, fast, good… pick two.

#define DEFAULT_MAX_FEEDRATE          { 5,5,5,5,5,5 }

#define CLASSIC_JERK // uncommented this to turn it on

#define S_CURVE_ACCELERATION // uncommented this to turn it on

I make sure to leave motors on so the arm doesn’t suddenly “go limp” at the worst time.

#define DISABLE_X false
#define DISABLE_Y false
#define DISABLE_Z false
#define DISABLE_I false
#define DISABLE_J false
#define DISABLE_K false

Range of motion is important, Marlin won’t let you go outside the limits. Remember this code was written for square box 3D printers, so some of the terms are a little silly for our needs.

// The size of the printable area
#define X_BED_SIZE 360
#define Y_BED_SIZE 360

// Travel limits (linear=mm, rotational=°) after homing, corresponding to endstop positions.
#define X_MIN_POS 0
#define X_MAX_POS 360
#define Y_MIN_POS 0
#define Y_MAX_POS 360
#define Z_MIN_POS 0
#define Z_MAX_POS 360
#define I_MIN_POS 0
#define I_MAX_POS 360
#define J_MIN_POS 0
#define J_MAX_POS 360
#define K_MIN_POS 0
#define K_MAX_POS 360

#define MIN_SOFTWARE_ENDSTOPS  // but no sub-values like MIN_SOFTWARE_ENDSTOP_X
#define MAX_SOFTWARE_ENDSTOPS  // but no sub-values like MAX_SOFTWARE_ENDSTOP_X

#define EEPROM_SETTINGS // save important data to EEPROM

#define SDSUPPORT

#define REPRAP_DISCOUNT_SMART_CONTROLLER // or your favorite flavor here

#define NUM_SERVOS 1 // for the gripper

Flash your board

Press the Compile button (1) to check for errors. Press the Upload button (2) to send it to your connected device. Press the Connect button (3) to open a serial monitor and check that your device says it is now a Marlin device. If all goes well, you’re ready to rock!

Test your new device

Even before your board is installed in an arm you should be able to home it with G28 and move it with G0/G1. Remember: every bug is just a test you didn’t run!

Final thoughts

Now that you have a 3D printer board setup to run Marlin, it should be able to receive angle values as gcode. Each set is one forward kinematic pose of the arm. Moving between two poses will send the arm in curving arcs. Lots of poses close together will create the look of straight lines. Planning all those poses is easy for apps like Robot Overlord. That’s why I wrote it!

Got more questions? Something out of date in this post? Join us on Discord.

News

Friday Facts 12: How to use Marlin in a Robot Arm

Building a robot arm is one thing, but what about writing the code to make it run? Some people want to learn the fine points of precision stepper motor control, forward and inverse kinematics, and then debug all that stuff. For the rest, working together gets the job done faster. For those people the Marlin 3D printer firmware is a great option. Today I’m going to show how I tweaked it to run in the Sixi 3 robot arm. Please share your experience with us so we can improve this post.

Marlin?

Marlin 3D printer firmware is the code in the brain of a very large number of printers. It is very flexible with a few changes. Most people might think of printers as having four motors – one for each direction and one for the extruder. But recent changes mean that Marlin can run up to six motors. That’s great for us, because most robot arms are 6 or less.

With Marlin installed you’ll be able to control the angle of each motor by sending gcode commands and even drive them simultaneously. With Marlin’s homing routines you could locate position, and new options coming in the near future will give real time feed back (more on that later)

What needs to be tweaked

Pour yourself a drink and settle in. This list will touch at least two files and take some time… OR you can use the sixi3 branch I maintain and adjust it for your speeds and gear ratios.

I keep trying new ways to make this list less dry. What do you think?

/Marlin/Configuration.h

Old valueNew Value
#define STRING_CONFIG_H_AUTHOR “(none, default config)”#define STRING_CONFIG_H_AUTHOR “(Sixi3, Marginally Clever Robots)”
#define MOTHERBOARD BOARD_RAMPS_14_EFB#define MOTHERBOARD BOARD_RUMBA
//#define CUSTOM_MACHINE_NAME “3D Printer”#define CUSTOM_MACHINE_NAME “Robot Arm”
//#define LINEAR_AXES 3#define LINEAR_AXES 6
#define AXIS4_NAME ‘A’#define AXIS4_NAME ‘U’
#define AXIS5_NAME ‘B’#define AXIS5_NAME ‘V’
#define AXIS6_NAME ‘C’#define AXIS6_NAME ‘W’
#define EXTRUDERS 1define EXTRUDERS 0
#define USE_XMIN_PLUG
#define USE_YMIN_PLUG
#define USE_ZMIN_PLUG
//#define USE_XMIN_PLUG
//#define USE_YMIN_PLUG
//#define USE_ZMIN_PLUG
//#define I_DRIVER_TYPE A4988
//#define J_DRIVER_TYPE A4988
//#define K_DRIVER_TYPE A4988
#define E0_DRIVER_TYPE A4988
#define I_DRIVER_TYPE A4988
#define J_DRIVER_TYPE A4988
#define K_DRIVER_TYPE A4988
//#define E0_DRIVER_TYPE A4988
#define DEFAULT_AXIS_STEPS_PER_UNIT { 80, 80, 400, 500 }#define DEFAULT_AXIS_STEPS_PER_UNIT { 105, 105, 105, 105, 105, 105 }
#define DEFAULT_MAX_FEEDRATE { 300, 300, 5, 25 }#define DEFAULT_MAX_FEEDRATE { 5, 5, 5, 5, 5, 5 }
#define DEFAULT_MAX_ACCELERATION { 3000, 3000, 100, 10000 }#define DEFAULT_MAX_ACCELERATION { 10, 10, 10, 10, 10, 10 }
//#define CLASSIC_JERK#define CLASSIC_JERK
//#define S_CURVE_ACCELERATION#define S_CURVE_ACCELERATION
#define E_ENABLE_ON 0 // For all extruders
//#define I_ENABLE_ON 0
//#define J_ENABLE_ON 0
//#define K_ENABLE_ON 0
//#define E_ENABLE_ON 0 // For all extruders
#define I_ENABLE_ON 0
#define J_ENABLE_ON 0
#define K_ENABLE_ON 0
#define INVERT_Y_DIR true#define INVERT_Y_DIR false
//#define INVERT_I_DIR false
//#define INVERT_J_DIR false
//#define INVERT_K_DIR false
#define INVERT_I_DIR false
#define INVERT_J_DIR false
#define INVERT_K_DIR false
//#define I_HOME_DIR -1
//#define J_HOME_DIR -1
//#define K_HOME_DIR -1
#define I_HOME_DIR -1
#define J_HOME_DIR -1
#define K_HOME_DIR -1
define X_BED_SIZE 200
define Y_BED_SIZE 200
//#define X_BED_SIZE 200
//#define Y_BED_SIZE 200
#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 X_MIN_POS -360
#define Y_MIN_POS 360
#define Z_MIN_POS -360
#define X_MAX_POS 360
#define Y_MAX_POS -360
//#define I_MIN_POS 0
//#define I_MAX_POS 50
//#define J_MIN_POS 0
//#define J_MAX_POS 50
//#define K_MIN_POS 0
//#define K_MAX_POS 50
#define I_MIN_POS -360
#define I_MAX_POS 360
#define J_MIN_POS -360
#define J_MAX_POS 360
#define K_MIN_POS -360
#define K_MAX_POS 360
#define HOMING_FEEDRATE_MM_M { (50*60), (50*60), (4*60) }#define HOMING_FEEDRATE_MM_M { (4*60), (4*60), (4*60), (4*60), (4*60), (4*60) }
//#define EEPROM_SETTINGS#define EEPROM_SETTINGS
//#define SDSUPPORT#define SDSUPPORT
//#define REPRAP_DISCOUNT_SMART_CONTROLLER#define REPRAP_DISCOUNT_SMART_CONTROLLER

/Marlin/Configuration_adv.h

define AXIS_RELATIVE_MODES { false, false, false, false }#define AXIS_RELATIVE_MODES { false, false, false, false, false, false }
#define HOMING_BUMP_MM      { 5, 5, 2 }
#define HOMING_BUMP_DIVISOR { 2, 2, 4 }
#define HOMING_BUMP_MM      { 5, 5, 5, 5, 5, 5 }
#define HOMING_BUMP_DIVISOR { 2, 2, 2, 2, 2, 2 }

Notes

  • MOTHERBOARD is your choice of brain board. Anything Mariln supports AND has 6 axies will work.
  • DEFAULT_AXIS_STEPS_PER_UNIT is the gear ratio at the given joint. For all sixi3 gearboxes the ratio is 70:1 (harmonic) * 54:20 (timing belt) * 200/360 (for 1.8 degree stepper motors at full step) = 105.
  • Because the gear ratio is so high the motors are not physically able to exceed the DEFAULT_MAX_FEEDRATE. If you use faster motors or a faster brain board you may be able to improve on these numbers.
  • EEPROM_SETTINGS, SDSUPPORT, and REPRAP_DISCOUNT_SMART_CONTROLLER are not required. I use these to tweak settings for testing, run programs from the SD card, and to have an LCD panel on my robot.
  • Every other change is to adjust from 3 axies to 6.

Homing and Real time feedback

There are some exciting new features coming to Marlin that should make real time feedback possible. This means we’ll know the robot position without having to guess or to home. It also means we can tell when the actual position deviates from the expected position too much that a collision has occurred and that can save a lot of trouble! The new configuration options to explore are:

  • REALTIME_REPORTING_COMMANDS adds some “quick commands” that get processed before anything else in the gcode buffer of the robot. Great for emergency breaking and for requesting position information (Gcode “S000”)
  • M114_REALTIME adds “M114 R” which reports the real-time position of the robot instead of the projected position at the end of the planned moves.
  • I2C_POSITION_ENCODERS is a first pass at adding real time sensors. This will no doubt be expanded later to include other types and features.

Further Reading

The Marlin Configuration guide online

News

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.

Marlin\Configuration.h

#define MOTHERBOARD BOARD_RAMPS_14_EFB

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.

#define HYPOTENEUSE_LENGTH_AT_HOME_POSITION 1035.0

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.

Image
Image

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.

#if MOTHERBOARD == BOARD_RUMBA
  #define X_MAX_PIN       35
  #define Y_MAX_PIN       34
#endif

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.

#define USE_XMIN_PLUG
#define USE_YMIN_PLUG
#define USE_ZMIN_PLUG

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.

//#define EEPROM_SETTINGS

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.

//#define DEACTIVATE_SERVOS_AFTER_MOVE

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.

Marlin\Configuration_adv.h

#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

#define REPRAP_DISCOUNT_SMART_CONTROLLER

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.

Custom hardware and DEFAULT_AXIS_STEPS_PER_UNIT

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 https://marlinfw.org/meta/gcode/