Dual X Axis improvements

hi there,

i was working again on my dual x carriage machine and i went and tried out marlin's handling of the dual x carriage.

i must say that it is actually pretty neat, particularly an interesting behaviour you can achieve with it and i thought it would be nice to have the same kind of functionality in repetier-fw

in short:

marlin has 2 modes (hot-switchable too) for dual x: full control (basically the firmware does no parking-unparking on toolchange) and autopark (which is similar to what repetier does)
however, the difference is that marlin has 2 additional values: X2_MIN_POS and X2_MAX_POS, and here's the neat behaviour:

  • if the current extruder is unparked, (basically over the bed area) it will park the old and unpark the new
  • if the current extruder is parked, it will NOT unpark the new (because the x coordinate is out of reach for the other carriage), it will instead change the current X coordinate of the machine

this is neat for a number of reasons: first, it almost eliminates the need for LAZY_DUAL_X (which is kind of clunky), second it allows nice stuff to be done in the park area of each extruder, third it simplifies setup A LOT.

so i wanted to give a shot at implementing that in repetier-fw, but i have few questions:

  • any chance it would be merged in 1.0?
  • how portable would it be to v2?
  • a quick look at the code makes me think the less intrusive way to implement that would be to have Printer::xMin and Printer::xLength swapped with X2 values in the toolchange function, having 2 new eeprom values. am i in the right direction?
  • it would be extremely neat to have a custom gcode for parking the current extruder (eliminating the need to hardcode coordinates in the slicer gcode). would that be ok?


  • on the subject of V2 i took a peek into the dev2 branch, i can answer myself to the second question: it is 100% different from v1.

    the good news is that your implementation in V2 seems to basically implement already what i am talking about here, as i see there are min and length defined for every axis.

    this kind of makes those 2 values pointless (correct me if i'm wrong, these are taken from the sample config) provided each extruder (or rather, tool) gets to keep xyz offsets

    #define DUAL_X_LEFT_OFFSET -44.5
    #define DUAL_X_RIGHT_OFFSET 404.7

    all in all, i really look forward V2, but i might still work on v1 in the meantime

  • You are right, V1 and V2 are completely different. V2 uses the A axis for right extruder, which also allows things like mirrored dual x extrusion and different steps per mm.

    I guess you are also right that the DUAL_X_LEFT_OFFSET are not used. Offsets are now set in printer definition. Many configs will expire in old configuration.h and it really needs a cleanup once I'm done.

    Regarding V1 I plan no deep changes to concentrate on V2 my self, but if you manage a good working solution as pull request on dev branch that is superior to old implementation I see no reason to not merge it. Maybe to make old config still possible it should be a different setup, lets say the lazy macro has 1 for current lazy version and 2 for the new one. If you introduce new eeprom values that might be a problem with vendors using old system as customers would loose settings on update.

    But I do not think you need extra parameter. I think you can compute area from the 2 offsets which are the extreme. Normally 0 is x2 min and x length would then be limit for x1 max. So you do not need to introduce new config values.
  • i'm at the point where the code is working, i just need to test and clean stuff up, i ended up doing as you said and did not introduce new parameters, however since it's a completely different feature than LAZY_DUAL_X it would be misleading and problematic to use that define.

    one question tho: i'd like to implement a custom M code to just move the current carriage to park position. Any preference on where to put it in the M numbers range?
  • Ok, I think then I did not understand the difference. As I understood it is just lazy switching with additional set of min/max positions to prevent collisions. It would unpark as soon as extrusion is needed. So what did I miss.

    I saw on https://reprap.org/wiki/G-code#M605:_Set_dual_x-carriage_movement_mode that 605 sets dual x modes for marlin, so M604 would be a nice number. I think I will also implement this in V2. Should be quite simple. Maybe I call this park extruder and if there is no park position it is just ignored. So I can also have this on other printer types. On deltas I could just move to top for example at end of print. Like the idea.
  • Sorry, need to revert. Use M603. M604 is already used by repetier.
  • maybe i didn't explain it correctly. you can think of this mode as something inbetween standard dual_x and lazy_dual_x.

    basically, the carriage will be parked/unparked normally, except for when the current carriage is already in parked position. then the new will not be unparked because it would never be able to reach that coordinate.

    for example: left carriage is @ -30mm when homed. if switching to right carriage, it will not unpark because it can't get to -30.00mm X coordinate.
    having useable space outside the bed area is made possible by assuming fixed 0 xOffset for left carriage and a negative xMin number, and for right carriage assuming xMin = 0 and xLength = xOffset.

    this is basically how marlin operates under their Auto-park mode.
  • Ok, so any move with x on bed area the extruder will move. On extruder switch new extruder will also move to that position if old was on bed otherwise will stay parked. That would be what the non lazy mode is supposed to do. If it does not that would be an error I guess.
  • that was the old behavior, kind of. except that with old system you are forced to put xoffset to both extruders so that they don't crash into eachoter, effectively making any extra X space outside bed area unavailable, so that condition could never happen

    new mode is working fine. testing it right now. i added M606 (M603 was already taken) to move to a position relative to the current carriage X park coordinate. it's very useful to put into the slicer's toolchange custom g-code.

    the new mode is not compatible with LAZY_DUAL_X. i either gotta write that in the documentation or just make them mutually exclusive, possibly without making a mess with #ifs and whatnot.

    anyway, my personal opinion is that LAZY_DUAL_X will be superseded by this. the only purpose of it was to make purging possible before the extruder gets positioned in the bed area, something that has to be done inside the custom toolchange g-code.
    with the new system, not only it is possible to purge, but to move, and half of the printing space lost (if any) due to the dual carriage is gained back in single printing mode.

  • Ok with M606, will adapt it for V2.

    I will have a look at your changes when you are ready and do a pull request. I will then decide how to handle it. I guess I still do not get it fully. Maybe because I normally never use dual x in action. Having laze dual x removed would be fine for me, but I know users wanted this so I need to see it in action. The reason for lazy change was mainly to reduce movements until print. E.g. left was at x=100 and extruder switched. Next extrusion was at x=150. Without it would go to 100 and then 150 oozing. In lazy mode it directly goes to x=150 reducing move by 100mm. In my eyes that is the only advantage. 
  • removing LAZY_DUAL from v1 does not make much sense, some user may actually use it (highly doubt tho, more on that later) so better leave it. just don't bother implementing it in v2.

    i'll make a video showing you the various modes and it'll be clear

  • here's the video. i hope it's sufficient to show the working of the various modes. will make more if needed
  • Great video. So to summarize it is more like the non lazy mode, but homing keeps it in the pocket and you can move until the full sides because you dynamically switch the limits. And switching while in the "hidden" area will not move the other extruder into the area because the x position is disallowed then.

    That all makes completely sense and I'd change the non lazy mode to this behaviour. The only difference for users having that mode currently is that after homing z is not 0 but the park position. Any moves will none the less be executed correctly.
  • edited October 2018
    precisely. anyway, no need to remove anything now imho, code looks tidy enough to me. gotta test some more and then i'll make the pr

    for v2 i suggest this mode only. then users can get the old behaviour if they really want by just playing with offsets and custom g-code on toolchange
  • v2 has already lazy mode but as eeprom parameter so you can easily switch. Implementation is also much easier there due to new design. But I think it should behave basically like what you implement and just add the move x on first extrusion move in addition.
  • pr done. i added some explanation in the config as it was a little obscure for first time users
  • Yes already merged and tested it a bit.
    The only 2 problems I see so far is that now heads can crash into each other. Need to see how that can now be prevented. Your bigger x range allows it to move left extruder into right one parking position. I think each extruders opposite limit should be reduced by -extruder 0 offset x. Assuming position 0 is reachable from extruder 1.

    Second thing is homing with second extruder being active does home it to x=0 and not to park position.

    Both should be easy to fix. Apart from this I like the new mode. Already adapted it a bit in V2 but need to test this as well.
  • edited October 2018
    uh. both shouldn't be possible. if configured properly heads won't crash ever. if they crash it's because the lenght of x axis is < than bed size + left and right carriage. in that situation you have just to increase XMin (or rather decrease, as it is a negative value) and decrease XLength.

    homing with extruder 2 should work fine. infact, it is what you see in the video (i have ext1 as right. but tested both ways). if it doesn't, i might have introduced a regression while cleaning up the code. will check.
  • edited October 2018
    yep, tested both issues right now and everything works. my guess is that you have some setting wrong.

    also, keep in mind that extruder 1 does not mean left or right. it depends on the X_HOME_DIR.

    so, if you have X_HOME_DIR = -1 then Ext0 is left, if you have X_HOME_DIR = 1 Ext0 is right.
    example of my config right now:

    #define X_HOME_DIR -1
    #define DUAL_X_AXIS 1
    #define DUAL_X_RESOLUTION 0
    #define X2AXIS_STEPS_PER_MM 100
    #define LAZY_DUAL_X_AXIS 0
    #define DUAL_X_AXIS_MODE 1

    #define X_MIN_POS -31 <-this is what you would have put in the left XOffset, but in mm
    #define X_MAX_LENGTH 248 <-this is how far the left carriage can travel from home to right without crashing into the other

    ext0 XOffset = 0 <-this MUST be 0
    ext1 XOffset = 24966

  • >  X_MAX_LENGTH will have to be the distance between left carriage home position and the right carriage 
    >  home position, while XOffset of the right carriage will have to be the distance (in steps)

    That is xoffset right - xoffset left which is what I used.

    Now you say
    #define X_MAX_LENGTH 248 <-this is how far the left carriage can travel from home to right without crashing into the other

    which is wat I interpreted minus crash distance. Will test that tomorrow and modify the description to be more clear. But I guess that will be my error here.
  • finding the right words is difficult here, as anything is kind of ambiguous. but basically it's completely different from old system. you have to play around with 3 values to align extruders and not make them crash: XMin, XLength and right extruder XOffset.

    left extruder XOffset must be 0, and right extruder XMin is assumed 0
  • Ok, your changes were all good. Homing problem was also my config error.

    I have uploaded github with some tiny changes to remove compiler warning and also to compile with old config without error. Will soon also adjust the config tool to contain the new version.

    After some tests of critical conditions all worked on the safe side, so really a good implementation. Thanks for the work.
  • no problem, thank you for the awesome work.
Sign In or Register to comment.