Close



Page 1 of 16 12311 ... LastLast
Results 1 to 10 of 172

Hybrid View

  1. #1
    Super Moderator Roxy's Avatar
    Join Date
    Apr 2014
    Location
    Lone Star State
    Posts
    2,182

    Saving G29 Bed Level Correction Matrix to EEPROM

    Several people have expressed an interest in not having to perform a G29 Auto Bed Leveling command prior to each print. This post has the instructions to do that. However, it has not been tested yet. My printer's power supply died and it will be a while until I can replace it. The changes and theory are fairly simple, but with that said, when this many trivial changes get made, usually something doesn't work right. If you proceed with that warning and run into a problem, just make a post detailing what is wrong and I'm pretty sure we can get the problem fixed.

    The theory is simple. The EEPROM (if enabled in Marlin's Configuration.h file) can save many settings that override the default settings. The changes we will make will stop the G28 homing command from resetting the Bed Level Correction Matrix. Instead, we will only do that when a G29 command is issued. Once this is accomplished, we just need to add a small amount of support to the EEPROM routines to make them smart enough to save and restore this matrix besides all of the other values they already save and restore. And of course, we add some code so the matrix can be printed out also.

    To use the code, the user would first issue a M502 (Restore Default Settings) command followed by a M500 (Save Current Settings to EEPROM). This is necessary to do once because the format of the data stored in the EEPROM is going to change. By doing a M502 followed by a M500 command we are forcing the EEPROM to conform to the new data format which includes space for the Bed Level Correction matrix. Failure to do this is going to result in your printer restoring all kinds of bad values from EEPROM into important variables that it uses to behave in a sane and rational way.

    Once the EEPROM is made aware of the new configuration, you need to issue a G28 followed by a suitable G29 command and if the values work as expected, an M500 command. From then on, you will only use the G29 command if you don't see the first layer going down perfect. The M500 will store the Bed Level Correction Matrix so the next time the Marlin firmware initializes itself, it will grab the last saved matrix.

    To make the firmware changes do the following:

    In Configuration.h find:

    Code:
    #define ENABLE_AUTO_BED_LEVELING // Delete the comment to enable (remove // at the start of the line)
    #define Z_PROBE_REPEATABILITY_TEST  // If not commented out, Z-Probe Repeatability test will be included if Auto Bed Leveling is Enabled.
    In order to do this in a fully legitimate manner, we need to be able to control whether the feature is turned on or not. This will be required to get these enhancements folded back into the main code base. Change this code to:

    Code:
    #define ENABLE_AUTO_BED_LEVELING // Delete the comment to enable (remove // at the start of the line)
    #define Z_PROBE_REPEATABILITY_TEST  // If not commented out, Z-Probe Repeatability test will be included if Auto Bed Leveling is Enabled.
    #define SAVE_G29_CORRECTION_MATRIX  // if not commented out and the EEPROM is used to save settings, the G29 information will also be saved.
    In Marlin_main.cpp find:
    Code:
    case 28: //G28 Home all Axis one at a time
    #ifdef ENABLE_AUTO_BED_LEVELING
        plan_bed_level_matrix.set_to_identity();  //Reset the plane ("erase" all leveling data)
    #endif //ENABLE_AUTO_BED_LEVELING
    We don't want the G28 to reset our Bed Level Correction Matrix anymore. We want it left alone when the printer is Homed.
    Delete the last 3 of those lines so you only have:
    Code:
    case 28: //G28 Home all Axis one at a time
    We do want the G29 to start with a reset Bed Level Correction Matrix. This used to happen because a G28 is always issued prior to doing a G29. But with the G28 not clearing the matrix, we need to do it in the G29 now. Find the following lines:

    Code:
    #ifdef ENABLE_AUTO_BED_LEVELING
        case 29: // G29 Detailed Z-Probe, probes the bed at 3 or more points.
            {
                #if Z_MIN_PIN == -1
                #error "You must have a Z_MIN endstop in order to enable Auto Bed Leveling feature!!! Z_MIN_PIN must point to a valid hardware pin."
                #endif
    Add the line deleted after them. Change them to be:
    Code:
    #ifdef ENABLE_AUTO_BED_LEVELING
        case 29: // G29 Detailed Z-Probe, probes the bed at 3 or more points.
            {
                #if Z_MIN_PIN == -1
                #error "You must have a Z_MIN endstop in order to enable Auto Bed Leveling feature!!! Z_MIN_PIN must point to a valid hardware pin."
                #endif
                plan_bed_level_matrix.set_to_identity();  //Reset the plane ("erase" all leveling data)
    We need to make the bulk of the changes in ConfigurationStore.cpp. This is the file that handles the functionality of saving and restoring values from the EEPROM. Find:
    Code:
    void Config_StoreSettings() 
    {
      char ver[4]= "000";
      int i=EEPROM_OFFSET;
      EEPROM_WRITE_VAR(i,ver); // invalidate data first 
      EEPROM_WRITE_VAR(i,axis_steps_per_unit);
      EEPROM_WRITE_VAR(i,max_feedrate);  
      EEPROM_WRITE_VAR(i,max_acceleration_units_per_sq_second);
      EEPROM_WRITE_VAR(i,acceleration);
    Now when a M500 command is given, we want it to store the Bed Level Correction Matrix. Change this code block to:
    Code:
    void Config_StoreSettings() 
    {
      char ver[4]= "000";
      int i=EEPROM_OFFSET;   
      EEPROM_WRITE_VAR(i,ver); // invalidate data first 
      EEPROM_WRITE_VAR(i,axis_steps_per_unit);
      EEPROM_WRITE_VAR(i,max_feedrate);  
      EEPROM_WRITE_VAR(i,max_acceleration_units_per_sq_second);
      EEPROM_WRITE_VAR(i,acceleration);
    #ifdef SAVE_G29_CORRECTION_MATRIX
      EEPROM_WRITE_VAR(i,plan_bed_level_matrix);
    #endif
    And of course, we need to be able to get those values back out of the EEPROM when the printer resets and the firmware re-initializes itself. Find:
    Code:
    void Config_RetrieveSettings()
    {
        int i=EEPROM_OFFSET;
        char stored_ver[4];
        char ver[4]=EEPROM_VERSION;
        EEPROM_READ_VAR(i,stored_ver); //read stored version
        //  SERIAL_ECHOLN("Version: [" << ver << "] Stored version: [" << stored_ver << "]");
        if (strncmp(ver,stored_ver,3) == 0)
        {
            // version number match
            EEPROM_READ_VAR(i,axis_steps_per_unit);
            EEPROM_READ_VAR(i,max_feedrate);  
            EEPROM_READ_VAR(i,max_acceleration_units_per_sq_second);
            
            // steps per sq second need to be updated to agree with the  units per sq second (as they are what is used in the planner)
            reset_acceleration_rates();
            
            EEPROM_READ_VAR(i,acceleration);
    Change it to:
    Code:
    void Config_RetrieveSettings()
    {
        int i=EEPROM_OFFSET;
        char stored_ver[4];
        char ver[4]=EEPROM_VERSION;
        EEPROM_READ_VAR(i,stored_ver); //read stored version
        //  SERIAL_ECHOLN("Version: [" << ver << "] Stored version: [" << stored_ver << "]");
        if (strncmp(ver,stored_ver,3) == 0)
        {
            // version number match
            EEPROM_READ_VAR(i,axis_steps_per_unit);
            EEPROM_READ_VAR(i,max_feedrate);  
            EEPROM_READ_VAR(i,max_acceleration_units_per_sq_second);
            
            // steps per sq second need to be updated to agree with the  units per sq second (as they are what is used in the planner)
            reset_acceleration_rates();
            
            EEPROM_READ_VAR(i,acceleration);
    #ifdef SAVE_G29_CORRECTION_MATRIX
            EEPROM_READ_VAR(i,plan_bed_level_matrix);
    #endif
    Just to be clean, we want to fully support the M502 command to reset everything to a default state. Setting the Bed Level Correction matrix to unity makes sense. Find:
    Code:
    void Config_ResetDefault()
    {
        float tmp1[]=DEFAULT_AXIS_STEPS_PER_UNIT;
        float tmp2[]=DEFAULT_MAX_FEEDRATE;
        long tmp3[]=DEFAULT_MAX_ACCELERATION;
    Change it to:
    Code:
    void Config_ResetDefault()
    {
        float tmp1[]=DEFAULT_AXIS_STEPS_PER_UNIT;
        float tmp2[]=DEFAULT_MAX_FEEDRATE;
        long tmp3[]=DEFAULT_MAX_ACCELERATION;
    #ifdef SAVE_G29_CORRECTION_MATRIX
        plan_bed_level_matrix.set_to_identity();
    #endif
    And of course, we want to be able to print out all the settings in the EEPROM. So we need to teach it how to display the Bed Level Correction Matrix that it has stored for us. This command is invoked with the M503 command. Probably the spacing and new lines are not going to be right on this initial code. If it looks horrible, please make a post showing what it looks like and we can make a quick change to fix it. Find:
    Code:
    void Config_PrintSettings()
    {  // Always have this function, even with EEPROM_SETTINGS disabled, the current values will be shown
        SERIAL_ECHO_START;
        SERIAL_ECHOLNPGM("Steps per unit:");
        SERIAL_ECHO_START;
        SERIAL_ECHOPAIR("  M92 X",axis_steps_per_unit[0]);
        SERIAL_ECHOPAIR(" Y",axis_steps_per_unit[1]);
        SERIAL_ECHOPAIR(" Z",axis_steps_per_unit[2]);
        SERIAL_ECHOPAIR(" E",axis_steps_per_unit[3]);
        SERIAL_ECHOLN("");
    Chang it to:
    Code:
    void Config_PrintSettings()
    {  // Always have this function, even with EEPROM_SETTINGS disabled, the current values will be shown
        SERIAL_ECHO_START;
        SERIAL_ECHOLNPGM("Steps per unit:");
        SERIAL_ECHO_START;
        SERIAL_ECHOPAIR("  M92 X",axis_steps_per_unit[0]);
        SERIAL_ECHOPAIR(" Y",axis_steps_per_unit[1]);
        SERIAL_ECHOPAIR(" Z",axis_steps_per_unit[2]);
        SERIAL_ECHOPAIR(" E",axis_steps_per_unit[3]);
        SERIAL_ECHOLN("");
    #ifdef SAVE_G29_CORRECTION_MATRIX
        SERIAL_ECHO_START;
        plan_bed_level_matrix.debug("\n\nBed Level Correction Matrix:");
        SERIAL_ECHOLN("");
    #endif
    Good luck!
    Last edited by Roxy; 11-01-2014 at 08:39 AM. Reason: Allow Configuration.h to select whether correction matrix is saved.

  2. #2
    Super Moderator Geoff's Avatar
    Join Date
    Nov 2013
    Location
    NSW, Australia
    Posts
    1,824
    Add Geoff on Thingiverse
    I have printed omitting the G29 on the kossel, and to be honest for the few seconds it takes to perform the point check, I think I'll stick with it. I remove the glass plate alot so saving the g29 codes or re-using them might be bad for me on the kossel.
    Hex3D - 3D Printing and Design http://www.hex3d.com

  3. #3
    Super Moderator Roxy's Avatar
    Join Date
    Apr 2014
    Location
    Lone Star State
    Posts
    2,182
    Quote Originally Posted by Geoff View Post
    I have printed omitting the G29 on the kossel, and to be honest for the few seconds it takes to perform the point check, I think I'll stick with it. I remove the glass plate alot so saving the g29 codes or re-using them might be bad for me on the kossel.
    I agree... I'm not actually going to have this active in my firmware. But some people really want it! So here it is!

  4. #4
    Quote Originally Posted by Geoff View Post
    I have printed omitting the G29 on the kossel, and to be honest for the few seconds it takes to perform the point check, I think I'll stick with it. I remove the glass plate alot so saving the g29 codes or re-using them might be bad for me on the kossel.
    See, I just ran into an instance (prior I thought the same way you do) where I need to do this because if I want to multicolor print using a single extruder with the old code you just can't

    Quote Originally Posted by Roxy View Post
    I agree... I'm not actually going to have this active in my firmware. But some people really want it! So here it is!
    Thank you so much and I will try this in a few days as Halloween is here and I am busy busy with fixing an ancient mechanical skeleton butler/decorations and doing family things.

  5. #5
    Engineer
    Join Date
    Jul 2014
    Location
    Eastern Colorado
    Posts
    536
    Now that we have this mod to save the G29 matrix for an entire print session (or longer), it is no longer necessary to add a G29 to the start gcode when slicing. However, those of us who run our printers standalone, we need another way of running the G29 when we change a setting or a glass plate. I believe that many who run their printer standalone have an LCD display on their printer. Here's what I did to add G29 to the LCD menu:

    In ultralcd.cpp, find MENU_ITEM(gcode, MSG_AUTO_HOME, PSTR("G28"));
    Just after it, add MENU_ITEM(gcode, MSG_BED_LEVEL, PSTR("G29 n5"));

    In language.h, find #define MSG_ENDSTOP_ABORT "Endstop abort"
    Just after it, add #define MSG_BED_LEVEL "G29 Bed Level"


    Roxy, I ran into an error adding your code:

    ConfigurationStore.cpp: In function ‘void Config_PrintSettings()’:
    ConfigurationStore.cpp:129:65: error: void value not ignored as it ought to be
    plan_bed_level_matrix.debug("\n\nBed Level Correction Matrix:")
    ^ (this caret should be under the closing parenthesis after "Matrix")

    That is the only error. Commenting out only the added code block from Config_PrintSettings let it compile cleanly.
    Last edited by AbuMaia; 10-31-2014 at 10:51 PM.

  6. #6
    Super Moderator Roxy's Avatar
    Join Date
    Apr 2014
    Location
    Lone Star State
    Posts
    2,182
    Quote Originally Posted by AbuMaia View Post
    Roxy, I ran into an error adding your code:

    ConfigurationStore.cpp: In function ‘void Config_PrintSettings()’:
    ConfigurationStore.cpp:129:65: error: void value not ignored as it ought to be
    plan_bed_level_matrix.debug("\n\nBed Level Correction Matrix:")
    ^ (this caret should be under the closing parenthesis after "Matrix")

    That is the only error. Commenting out only the added code block from Config_PrintSettings let it compile cleanly.
    It's fixed now. Somehow during the Cut & Paste I didn't get the very last character of the line (which was a semi-colon. The compiler knows it is missing a semi-colon, can't it just put it in there for me???

    Any way, if you go add the semi-colon it should compile clean and let you print out the Bed Level Correction Matrix. I'm not sure how the output is going to look because I can't run any of this code yet to test it.

    AbuMaia, does the code behave as expected and do what people wanted? Can you add the semi-colon and invoke the EEPROM Print so we can check if the matrix prints OK ?
    Last edited by Roxy; 11-01-2014 at 02:08 PM.

  7. #7
    Engineer
    Join Date
    Jul 2014
    Location
    Eastern Colorado
    Posts
    536
    Quote Originally Posted by Roxy View Post
    does the code behave as expected and do what people wanted? Can you add the semi-colon and invoke the EEPROM Print so we can check if the matrix prints OK ?
    Connecting...
    start
    Printer is now online.
    echo: External Reset
    Marlin1.0.0
    echo: Last Updated: Nov 1 2014 10-20-14 13:55:13 | Author: (AbuMaia, MakerFarm Prusa i3v 8)
    Compiled: Nov 1 2014
    echo: Free Memory: 3486 PlannerBufferBytes: 1232
    echo:Stored settings retrieved
    echo:Steps per unit:
    echo: M92 X80.00 Y80.00 Z4000.00 E900.00
    echo:
    Bed Level Correction Matrix:
    1.000000 0.000000 0.000000
    0.000000 1.000000 0.000000
    0.000000 0.000000 1.000000
    echo:Maximum feedrates (mm/s):
    echo: M203 X250.00 Y250.00 Z2.00 E22.00
    echo:Maximum Acceleration (mm/s2):
    echo: M201 X1000 Y1000 Z5 E1000
    echo:Acceleration: S=acceleration, T=retract acceleration
    echo: M204 S500.00 T500.00
    echo:Advanced variables: S=Min feedrate (mm/s), T=Min travel feedrate (mm/s), B=minimum segment time (ms), X=maximum XY jerk (mm/s), Z=maximum Z jerk (mm/s), E=maximum E jerk (mm/s)
    echo: M205 S0.00 T0.00 B20000 X20.00 Z0.40 E5.00
    echo:Home offset (mm):
    echo: M206 X0.00 Y0.00 Z0.00
    echo:PID settings:
    echo: M301 P24.49 I2.34 D64.21
    echo:SD card ok
    SENDING:G28
    SENDING:G29 n 4
    Eqn coefficients: a: 0.00 b: 0.00 d: 1.88
    planeNormal x: -0.00 y: -0.00 z: 1.00

    Bed Level Correction Matrix:
    0.999993 0.000000 0.003794
    -0.000001 1.000000 0.000163
    -0.003794 -0.000163 0.999993
    echo:endstops hit: Z:2.00
    >>>M500
    SENDING:M500
    echo:Settings Stored
    >>>M503
    SENDING:M503
    echo:Steps per unit:
    echo: M92 X80.00 Y80.00 Z4000.00 E900.00
    echo:
    Bed Level Correction Matrix:
    0.999993 0.000000 0.003794
    -0.000001 1.000000 0.000163
    -0.003794 -0.000163 0.999993
    echo:Maximum feedrates (mm/s):
    echo: M203 X250.00 Y250.00 Z2.00 E22.00
    echo:Maximum Acceleration (mm/s2):
    echo: M201 X1000 Y1000 Z5 E1000
    echo:Acceleration: S=acceleration, T=retract acceleration
    echo: M204 S500.00 T500.00
    echo:Advanced variables: S=Min feedrate (mm/s), T=Min travel feedrate (mm/s), B=minimum segment time (ms), X=maximum XY jerk (mm/s), Z=maximum Z jerk (mm/s), E=maximum E jerk (mm/s)
    echo: M205 S0.00 T0.00 B20000 X20.00 Z0.40 E5.00
    echo:Home offset (mm):
    echo: M206 X0.00 Y0.00 Z0.00
    echo:PID settings:
    echo: M301 P24.49 I2.34 D64.21
    Disconnected. (I powered off the printer here, then turned it back on and re-connected)
    Connecting...
    start
    Printer is now online.
    echo: External Reset
    Marlin1.0.0
    echo: Last Updated: Nov 1 2014 10-20-14 13:55:13 | Author: (AbuMaia, MakerFarm Prusa i3v 8)
    Compiled: Nov 1 2014
    echo: Free Memory: 3486 PlannerBufferBytes: 1232
    echo:Stored settings retrieved
    echo:Steps per unit:
    echo: M92 X80.00 Y80.00 Z4000.00 E900.00
    echo:
    Bed Level Correction Matrix:
    0.999993 0.000000 0.003794
    -0.000001 1.000000 0.000163
    -0.003794 -0.000163 0.999993
    echo:Maximum feedrates (mm/s):
    echo: M203 X250.00 Y250.00 Z2.00 E22.00
    echo:Maximum Acceleration (mm/s2):
    echo: M201 X1000 Y1000 Z5 E1000
    echo:Acceleration: S=acceleration, T=retract acceleration
    echo: M204 S500.00 T500.00
    echo:Advanced variables: S=Min feedrate (mm/s), T=Min travel feedrate (mm/s), B=minimum segment time (ms), X=maximum XY jerk (mm/s), Z=maximum Z jerk (mm/s), E=maximum E jerk (mm/s)
    echo: M205 S0.00 T0.00 B20000 X20.00 Z0.40 E5.00
    echo:Home offset (mm):
    echo: M206 X0.00 Y0.00 Z0.00
    echo:PID settings:
    echo: M301 P24.49 I2.34 D64.21
    echo:SD card ok

  8. #8
    Super Moderator Roxy's Avatar
    Join Date
    Apr 2014
    Location
    Lone Star State
    Posts
    2,182
    Quote Originally Posted by AbuMaia View Post
    Connecting...
    start
    Printer is now online.
    ..
    echo:Stored settings retrieved
    echo:Steps per unit:
    echo: M92 X80.00 Y80.00 Z4000.00 E900.00
    echo:
    Bed Level Correction Matrix:
    1.000000 0.000000 0.000000
    0.000000 1.000000 0.000000
    0.000000 0.000000 1.000000
    echo:Maximum feedrates (mm/s):
    echo: M203 X250.00 Y250.00 Z2.00 E22.00
    So I suspect we need a blank line (or one that just says echo after the last line of the matrix. But I kind of hate to add blank lines of output. Opinions anybody???

  9. #9
    Technologist
    Join Date
    Oct 2014
    Posts
    114
    [QUOTE=AbuMaia;33795]Now that we have this mod to save the G29 matrix for an entire print session (or longer), it is no longer necessary to add a G29 to the start gcode when slicing. However, those of us who run our printers standalone, we need another way of running the G29 when we change a setting or a glass plate. I believe that many who run their printer standalone have an LCD display on their printer. Here's what I did to add G29 to the LCD menu:

    In ultralcd.cpp, find MENU_ITEM(gcode, MSG_AUTO_HOME, PSTR("G28"));
    Just after it, add MENU_ITEM(gcode, MSG_BED_LEVEL, PSTR("G29 n5"));

    In language.h, find #define MSG_ENDSTOP_ABORT "Endstop abort"
    Just after it, add #define MSG_BED_LEVEL "G29 Bed Level"

    I added this and it was working fine. Had a show yesterday and it didn't work anymore.
    Got this message. When I do a g29 n5 in Repetier it works fine. Any ideas?
    13:38:15.257 : echo:enqueing "G29 n5"
    13:38:15.267 : ?Number of probed points not plausable.

  10. #10
    Engineer-in-Training beerdart's Avatar
    Join Date
    Feb 2014
    Location
    CT
    Posts
    345
    Quote Originally Posted by AbuMaia View Post
    Now that we have this mod to save the G29 matrix for an entire print session (or longer), it is no longer necessary to add a G29 to the start gcode when slicing. However, those of us who run our printers standalone, we need another way of running the G29 when we change a setting or a glass plate. I believe that many who run their printer standalone have an LCD display on their printer. Here's what I did to add G29 to the LCD menu:

    In ultralcd.cpp, find MENU_ITEM(gcode, MSG_AUTO_HOME, PSTR("G28"));
    Just after it, add MENU_ITEM(gcode, MSG_BED_LEVEL, PSTR("G29 n5"));

    In language.h, find #define MSG_ENDSTOP_ABORT "Endstop abort"
    Just after it, add #define MSG_BED_LEVEL "G29 Bed Level"

    Thank you works awesome just need to "Auto Home" prior to G29

Page 1 of 16 12311 ... LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •