Marlin: Move Axis until Pin Triggered?

Created on 6 Jan 2017  路  41Comments  路  Source: MarlinFirmware/Marlin

Is it possible to have an axis keep moving until a pin is triggered, similar to how the homing works, but during a standard move command?

For example. I have a special use for the printer and I would like the Z axis to move up until a pin is triggered (either pulled up or down). Im not sure if this is possible but I would image it would work something like, G1 Z10 (axis moves up 10mm) but is monitoring a pin via M226 and will stop the Z axis before it reaches 10mm if the pin is triggered, but if its not triggered it will continue to 10mm.

Is something like this possible?

Thanks for any advice.

Configuration Calibration Solved Question

All 41 comments

Would defining that pin as your Z_MAX endstop work?

Not sure, I havent tried that. Wouldnt that just put the printer into a fault state? could more gcode be run after its triggered its Z_MAX? also, the trigger is not an endstop, its a signal from another Arduino. Id like to used a pin on the other Arduino to signal a pin on my RAMPS so im not sure if that would work?

It's not in a fault state. You just can't move up any further until the signal is removed.

There's also the G38.3 command. G38.3 X20 will move to the X20 position unless the Z_MIN endstop is activated. G38.3 can be used with just X, Y, Z or any combination.

That sounds like it could work, Will the G38.3 command reset and home locations?

The only other thing I would need to do is record how much the axis moved before it got triggered to stop, as I would need to return the axis back to its original position Minus the layer height. So if it moved 2.11mm and then stopped on one layer and 2.43mm on another I would need to be able to record that so I can return to the starting location -LayerHeight accurately. The position the trigger will stop the axis move will change between each layer. Is there a way to do this?
The only thing I can think of is recording the position when triggered and using that value in a G1 command, but im not sure how that would work.

Thanks for all your help so far!

The true (X,Y,Z) position isn't invalidated when an endstop is triggered. The only time it gets messed up is if you hit a physical barrier (controller still sends step pulses but there is no physical movement).

You may be right about going into an error state if you're printing and hit an endstop. I've never done that so I don't know for sure.

I'm getting a headache thinking of all the ways the extruder position could cause problems.

I think the biggest problems will be:

  • How to stop running commands that move the extruder after hitting the end stop
  • How to get to the "go back to start" commands

I'm assuming you want everything controlled by a g-code program.

In Marlin there's very little computational capability within a g-code program and there's no branching. The other thing is that most commands are executed immediately (they don't wait for the G0, G1, G2 & G3 commands to finish). As an example, if you issue G1 X10, then G1 X100 and then M114, the M114 will report the position probably around X10.

I see a future filled with custom coding.

How were you going to generate the g-code program? I expect you're planning to use a slicer but then you'd have to manually (custom utility?) add the "go back to start" commands.

Perhaps the solution is to re-define the problem. Can you describe what you want to do and why? Once we know what the goals are then maybe a different solution will become apparent.

Ok, so basically I am running a Z axis stage that peels a material off of a surface. The peel distance is variable and depends on the "stickiness" of the substrate im peeling off. I have a force sensor setup on another arduino and it measures this stick force and relays it back to a graph on the PC. I have a program that sends Gcode commands to the RAMPS board, The Gcode is written manually and is pretty basic as im only moving a Z axis up and down.

I was thinking I could Home the Z to the Zmin limit switch then use the G38.3 to raise the Z axis and make the force sensor arduino pull a pin high or low to simulate a endstop. This pin would be connected to the Zmax pin on RAMPS and once triggered would stop the axis at this position. I would then switch to absolute coordinates and G1 Z0 to return to the start/home position, this would then cycle over again. Each time raising only as far as the force sensor trigger was set to.

The idea is to only raise the Z stage as high as is necessary to peel the material off the surface substrate.

What do you think?

Much simpler than I thought.

I think that a G0 (or G1) would work better than the G38 command. G38 only uses the Z_MIN endstop. If you use the Z_MAX endstop then the G0 command will do exactly as you want.

What are you using as your force sensor? I'm looking for a backup system for my BLTouch. I've had a couple if incidents where the Z_MIN signal was missed and the print head was driven into the bed.

is G38 in the update only? can't find it in the July version

see it in the update, nvm

@Bob-the-Kuhn : For your bltouch problem have a look at thread #5650. Maybe it solves it.

Anyone know how I could modify M600 to treat the filament runout sensor as an endstop? Want to use two extruders for two lead screws.

Im using some expensive load cells, a custom amp and combiner board for my force measuring system. I think it would be expensive and over kill for a backup system to your BLTouch. You could acheive the same result with some cheap "Human weight load cells" from Ebay and an Arduino but it would be less accurate.

@1stsetup - thanks for the pointer. I've joined that thread.

@jerryerry - have you tried enabling FILAMENT_RUNOUT_SENSOR in Configuration.h and adding a define for FIL_RUNOUT_PIN in your pins_XXX.h file?

yes, tried using pin 14: I undefined pin 14 as an endstop in the configuration, and hooked an optical switch up and made sure the logic was correct. But the extruder doesn't respond

I tried adding the changes needed to use G38 (I don't want to completely update to the latest version because I've made too many changes) but there are quite a few errors popping up, so gave up on that. Will try add the g38 again when if I can't get m600 to work. Problem is that I don't want the print to pause when the filament_runout_sensor is activated, nor do I want anything to move or become disabled..

@jerryerry - I'm confused. What do you want to happen when the FILAMENT_RUNOUT_SENSOR is triggered?

Also, how are you testing it? As I read the code the idle task will kick off M600 if the FIL_RUNOUT_PIN is active and if either 1) an SD print is happening or 2) the print job timer is running. Maybe you need to issue a M75 command before you test it.

@jerryerry - to answer a couple of the earlier questions ...

Modifying M600 functionality - an easy way to connect your filament sensor to custom code is to go to Configuration.h and change #define FILAMENT_RUNOUT_SCRIPT "M600" to "custom_code()".

As to using it as an endstop - endstops.cpp only checks the max & min endstops on the X, Y & Z axis. You'd need to modify the update() routine to add endstops for another axis.

PS - don't forget that the G38 command only uses the Z_MIN endstop. The G38 claim to fame is that it checks the Z_MIN endstop on all three axis and for both + and - directions.

Hey Guys,

Been testing this and Im having a problem. Endstop dont stop the axis. I have the Z stage setup with 2 endstop for testing and it will home to the Zmin with no issue. I can also confirm via M119 that the Zmin and Zmax endstop can report triggered and open correctly.

Problem is that if I command the axis to move G1 Z10 it will move but if I press either of the endstop the axis does not stop, it will continue till 10 and ignore the endstops. Im using the latest version of marlin in case that matters.

Anyone got any ideas? not sure what the problem is. Axis wont stop in either direction with either endstop.

`Configuration_adv.h

// @section homing

// If you want endstops to stay on (by default) even when not homing
// enable this option. Override at any time with M120, M121.
//#define ENDSTOPS_ALWAYS_ON_DEFAULT

???

Yep, that was it.. Thanks so much Blue-Marlin, I missed that definition. Guess its commented out by default. Its working as it should now.

New Issue,

I am homing to an endstop at Z_Max, but I want the Z axis to stop when moving in the Z+ direction and my simulated endstop is triggered. Currently the simulated endstop is on Z_Min pin, but it does not stop travel in Z+, it only works when travelling towards Z-. From what I understand, the endstops only respond to travel in their direction.
Any Ideas how I can make this work? my endstop is at Z_Max and its not a simple task to move it to the Z_min travel. I know I need my simulate endstop to be on the Z_Max pin as that is the direction I want it to cause the stop.

Can I change the Z_Max endstop to another pin for homing then switch back after homing? Or can I Change the behavior of the endstops so when anyone is triggered all axis stop? Or maybe something else?

@Phife54
If it can be a custom solution-
endstops.cpp
```diff
@@ -328,11 +328,11 @@ void Endstops::update() {
// Head direction in -Z axis for CoreXZ or CoreYZ bots.
// If DeltaA == DeltaB, the movement is only in X or Y axis
if ((stepper.current_block->steps[CORE_AXIS_1] != stepper.current_block->steps[CORE_AXIS_2]) || (stepper.motor_direction(CORE_AXIS_1) != stepper.motor_direction(CORE_AXIS_2))) {
if (stepper.motor_direction(Z_HEAD))
#else
- if (stepper.motor_direction(Z_AXIS))
+ //if (stepper.motor_direction(Z_AXIS))
#endif
{ // Z -direction. Gantry down, bed up.
#if HAS_Z_MIN

       #if ENABLED(Z_DUAL_ENDSTOPS)

@@ -364,11 +364,12 @@ void Endstops::update() {
UPDATE_ENDSTOP(Z, MIN_PROBE);
if (TEST_ENDSTOP(Z_MIN_PROBE)) SBI(endstop_hit_bits, Z_MIN_PROBE);
}
#endif
}
- else { // Z +direction. Gantry up, bed down.
+ //else
+ { // Z +direction. Gantry up, bed down.
#if HAS_Z_MAX

       // Check both Z dual endstops
       #if ENABLED(Z_DUAL_ENDSTOPS)

```
will check both switches in both of the directions.

As I understand, it you want one pin to stop the movement in both the Z+ and the Z- directions.

The G38.3 command will do that for you. It works like a G0 command except that movement will stop if the Z_MIN_PIN goes active no matter which axis is moving (or if all three are moving) or the direction of the movement.

If it will check both Zmin and Zmax switches on either direction during G1 moves then that should work. I will give it a try tomorrow.

I dont need the movement to stop in both directions, only the Z+. But im homing to Z+ so I cant use the same Zmax pin for both the endstop and simulated endstop/sensor. So I need to use another input for the sensor.

I cant seem to get G38.3 to do anything. My board responds with an "OK" after issuing G38.3 Z10 but nothing happens. No movement.

I cant seem to get G38.3 to do anything. My board responds with an "OK" after issuing G38.3 Z10 but nothing happens. No movement.

By chance is the head already at 10? G38.3 Z10 then G38.3 Z20 will produce movement unless G38 isn't enabled or the head is already at the Z_MAX_PIN endstop.

G38 was added to Marlin between the RC7 and the RC8 releases. There's also a flag in Configuration.h that needs to be defined.

I misunderstood - you want two different signals to stop the Z+ movement. The G38.3 command should still work. The Z_MAX_PIN is still checked and the Z_MIN_PIN will also stop it when going in the + direction.

Ok, perhaps I am missing the G38 part in Configuration.h that needs to be defined, I will see if I can find it.

As for the code change suggested by Blue-Marlin, It works, but after homing it does not allow the axis to move off the triggered endstop, says "endstops hit", I disabled the stepper and moved the axis by hand off the endstop and I was able to move again as normal, I could confirm the axis stops in both direction when my simulated endstop is triggered, its just not moving off home, or homing correctly now, it only moves to the endstop and stops, does not bounce off the endstop and hit it again slowly.

I cant seem to find what needs to be defined in the firmware to allow G38.3 to function, any help would be greatly appreciated.

Sorry - it's in Configuration_adv.h

Ok, I got G38.3 working, I enabled it in config_adv.h also had to enable a Z Probe in Config.h for it to work, otherwise it would not compile.

The current setup is, Z Endstop for homing is on Z_Max endstop input. I have the machine set to home to Zmax. I have the simulated endstop on Z_MIN endstop input.

Its still not working correctly though, I can home correctly and everything works as normal, After homing I move to Z0 and issue the G38.3 Z50 command, the axis starts to move up but does not stop when triggering the Z_MIN endstop, it only responds to the Z_MAX endstop (which is the home switch its moving towards) I want to be able to stop the axis movement with the Z_MIN endstop before it reaches the Z_MAX endstop. It seems like the G38 command only responds to the endstop its moving towards like a regular move command.

Perhaps I have the setting wrong for defining what the Endstop input for homing and probing are. Any help here would be greatly appreciated. It looks like I can do this in a few different ways, but so far nothing is working 100%. I like Blue-Marlin's idea of making the axis respond to either endstop in either direction, but for some reason, this breaks the regular homing routine.

Been working on this all morning, cant seem to get it to work at all. G38.3 just doesnt stop when the endstop is triggered and moving toward Max. I tried the endstop on ZMIN, and YMAX as I have those open, I changed the pins for the Z Probe to the correct pins, I can see when I issue M119 that the Zmax endstop triggers correctly when the axis is on the endstop and I can see the ZProbe endstop working correctly when I manually trigger it. So I its registering and reporting the correct state of the probe/endstop. I dont know why its not stopping.

Perhaps there is a problem with the firmware and G38.3? I know it was just added so perhaps it doesnt work right? It will work if im moving towards the direction that it expects the endstop to be. So If im moving towards MAX then it will not respond to the MIN endstop/probe. Maybe there is some code similar to the code Blue-Marlin mentioned that allows it to respond to the endstop regardless of direction?

Or perhaps I should forget about G38 for now and see If I can get Blue-Marlins method working? The only issue with that is that it will not move off end endstop after homing, it responds with Endstop Hit when trying to move after homing.

@1stsetup
I'm sorry, but my method can't work. There is no way to leave a triggered endstop.
Switching on and off the direction independency on demand in every home/probe procedure would be too much of a change.

What about changing the way G38 works so that it responds to movement in both directions?

@Phife54
I was able to get G38 to work on my machine in both directions. My definitions are:

#define G38_PROBE_TARGET
#define FIX_MOUNTED_PROBE
#define Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN
#define USE_ZMIN_PLUG

With this setup you don't have to remove the Z-MIN trigger to do G0 & G1 commands. Z_MIN_PIN is only checked when the G38 command is active.

@Bob-the-Kuhn
Youve been such a great help, thank you! I tried your settings, I know I tried these settings and they did not work, I tried again and same results. But since you confirmed it does work, I started to think about what else is different about my setup vs yours that could affect this.

Turns out, I have Dual Endstop Homing enabled for my Z axis as It uses 2 steppers on their own driver, I also wanted to be able to home each end to its own switch. This is causing the G38 command not to work correctly. Once I disabled dual endstop homing the G38 command now works.

So perhaps something is still broken in the firmware with Dual endstop homing and G38.

The only issue I have now is that when that the G38 command moves the axis towards my probe and stops when it hits it, but it does a homing type bounce where it will hit the probe then move off and back onto it slowly. I would prefer it just stops, any way to do this and still have it do the bounce with homing?

Yes, G38 has a double touch built into it.

To disable you need to comment out the following code in Marlin_main.cpp:

    // Only do remaining moves if target was hit
    if (G38_endstop_hit) {

      G38_pass_fail = true;

      // Move away by the retract distance
      set_destination_to_current();
      LOOP_XYZ(i) destination[i] += retract_mm[i];
      endstops.enable(false);
      prepare_move_to_destination();
      stepper.synchronize();

      feedrate_mm_s /= 4;

      // Bump the target more slowly
      LOOP_XYZ(i) destination[i] -= retract_mm[i] * 2;

      endstops.enable(true);
      G38_move = true;
      prepare_move_to_destination();
      stepper.synchronize();
      G38_move = false;

      set_current_from_steppers_for_axis(ALL_AXES);
      SYNC_PLAN_POSITION_KINEMATIC();
    }

Here's the code change to make double touch optional. All I did was make the double touch portion a conditional compile based on the PROBE_DOUBLE_TOUCH flag in Configuration.h

    if (G38_endstop_hit) {

      G38_pass_fail = true;

      #if ENABLED(PROBE_DOUBLE_TOUCH)
        // Move away by the retract distance
        set_destination_to_current();
        LOOP_XYZ(i) destination[i] += retract_mm[i];
        endstops.enable(false);
        prepare_move_to_destination();
        stepper.synchronize();

        feedrate_mm_s /= 4;

        // Bump the target more slowly
        LOOP_XYZ(i) destination[i] -= retract_mm[i] * 2;

        endstops.enable(true);
        G38_move = true;
        prepare_move_to_destination();
        stepper.synchronize();
        G38_move = false;

        set_current_from_steppers_for_axis(ALL_AXES);
        SYNC_PLAN_POSITION_KINEMATIC();
      #endif
    }

Perfect, its working as I had hoped now. Only wish I could use Dual Endstop homing as well. I was broken in the last RC and didnt work right for me, I was excited to see it working correctly in the latest RC but it seems that it doesnt play nice with G38. Maybe in the next RC...

Thanks so much to everyone for all your help!

@Bob-the-Kuhn thanks, M75 did the trick. What I was trying to do was just run the extruder until it hit a mechanical switch.
I couldn't figure out how to make m600 run immediately as the switch as triggered and couldn't get it to work by adding it to emergency_parser .
I just rewrote over g12 (since i had no use for it) to do an external method:

  while ((digitalRead(3) == HIGH))      //using pin 3 for endstop
  {
    destination[E_AXIS] += 0.001;
    prepare_move_to_destination();         // set_current_to_destination
    stepper.synchronize();
    refresh_cmd_timeout();
  }

it works well enough although it isn't smooth

Thank you all so much - I am so impressed by the support that Marlin gives

@jerryerry - try adding the following line to the beginning of the update() function in endstops.cpp
if (READ(3) == LOW) stepper.endstop_triggered(E_AXIS);

Issuing a G0 E10 command should move the E axis until pin 3 goes low or the destination is reached.

If you want debounce then more code is needed.

Was this page helpful?
0 / 5 - 0 ratings