I got stuck in configuring a dual x carriage setup

Hi all,

I am quite a newbie if it comes to dual X carriage configuration. A friend of me build this giant Prusa-like printer with a double X axis. He gave up on it to get it working and asked me if I could help him out.I never used used a setup like this and tried to make a firmware using the configurator.

But I cannot find how to set up the second X-axis. Both have a endstop, but there are no options to configure a endstop for the second X-carriage. 

I am using a Ultratronics pro motherboard and have my second X motor connected to the E2 stepper driver. 

Can someone help me to find out on how to make a configuration like this?

Thank you in advance,


  • Depends on firmware you use. If you have V1 the right endstop is used for second right extruder. In x motor select to have dual x and you can select one. Important are the x offsets of the 2 extruders. These are the offset from the bed 0 position so left extruder gets negative value and right one a quite big positive number. That is all you need to define.

    For V2 there is a sample configuration for dual x provided. You find it on github in dev2 branch. With that board you can use both solution. If can do programming a bit and are not scared of manual configuration ( no config tool) try V2.
  • Thank you for the reply, I have installed Visual Code and the required plugins, but I don't find how to open the dual x sample configuration in it. Could someone explain me how to do that?

    I never used manual configuration before, I am all new to this but always willing to learn more.

    Thank you in advance,
    Kind regards,
  • Use your explorer and go to src/SampleSystems/Dual-X-Axis/Stacker X2 and copy the 2 config files to src/Repetier as replacement. Then config is for the right printer type and you only need to change the pins and temperature handling and size, steps per mm to match your printer. Make sure to read in parallel the doc page which describes all the macros in configuration_io.h in detail so you can switch to the correct one for your hardware.
  • edited April 30
    I have been struggling a lot to open the V2 firmware in VSCode, but now I finally got it open and in the dev2 branch.
    However, when I open Configuration.h, I get error messages:

    #include errors detected, please update your includePath, Squiggles are disabled for this translation unit (C:\Users\Blahblah....\Repetier Firmware\src\Configuration.ccp) C/C++(1696) [179, 1]  
    --> this points to the line 179 in Configuration.h where it says: #include "boards/pins.h"

     -Cannot open source file "Program.h" (dependency of "boards/pins.h) C/C++ (1696) [179, 1]
     -Cannot open source file "Stream.h" (dependency of "drivers/drivers.h) C/C++ (1696) [184, 1]

     This is very new for me and I almost have no clue of what I am doing, But I guess I have some settings wrong in VSCode or I am missing some files..... Can Someone point me to the right direction?
     Thank you in advance, K.
  • Did you install the PlatformIO extension in VSCode?
    That is all you need. After first compilation it will install the arduino libraries which you referenced here. mIt is no problem if vsc can not find the files Only important is if you can compile with vsc and that should work if there are no config errors and platformio is installed.
  • I have PlatformIO installed. I used the "Clone git project" from the PlatformIO toolbar on the side and pasted the link.
    Next "Repetier Firmware" opened in the explorer on the side. In the bottom left corner I changed the branch to dev2.

    As from then I have no Idea what I need to do..... I don't find a compile button like in the Arduino IDE, and if I open any file from the "src" folder I get a bunch of errors.

    I feel really ashamed to ask it like this, but I don't know how the VSCode works. If I have my screen like in the image, what should I do next to compile the firmware and get the missing Arduino libraries installed?


    Thank you very much, 
  • The clone from git is part of the problem. The git contains more then just the PlatformIO project. But at least you already have all files:-)
    In VSC go to file ->open directory and open the src/Repetier folder of what you downloaded. Then PlatformIO will detect the project and in the blue bottom line you get a Checkmark that you hit to compile. It will download all files still needed. The button arrow right compiles and uploads. Make sure you have selected the correct cpu typ ein platformio.ini - the file commented and lists all available options.
  • @Repetier, thank you a lot!!!

    So what would be better then towards the future? Download a Zip of the dev2 Repetier-Firmware/src/Repetier directory instead of cloning from git, and open it like you described?

    Thank you for your patience and helpful answers.
    Kind regards,
  • Your solution was good except that it selected wrong start direction. Zip also leads to same files. Maybe easier to handle if you have no git experience. But with git it is easy now to update to latest release just by pulling changes. But as said requires git knowledge. So use what you are comfortable with - result is the same.
  • I am going through the Configuration.h now, and changed heated bed to 0 and heaters to 2 since the printer has no heated bed. Do I also have to delete the red marked &HeatedBed1 ?

    Clickable :)

    Kind regards,
  • Ye they also need to be deleted. And don't forget configuration_io.h where they get defined. This firmware requires 2 configuration files and both are equally important for it to work. But that is all described in detail in our documentation here https://docfirmwarev2.repetier.com/ I hope you are using as reference. Otherwise it is hard to understand.
  • Thank you.
    Yes I am using the documentation as a reference, but even then it's hard to understand for me. Till now I've been using the Repetier online configurator for rather simple and basic setups.... I have also read some threads on the forum here about IDEX configurations, but so much different inputs and point of views makes it just harder for me... 

    Kind regards,
  • Most important is this: https://docfirmwarev2.repetier.com/config/printer_type#idex
    it describes which extra variables are needed for idex printers in V2.
  • As far as compiling the firmware it all went well, got no errors and could transfer to the ultratronics board.

    When I connect with Repetier Host, the connection is made, temperatures are read, but the status keeps hanging on "Waiting"
    Did I miss something?

    Output from Repetier Host: (clickable)

    Kind regards,
  • I have a working connection now. I compiled it in dueUSB in Platformio.ini.

    What's the difference between the due and dueUSB?

    Kind regards,
  • When you mean in platformio.ini then the difference is to which usb port you are connected. They require different upload settings to upload, but create the same binaries.

    Connection in image looks good. I think "Wachtend" was the translaters choice for idle - meaning printer is waiting for commands.
  • edited May 3
    So far I still have no success. The only thing working is the 2 temperature readings from both extruders and the heating of both extruders .... 

    To avoid misunderstandings on the hardware side, here is what is used:

    - Ultratronics Pro V1.0 rev e (defined as 409 in Configuration.h)
    - RAPS128 drivers for X, Y and A (A is connected to the E2 motor on the Ultratronics)
    - A4988 for Z (2 motors parallel) and Extruder1 & Extruder2
    - No heated bed so the connector HB and T0 are not used
    - Heater Extruder1 (X) is connected to connector E0 on Ultratronics 
    - Heater Extruder2 (A) is connected to connector E1 on Ultratronics
    - Thermistors from extruders are connected to T1 and T2 on Ultratronics
    - Makerbot electronic endstop clones
    - Z endstop connected to Z- on Ultratronics
    - Y endstop connected to Y- on Ultratronics
    - X endstop connected to X- on Ultratronics
    - A endstop connected to X+ on Ultratronics
    - SD card as Eeprom
    - E3D hotend cooling fans are directly connected to 12V on Ultratronics
    - For each hotend a part cooling fan connected to Fan1 & Fan2 connectors on Ultratronics
    - Titan extruders with 0.9° steppers

    i started off the Configuration.h and Configuration_io.h files from the Dual_X example.

    What is working:
    -Heating extruder 1 & 2
    -Temperature reading from both extruders on T1 and T2
    -Endstop readings with M119 if not activated respond as "L" in Repetier Host and if activated they respond as "H"
    -Cooling fan connected to Fan 1 connector on Ultratronics

    What is not working:
    -no movement of any motors 

    I see TMC drivers defined but I didn't find anything about RAPS128 drivers so maybe the error is there? And if so, How can I tell the firmware to use RAPS128 drivers?

    I put a piece of code concerning the motors from Configuration.h and Configuration_io.h below.
    Kind regards,

    here is a snippet from Configuration.h:

    // Array to call motor related commands like microstepping/current if supported.
    // Id's start at 0 and depend on position in this array.
    #define NUM_MOTORS 6
    #define MOTORS \
        { &XMotor, &YMotor, &ZMotor, &AMotor, &E1Motor, &E2Motor }
    #define MOTOR_NAMES \
        { PSTR("X left"), PSTR("Y"), PSTR("Z"), PSTR("X right"), PSTR("E0"), PSTR("E1") }

    // Some common settings for trinamic driver settings
     Chopper timing is an array with
     {toff, hend, hstrt}
     See TMC datasheets for more details. There are some predefined values to get you started:
     CHOPPER_TIMING_DEFAULT_12V = { 3, -1, 1 }
     CHOPPER_TIMING_DEFAULT_19V = { 4, 1, 1 }
     CHOPPER_TIMING_DEFAULT_24V = { 4, 2, 1 }
     CHOPPER_TIMING_DEFAULT_36V = { 5, 2, 4 }
     CHOPPER_TIMING_PRUSAMK3_24V = { 3, -2, 6 }

    // true = interpolate to 256 microsteps for smoother motion
    #define TMC_INTERPOLATE true
    // Current used when motor stands still
    #define TMC_HOLD_MULTIPLIER 0.5
    // Reduce current on over temperature warnings by x milli ampere, 0 = disable
    #define TMC_CURRENT_STEP_DOWN 50
    // Define which data should be stored to eeprom

    // x axis extruders are 62mm width, distance after homing 503mm

    #define X_MAX_LENGTH 300    //376
    #define Y_MAX_LENGTH 300    //385
    #define Z_MAX_LENGTH 300
    define Z_MAX_LENGTH 610

    #define A_MAX_LENGTH 300    //450
    #define X_MIN_POS 0
    #define Y_MIN_POS 0
    #define Z_MIN_POS 0
    #define A_MIN_POS X_MIN_POS
    #define BED_X_MIN 0
    #define BED_Y_MIN Y_MIN_POS
    #define BED_Y_MAX (Y_MIN_POS + Y_MAX_LENGTH)
    // Park position used when pausing from firmware side
    #define PARK_POSITION_X (0)
    #define PARK_POSITION_Y (70)


    #ifdef RAPS128_XY
    #define XAXIS_STEPS_PER_MM 146.1 * 4.0
    #define AAXIS_STEPS_PER_MM 146.1 * 4.0
    #define YAXIS_STEPS_PER_MM 146.1 * 4.0
    #define XAXIS_STEPS_PER_MM 1280 //146.1
    #define AAXIS_STEPS_PER_MM 1280 //146.1
    #define YAXIS_STEPS_PER_MM 1280 //146.1
    #define ZAXIS_STEPS_PER_MM 200  //404.18
    #define MAX_FEEDRATE_X 400
    #define MAX_FEEDRATE_Y 250
    #define MAX_FEEDRATE_Z 8
    #define MAX_FEEDRATE_A 400

    And from Configuration_io.h

    /* Define motor pins here. Each motor needs a setp, dir and enable pin. */


    #ifdef RAPS128_XY
    // X Motor left


    // X Motor right


    // Y Motor


    // X Motor left
    IO_OUTPUT_INVERTED(IOX1Enable, ORIG_X_ENABLE_PIN)   // Enable inverted RAPS128 driver

    // X Motor right

    IO_OUTPUT_INVERTED(IOAEnable, ORIG_E2_ENABLE_PIN)   // Enable inverted RAPS128 driver

    // Y Motor

    IO_OUTPUT_INVERTED(IOY1Enable, ORIG_Y_ENABLE_PIN)   // Enable inverted RAPS128 driver

    // Z Motor

    IO_OUTPUT(IOZ1Enable, ORIG_Z_ENABLE_PIN)            // Enable not inverted A4988 driver
    // IO_OUTPUT_LOG(IOZ1Enable, IOZ1EnableT, true)

    // E0 Motor

    IO_OUTPUT_INVERTED(IOE1Dir, ORIG_E0_DIR_PIN)        // Dir inverted Titan extruder
    IO_OUTPUT(IOE1Enable, ORIG_E0_ENABLE_PIN)           // Enable not inverted A4988 driver

    // E1 Motor

    IO_OUTPUT_INVERTED(IOE2Dir, ORIG_E1_DIR_PIN)        // Dir inverted Titan extruder
    IO_OUTPUT(IOE2Enable, ORIG_E1_ENABLE_PIN)           // Enable not inverted A4988 driver

  • You need just the simple stepper driver. The config has at the beginning
    // define RAPS128_XY
    Uncomment this so it uses the definition for raps driver. Or just remove the #ifdef RAPS128_XY else part in configuration_io. RAPS128 have enable signal inverted to regular stepper drivers like A4988 so they use
    while A4988 would require

  • Thank you very much, motors are running now, however not as it should be.
    Both X Left and X Right work fine, homing goes well and I can move them manually from RH.
    Z homing does strange. When I click the Z-Home, the steppers make a whining noise, they move about 1 revolution. If I hit the endstop, they move fine and do the last 2 steps of the homing process. After this I can move manually from RH without problems. If I hit homing again, same problem. Vref is set as it should. For try I moved the Vref from min to max, that doesn't change anything. I swapped the A4988 for a DRV8829, same result.

    Eeprom settings for Z movement:

    The Y axis is moving 165mm after homing towards  Ymax . I could not find any settings or parameters that can cause this behaviour:

  • Whining sound are lost steps normally. Since other moves work you should try reducing z home and z move feedrate until it works. With 2 Motors on 1 driver you only have half of current/force. You can split it on 2 drivers using the mirror driver connected to 2 simple drivers. Also are steps per mm correct? Moves look quite fast for z. Can also be acceleration but 8 is not much for z axis so normally should work and you start without jerk so no problem here expected.

    Regarding Y it could be a homing position you defined or move back after homing. Depend on what M114 says after homing.
  • edited May 29
    I still have a lot of issues with this configuration. I found out that the Y-movement is the Y-offset between the nozzles. It seemed a large distance but that was due to a calculation error in the steps/mm.
    After homing the axes position like on the sketch above.
    M114 after homing:
    Moving tool E0(EX1) moves it to the correct position on the bed.

    If I select in RepetierHost Tool E1(EX2) it moves towards the position of X1 but then give the next warning:

    I don't know anymore what to do.
    these are my settings in Repetier Host:
    My Configuration.h and Configuration_IO.h files:

  • The problem is in these lines:
    // Extra parameter in case you have a dual x axis
    #define DUAL_X_LEFT_OFFSET -17  //-64
    #define DUAL_X_RIGHT_OFFSET 317 //448.25
    // Minimum distance between both heads
    #define DUAL_X_MIN_DISTANCE 1   //X and A axes run on different rails, they could physically cross each other without collision
    #define LAZY_DUAL_X_AXIS 0

    DUAL_X_MIN_DISTANCE is the minimum distance between the nozzles. 1 Means when left one is at -17 you can move the right one so both nozzles are just 1mm away. I doubt that this is physically possible and that is the reason you get your crash. That value should be a bit higher then the width of a carrier.

    Also the bed start is DUAL_X_LEFT_OFFSET + DUAL_X_MIN_DISTANCE so it is a good thing to define this as -DUAL_X_MIN_DISTANCE. Bed is where you can move without colliding with the parked extruder so you will loose some mm from what you currently think you have. 
  • edited May 30
    Repetier said:

    DUAL_X_MIN_DISTANCE is the minimum distance between the nozzles. 1 Means when left one is at -17 you can move the right one so both nozzles are just 1mm away. I doubt that this is physically possible and that is the reason you get your crash. That value should be a bit higher then the width of a carrier.

    Also the bed start is DUAL_X_LEFT_OFFSET + DUAL_X_MIN_DISTANCE so it is a good thing to define this as -DUAL_X_MIN_DISTANCE. Bed is where you can move without colliding with the parked extruder so you will loose some mm from what you currently think you have. 
    The carriages can be physicly on the same position, as they run on seperate rails back to back. They don't collide but the RH gives this warning that the positions can't be trusted anymore. It also doesn't allow me to move the axes anymore until I home them again.

    I've changed my configuration.h as followed concerning your suggestions:


    The result is the same, but now the position of A with M114 is 33 instead of -16 previous.
    however, X is here also on 33, but it physicly didn't move away from it's -17 position from homing....
    Why would it want to send X also to the same position as A?

    And now sometimes, not always,  the printer tries to move both X and A axes while homing Y or Z, even when both endstops are hit...... This is driving me crazy... :(

  • The message about illegal position comes from firmware not host.

    Only the 3 values I gave you are used for dualX as you see in this method computing bed position etc:
    void PrinterType::updateDerived() {
    Motion1::homingFeedrate[A_AXIS] = Motion1::homingFeedrate[X_AXIS];
    Motion1::maxAcceleration[A_AXIS] = Motion1::maxAcceleration[X_AXIS];
    Motion1::maxFeedrate[A_AXIS] = Motion1::maxFeedrate[X_AXIS];
    Motion1::moveFeedrate[A_AXIS] = Motion1::moveFeedrate[X_AXIS];
    Motion1::maxYank[A_AXIS] = Motion1::maxYank[X_AXIS];
    Motion1::minPos[X_AXIS] = endPos[0];
    Motion1::maxPos[X_AXIS] = endPos[1] - DUAL_X_MIN_DISTANCE;
    Motion1::minPos[A_AXIS] = endPos[0] + DUAL_X_MIN_DISTANCE;
    Motion1::maxPos[A_AXIS] = endPos[1];
    bedRectangle[X_AXIS][0] = RMath::max(bedRectangle[X_AXIS][0], Motion1::minPos[A_AXIS]);
    bedRectangle[X_AXIS][1] = RMath::min(bedRectangle[X_AXIS][1], Motion1::maxPos[X_AXIS]);
    bedCenter = 0.5f * (bedRectangle[X_AXIS][0] + bedRectangle[X_AXIS][1]);

    In your special case I think DUAL_X_MIN_DISTANCE 0 would be correct then. Untypical but that gives both the same motion range, no limits.

    I currently don't see why it does not move to bed start at homing. Need to check that case later when I have more time. In your special case min distance 0 should solve everything anyway. Don't forget that values are likely different in eeprom.

  • edited June 4
    I made some good progress today.... Apparantly I f*cked up with the offsets and the other limit values. I had max X and A on 317mm because I reasoned max bed size + offset... but actually it needs to be 334mm, max bed + both X and A offsets. No more warnings after selecting tool 2 now.
    The DUAL_X_MIN_DISTANCE at 0 is also not a problem anymore. They position now nicely on the same position back to back.
    Also I had similar issues on the Y caused by the very big Y offset due to the back to back mounting of the carriages, but also these seem to be fixed now.

    The only thing that still confuses me now, is the difference between the nozzles in the Z direction.
    I suppose that offset needs to be set in Configuration_IO.h at the lines

    TOOL_EXTRUDER(ToolExtruder1, 0, 0, 0, HeaterExtruder1, E1Motor, 1.75, 837, 5, 60, 5000, 177, "M117 Extruder 1", "", &Fan1PWM)
    TOOL_EXTRUDER(ToolExtruder2, 0, 83, 0, HeaterExtruder2, E2Motor, 1.75, 837, 5, 60, 5000, 177, "M117 Extruder 2", "", &Fan2PWM) 

    The Bold marked "0" represent the offZ according to the manual....
    But how do I refer to it?
    X2 is lower then X1. Which is taken as a reference? the lowest and then add a offZ of +Value to EX1?

  • ToolExtruder1 is the reference, so z offset is 0. So ToolExtruder2 is relative to this height. Positive value means it is higher so when selecting it, it needs to go down.

    Ideally offset is 0 or you will loose the ditto print function which only works when both are at same height. 
  • OK, I will ask my friend who owns the printer to redesign the carriages so that we can adjust the Z position of them to eliminate the Z offset between the nozzles.

    Thank you for the help and support, and the patience! I've learned a lot from this project. I hope we can start printing with it soon!!
  • You can print also with different z offset. Just not with both heads the same time (ditto printing). That doubles speed if you have 2 identical objects to print or 2 mirrored objectes.
Sign In or Register to comment.