Backlash compensation

2»

Comments

  • Firs execute FString inside a command already called from a gcode can be dangerous, also in this case it is ok I think.

    Why jerk gets interesting here is that the planner sees a direction change of 90° for the extra move twice so it assumes jerk is an issue here. What force is required here depends on where the reason lies and if it start moving a mass (especially with wrong backlash length this will happen). But since jerk 100 makes it not slow down it should work,  but I think you are resetting too early. Think of a circle at top. You want to change y from + to - direction while going to the right. It adds a move x=0, y = backlash so your setting is valid for the first 90° switch but the next one when the planned move is added also has 90° and you reduce jerk before that, so it will slow down on the second corner, but not the first one.

    For speep reasons do not use executeFString, just run

     Printer::maxJerk = 10;

    which is all that M207 X10 does.

  • Thank you for the quick reply.

    I see... It may be correct that I am resetting too early the jerk value to the original. Where should it be reset then?
  • At the end of the function after "calculateMove" which is where it gets added and analysed.
  • aizaiz
    edited June 2018
    Hi again,

    It is not working as expected...

    The code now looks like this:



    #if ENABLE_BACKLASH_COMPENSATION
        if((p->isXYZMove()) && ((p->dir & XYZ_DIRPOS) ^ (Printer::backlashDir & XYZ_DIRPOS)) & (Printer::backlashDir >> 3)) { // We need to compensate backlash, add a move
    ;

                    Printer::maxJerk = 70;

            waitForXFreeLines(2);             
            uint8_t wpos2 = linesWritePos + 1;
            if(wpos2 >= PRINTLINE_CACHE_SIZE) wpos2 = 0;
            PrintLine *p2 = &lines[wpos2];
            memcpy(p2, p, sizeof(PrintLine)); // Move current data to p2
            uint8_t changed = (p->dir & XYZ_DIRPOS) ^ (Printer::backlashDir & XYZ_DIRPOS);
            float back_diff[4]; // Axis movement in mm
            back_diff[E_AXIS] = 0;
            back_diff[X_AXIS] = (changed & 1 ? (p->isXPositiveMove() ? Printer::backlashX : -Printer::backlashX) : 0);
            back_diff[Y_AXIS] = (changed & 2 ? (p->isYPositiveMove() ? Printer::backlashY : -Printer::backlashY) : 0);
            back_diff[Z_AXIS] = (changed & 4 ? (p->isZPositiveMove() ? Printer::backlashZ : -Printer::backlashZ) : 0);
            p->dir &= XYZ_DIRPOS; // x,y and z are already correct
            for(uint8_t i = 0; i < 4; i++) {
                float f = back_diff[i] * Printer::axisStepsPerMM[i];
                p->delta[i] = abs((long)f);
                if(p->delta[i]) p->dir |= XSTEP << i;
            }
            //Define variables that are needed for the Bresenham algorithm. Please note that  Z is not currently included in the Bresenham algorithm.
            if(p->delta[Y_AXIS] > p->delta[X_AXIS] && p->delta[Y_AXIS] > p->delta[Z_AXIS]) p->primaryAxis = Y_AXIS;
            else if (p->delta[X_AXIS] > p->delta[Z_AXIS] ) p->primaryAxis = X_AXIS;
            else p->primaryAxis = Z_AXIS;
            p->stepsRemaining = p->delta[p->primaryAxis];
            //Feedrate calc based on XYZ travel distance
            xydist2 = back_diff[X_AXIS] * back_diff[X_AXIS] + back_diff[Y_AXIS] * back_diff[Y_AXIS];
            if(p->isZMove())
                p->distance = sqrt(xydist2 + back_diff[Z_AXIS] * back_diff[Z_AXIS]);
            else
                p->distance = sqrt(xydist2);
            // 56 seems to be xstep|ystep|e_posdir which just seems odd
            Printer::backlashDir = (Printer::backlashDir & 56) | (p2->dir & XYZ_DIRPOS);
            p->calculateMove(back_diff, pathOptimize, p->primaryAxis);
            p = p2; // use saved instance for the real move



                   
        }
    #endif

        //Define variables that are needed for the Bresenham algorithm. Please note that  Z is not currently included in the Bresenham algorithm.
        if(p->delta[Y_AXIS] > p->delta[X_AXIS] && p->delta[Y_AXIS] > p->delta[Z_AXIS] && p->delta[Y_AXIS] > p->delta[E_AXIS]) p->primaryAxis = Y_AXIS;
        else if (p->delta[X_AXIS] > p->delta[Z_AXIS] && p->delta[X_AXIS] > p->delta[E_AXIS]) p->primaryAxis = X_AXIS;
        else if (p->delta[Z_AXIS] > p->delta[E_AXIS]) p->primaryAxis = Z_AXIS;
        else p->primaryAxis = E_AXIS;
        p->stepsRemaining = p->delta[p->primaryAxis];
        if(p->isXYZMove()) {
            xydist2 = axisDistanceMM[X_AXIS] * axisDistanceMM[X_AXIS] + axisDistanceMM[Y_AXIS] * axisDistanceMM[Y_AXIS];
            if(p->isZMove())
                p->distance = RMath::max((float)sqrt(xydist2 + axisDistanceMM[Z_AXIS] * axisDistanceMM[Z_AXIS]), fabs(axisDistanceMM[E_AXIS]));
            else
                p->distance = RMath::max((float)sqrt(xydist2), fabs(axisDistanceMM[E_AXIS]));
        } else
            p->distance = fabs(axisDistanceMM[E_AXIS]);
        p->calculateMove(axisDistanceMM, pathOptimize, p->primaryAxis);


    }               
    #endif

    void PrintLine::calculateMove(float axisDistanceMM[], uint8_t pathOptimize, fast8_t drivingAxis) {

    if(Printer::maxJerk != 20){

                    Printer::maxJerk = 20;
    }


    I've put the last change inside an if because if not it seems that it is redefining all the time the maxJerk and the print is not running fluent.

    Is it possible that the path planner doesn't like changes in the Jerk value and introduces a stop whenever the maxJerk is changed?

    Any idea on how to make it work?

    Thanks!
  •     p->calculateMove(axisDistanceMM, pathOptimize, p->primaryAxis);

    //// reset jerk here !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    }                
    #endif

    resetting maxJerk in calculateMove void all your tries to set it to 70 of course.

  • Hi!

    Thanks! I had tried to put the jerk change also in this position but it is also not working.

    With the change here, the second 90º corner of the backlash seems to be fast, as desired, but still, before doing the first corner, the extruder is decelerated.
  • All I can say is that you need it high for both calculateMove calls after detecting you want backlash to cover both edges. Shoudl all be done in queue move as that is the only place where you know about the special case. Once the max junction speed is computed, there should be no update required any more. If it gets updated another time it would use the currently set maxJerk. This is a bit tweaking a variable that was never meant to be changed during print, but none the less I think it should work.
Sign In or Register to comment.