repetier / Repetier-Firmware

Firmware for Arduino based RepRap 3D printer.
812 stars 734 forks source link

Bug with not unloading buffer #863

Open Goodfeat opened 5 years ago

Goodfeat commented 5 years ago

Hello, I found another bug because of which you cannot start printing again The reason of this bug is not clear, but it appears in several versions 1.04 It is possible to experience the bug even after reloading the arduino. The sequence of actions in which it appears:

Arduino due + Ruramps4d, Delta printer

repetier commented 5 years ago

Is the do parking required to get the error? What does "Do parking" mean for you? Do you wait here until heaters are hot or do you disturb when it is waiting for extruder temperature?

From description it sounds like you manage to leave the main look that polls commands and never come back so commands start piling up in host. But I need to see that myself I think to see what is happening.

Goodfeat commented 5 years ago

parking is the g28 command IMG_20190428_195110

buffer = 3 Commands remain in the buffer after starting reprinting. It does not fix until you click on the reset

Goodfeat commented 5 years ago

https://youtu.be/xFIcR6_K_xs this video is with a bug

repetier commented 5 years ago

Parking is called homing normally. I have tried it with latest 1.0.4 from thursday on a cartesian printer. Tested it 2 times with success. There I had fixed 2 things you mentioned in an earlier post (hopefully).

What does M119 return after homing for you? Should list all end stops as L or next homing will fail at least in newer firmware versions.

So I'm not sure if the bug is fixed or delta specific. If you do not home before starting your print would it then work as then endstops are not triggered?

Goodfeat commented 5 years ago

After the commands remain in the buffer, no other command executes. Not M119, not even M112. The firmware goes into a “while” loop. But it does not freeze and continues to show data about temperatures. I tried using the standard configuration.h file with minimal changes. Corrected only limit switches and stepper motors. Surprisingly, out of 20 tests, it froze only once. Therefore, there is something in the configuration that prevents the normal operation of the printer. However, the problem comes out if you take another step - pulling the thread up by 100 mm.

This sequence of actions causes a stable freeze.

Goodfeat commented 5 years ago

I found out that the host processes the stop as a pause, but this does not completely solve the problem. If you stop the printer via UI display, after the G28 and G1 E-100 command, the program freezes.

P.S noticed something: after G28, the extruder with the first command G1 E-100 does not want to execute the code

P.P.S You can reduce the order of the commands to 3, this takes you to the heart of the problem

P.P.P.S. Found the cause of the problem, but do not know yet what to do with it

the problem is Printer :: homeAxis lines in Printer.ccp 1580 updateCurrentPosition (true); 1588 Printer :: updateCurrentPosition ();

I commented on them and the problem went away. I keep testing like this, but surely there are some new bugs

Goodfeat commented 5 years ago

I found what causes the error. The reason was not evident The code snippet because of which the bug occurs:

#define DISTORTION_CORRECTION 0  /// это вызывает ошибку при хоуминге при G28 и G1 E-100
#define DISTORTION_CORRECTION_POINTS 5
/** Max. distortion value to enter. Used to prevent dangerous errors with big values. */
#define DISTORTION_LIMIT_TO 2
/* For delta printers you simply define the measured radius around origin */
#define DISTORTION_CORRECTION_R 80
/* For all others you define the correction rectangle by setting the min/max coordinates. 
Make sure the the probe can reach all points! */
#define DISTORTION_XMIN -110
#define DISTORTION_YMIN -110
#define DISTORTION_XMAX 110
#define DISTORTION_YMAX 110

If DISTORTION_CORRECTION 0, there are glitches with the buffer. If DISTORTION_CORRECTION 1, the bug disappears: at least now the printer is more stable. But why must I use this fuction if I do not need it?

Goodfeat commented 5 years ago

I managed to solve the problem. It turns out under certain circumstances in fdifference [] the value is 0.00 or -0.00. This breaks the logic of the printer and stops it with an unloaded buffer.

This makes the value not equal to 0, but it still remains zero. Multiplication or division by zero creates an error.

The solution is simple: Since the root of the problem is somewhere in the depths of the firmware, I wrote a small check. It makes the correct value from float 0.00 to int 0

motion.cpp

void PrintLine::calculateDirectionAndDelta(float fdifference[], int32_t difference[], 
ufast8_t *dir, int32_t delta[])
{
    *dir = 0;
    //Find direction
    for(int i=0;i< 8;i++)
    {
        if(fdifference[i] > -0.001f && fdifference[i] <= 0 || 
               fdifference[i] >= 0 && fdifference[i] < 0.001f )
                  {
                   fdifference[i]=0;
                  } 
    }
...

Buffer error does not occur

repetier commented 5 years ago

I'm sorry but that solution makes me not really happy. Apart from fdifference array only being 4 long the solution looks a bit arbitrary and will likely strike again for someone. I think the problem happens when the move contains 0 steps but gets added to the motion buffer. So error should be more in queueNonlinearMove. If I think the effect of your change cartesianDistance gets zero and cartesianDir is also 0 at least for these axis. I think problem only occurs if that happens to all directions. So it will run into

 if (!(cartesianDir & XYZ_STEP))
    {
        queueEMove(difference[E_AXIS], check_endstops, pathOptimize);
        return true;
    }

which leads to no move if e has also no steps. So solution to not add a move with no steps is what is needed, but we should not use arbitrary testing values. If that only leads to one lost step your print is not perfect.

So lets look further. Without the mod we have a tiny motion, so seconds is a short time and segmentCount = RMath::max(1, static_cast<int16_t>(sps * seconds));leads to one segment.

segmentCount = RMath::max(1, static_cast(sps * seconds)); will calulate the axis with most steps to be used as virtual axis. That might differ a bit depending on using a due or 8 bit avr processor. In my case it will be a due. But regardless of what we use, if result is 0 we can expect the error to happen then.

    ```

if (virtualAxisSteps > p->delta[E_AXIS]) { // Is delta move or E axis leading p->stepsRemaining = virtualAxisSteps; axisDistanceMM[VIRTUAL_AXIS] = p->distance; //virtual_axis_move * Printer::invAxisStepsPerMM[Z_AXIS]; // Steps/unit same as all the towers // Virtual axis steps per segment p->numPrimaryStepPerSegment = maxStepsPerSegment;

if DRIVE_SYSTEM != DELTA

        if (cartesianDeltaSteps[Z_AXIS] > cartesianDeltaSteps[X_AXIS] && cartesianDeltaSteps[Z_AXIS] > cartesianDeltaSteps[Y_AXIS])
            drivingAxis = Z_AXIS;

endif

    } else {
        // Round up the E move to get something divisible by segment count which is greater than E move
        p->numPrimaryStepPerSegment = (p->delta[E_AXIS] + segmentsPerLine - 1) / segmentsPerLine;
        p->stepsRemaining = p->numPrimaryStepPerSegment * segmentsPerLine;
        axisDistanceMM[VIRTUAL_AXIS] = -p->distance; //p->stepsRemaining * Printer::invAxisStepsPerMM[Z_AXIS];
        drivingAxis = E_AXIS;
    }
is the next code of importance. virtualAxisSteps will be 0 so we go to else part. You got problems at homing so delta[E_AXIS] = 0. numPrimaryStepPerSegment will be 0 leading to stepsRemaining = 0, but p->distance will be the small error distance we could not execute! drivingAxis is E_AXIS with 0 steps.

void PrintLine::calculateMove(float axisDistanceMM[], uint8_t pathOptimize, fast8_t drivingAxis) { if (stepsRemaining == 0) { // need at least one step for bresenham return; }



Is reponsible for pushing the line for execution, but with stepsRemaining = 0 it will not add it.

This is the analysis for 1.0.4. So as it looks it should not happen here. Not sure what version you are using. You seem to be using different version.

I'm currently repairing my delta, so hope I can test if I can produce the error. Will test with DISTORTION_CORRECTION = 0 also it is unclear why omitting a lot of code does cause precision problems. I also do not see where that tiny move comes from during homing where you get the block. All moves are normally more then 1 step. Maybe you can post your config here to see if there is something that is not expected by me.
Goodfeat commented 5 years ago

Perhaps the solution is not perfect. I came to this solution because the fdifference [i] data is measured in millimeters. That is the form in which they appear in the host. I discovered that in g-code there really are extruder values that have 5 decimal places. To be precise. The whole thing is in the fdifference [Z_AXIS], it is not necessary to check the remaining axes and the extruder. There is an error in the Z axis. You could not check axes X,Y and E

I attach one working file and one test file which was configured on the site today. I needed it for verification. Both configurations cause an error

I also attached the modified motion.cpp file, where I made my changes.

2 config + motion.cpp.zip

Goodfeat commented 5 years ago

I came to the conclusion that it makes no sense to reset the data you can simply add a check to the existing condition

if (fdifference[Z_AXIS] != 0 && difference[Z_AXIS] !=0 )// <---------------------------- 
    {
        if (fdifference[Z_AXIS] < 0)
        {
            delta[Z_AXIS] = -difference[Z_AXIS];
            fdifference[Z_AXIS] = -fdifference[Z_AXIS];
            *dir |= ZSTEP;    
        }
        else
        {
            delta[Z_AXIS] = difference[Z_AXIS];
            *dir |= Z_DIRPOS + ZSTEP;  
        }
    }
    else
    {
        delta[Z_AXIS] = 0; 
    }

It works and does not affect problems with small calculations. I looked at the debugger: the "difference" variable can be filled while the "fdifference" remains empty, but not vice versa

I think it will fit in as a temporary solution until you find a reason.

P.S. All the same, you need to add additional checks to all axes. After auto-calibration I caught a bug again

Goodfeat commented 5 years ago

Unfortunately, my method does not work properly. After auto-calibration, problems with calculations begin. Everything gets worse if you change linear_advanced I set the value to 80, and now the extruder works completely inadequately

This happens even with the original motion.cpp. DISTORTION_CORRECTION 1 no longer corrects the situation.

I noticed that the value 1000 falls into the segmentCount Should such a value fall into segmentCount? error

repetier commented 5 years ago

Yes 1000 segments can happen if you have high value for segments per second. I have 600 so a 1.5 second move would already have 900 segments. What I noted is that your steps per mm values must be quite high. So I guess your CPU is working quite hard here. Not sure what you have for extrusion but 80 for advance is also a high value. My linear advance is normally 40-50 for direct extruder. For bowden it makes no sense as it would need to be so high that extrusion inverts direction all the time and can not follow.

I have to wait for a spare part for my delta to assemble it again:-( And it has only 80 steps per mm, so not sure if it reproduces the error at all.

Goodfeat commented 5 years ago

but 1000 segments appeared during the team G1 E-100 ? I realized that when I squeeze the filament, the program should complete the next check.

 if (!(cartesianDir & XYZ_STEP))
    {

        queueEMove(difference[E_AXIS], check_endstops, pathOptimize);
        return true;
    }

but the program is trying to make some kind of microscopic movement

repetier commented 5 years ago

queueEMove does not use subsegments at all if I see it correctly. So there should be no segments. So there must be a xyz move somehow that it does not go into the if cond. I assume the output will not be in queueEMove. So sure it happens with that move? Depending on what you did coordinates are taken from 2 different sources, but if you only have g0 moves around that should not be the reason.

Goodfeat commented 5 years ago

I have to wait for a spare part for my delta to assemble it again:-( And it has only 80 steps per mm, so not sure if it reproduces the error at all.

I can try to reduce microstep until 80 and try to reproduce this error

Goodfeat commented 5 years ago

I have two news, bad and good.

bad news: the problem with the bug has not gone away Good news: you can reproduce the error

I set microstep 1/16 = 80, the error did not disappear

Goodfeat commented 5 years ago

I discovered the following. My printer has two extruders with different offsets. I made the printer autocalibrate. After that, I try to bring it home with the G28 team. The printer returns to the starting point. At this time, he is trying to establish the position according to the extruder offset (X-offset 7470), but without taking into account auto-calibration (fractionalSteps 147) ) The printer does not take calibration at G28 into account, although it must set the X-offset 7327 to currentPositionStep when completed. When I try to make the G1 E-100 command, instead of drawing in the plastic, the printer tries to set the offset according to auto calibration (7327). Therefore, the printer starts to fail, showing crazy segmentCount values ​​(1000,1500,2500) In addition, with this error, the function PrintLine :: calculateDirectionAndDelta is called repeatedly (10-20 times in a row)

Why the G28 Team can not immediately set the correct offset of the extruder given the auto-calibration? How to make sure that the correct value is immediately written to Printer :: currentPositionSteps [i] by the command G28

repetier commented 5 years ago

My delta also has 2 extruders with offset in y direction. Looking into void Printer::homeZAxis() { // Delta z homing

you see near the end:

Extruder::selectExtruderById(Extruder::current->id);

if FEATURE_BABYSTEPPING

Printer::zBabysteps = 0;

endif

} here the selectExtruderById should have added the offset. Okay, as you say offset was added but the move was not executed which happened with the next E-100 move so it was not pure E move as I already thought. Now since E-100 takes a lot of time it generates lot of small segments as you already found out. I wonder if that is even causing the hang at the end (do you have this E-100 in your gcode you start?). Or is calling G28 several times in a row already enough to get the hang?

Hope I get my part early next week. They say 1-7 days delivery time. Then I can test. At least the removing of the offset is expected and happened as far as I remember, but that was x changes ago.

Goodfeat commented 5 years ago

I make only two teams first G28 then G1 E100 I send all the codes from the host

I will continue to experiment

Goodfeat commented 5 years ago

I discovered new bugs in the calculations. I am testing printer movement with console output with the values ​​Printer :: currentPositionSteps [i] and fractionalSteps [i]. for (fast8_t i = 0; i <E_AXIS_ARRAY; i ++)         {             Printer :: currentPositionSteps [i] + = fractionalSteps [i];             Com :: printF (PSTR ("currentPosit ="), Printer :: currentPositionSteps [i]);             Com :: printF (PSTR ("fractionalSteps ="), fractionalSteps [i]);         } If you make G28, and then make the command to lower the extruder along the axis -Z10, then the data of Printer :: currentPositionSteps decreases (relative to the position of the auto-calibration). (7470> 7326> 7329> 7332 ...) Suppose this is correct, as the delta is slightly curved. The firmware allows for a slight tilt We switch the extruder from the first to the second, and then from the second to the first. Instead of returning to coordinate 7332, the extruder moves to coordinate 7479. Again, reduce the Z position down. Now Printer :: currentPositionSteps is starting to grow. (7479> 7482> 7485> 7488 ...) This is not normal!

https://youtu.be/CkM3L2kNiJg

Goodfeat commented 5 years ago

Hi, I seem to have solved the hang problem. I added an extra move after turning on auto-level.

The code is as follows: printer.cpp

EVENT_BEFORE_Z_HOME;
    homeZAxis ();
    moveToReal (0, 0, Printer :: zLength - zBedOffset, IGNORE_COORDINATE, homingFeedrate [Z_AXIS]); // Move to designed coordinates including translation
    updateCurrentPosition (true);
    updateHomedAll ();
    UI_CLEAR_STATUS
    EVENT_AFTER_Z_HOME;
    Commands :: printCurrentPosition ();
    setAutolevelActive (autoLevel);
    // --- now sets home with offets + autolevel
    moveToReal (0, 0, Printer :: zLength - zBedOffset, IGNORE_COORDINATE, homingFeedrate [Z_AXIS]); // Move to designed coordinates including translation
    updateCurrentPosition (true);
    updateHomedAll ();
    UI_CLEAR_STATUS
    EVENT_AFTER_Z_HOME;
   Commands :: printCurrentPosition ();
    // --- end sets home with offets + autolevel
#if defined (SUPPORT_LASER) && SUPPORT_LASER
    LaserDriver :: laserOn = oldLaser;
#endif
    Printer :: updateCurrentPosition ();
    setNoDestinationCheck (nocheck);
}

The printer needs the position to be correctly shifted not only with offset, but also with auto level, otherwise it causes bugs

While there were no failures, I also tested it with DISTORTION_CORRECTION 0 turned off, auto level turned off, auto level turned on with preliminary auto-calibration

True with one caveat I used mod in motion.cpp

if (fdifference [X_AXIS]! = 0 && difference [X_AXIS]! = 0)
if (fdifference [Y_AXIS]! = 0 && difference [Y_AXIS]! = 0)
if (fdifference [Z_AXIS]! = 0 && difference [Z_AXIS]! = 0)
if (fdifference [E_AXIS]! = 0 && difference [E_AXIS]! = 0)

Alas, but without it, hangs occur due to 0.00 in the fdifference. Unfortunately, I could not fix it

Goodfeat commented 5 years ago

I found another bug. The error is related to the retract and the factor K and L The standard retract function does not work when you manually switch extruders. But I needed to roll back the plastic when switching the extruder I concluded that the G10 / G11 command should be placed in the lines:

define EXT0_SELECT_COMMANDS "G11 S1"

define EXT0_DESELECT_COMMANDS "G10 S1"

and

define EXT1_SELECT_COMMANDS "G11 S1"

define EXT1_DESELECT_COMMANDS "G10 S1"

but it does not work properly

EXT0_SELECT_COMMANDS when K is turned on, it starts to conflict with the K-factor

For example, with the K-factor of 10 turned on, after switching the extruder, the engine starts making strange sounds.

The most annoying thing is that because of the included K in the firmware, a failure occurs and the engine of the extruder may freeze and stop feeding plastic during printing. The same with the L-coefficient. He also trashes on my delta.

I tried not to use G10 / G11 commands, but to use a bunch from other commands.

define EXT0_SELECT_COMMANDS "G91 \ nG1 E20 F5000 \ nG90 \ n"

define EXT0_DESELECT_COMMANDS "M401 \ nG91 \ nG1 Z10 F5000 \ nG1 E-20 F5000n \ nM402"

However, the problem repeated again.