# Specific 3D Printers, Scanners, & Hardware > RepRap Format Printer Forum > Firmware Enhancements to Marlin >  Doing Filament Change Command (M600) using limit switches

## DarkAlchemist

> I don't understand how this helps with multi-colour prints. I just pause the print with an M600 whenever I need to change colours.


When doing multi prints that interlock to form the whole.  The other issue is, as I understand it, that M600 is only made to work with LCD panels and while I have one I never liked it and went back to the Linux box using Pronterface.

----------


## Roxy

> When doing multi prints that interlock to form the whole.  The other issue is, as I understand it, that M600 is only made to work with LCD panels and while I have one I never liked it and went back to the Linux box using Pronterface.


Here is a thread you might want to read:

http://3dprintboard.com/showthread.p...ltipanel-Users

----------


## DarkAlchemist

> Here is a thread you might want to read:
> 
> http://3dprintboard.com/showthread.p...ltipanel-Users


After I posted I did a Google search for M600 gcode and up popped that thread from April I believe.  I have to admit I got lost because I looked at the Marlin_Main.cpp and I see nothing locking me into the LCD panel but it sure seems like it would rock if it works.

As I said I use Pronterface to print with but a lot of people seem to use Repetier and it has some nice things for dealing with this.  Move the head up and out of the way and remove the filament, load in the new filament, and purge the head then continue printing.

I am still wondering how people do multi interlocking pieces because the bed must cool down for the print to pop off and your G29 matrix is surely (I say surely because I have not tested this) off at that point.  50c vs 85-110c.

edit: Oh, I almost forgot but I use a Ramps 1.4 board and I am not even sure what that board was/is in your write up/post.

----------


## Roxy

> edit: Oh, I almost forgot but I use a Ramps 1.4 board and I am not even sure what that board was/is in your write up/post.



I wish I had a RAMPS board, but I have a PrintrBoard.   However, that really doesn't matter.   You just need to find an unused GPIO pin on your board and wire a switch to it (and declare that pin for use by the firmware).   It is pretty straight forward to check if you have the switch wired up correctly.   If you decide to do that, I'll help you get the M600 code working on your board.

----------


## DarkAlchemist

> I wish I had a RAMPS board, but I have a PrintrBoard.   However, that really doesn't matter.   You just need to find an unused GPIO pin on your board and wire a switch to it (and declare that pin for use by the firmware).   It is pretty straight forward to check if you have the switch wired up correctly.   If you decide to do that, I'll help you get the M600 code working on your board.


My ramps had no pins so I had to add them for the ABL but what a PITA getting all of those wires back on for the motors etc...  I never added the ones that didn't have anything to do with the servo.  :Frown:   Every time I take that off I always end up missing a wire when I put it back together.

Why do I need to wire something else up to get M600 to work?

----------


## Roxy

> My ramps had no pins so I had to add them for the ABL but what a PITA getting all of those wires back on for the motors etc...  I never added the ones that didn't have anything to do with the servo.   Every time I take that off I always end up missing a wire when I put it back together.


Every picture of RAMPS boards I've seen have lots of GPIO pins sticking up to put other boards on.  If you don't have dual extruders, I would think there should be extra GPIO pins on the Arduino board that would handle that if it was plugged in.   In that case, you just plug a wire like here and run it to a switch:

http://www.ebay.com/itm/10pcs-Female...item4d1baa25fc




> Why do I need to wire something else up to get M600 to work?


Because the Arduino can't read your mind and know when the filament change is completed.  It needs you to tell it that everything is done and it can continue.  If you wanted to be really lame, you could look at one of your limit switches for one of the axis instead of a new switch.   But connecting up a switch is really pretty simple and a better way to go.

----------


## DarkAlchemist

I gotta tell you the only pins they give you on a Sainsmart board (never ever again will I touch Sainsmart and trust me I have talked to them they are a horrible company with horrible products but oddly their 2560 isn't bad at all) are the pins for the end stops and steppers and nothing else.  Thank goodness the holes are there for the rest of the normal Ramps 1.4 pinout or I would have not been able to remove the ramps+arduino from the i3 frame then remove the ramps from the arduino then solder on the pin headers for all of the pins needed for the ABL to work.  I did add all 4 places for servos (though only one is used) but anything else down the edge of the ramps is still missing.  If I ever need to add something or take it off for any reason I am ready to solder on the rest of the pins.

In Red is the LCD control panel hookup and in white are all of the missing pins.

The first two white rings is what must be added for ABL and the last two are digital and analog pins I did not add.

----------


## DarkAlchemist

> Because the Arduino can't read your mind and know when the filament change is completed.  It needs you to tell it that everything is done and it can continue.  If you wanted to be really lame, you could look at one of your limit switches for one of the axis instead of a new switch.   But connecting up a switch is really pretty simple and a better way to go.


That is precisely what I was talking about as this dude on Youtube had Repetier do that without any extra hardware or wires.  What he did was press continue and it went back to where it was and continued and he said that was built in to Repetier.  Well, that isn't in Pronterface sadly.  Continue is there but it is a continue where you left off not a continue on a M600 going right back where it was and continuing with the new color.

----------


## Roxy

OK...  I understand your problem!   You could try just heating up the one pin where you want the connection and inserting a wire like this:

http://www.ebay.com/itm/40pcs-20cm-M...item20ef967429

But...   If you want, we can make a small change to the firmware to watch which ever limit switch you want to use.    What would happen is the printer would get the M600 filament change command and do its thing.  After you get the filament changed and the nozzle purged of the old filament, you would press and release the specified limit switch.  And everything would continue on its way.   Do you want to try that?

----------


## DarkAlchemist

> OK...  I understand your problem!   You could try just heating up the one pin where you want the connection and inserting a wire like this:
> 
> http://www.ebay.com/itm/40pcs-20cm-M...item20ef967429
> 
> But...   If you want, we can make a small change to the firmware to watch which ever limit switch you want to use.    What would happen is the printer would get the M600 filament change command and do its thing.  After you get the filament changed and the nozzle purged of the old filament, you would press and release the specified limit switch.  And everything would continue on its way.   Do you want to try that?


Sure.  Eventually I will get those other pins wired up with the header pins as I had to do for ABL but frankly I had it all installed and did a Homer Simpson DOH! when I noticed I had forgotten those digital and analog pins.  With those added adding another switch would be easy.

----------


## Roxy

> Sure.  Eventually I will get those other pins wired up with the header pins as I had to do for ABL but frankly I had it all installed and did a Homer Simpson DOH! when I noticed I had forgotten those digital and analog pins.  With those added adding another switch would be easy.


Which limit switch is easy to get at when you are standing over your printer?

----------


## DarkAlchemist

Y would be.

Here is the video I mentioned before as I just found it again:



Basically he is doing something like this and I am unsure how M600 compares ->


```
M83 ; turn on relative movement for extruder  
G1 E-5.000000 F6000 ; retract filament 5mm  
G1 X0.000000 Y0.000000 Z4.000000 F9000 ; home X and Y axis leave Z at current height  
M84 E ; release extruder stepper motor from 'holding' position  
@pause ; pause print!
G1 X0.000000 Y0.000000 F9000 ; upon resume, rehome X/Y in case position was bumped out  
G1 X69.080000 Y58.560000 F9000 ; move back to next layer starting position  
G1 E0 F6000 ; reset extruder, ready to push out plastic again  
G1 F9000  
M82 ; set extruder movement back to absolute ready for next layer
```

----------


## Roxy

One bad thing about what he is doing is he is turning all the motors off.  It is very difficult not to move the X & Y when you do this as you are feeding new filament into the extruder.  The M600 selectively turns off only the Extruder's motor.   

We can leverage the M119 code to look for the Y Limit switch being pressed.   It looks like:

      #if defined(Y_MIN_PIN) && Y_MIN_PIN > -1
        SERIAL_PROTOCOLPGM(MSG_Y_MIN);
        SERIAL_PROTOCOLLN(((READ(Y_MIN_PIN)^Y_MIN_ENDSTOP_  INVERTING)?MSG_ENDSTOP_HIT:MSG_ENDSTOP_OPEN))
      #endif

I think if you replace this section of code in your Marlin_main.cpp it will probably work.  Probably, you should just add a M600 command to something small you can print and see if it does the right thing.  My concern is if your print homes to the max position of the bed we might have to swap the Y_MIN_PIN label with Y_MAX_PIN.



```
#ifdef FILAMENTCHANGEENABLE
#ifndef ULTIPANEL

bool lcd_clicked()
 {
        int pin_being_examined;
        int ii, iii, jj;
        
        pin_being_examined=Y_MIN_PIN;                     
        
        pinMode(pin_being_examined, INPUT_PULLUP);  // Set it to Input with a pull up if it hasnt
        delay(50);                                  // been used since RESET.
        
        iii = digitalRead(pin_being_examined);      // Get the current state of pin.  

        return !iii;
}

void lcd_pressed()
 {

    while( lcd_clicked() != 0 )            // Wait for the switch to be released
        ;
    delay(50);
    while( lcd_clicked() != 1 )            // Wait for the switch to be pressed
        ;
    delay(50);
}
#endif 
#endif
```

Once you get that change folded into your code and tested, please report back.   If everything works as expected, I'm going to change the directions on the M600 Filament Change thread to allow using limit switches as an option.

----------


## revwarguy

Hi Roxy,

I was thinking of doing something along these lines, but using Y_MIN on a switch to detect filament being out, i.e., TRIGGERED if filament present, if OPEN filament is out.  Then, when you run out of filament, it executes an M600.  

To do this, would you place a check for Y_MIN at the top of the marlin_main.cpp loop, and if OPEN try to jump to the M600 code somehow?  Would it be best to remove the M600 code to a routine that could be called by both the trigger and the main case code?

----------


## Roxy

> Hi Roxy,


Hi!   I got your posts approved!




> I was thinking of doing something along these lines, but using Y_MIN on a switch to detect filament being out, i.e., TRIGGERED if filament present, if OPEN filament is out.  Then, when you run out of filament, it executes an M600.  
> 
> To do this, would you place a check for Y_MIN at the top of the marlin_main.cpp loop, and if OPEN try to jump to the M600 code somehow?  Would it be best to remove the M600 code to a routine that could be called by both the trigger and the main case code?


I believe the main line Marlin code at GitHub has the logic to handle a filament check now.  But it might be tied to having an LCD Panel.  I don't know.  I haven't looked at that.   But to your question, Yes, the check would have to be in the main loop somewhere.  That is the only higher level piece of code that is always running.

This is a bit of hack...   But it is how the LCD Panels do their work.   When you see the filament run out, you could use the function:

bool enquecommand(const char *cmd)         

in Marlin_main.cpp to put a M600 into the buffer and then just return back to the main loop.  The main loop would think the M600 command was part of the .GCODE file that it was processing.  It would blindly do as told and do a filament change.

----------


## revwarguy

thanks for approving my posts!

 I will look into the enquecommand call, and if you don't mind, I'll report back here on what happens. 

Thanks again!

----------


## toybuilder

We've been using the "Ziggy" modification (https://docs.google.com/viewer?a=v&p...MzQzNTQyNjJmMA) to enqueue the M600 command when a filament fault is detected with our Tunell Filament Monitor (http://www.toybuilderlabs.com/produc...lament-monitor).  

Here's a demo of it working with the Fusion3 F306: https://www.youtube.com/watch?v=6IJ5EZDe62Q

----------

