Motorized Bed Level Correction with 4 Independent Z Screws?

I've been reading through the z-probing guide to get auto bed leveling to work. So far I've made good progress, and have successfully ran a G32 using the nxn grid method, and the software correction of rotation. However I would like to use the mechanical motorized bed leveling, because as far as I understand, the software correction will correct mid print but won't actually adjust the level of the bed outside of that mid print context. However, the guide on motorized correction says it needs a bed fixed on 3 points which 2 have a motor to change the height. The bed I'm using has 4 independent z screws, each with a motor, so I don't understand if there's a way to adapt the instructions I read to my setup or not.

Comments

  • G32 is corrected during the complete print. Only bump correction measured with G33 is corrected at the bottom normally also you could set it to correct until top as well.

    4 bed motorized leveling is not supported. I never had a printer with that design and it has the problem that you can not move just one motor without the other blocking or bending the bed. The system is statically undefined so it puts extra forces on bed to bend it if you move them out of plane. Guess no problem if they are spring loaded or the bed is flexible enough to do small corrections on one edge. But problem is still that it is not implemented.
  • Is it possible to set up the mortorized leveling with your firmware as is somehow? Or do I need to wait for you to support 4 screw motorized leveling? While I'm at it, how does the software correction work exactly anyways? I read you create an approximate plane after measuring the points on the bed but what is considered a significant enough difference to warrant a correction versus what is considered level?
  • Exactly. From the measured points we compute a regression plane. For motorized 3 point leveling we then assume one motor height as reference and move the other 2 to match the theoretical horizontal level. Then you can retest and update the update, so error reduces.

    Due to bending problem this does not really work for 4 point correction. I think here it would be best to test at 4 points as close to spindle as possible, make one reference and adjust the other 3 instead. With some programming knowledge you should be able to write this:-)
  • Alright so I've started digging into the leveling code. Correct me if I'm wrong but I believe this is the section in need of editing to make it work

    void correctAutolevel(Plane &plane) {
    #if BED_CORRECTION_METHOD == 0 // rotation matrix
        //Printer::buildTransformationMatrix(plane.z(EEPROM::zProbeX1(),EEPROM::zProbeY1()),plane.z(EEPROM::zProbeX2(),EEPROM::zProbeY2()),plane.z(EEPROM::zProbeX3(),EEPROM::zProbeY3()));
    Printer::buildTransformationMatrix(plane);
    #elif BED_CORRECTION_METHOD == 1 // motorized correction
    #if !defined(NUM_MOTOR_DRIVERS) || NUM_MOTOR_DRIVERS < 2
    #error You need to define 2 motors for motorized bed correction
        Commands::waitUntilEndOfAllMoves(); // move steppers might be leveling steppers as well !
        float h1 = plane.z(BED_MOTOR_1_X,BED_MOTOR_1_Y);
        float h2 = plane.z(BED_MOTOR_2_X,BED_MOTOR_2_Y);
        float h3 = plane.z(BED_MOTOR_3_X,BED_MOTOR_3_Y);
        // h1 is reference heights, h2 => motor 0, h3 => motor 1
        h2 -= h1;
        h3 -= h1;
    #if defined(LIMIT_MOTORIZED_CORRECTION)
    if(h2 < -LIMIT_MOTORIZED_CORRECTION) h2 = -LIMIT_MOTORIZED_CORRECTION;
    if(h2 > LIMIT_MOTORIZED_CORRECTION) h2 = LIMIT_MOTORIZED_CORRECTION;
    if(h3 < -LIMIT_MOTORIZED_CORRECTION) h3 = -LIMIT_MOTORIZED_CORRECTION;
    if(h3 > LIMIT_MOTORIZED_CORRECTION) h3 = LIMIT_MOTORIZED_CORRECTION;
        MotorDriverInterface *motor2 = getMotorDriver(0);
        MotorDriverInterface *motor3 = getMotorDriver(1);
        motor2->setCurrentAs(0);
        motor3->setCurrentAs(0);
        motor2->gotoPosition(h2);
        motor3->gotoPosition(h3);
        motor2->disable();
        motor3->disable(); // now bed is even
        Printer::currentPositionSteps[Z_AXIS] = h1 * Printer::axisStepsPerMM[Z_AXIS];
    #if NONLINEAR_SYSTEM
    transformCartesianStepsToDeltaSteps(Printer::currentPositionSteps, Printer::currentNonlinearPositionSteps);
    #error Unknown bed correction method set
    }

    So I can add this line pretty easily to create the variable for the new motor

    float h4 = plane.z(BED_MOTOR_4_X,BED_MOTOR_4_Y);

    But I'm somewhat unsure where to go from there. Any tips?
  • You need to add a third motor driver in addition and also do the same with it as for the other 2.

    The problem is this assumes a flat bed and will probably not iterate correctly with 4 points since it is statically undefined. You only need 3 point to hold a plate in position. The 4th as I said might bend the plate and that causes errors in plane measurement and assigning correction values. You need a completely different approach where you measure close to the 4 plane fixtures and then correct 3 of them by using the fixed one as reference. This would result sooner or later into a perfect leveling. For faster iteration you need to add some math for better prediction, but this should already suffice.
  • I don't think I understand. To help me understand I'm including a picture of the 4 screw system we have going https://imgur.com/URd9XEA. I believe we have measures in place already to counteract the bending you're worried about. the plate we sit our bed on is quite thick so it resists most bending. the screws themselves are set up to allow some tilting to avoid bending as well. I believe as a result our bed stays pretty flat and that our main issue is making our flat bed, level. Please tell me if there's something I'm missing in that regard. As for adding the third motor driver this is the code I've made based on what's already there. I don't fully understand how this code works yet so right now I've pretty much just copy pasted the parts with the other motors and added a new motor in each section. Please let me know if I've made a mistake here.

    void correctAutolevel(Plane &plane) {
    #if BED_CORRECTION_METHOD == 0 // rotation matrix
        //Printer::buildTransformationMatrix(plane.z(EEPROM::zProbeX1(),EEPROM::zProbeY1()),plane.z(EEPROM::zProbeX2(),EEPROM::zProbeY2()),plane.z(EEPROM::zProbeX3(),EEPROM::zProbeY3()));
    Printer::buildTransformationMatrix(plane);
    #elif BED_CORRECTION_METHOD == 1 // motorized correction
    #if !defined(NUM_MOTOR_DRIVERS) || NUM_MOTOR_DRIVERS < 3
    #error You need to define 3 motors for 4 screw motorized bed correction
        Commands::waitUntilEndOfAllMoves(); // move steppers might be leveling steppers as well !
        float h1 = plane.z(BED_MOTOR_1_X,BED_MOTOR_1_Y);
        float h2 = plane.z(BED_MOTOR_2_X,BED_MOTOR_2_Y);
        float h3 = plane.z(BED_MOTOR_3_X,BED_MOTOR_3_Y);
        float h4 = plane.z(BED_MOTOR_4_X,BED_MOTOR_4_Y);
        // h1 is reference heights, h2 => motor 0, h3 => motor 1, h4 => motor 2
        h2 -= h1;
        h3 -= h1;
        h4 -= h1;
    #if defined(LIMIT_MOTORIZED_CORRECTION)
    if(h2 < -LIMIT_MOTORIZED_CORRECTION) h2 = -LIMIT_MOTORIZED_CORRECTION;
    if(h2 > LIMIT_MOTORIZED_CORRECTION) h2 = LIMIT_MOTORIZED_CORRECTION;
    if(h3 < -LIMIT_MOTORIZED_CORRECTION) h3 = -LIMIT_MOTORIZED_CORRECTION;
    if(h3 > LIMIT_MOTORIZED_CORRECTION) h3 = LIMIT_MOTORIZED_CORRECTION;
    if(h4 < -LIMIT_MOTORIZED_CORRECTION) h4 = -LIMIT_MOTORIZED_CORRECTION;
    if(h4 > LIMIT_MOTORIZED_CORRECTION) h4 = LIMIT_MOTORIZED_CORRECTION;
        MotorDriverInterface *motor2 = getMotorDriver(0);
        MotorDriverInterface *motor3 = getMotorDriver(1);
        MotorDriverInterface *motor4 = getMotorDriver(2);
        motor2->setCurrentAs(0);
        motor3->setCurrentAs(0);
        motor4->setCurrentAs(0);
        motor2->gotoPosition(h2);
        motor3->gotoPosition(h3);
        motor4->gotoPosition(h4);
        motor2->disable();
        motor3->disable();
        motor4->disable(); // now bed is even
        Printer::currentPositionSteps[Z_AXIS] = h1 * Printer::axisStepsPerMM[Z_AXIS];
    #if NONLINEAR_SYSTEM
    transformCartesianStepsToDeltaSteps(Printer::currentPositionSteps, Printer::currentNonlinearPositionSteps);
    #error Unknown bed correction method set
    }
  • Under your assumptions the solution looks correct. Just consider that BED_MOTOR_... is the position of the spindles here not where the bed is held to the underlaying frame.
  • alright. how is this code referenced? Do I need to change anything there or should I be able to replace this section of code in my firmware and reupload then run it? After enabling motorized correction of course.
  • Since you replaced the 3 fixtures solution you have to select that in configuration along with your modified version and then upload and test if it works as expected.
  • I've begun setting up the system in the firmware configurator and I wanted to check back here to make sure what I'm assuming is correct so I don't mess anything up. We're using z motor mirroring as shown in this picture
    https://imgur.com/a/sM014fY. Then on the features tab I read that I can define the motor drivers below https://imgur.com/e8WtPBL. Then am I right in assuming that for the system I've described above I should add 4 motors here https://imgur.com/OlB1h8D then define them as the pins, steps per mm, etc, for the z stepper and extruders 2, 3, and 4 as shown in the first picture?
  • Not exactly. You need 3 extra motor drivers. You assume first motor to be the master height and only correct the other 3 so only 3 positions need to be changed. You also see this in your code where you use only 3 motors for correction. Also make sure to define
    BED_MOTOR_4_X and BED_MOTOR_4_Y which are not available in config tool. So add them in manual additions.
Sign In or Register to comment.