MarlinFirmware / Marlin

Marlin is an optimized firmware for RepRap 3D printers based on the Arduino platform. Many commercial 3D printers come with Marlin installed. Check with your vendor if you need source code for your specific machine.
https://marlinfw.org
GNU General Public License v3.0
16.17k stars 19.21k forks source link

[FR] Crash Detection #8765

Open psavva opened 6 years ago

psavva commented 6 years ago

Dear Marlin Devs,

This is a Feature Request to allow a Print to re-home once TMC2130 (and similar) detects a missed step (which is reported to the driver)

The idea is that when the TMC drivers detect missed steps, the printer will automatically re-home the X or the Y, depending on which axis skipped a step.

This will be extremely useful to recover what would have been a failed print due to any skipped steps.

@teemuatlut do you think you could do this?

teemuatlut commented 6 years ago

It's mostly a matter of Marlin reacting to a triggered endstop signal on moves that are not deliberate homing moves. But since I personally use stealthChop all the time, it's a low priority for me. Maybe I'll look into it when I get more into playing with the TMC2660 drivers. Just don't expect this to happen anytime soon.

DavidBjerreBjoerklund commented 6 years ago

I agree, this would be an awesome feature and save great amounts of plastic.

alexborro commented 6 years ago

There is no need to re-home. The driver reports how many steps was lost. The firmware just need to perform that missed steps.

Em 12 de dez de 2017 18:40, "DavidBjerreBjoerklund" < notifications@github.com> escreveu:

I agree, this would be an awesome feature and save great amounts of plastic.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/MarlinFirmware/Marlin/issues/8765#issuecomment-351187211, or mute the thread https://github.com/notifications/unsubscribe-auth/AE-ZE6utXdai6ZDyilajZ8ZbN_m1yah6ks5s_uSxgaJpZM4Q_HyT .

psavva commented 6 years ago

@alexborro, Do you have any reference documentation/datasheets showing how the driver reports how many steps were missed?

As far as I know, it's impossible to determine how many steps were missed unless you have a closed loop system.

alexborro commented 6 years ago

Yes, I have studied a lot this driver because I'm developing a 3D printer board with 8 of them. Through SPI the software can read a register the register LOST_STEPS (0x73). Bear in mind the missed steps counting just takes place in dcStep mode.

In other modes, the software should tracks the driver load and avoid missing steps.

Cheers

Alex.

Em 13 de dez de 2017 02:00, "Panayiotis Savva" notifications@github.com escreveu:

@alexborro https://github.com/alexborro, Do you have any reference documentation/datasheets showing how the driver reports how many steps were missed?

As far as I know, it's impossible to determine how many steps were missed unless you have a closed loop system.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/MarlinFirmware/Marlin/issues/8765#issuecomment-351275602, or mute the thread https://github.com/notifications/unsubscribe-auth/AE-ZExXAVJEBraIV81im-QKwbgl2gWAIks5s_0vugaJpZM4Q_HyT .

psavva commented 6 years ago

@alexborro Do I understand correctly that dcStep is only supports full steps? Ie, it cannot detect microsteps skipped, but full steps only? We lose resolution in this case.

I also see that under certain conditions, it may loose positional accuracy when stalling, and when that happens stallguard2 is activated.

It seems that re-homing a stalled axis would be beneficial in both cases, with and without dcstep.

Did you manage to implement anything in Marlin from your research and build?

teemuatlut commented 6 years ago

I've looked into a bit more and it is possible to use microstepping along with dcStep. However, it's likely this line on page 74 was what initially made me not consider it more throughly: dcStep operates the motor in fullstep mode at the target velocity or at reduced velocity if the motor becomes overloaded Fullstep operation is also hinted at p77 when vhighfs and vhighchm are required for dsStep: As soon as VDCMIN becomes exceeded, the chopper becomes switched to fullstepping

alexborro commented 6 years ago

@psavva in dcStep mode the driver drives the motor like a DC motor.. there is no more "steps", although the driver still keeps the current position in the internal step table. The LOST_STEPS will have the microstep resolution, so it can be used to further send the lost microsteps.

Although you can re-home the axis as well in case of lost steps, I think the best approach will monitor the motor torque (using stallGuard2 feature) and avoid missing steps. I need to read the manual again to check if the driver can provide how many steps was missed if not in dcStep.. I guess it cannot.

I have the TMC2130 development kit from Trinamic, I just need to set it up and make somes tests.. and make it worth the 200 bucks I spend on it!!!!

Cheers.

Alex.

AnHardt commented 6 years ago

Is there a way to lose microsteps? I don't think so. With an external moment you can displace the rotor by microsteps. But if the moment is gone it will return to its place. If the moment is too high the motor can't snap in again before it turned at least 4 full steps. But when it will snap in and the moment is away, then it will have the correct microstep (not full step) again.

Ah i see (18.3.1). They have an other definition of lost (delayed) (micro) steps.

lonelymyp commented 6 years ago

In the Prusa MK3 this function is already implemented (will be implemented), so there is no reason why it should not be done. here's a video with a running feature https://www.youtube.com/watch?v=sPvTB3irCxQ&feature=youtu.be&t=4m12s

psavva commented 6 years ago

@alexborro, I can confirm that the skipped steps are only recorded in the dcStep mode.

On page 30 of the datasheet: LOST_STEPS - Number of input steps skipped due to higher load in dcStep operation, if step input does not stop when DC_OUT is low. This counter wraps around after 2^20 steps. Counts up or down depending on direction. Only with SDMODE=1.

I think the best option would be to configure StallGuard and in case of a stall, re-home.

This would minimise skipped steps due to StallGuard,, and finally if a step is skipped due to a mechanical reason, then re-home and continue...

@teemuatlut, I wanted to attempt the implementation, but this would be my first time in C and at this level... I will need help :)

I'm a Database programmer using Oracle...

psavva commented 6 years ago

Oops..

Hywelmartin commented 6 years ago

For a while ago I managed to hear when my printer skipped a step (or a lot of steps). I paused, rehomed and then continued the print. It finished nice ....

One thing is that the babysteps got lost because I rehomed...

thinkyhead commented 6 years ago

no reason why it should not be done.

It's cool that vendors who have very specific architectures are implementing this for their machines. Just be aware that for the main fork we must implement it in a way that works for Cartesian, CoreXY, Delta, and SCARA.

dedalodaelus commented 6 years ago

@teemuatlut this control of the lost steps could be placed this on the monitor_tmc_driver() function on tmc_utils.cpp?

teemuatlut commented 6 years ago

No it needs to be a reaction to the stallGuard signal.

Robotec101 commented 6 years ago

Hi, taking a look into your comments and the working of the mk3 its obvius that in the mk3 the printer is put on hold by the stallGuard signal and executes a macro consisting in raising Z, rehoming X and Y and continuing the printing.

I´m trying to do the same on a RAMPS 1.4 inyecting the OR gate of the X and Y signals of the 2 drivers into a interrupt pin, then i have to pause the printing and execute the macro mencioned above.

The problem comes when i have to make an interrupt in marlin , i dont know how it will affect other subsystems and how to execute a gcode macro in the coding, im looking at the code but its huge at first glance , and i was looking for something relatively easy to avoid layer faults.

In short i need a way to make an interruption rutine that execute gcode or sets a flag to execute it without disrupting timers and etc, any idea its welcome.

Roxy-3D commented 6 years ago

In short i need a way to make an interruption rutine that execute gcode or sets a flag to execute it without disrupting timers and etc, any idea its welcome.

If the signal is latched (not a pulse... does not go away...) you can do it similar to how the filament run out sensor does its work. No interrupt needed. The signal is checked in the manage_inactivity() code and action is taken if the signal shows up...

class FilamentRunoutSensor {
  public:
    FilamentRunoutSensor() {}

    static void setup();

    FORCE_INLINE static void reset() { runout_count = 0; filament_ran_out = false; }

    FORCE_INLINE static void run() {
      if ((IS_SD_PRINTING || print_job_timer.isRunning()) && check() && !filament_ran_out) {
        filament_ran_out = true;
        enqueue_and_echo_commands_P(PSTR(FILAMENT_RUNOUT_SCRIPT));
        stepper.synchronize();
      }
    }
  private:
FORCE_INLINE static bool check() {
  #if NUM_RUNOUT_SENSORS < 2
    // A single sensor applying to all extruders
    const bool is_out = READ(FIL_RUNOUT_PIN) == FIL_RUNOUT_INVERTING;
  #else
    . . .
  #endif
  return (is_out ? ++runout_count : (runout_count = 0)) > FIL_RUNOUT_THRESHOLD;
}
teemuatlut commented 6 years ago

Doesn't work that way. Think of a full bed sized rectangle being printed without bed leveling (so movements don't get split). Each side of the square is then one block in the planner queue. With a typical queue size of 16 you'd get 4 full rounds of the print before reacting to anything. Even more if you enqueue the actions to the end of the gcode buffer. Even if you pause the print when the endstop (stallGuard) is triggered, you still can't enqueue the commands because you still have a full queue movements before. If you discard the full queue to execute your commands, you also lose all those commands and you no longer know the position where the skipped step happened so you could return to that point. You also shouldn't execute the motion block to the end where the skipped step happened. Again, if that particular motion is a long one, it'll definitely show in the print. Then if you manage to pause the print, halt the queue, execute raise Z, home XY, return to XY step where the skip happened, lower Z. Then you can't just return to executing the interrupted block because it likely was in nominal rate state of the motion. You need to recalculate the block with new acceleration and deceleration ramps.

So there are many more things to consider than just if this then insert this.

thinkyhead commented 6 years ago

If you discard the full queue to execute your commands, you also lose all those commands

It's true! If steps get lost, the firmware has to:

Robotec101 commented 6 years ago

So there are many more things to consider than just if this then insert this.

Yeah, i was afraid of that and it was the reasoning behind my post but as well, if it was so easy someone would have done it already.

Roxy-3D, thanks for the tip, im looking at the handle_filament_runout routine and it looks that it takes the solution of putting the necesary gcode in the gcode queue to solve the problems described by teemualut.

well, looking at the aviable options(without taking into account redeveloping the motion planner) the easy way it to put the gcode on queue like that routine does, For a first implementation enqueue_and_echo_commands_P should put the homing as the first action in the planner, it will drain other commands but for a first aproach i think its the most simple solution.

The right one by looking at he code and traspasing what thinkyhead was saying would be (correct me if im mistaken)

-Cloning command_queue and current_command into a variable. -clear command_queue(all empy? or 0'?). -stepper.synchronize();(pauses the print in conjuction with the buffer clear,clearing remaining steps.) -save current position. -insert G28 XY as the current command then G1 saved position and add the saved commands to the command_queue ,problem here its that the queue would be 2 commands longuer than the maximum. .Resuming the job-would be automatically done right?

teemuatlut commented 6 years ago

Due to the issues I described you can't use the same method as in filament runout. A simple solution is not a sufficient one.

The way I've been thinking about it is

I don't think we can use stepper.synchronize as that will clean out the planner queue and execute blocks when we especially don't want to do that.

Roxy-3D commented 6 years ago

Also... Consider this: Homing is a very dangerous operation if there is a partial print on the bed. If on your printer you home to Z-Max, that will help a lot. But in general, most printers home to Z-Min and there is no way to know what is in the way of the Z-Axis homing operation.

stevereno30 commented 6 years ago

This is true, but in my experience, skipped steps is not an issue with z position or z motion but with x or y motion. With this in mind, the printer could raise z 5mm, home x and y, return to the expected xy position, drop z 5mm and continue printing. There would be no risk of crashing unless the printer was printing multiple parts in sequence.

thinkyhead commented 6 years ago

@teemuatlut — I realize that to be 100% thorough and respond as quickly as possible you would need to halt the stepper ISR and copy all the planner blocks, but that would require even more SRAM and meticulous adjustment. To continue a block from the middle, with a ramp up in speed from zero, requires reconstructing the partial move and re-sending it to the planner anew. Certainly possible, just very challenging.

We don't actually need to formally populate a command queue with the various commands for recovery, as we now have methods that can go straight to the parser, and/or we can just do direct planner moves, removing some of the complications at that level.

My suggestion to let the planner queue run out does mean a slower recovery and more errant printing than a very fast stop, but it gives a simpler implementation and less SRAM usage than saving off the planner blocks, and SRAM usage is one of our major concerns since we have so little to spare.

p3p commented 6 years ago

I'd be a bit concerned with how long the planner buffer can take to empty given simple geometry.

teemuatlut commented 6 years ago

halt the stepper ISR and copy all the planner blocks

I'm more thinking of: halt stepper ISR and then execute from secondary buffer but do not mess with the main one (other than discarding the current one where the skipped step happened). Then return to main block queue once the secondary is empty.

An alternative option: because the needed steps for correction are roughly the same every time, the secondary buffer could only contain one block that would each time be populated by a state machine. This could reduce memory usage as we wouldn't have to allocate memory for a full buffer size. Or use a linked list. I know you'd like those. Execution speed really doesn't matter during the whole process as long as it starts at the right time.

thinkyhead commented 6 years ago

secondary buffer but do not mess with the main one

A general change, such as adding a secondary buffer, would add overhead for all planner operations. If the planner code can remain unaltered and just refer to the one buffer, that is best.

Roxy-3D commented 6 years ago

secondary buffer but do not mess with the main one

A general change, such as adding a secondary buffer, would add overhead for all planner operations. If the planner code can remain unaltered and just refer to the one buffer, that is best.

There is a huge amount of room for debate on this topic.... But if I was going to tackle the problem, I would freeze everything at the point it was detected. I would try to 'save the state' of the machine at the point the problem was detected. And then I would try to figure out how I can get back to that same state (minus some amount of time...).

Personally.... I think this problem is too hard to solve for the general case. But if we know that the printer homes to Z-Max, and a few other things... I bet we can solve it.

With that said... I personally don't like the idea of adding features that encourage people to home to Z-Max. That just adds complexity. But... Being able to recover a failed print is a super seductive idea. What if we limit the scope of the discussion to the 'easiest case' to solve this problem. Even people with Prusa i3 printers could move their Z-Axis endstop to Max if they really wanted the feature????

And if we can get it working in one setup.... We will learn a lot and be able to start making it work in other setups????

thinkyhead commented 6 years ago

I personally don't like the idea of adding features that encourage people to home to Z-Max.

That's not in any way necessary. This feature would only be concerned with the XY steppers on Cartesians, and when steps are lost, only X and Y would be re-homed. Z can be safely assumed to be where it was. See one of the video demonstrations of the Prusa MK3 lost steps recovery to see how it works.

As noted, on Delta, XYZ would all have to be re-homed to the top before continuing, and that is safe.

Robotec101 commented 6 years ago

Well guys, i have started testing this way:

-Stallguard deactivation after homing deactivated and mode set to spreadchop.

attachInterrupt(digitalPinToInterrupt(2), StallingHandler, RISING);//MaxPIN ISR in the setup.

void StallingHandler()
{
  enqueue_and_echo_commands_P(PSTR("G28 XY")); 
}

well this is my basic setup for testing and the problem is not even there.(although i must say that this is a primitive approach it works for the time being to detect other concept problems.)

They have sold us stallguard as the own name suggests as a counter stalling system,The problem is that it isn`t that.

Stallguard is a load measurament system with a threshold over which a signal is activated. What`s the problem? if a axis is moving in one direction and suddenly it moves in the contrary direction stallguard detecs the current spike as stalling and begins the interruption.

As the datasheet shows stallguards is designed to be calibrated as max speed and max load, for example in Y axis that would be with a big weight of plastic,the problem there is that we have to ignore the current spikes or find a way to make moves more smooth.

Right now i´m trying a electronic aproach

2018-05-02 13_02_05-1 schematic - d__drive_archivos pena_eagle_new_project_untitled sch - eagle 7 6

The idea is to set the threshold of stall guard to be sensible enough to detect the current spikes and the stalling but then to get the stalling right we pick X and Y signals with a low pass and use a Schmitt to give some hysteresis.

That way by the test i have done if a stalling happens, X and Y gives current to the capacitor and it rises voltage quickly,also in a real stalling several stalling pulses happen or larguer ones which activates the circuit.

as always, any idea it`s welcome.

teemuatlut commented 6 years ago

I don't think it's a good idea to ask users to start adding hardware to their setup. That shouldn't be needed. Also you don't need to add an interrupt as endstop bits are checked on every step.

You could try enabling stallguard filtering to see what that does.

Robotec101 commented 6 years ago

I don't think it's a good idea to ask users to start adding hardware to their setup.

Well adding the drivers and the com interface sure counts as adding hardware.

Also you don't need to add an interrupt as endstop bits are checked on every step.

You are right but i dont have the endstop isr`s enabled, that way i can use that pin to my own interruption.

You could try enabling stallguard filtering to see what that does.

Works like a charm, your libraries are awesome.

Well, here you go the first working release of this feature, but first ,things to know beforehand:

Its very important to set JERK XY to 0 this feature doesnt like sudden movement changes without aceleration ramps.

-Set Z raise to zero to avoid putting more Gcode commands than necesary.

You will have to calibrate the Minimun stepper motor current needed (mine was 400mA) so the spikes are more evident and then calibrate the sensibility threshold while the printer its working in a normal status and start rising the sensibility up to the point that it doesnt detect normal movements(here a osciloscope is recommended but it can be made with pronterface).

They way i`have implemented it includes the code from the original marlin which deactivates the signal from the tmc2130 after homing, i wanted to leave it as i found it , so now i call the autohoming enabling function every layer(M920).

The autohoming can enter a loop so i put a bool condition to avoid it, in conjuction with the previous condition it can enter autohoming once per layer.

I have put all the code in M920 command(i will post it down) so it can be called every layer and in the starting gcode to be activated after the homing which produces current spikes almost all the times.

In marlin main.cpp

bool Autohoming = false;
void StallingHandler()
{
 /* String SavePosition={};
  SavePosition="G1 X" + String(current_position[X_AXIS])+ "Y" + String(current_position[Y_AXIS]) + "Z" + 
  String(current_position[Z_AXIS]);
  char Saveposition1;
  SavePosition.toCharArray(Saveposition1,SavePosition.length());
  Serial.println(Saveposition1);
  enqueue_and_echo_commands_P(Saveposition1);*/

//Try to make the printer go back to the previous position but it was a failure.

  if(Autohoming == false)
  {
    enqueue_and_echo_commands_P(PSTR("G28 XY")); 
    Autohoming = true;
  }
  SERIAL_ECHOLNPGM("\nAuto homing");

}
 inline void gcode_M920() {
  stepperX.sg_filter(1);
 stepperY.sg_filter(1);//filter activation.
 //tmc_set_sgt(stepperX, extended_axis_codes[TMC_X], 7);//this its to set the current threshold of the signal,to calibrate it its better to use M914.
 //tmc_set_sgt(stepperY, extended_axis_codes[TMC_Y], 7);
 tmc_sensorless_homing(stepperY, true);

/*Better to use the function instead of the tmc code because this changues the mode to spreadchop too, so if someone wants, he can have the printer in stealthchop by 
 default and activating this function stepper  changues to spreadchop and activates the autohoming.*/
 tmc_sensorless_homing(stepperX, true);
 attachInterrupt(digitalPinToInterrupt(2), StallingHandler, RISING);//once the stepper are configured we activate the interrupt.
 SERIAL_ECHOLNPGM("\nAutoming Enabled");//serial confirmation
 Autohoming = false;

In the Mcodes part of Marlin:main.cpp line 12381:

 case 920:
          gcode_M920();//Set auto homing on stall fault.
 break;

also my final hardware implementation is this one:

2018-05-02 13_02_05-1 schematic - d__drive_archivos pena_eagle_new_project_untitled sch - eagle 7 6

I dont think that will change much more. this implementation works for me and i think it can be usefull for the developers to apply this knowledge and the ideas developt in the main version of marlin.

thinkyhead commented 6 years ago

@Robotec101 — Welcome to GitHub!

teemuatlut commented 6 years ago

Can you test my prediction with this model?

I suspect that when the driver detects a skipped step, it'll take a considerable time before Marlin will react to it due to command buffers and queues. Please also disable any bed leveling features as those will split movements. You can enable DRYRUN with M111 S8 as extruding isn't important here. You can also use a simple switch to trigger the interrupt pulse.

Robotec101 commented 6 years ago

Can you test my prediction with this model?

Well you were right , introducing the comand at the beginning of the printing it around 4 gcodes in executing

You can also use a simple switch to trigger the interrupt pulse.

I was doing it that way.

Also i been thinking of the possible use of this function, and looking into forums i have found this:

This is basically a solution in search of a problem. Everyone buys into the myth that stepper motors WILL always lose steps, which is simply wrong. If a stepper system is losing steps, it is because it was not properly designed for the load, period. Then they buy into the myth that servos will never lose steps, because they have encoders for feedback, so if you put an encoder on a stepper, you can get servo performance. What they miss is the fact that servos have lots of reserve torque, so they can react to following error by increasing their torque output. Steppers, OTOH, run at max torque all the time. Once you get unacceptable following error, you're toast. There is nothing you can do to recover, other than slow down the trajectory, which low-end CNC controller software (like Mach3, etc.) cannot do. Thinking stopping the process when unacceptable following error is detected is naive, because by that point, the part is already scrap, as the tool is already off-position.

So, with this in mind i redisigned the objetive of the function, if will rehome, thats true, but it wont solve the problem if it still lose steps in the next pass.That why i have introduced a automatic rising in the current each time that the printer enters the interruption, also it has to rise the current threshold of activation.

This way in theory the printer will have more torque when detects a layer stall error and can overcome it,if its unable to do so it will cancel the printing to avoid wasting plastic.

Also i have separated the code in a init (M919) to call in the starting scrip and the layer part (M920):

 case 919:
          gcode_M919();//Set auto homing init.
          break;

        case 920:
          gcode_M920();Set auto homing on stall fault.
          break;
 bool Autohoming = false;
 unsigned int Autohoming_Counter = 0;
void StallingHandler()
{
  if(Autohoming == false)
  {
     Autohoming_Counter++;
    if(X_CURRENT+200*Autohoming_Counter > 1000)
    {
        SERIAL_ECHOLNPGM("\nStalling detected,unable to correct");
        enqueue_and_echo_commands_P(PSTR("M112")); 

    }
    else
    {
    stepperX.setCurrent(X_CURRENT+200*Autohoming_Counter, R_SENSE, HOLD_MULTIPLIER);
    stepperY.setCurrent(Y_CURRENT+200*Autohoming_Counter, R_SENSE, HOLD_MULTIPLIER);
    tmc_set_sgt(stepperX, extended_axis_codes[TMC_X], (X_HOMING_SENSITIVITY+4*Autohoming_Counter));
    tmc_set_sgt(stepperY, extended_axis_codes[TMC_Y], (Y_HOMING_SENSITIVITY+4*Autohoming_Counter));  
    enqueue_and_echo_commands_P(PSTR("G28 XY")); 
    Autohoming = true;
        SERIAL_ECHOLNPGM("\nAuto homing");
    }

  }

}

 inline void gcode_M919() {
 stepperX.sg_filter(1);
 stepperY.sg_filter(1);
 stepperX.setCurrent(X_CURRENT, R_SENSE, HOLD_MULTIPLIER);
 stepperY.setCurrent(Y_CURRENT, R_SENSE, HOLD_MULTIPLIER);
 tmc_set_sgt(stepperX, extended_axis_codes[TMC_X], (X_HOMING_SENSITIVITY));
 tmc_set_sgt(stepperY, extended_axis_codes[TMC_Y], (Y_HOMING_SENSITIVITY)); 
 tmc_sensorless_homing(stepperY, true);
 tmc_sensorless_homing(stepperX, true);
 attachInterrupt(digitalPinToInterrupt(2), StallingHandler, RISING);
 SERIAL_ECHOLNPGM("\nAutohoming Enabled");
 }

 inline void gcode_M920() {
 tmc_sensorless_homing(stepperY, true);
 tmc_sensorless_homing(stepperX, true);
 SERIAL_ECHOLNPGM("\nAutohoming Layer Enabled");
 Autohoming = false;
 }

Now, the hard part will be executing the homing the right way(my original question), but i dont see myself being able to change half the cmd structure and not breaking anything(nor i have the time to do so, this was supossed to be a afternoon project and i have been with this 4 days).

Robotec101 commented 6 years ago

Also ihave been looking into the mk3 libraries after so much talking about how to do, this is how prusa did it..:

#ifdef AUTOMATIC_RECOVERY_AFTER_CRASH
    bool yesno = true;
#else
    bool yesno = lcd_show_fullscreen_message_yes_no_and_wait_P(MSG_CRASH_DETECTED, false);
#endif
    lcd_update_enable(true);
    lcd_update(2);
    lcd_setstatuspgm(MSG_CRASH_DETECTED);
    if (yesno)
    {
        enquecommand_P(PSTR("G28 X Y"));
        enquecommand_P(PSTR("CRASH_RECOVER"));
    }
    else
    {
        enquecommand_P(PSTR("CRASH_CANCEL"));
    }

Well, its good to know that i came to the same answer.

Last thing left its knowing how to reset the stall guard flag, i tried resetting with stealth mode but i cant.

teemuatlut commented 6 years ago

Did I understand correctly that the Prusa MK3 exhibits the same problem that the homing procedure is always delayed by the length of the command buffer?

Try setting the SG threshold to 63 as a way to reset the flag.

Robotec101 commented 6 years ago

Did I understand correctly that the Prusa MK3 exhibits the same problem that the homing procedure is always delayed by the length of the command buffer?

it seems that way unless they treat the buffer in a diferent way, but that command put the command first in the queue to enter the cmd.

Try setting the SG threshold to 63 as a way to reset the flag.

Didnt work, maybe the driver is damaged but i doubt it, cannot clear that flag by command is a problem.

Robotec101 commented 6 years ago

well, this its my final post on this matter, after several tries i couldnt calibrate the TMC2130 gave a lot of false triguers, this its due to my ramps working at 12V (24V its much better for the stallguard system), maybe low cuality motors and the variation of measuring with the motor temperature.

I leave all my work here for everyone who wants to continue the project, i will buy some encoder and put a safety controller with the step and dir signals this way if it goes out of hand it will triguer the home XY signal. :

unsigned int Xparameter = X_HOMING_SENSITIVITY;
unsigned int Yparameter = Y_HOMING_SENSITIVITY;

void ClearStallguardFlag()
{
  stepperX.stealthChop(1);
  stepperY.stealthChop(1); 
  stepperY.coolstep_min_speed(0); \
  stepperY.sg_min(0); \
  stepperY.sg_max(0);
  stepperX.coolstep_min_speed(0); \
  stepperX.sg_min(0); \
  stepperX.sg_max(0);
  stepperX.stealthChop(0); 
  stepperY.stealthChop(0); 
  stepperY.coolstep_min_speed(1024UL * 1024UL - 1UL); \
  stepperY.sg_min(0); \
  stepperY.sg_max(3);
  stepperX.coolstep_min_speed(1024UL * 1024UL - 1UL); \
  stepperX.sg_min(0); \
  stepperX.sg_max(3);
 }
}

bool Autohoming = false;
unsigned int Autohoming_Counter = 0;
void StallingHandler()
{

  if(Autohoming == false)
  {
//     Autohoming_Counter++;
//    if(X_CURRENT+200*Autohoming_Counter > 1000)//taking action to avoid another stall
//    {
//        SERIAL_ECHOLNPGM("\nStalling detected,unable to correct");
//        enqueue_and_echo_commands_P(PSTR("M112"));
//    }
//    else
//    {
//        stepperX.setCurrent(X_CURRENT+200*Autohoming_Counter, R_SENSE, HOLD_MULTIPLIER);
//        stepperY.setCurrent(Y_CURRENT+200*Autohoming_Counter, R_SENSE, HOLD_MULTIPLIER);
//        tmc_set_sgt(stepperX, extended_axis_codes[TMC_X], (X_HOMING_SENSITIVITY+5*Autohoming_Counter));
//        tmc_set_sgt(stepperY, extended_axis_codes[TMC_Y], (Y_HOMING_SENSITIVITY+5*Autohoming_Counter));  
//     }

        Autohoming = true;
        SERIAL_ECHOLNPGM("\nAuto homing");

        enqueue_and_echo_commands_P(PSTR("G28 XY")); 

  }

   if(stepperX.sg_result()<100)//automatic calibration of X axis.
   {
    Xparameter++;
    if(63<Xparameter)
    {
      //SERIAL_ECHOLNPGM("\nUnable to calibrate Y Stallguard");
    }
    else
    {

     tmc_set_sgt(stepperX, extended_axis_codes[TMC_X], (Xparameter));
    }

   }
   if(stepperY.sg_result()<100)//automatic calibration of Y axis.
   {
    Yparameter++;
    if(63<Yparameter)
    {
      //SERIAL_ECHOLNPGM("\nUnable to calibrate X Stallguard");
    }
    else
    {
     tmc_set_sgt(stepperY, extended_axis_codes[TMC_Y], (Yparameter));
    }

   ClearStallguardFlag();

}

 inline void gcode_M919() 
 {
   stepperX.sg_filter(1);
   stepperY.sg_filter(1);
   stepperX.setCurrent(X_CURRENT, R_SENSE, HOLD_MULTIPLIER);
   stepperY.setCurrent(Y_CURRENT, R_SENSE, HOLD_MULTIPLIER);
   tmc_set_sgt(stepperX, extended_axis_codes[TMC_X],  (X_HOMING_SENSITIVITY));
   tmc_set_sgt(stepperY, extended_axis_codes[TMC_Y], (Y_HOMING_SENSITIVITY)); 
   tmc_sensorless_homing(stepperY, true);
   tmc_sensorless_homing(stepperX, true);
   attachInterrupt(digitalPinToInterrupt(2), StallingHandler, RISING);
   ClearStallguardFlag();
   SERIAL_ECHOLNPGM("\nAuthoming Enabled"); 
 }

 inline void gcode_M920() 
 {
   tmc_sensorless_homing(stepperY, true);
   tmc_sensorless_homing(stepperX, true);
   SERIAL_ECHOLNPGM("\nAutoming Layer Enabled");
   ClearStallguardFlag();
   Autohoming = false;
 }
YaronSoffer commented 6 years ago

Hi Robotec101

Take a look here https://github.com/ultimachine/Einsy-Rambo/blob/1.1a/board/Project%20Outputs/Schematic%20Prints_Einsy%20Rambo_1.1a.PDF

it seems that the Einsy board has both Diag0 AND Diag1 connected to the MCU ( through a pull up register). While in the schematic all of us use only the Diag1 pin is in use. I am thinking to follow your footsteps. Did you had both Diag1 and Diag0 connected in your testing ?

Robotec101 commented 6 years ago

Did you had both Diag1 and Diag0 connected in your testing ?

These pins can be configured by SPI commands to act as diagnostic pins, diag 0 is the one connected to the stallguard system therefore that is why is the only one used in out configurations.

You can see the possible warning outputs in the page 25 of the TMC 2130 datasheet(https://www.trinamic.com/fileadmin/assets/Products/ICs_Documents/TMC2130_datasheet.pdf) and teemuatlut made a good library to configure these pins.

i hope you will be more successful than me!

Grapsus commented 5 years ago

Would it be possible to merge those functions from the Prusa firmware ?

The ISR handling routine is here: https://github.com/prusa3d/Prusa-Firmware/blob/e6c80eaa0e5a94614dfcb63cec292dfc7fa8913c/Firmware/tmc2130.cpp#L239

And the save and restore print functionality is over there: https://github.com/prusa3d/Prusa-Firmware/blob/bbd4f70f41bfcb69be0494bca8a6052e429632f8/Firmware/Marlin_main.cpp#L8612

labotecno commented 5 years ago

hello every one something was implemented about this function for lost step ? on the new firmware ? thank you

MrStump commented 5 years ago

any news?

kingofl337 commented 4 years ago

I was just wondering is it a resources issue or do the developers of Marlin not like the implementation of Prusa's re-homing? I realize it's for a cartesian printer, but if someone were to take the time and migrate the code would it be accepted?

InsanityAutomation commented 4 years ago

Part resources, part looking for a better solution. More recently we injected new commands to the front of the queue so the prusa method is less objectionable.

stantond commented 4 years ago

Just came here to say that this is a very interesting feature Prusa have developed, and as StallGuard becomes more common as the 2209 drivers grow in adoption, this would now benefit even more Marlin users.

Can I suggest renaming this issue to "Accommodate for skipped steps with StallGuard"? Automatically re-homing is only part of the solution, you also want it to resume the print, and it now applies to multiple TMC drivers.

There's also an important caveat highlighted 4 minutes into this video that should be highlighted in any documentation for this feature. StallGuard will not detect skipped steps that occur in the current direction of travel. There must be an opposing force to trigger detection. This feature is still useful and worth implementing, but it's worth understanding exactly what problems it does and does not solve.

NovaViper commented 4 years ago

Hey is there any update on this? I'm willing to give any demo code a try! I just got some TMC2209s installed my Ender

TazerReloaded commented 4 years ago

I can understand that the whole deal with homing and resuming the print is very complicated, but I'd like an option to pause the printer if a stepper skips steps. Could be stuck filament or a broken part, in which case I don't want any automatic recovery attempt anyways. This could also be solved with a current limit, but I'd rather have my printer pause than rattling about until I notice it.