M600 Change Filament Bug

I recently tried to change the filament in the middle of a print from the LCD and it failed. It seemed to try to home the print head in the X,Y direction, but told the motors to go beyond the 0,0 point. There was lots of clicking and I had to turn the printer off. Has anyone successfully changed the filament using the LCD while printing?

Here are more details on what I did:

  1. Print from SD Card -> Use gcode params -> select "file.gcode" and start printing
  2. Tune -> Change Filament

It appears to try to move the Y beyond 0 and starts missing steps on the motor. If I let it continue, it won't go back to the right spot and resume printing. Clearly something is broken in this feature.

The Tune-> Change Filament menu item appears to be in ultralcd.cpp
static void lcd_tune_menu()
{
[....]
#ifdef FILAMENTCHANGEENABLE
MENU_ITEM(gcode, MSG_FILAMENTCHANGE, PSTR("M600"));
#endif
END_MENU();
}

And all it appears to do is send a parameter-less M600 command.

In Marlin_main.cpp, the M600 command is defined as:
// M600 - Pause for filament change X[pos] Y[pos] Z[relative lift] E[initial retract] L[later retract distance for removal]

and that command is processed in the 'M' case statement further down. There appears to be a bug in the X parameter. It should be absolute, but it's relative:
case 600: //Pause for filament change X[pos] Y[pos] Z[relative lift] E[initial retract] L[later retract distance for removal]
{
[....]
//move xy
if(code_seen('X'))
{
target[X_AXIS]+= code_value();
}
else
{
#ifdef FILAMENTCHANGE_XPOS
target[X_AXIS]= FILAMENTCHANGE_XPOS ;
#endif
}
[....]

This line should not have a + in it:
target[X_AXIS]+= code_value();
it should read:
target[X_AXIS]= code_value();

Which is what the Y axis does and is also consistent with the X-axis default on the 'else' side of the 'if'.

While that appears to be a bug, this does not explain the problem I am seeing.

If the LCD is sending a parameter-less M600, then it should be using the default values which are Configuration_adv.h:
#ifdef ULTIPANEL
#define FILAMENTCHANGEENABLE
#ifdef FILAMENTCHANGEENABLE
#define FILAMENTCHANGE_XPOS 100
#define FILAMENTCHANGE_YPOS 100
#define FILAMENTCHANGE_ZADD 10
#define FILAMENTCHANGE_FIRSTRETRACT -0
#define FILAMENTCHANGE_FINALRETRACT -200
#define FILAMENTCHANGE_FEEDRATE 600
#endif
#endif

Do those values even make sense on a Materia101? When I have more time, I'm going to try to modify the firmware, but I wanted to check to see if others are having this problem as well.

Thanks in advance for responses. I'm not sure if this post belongs here or should be over on github.

  • John

After some testing, I figured out where the problem was. My first post referred to a bug that was fixed
in the master copy of the firmware (the += was gone). Once I got the latest firmware, that problem was gone, but I still had the problem of the heads trying to move too far on a filament change during a print. I found the problem in the ultralcd.cpp file.

sc_101_change_right.h has the following constant in it
PROGMEM const prog_char CHANGE_RIGHT[] = {77,49,49,55,32,69,88,84,82,85,68,69,82,10,71,50,49,10,71,50,56,32,10,71,49,32,90,49,48,48,32,70,49,48,48,48,10,77,49,48,54,32,83,50,48,48,10,84,48,32,32,32,10,77,49,48,57,32,83,50,51,48,10,77,54,48,48,32,69,50,48,10,77,49,48,52,32,83,48,10,77,49,49,55,32,77,65,84,69,82,73,65,32,49,48,49,32,32,32,32,32,10,0 };
whose characters translate into these gcode commands:

M117 EXTRUDER
G21
G28
G1 Z100 F1000
M106 S200
T0
M109 S230
M600 E20
M104 S0
M117 MATERIA 101

The M600 command is the actual filament change and the stuff before homes
the print head and heats it up. That is how a filament changes is done when the
printer is not already printing, and that works well.

When the printer is printing, there is no need to home the print head or heat it up.
(and it might cause problems to try to home because it also homes the z-axis which could squash what is already there.)
When changing the filament while printing, they only command invoked is the M600 command with parameters.
It is the parameters in the ultralcd.cpp file that are the problem.

While printing, filament change can be accomplished two ways both of which have the same bug.

Tune -> Change Filament
or
Pause Printing followed by Prepare->Change Filament

For the Tune -> Change Filament case, this line in ultralcd.cpp:
MENU_ITEM(gcode, MSG_FILAMENTCHANGE, PSTR("M600 X220 Y200"));
tries to send the print head beyond the the home point of X140 Y110 that my printer supports.
(It would be nice to have that large of print bed.)

For the Pause Printing followed by Prepare->Change Filament case, this line in ultralcd.cpp:
MENU_ITEM(gcode, MSG_CHANGE_RIGHT, PSTR("M600 X220 Y200"));
tries to do the same thing.

The solution is to just get rid of the X and Y values in the M600 commands. The new lines look like:
MENU_ITEM(gcode, MSG_FILAMENTCHANGE, PSTR("M600"));
and
MENU_ITEM(gcode, MSG_CHANGE_SINGLE, PSTR("M600"));
(Note that I also changed the display string to MSG_CHANGE_SINGLE from MSG_CHANGE_RIGTH since there is only one print head.)

This causes the M600 command to pick up the X and Y values from cfg_materia101_adv.h:
#define FILAMENTCHANGE_XPOS 100
#define FILAMENTCHANGE_YPOS 100
which is the same place it picks them up when the filament is not being changed during a print.

I couldn't have answered you question better myself!

Thank for your contribution! Have some karma!