1. About
  2. Features
  3. Explore

On a Cartesian printer movements are really simple. If we assume the printer has 100 steps/mm on each axis, then a move of 10mm on a axis is just 1000 Steps on that axis.

Movements that are not aligned with one axis are also simple. Moving from x,y = 0,0 to 10,10 would be 1000 steps on x and y.

On deltas even for simple moves more than one motor has to move. And just calculating the amount of steps on each axis needed to reach the destination probably gives a curved move.

So what is the algorithm to calculate the steps for a given move for a delta printer?

1 Answer 1

I am describing how this is done in the Marlin firmware.

The first step is to split a linear movement from (x, y, z) to (x', y', z') into many discrete segments. To this end, the amount of time the move would take at a given speed is calculated, and the value delta_segments_per_second is used to calculate the number of segments used.

This is done in the function prepare_move_delta in the file Marlin_main.cpp. The endpoints of each of these segments is then passed to the function calculate_delta:

void calculate_delta(float cartesian[3]) { //reverse kinematics. // Perform reversed kinematics, and place results in delta[3] // The maths and first version has been done by QHARLEY . Integrated into masterbranch 06/2014 and slightly restructured by Joachim Cerny in June 2014 float SCARA_pos[2]; static float SCARA_C2, SCARA_S2, SCARA_K1, SCARA_K2, SCARA_theta, SCARA_psi; SCARA_pos[X_AXIS] = cartesian[X_AXIS] * axis_scaling[X_AXIS] - SCARA_offset_x; //Translate SCARA to standard X Y SCARA_pos[Y_AXIS] = cartesian[Y_AXIS] * axis_scaling[Y_AXIS] - SCARA_offset_y; // With scaling factor. #if (Linkage_1 == Linkage_2) SCARA_C2 = ((sq(SCARA_pos[X_AXIS]) + sq(SCARA_pos[Y_AXIS])) / (2 * (float)L1_2)) - 1; #else SCARA_C2 = (sq(SCARA_pos[X_AXIS]) + sq(SCARA_pos[Y_AXIS]) - (float)L1_2 - (float)L2_2) / 45000; #endif SCARA_S2 = sqrt(1 - sq(SCARA_C2)); SCARA_K1 = Linkage_1 + Linkage_2 * SCARA_C2; SCARA_K2 = Linkage_2 * SCARA_S2; SCARA_theta = (atan2(SCARA_pos[X_AXIS], SCARA_pos[Y_AXIS]) - atan2(SCARA_K1, SCARA_K2)) * -1; SCARA_psi = atan2(SCARA_S2, SCARA_C2); delta[X_AXIS] = SCARA_theta * SCARA_RAD2DEG; // Multiply by 180/Pi - theta is support arm angle delta[Y_AXIS] = (SCARA_theta + SCARA_psi) * SCARA_RAD2DEG; // - equal to sub arm angle (inverted motor) delta[Z_AXIS] = cartesian[Z_AXIS]; } 

This function takes care of the delta geometry and calculations needed to convert the (x,y,z) coordinates of the segment endpoints to corresponding positions for the carriages. The translated coordinates are then passed to plan_buffer_line, which calculates the steps needed for each stepper motor and actually makes these steps happen.

The exact kinematics used in this function are explained in much more detail at the Marlin github.

What is important to note is that plan_buffer_line moves the carriages linearly, and the printhead thus describes an arc and not a straight line. A straight line move is thus approximated by many small arcs.