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.

Art In the News Makelangelo

Friday Facts 18: New Makelangelo generators

The Makelangelo plotters software is always getting improvements and today I’d like to share some of the latest with you. As of today the last official release of Makelangelo Software is 7.37. But did you know that exciting work is always going on in the discussion group? Hot new stuff is being added all the time. We’re up to version 7.44. Here’s a list of changes.

  • Firmware can now be updated from every platform
  • Added image intensity to height converter
  • Added Quadtree-like instant filter
  • Added Circular mazes
  • Added Honeycomb mazes
  • Added more Truchet Tiles
  • Misc other fixes

Firmware can now be updated from every platform

OSX proved to be quite challenging. But it was worth it if it makes everyone’s life easier going forward. Firmware changes are rare and now they are that much less painful. So now when the code in the brain of the robot is changed you won’t have to jump through a lot of hoops. Instead you can use File > Update firmware and follow the prompts.

Added image intensity to height converter

The change in height of each line is affected by the intensity of the underlying image. Line spacing and line offset are adjustable from the menus.

Image

Added Quadtree-like instant filter

Contributed by itsMohammedThaier. Starting from the whole picture, divide the rectangle in 4 quadrants. if the chnage in color over a quadrant is too much, split this quadrant and repeat.

Image

Added Circular mazes

What’s not to love? Being randomly generated from a depth-first search, I’m pretty sure there are sometimes two ways to solve each maze.

Image

Added Honeycomb mazes

Would you believe all well-formed mazes are generated the same? The difference is in how the walls are drawn.

Image

Added more Truchet Tiles

Orthogonal, Diagonal, and Curved. You can mix and match them together!

Image

And more!

  • Better drawing of counterweights and belts
  • Added timestamps to Marlin conversation
  • Added more unit tests for unused translations and missing translations
  • Internally merged shared code for Vornoi diagrams
  • Internally merged shared code for Truchet tiles
  • Internally merged shared code for Mazes

Final thoughts

So if any of that seems interesting to you, check it out in the nightly builds.

Thank you to everyone who donated to support the software development. Your donations keep me in beer, and beer keeps me at Ballmer peak.

Discuss this and anything else plotter related on our Discord.

News

Robot Overlord 2.7.0: Vehicles

Today I’m delighted to announce that Robot Overlord 2.7.0 is out and it adds vehicles. Build your own or use presets like front-wheel drive, rear-wheel drive, motorcycle, mecanum, omni, or tank.

Here are the basic driving controls:

Image

This is what it looks like in the scene graph:

all vehicles start with a CarComponent:

Some wheels can be steered by adding a ServoComponent in the suspension:

I’m especially pleased by the graph tool I made for the PID controller and Torque Curve.

A PID controller (Proportional, Integral, Derivative controller) is a type of control system used to regulate different types of processes. It’s like an auto-pilot mode for controlling systems. Imagine you’re driving a car. You want to keep your car at a constant speed, say, 60 km/hour.

  • The “Proportional” part is like your foot on the gas pedal. If you’re going below 60, you press the pedal down more. If you’re going above 60, you let up on the pedal. The more you are below the target, the harder you press, and vice versa.
  • The “Integral” part is like your memory of what you’ve done so far. If you’ve been below 60 for a while, even if you’re close now, you might press a bit harder on the gas pedal because you remember you’ve been going too slow. It helps to correct sustained, systematic errors (like if your car was carrying heavy weight in the back).
  • The “Derivative” part is like your anticipation of what’s coming. If you’re below 60 but rapidly accelerating, you might ease up on the gas a little, because you’re anticipating hitting the target soon. It helps to mitigate sudden changes (like if you’re about to go downhill).

The torque curve is the relationship between motor speed and motor power. The example graph below is for a NEMA 17 stepper motor used in the Makelangelo art robot.

There’s also a WheelComponent that holds the size and shape of the tires

And of course vehicles need at least one motor

Why cars?

The goal of Robot Overlord is to simulate any kind of robot including robot cars. I would like to see Robot Overlord become the sim/control app used everywhere: All the goodness of free open source, no funky linux like ROS. Tell your teachers, your friends, your preacher, your boss, your employees, your lover, your best friend…everybody.

Plus! The previous way of making robot arms had bones and was missing motors. Now that vehicles have been used to test motors all the arms can be upgraded to use the new system. In app I made one motor with one output and then copy/pasted to LEGO together a 6 axis robot arm. Stepping the motors makes the arm move.

That’s incredibly powerful modular design at work. Love it!

Final thoughts

This is the first version that can be downloaded in all three flavors: Windows, OSX, and Linux. Choose your favorite from the Robot Overlord store page. Huzzah!

2.8.0 will likely be an interim version that converts the existing robot arms to the new motor-driven system.

Full instructions for building custom vehicles are in the Robot Overlord wiki.

As always, you can find me on Discord where I often live code and talk robots.

News

Daisy Driver 2.2

Today I’m delighted to bring you an update to my earlier post about the Daisy Driver motor controller. The latest version meets all my requirements and now I can focus on the next parts of the Sixi 3 robot arm project. I’m making it availble to you right here, right now. Join me in building a world with more interesting robots and read on for all the details.

Read more: Daisy Driver 2.2

What’s in the board?

The Daisy Driver can do so much!

  • The STM32F405 brain is huge and crazy fast. 168 MHz CPU/210 DMIPS, up to 1 Mbyte of Flash.
  • The TMC2130 motor driver can handle up to 1.5amps and includes current change sensing, which could be used for collaborative robots that sense collisions.
  • The IPS2200 rotation sensor is absolute – no need to “home” – touch off a limit switch – when the robot turns on. It always knows where it is.
  • The rotation sensor is also hollow-shaft. A wire can go through the sensor, through the center of the gearbox, and out to the next Sixi 3 actuator.
  • The board can be connected to its neighbors in a linked-list of actuators. They talk to each other through the CANbus network using the CANOpen protocol. This makes electrical work a breeze.
  • Since every CAN device needs a unique address, 6 dip switches make it easy to setup. No pads to solder!
  • It also has a USB connection so you can use a normal Serial interface from your favorite app to talk to the device.
  • The JTAG programming pins make it simple to upload new code from Arduino. Check out our daisy driver Arduino firmware.
  • The RGB LED is a handy status indicator. Have it display CANbus traffic, sensor angle, or morse code!

So why is this important?

Sixi 2 with inside wiring
Sixi 3 with outside wiring

The Sixi 2 robot was my fourth robot arm. It was big, strong, and gorgeous. But it was also 1300 parts in 250 types and it had long cables that ran from the wrist, through the elbow, and into the base. If I’m going to make robots easy for everyone then this is not workable. So I went back to the drawing board again and decided to build a modular robot arm out of identical pieces. The Sixi 3 actuator has less than 50 parts in about 20 types. Even with six actuators in a chain to make a Sixi 3 robot arm that’s less than 300 parts total and none of them are one-offs. production and maintenance at scale! The factory must grow.

Why Daisy Chain?

There are three main ways to wire the joints in a robot arm: all-outside, all-inside, and daisy chain.

All outside wires are easy for maintenance but hard to manage while the robot is running. I’ve had robots try to strangle themselves on their own cabling by accident.

All inside wires are tidy and elegant, but doing any service work means dismantling the entire arm.

Daisy chain is the best of both worlds: no outside wiring and easy maintenance. I’ve tested replacing the elbow of a Sixi 3. It takes about 10 minutes.

So now what?

Next up is to share the goodness with you. The board is available now. More are on the way and I can now refocus my energy on the next step in the bigger picture: using one arm to assemble another arm. As that happens I’m going to need more actuators, more boards, and more gearboxes, plus the Robot Overlord software to run everything.

I’m very interested in talking to anyone that would like to help make an awesome harmonic gearbox, anyone into creating data sheets for electronics, anyone who sees the potential.