Marlin: Question Skew Correction

Created on 20 Dec 2017  Â·  33Comments  Â·  Source: MarlinFirmware/Marlin

//#define SKEW_CORRECTION

The codes references a thingiverse model to print and measure. I followed the link. There is a vertical and horizontal version.
Which version are delta's suppose to use?
Does it matter?
Does orientation on build plate matter?
Measure from build plate necessary?
Print outside walls 1st?

Calibration Question

Most helpful comment

The trouble is here

SERIAL_ECHOPAIR(MSG_SKEW_FACTOR " XY: ", planner.xy_skew_factor);
and here
SERIAL_ECHOLNPAIR(" M852 S", LINEAR_UNIT(planner.xy_skew_factor));

which truncate the value to the second decimal place.
They do not round it so if in my case the skew is -0.004047 is returned -0.00 (note the minus)

I did a simple test multiplying the skew by 10,000 and you can clearly see that it is calculated exactly.

SERIAL_ECHOLNPAIR(" M852 S", LINEAR_UNIT(10000 * planner.xy_skew_factor));

Recv: echo: M851 Z-0.20
Recv: echo:Skew Factor:
Recv: echo: M852 S -40.47
Recv: echo:Linear Advance:

All 33 comments

The codes references a thingiverse model to print and measure. I followed the link. There is a vertical and horizontal version.

The flat version is for measure XY-skew.
The high version is for measuring XZ-skew when oriented parallel to X.
The high version is for measuring YZ-skew when oriented parallel to Y.

Which version are delta's suppose to use?

That depends not from if you have a delta or not. It depends on what you want to measure.

Does it matter?

That depends.

Does orientation on build plate matter?

The flat version is for measure XY-skew.
The high version is for measuring XZ-skew when oriented parallel to X.
The high version is for measuring YZ-skew when oriented parallel to Y.

Measure from build plate necessary?

Not as long as the part fits on your build plate. If not, you have to skale it. Your measurements error will be relative smale when the part is relative big.

Print outside walls 1st?

Print the calibration part that way you get the best possible outer shape.

Does it matter?

Nothing special about delta when it comes to skew.

Thanks for the answers.

Need a little more clarification on:

Not as long as the part fits on your build plate. If not, you have to skale it. Your measurements error will be relative smale when the part is relative big.

The model fits on my build plate. But it takes up 85-90% of printable radius. So should I scale it smaller for better measurement error? How much?

When i wrote my first answer i was not sure if you want to provoke with a silly question.
Now i'm confident you are joking.

If at all - the other way around.

I wasnt trying to troll you by provoking a "silly question."

I'm new to modifying marlin firmware, and 3d printing. Thank you for taking the time to answer my questions.... there was a time when you knew less also.

I have an other question regarding skew correction : I use marlin with a CNC (in addition of my 3D printer), and would like to use SKEW correction on that one since my XY axes are not square. However, the skew correction doesn't seem to have any effect.

After a fast look at the code, it seems it's only used with bed levelling ( the skew function and unskex functions are only celled in the apply_leveling / unapply_leveling functions), which I don't want to use on the CNC.

Is that limitation of skew correction a feature ? or should I file a bug ?

@mylife4aiurr what @AnHardt was pointing out, is that the measurement is more precise, the bigger your part is. Or put otherwise: The measurement ERROR will decrease with the size of the part. This means the smaller the part is, the bigger the influence of any measurement inaccuracies will become.

I'm new..... So how activate this feature?

I removed // from //#define SKEW_CORRECTION
I removed // from //#define SKEW_CORRECTION_GCODE
I entered my measured values

#define SKEW_CORRECTION

#if ENABLED(SKEW_CORRECTION)
  // Input all length measurements here:
  #define XY_DIAG_AC 141.03
  #define XY_DIAG_BD 141.56
  #define XY_SIDE_AD 100.89

  // Or, set the default skew factors directly here
  // to override the above measurements:
  #define XY_SKEW_FACTOR 0.0

  #define SKEW_CORRECTION_FOR_Z
  #if ENABLED(SKEW_CORRECTION_FOR_Z)
    #define XZ_DIAG_AC 140.64
    #define XZ_DIAG_BD 140.49
    #define YZ_DIAG_AC 139.79
    #define YZ_DIAG_BD 139.91
    #define YZ_SIDE_AD 99.23
    #define XZ_SKEW_FACTOR 0.0
    #define YZ_SKEW_FACTOR 0.0
  #endif

  // Enable this option for M852 to set skew at runtime
#define SKEW_CORRECTION_GCODE
#endif

Complied. upload to printer
then:

G33 P3 V1;
M500 ;
G29 P1;
G29 S1;
G29 A;
M500;

M852 returns:
Recv: echo:Skew Factor XY: 0.00 XZ: 0.00 YZ: 0.00
Recv: ok P15 B3

Then I tried:

#define SKEW_CORRECTION

#if ENABLED(SKEW_CORRECTION)
  // Input all length measurements here:
  #define XY_DIAG_AC 141.03
  #define XY_DIAG_BD 141.56
  #define XY_SIDE_AD 100.89

  // Or, set the default skew factors directly here
  // to override the above measurements:
  //#define XY_SKEW_FACTOR 0.0

  #define SKEW_CORRECTION_FOR_Z
  #if ENABLED(SKEW_CORRECTION_FOR_Z)
    #define XZ_DIAG_AC 140.64
    #define XZ_DIAG_BD 140.49
    #define YZ_DIAG_AC 139.79
    #define YZ_DIAG_BD 139.91
    #define YZ_SIDE_AD 99.23
    //#define XZ_SKEW_FACTOR 0.0
    //#define YZ_SKEW_FACTOR 0.0
  #endif

  // Enable this option for M852 to set skew at runtime
  #define SKEW_CORRECTION_GCODE
#endif

Complied. upload to printer
then:

G33 P3 V1;
M500 ;
G29 P1;
G29 S1;
G29 A;
M500;

but same result for M852:
Skew Factor XY: 0.00 XZ: 0.00 YZ: 0.00

Here's my startup

Send: M501
Recv: echo:V47 stored settings retrieved (614 bytes; crc 7605)
Recv: Unified Bed Leveling System v1.01 active.
Recv: 
Recv: Unified Bed Leveling initialized.
Recv: 
Recv: Mesh loaded from slot 1
Recv: Mesh 1 loaded from storage.
Recv: echo:  G21    ; Units in mm
Recv: echo:  M149 C ; Units in Celsius
Recv: 
Recv: echo:Filament settings: Disabled
Recv: echo:  M200 D1.75
Recv: echo:  M200 D0
Recv: echo:Steps per unit:
Recv: echo:  M92 X80.00 Y80.00 Z80.00 E110.34
Recv: echo:Maximum feedrates (units/s):
Recv: echo:  M203 X300.00 Y300.00 Z300.00 E200.00
Recv: echo:Maximum Acceleration (units/s2):
Recv: echo:  M201 X4000 Y4000 Z4000 E3000
Recv: echo:Acceleration (units/s2): P<print_accel> R<retract_accel> T<travel_accel>
Recv: echo:  M204 P1000.00 R2000.00 T3000.00
Recv: echo:Advanced: S<min_feedrate> T<min_travel_feedrate> B<min_segment_time_us> X<max_xy_jerk> Z<max_z_jerk> E<max_e_jerk>
Recv: echo:  M205 S0.00 T0.00 B20000 X20.00 Y20.00 Z20.00 E5.00
Recv: echo:Unified Bed Leveling:
Recv: echo:echo:  M420 S1
Recv: 
Recv: Unified Bed Leveling System v1.01 active.
Recv: 
Recv: Active Mesh Slot: 1
Recv: EEPROM can hold 8 meshes.
Recv: 
Recv: echo:Endstop adjustment:
Recv: echo:  M666 X0.00 Y-1.04 Z-1.32
Recv: echo:Delta settings: L<diagonal_rod> R<radius> H<height> S<segments_per_s> B<calibration radius> XYZ<tower angle corrections>
Recv: echo:  M665 L228.00 R108.59 H296.73 S160.00 B70.00 X-0.47 Y0.32 Z0.16
Recv: echo:Material heatup parameters:
Recv: echo:  M145 S0 H205 B60 F255
Recv: echo:  M145 S1 H240 B100 F255
Recv: echo:PID settings:
Recv: echo:  M301 P21.04 I1.24 D89.65
Recv: echo:Z-Probe Offset (mm):
Recv: echo:  M851 Z0.15
Recv: echo:Skew Factor:
Recv: echo:  M852 I0.00 J0.00 K0.00
Recv: echo:Linear Advance:
Recv: echo:  M900 K170.00 R0.03

How about a M502 to read the programmed settings at least once?

Yes did M502.

This is my procedure between firmware uploads
G29 P0;
M502
M500
M140 S60 ;
M104 S160 ;

G28
M665 B70 ; (error with g33 unless this command 1st)
G33 P3 V1 ;
M500 ;

G28;
G29 P1;
G29 S1;
G29 A;
M500;

Then I tried…
Complied. upload to printer
then:

G33 P3 V1;
M500 ;

Whoops. That M500 just loaded the skew settings from whatever's in the EEPROM.

G29 P1;
G29 S1;
G29 A;
M500;

but same result for M852:
Skew Factor XY: 0.00 XZ: 0.00 YZ: 0.00

So, the EEPROM had 0, 0, 0 in it.

Just do M502 followed by M852. You'll see the skew has been reset to the factors you set in your configuration. Then, use M500 to save to EEPROM so it will be loaded next time.

Ok I've tried everything I know to get this working. Upgraded to v1.1.8, this weekend. Transfered measured skew values to new firmware. Enabled it in firmwaire. If this is working for others than I don't know what I'm doing wrong.
Have a delta printer, with nozzle as probe, heated aluminum bed, blue tape surface. I'm using:
auto delta config G33
UBL bedleveling,
then fine tuning mesh with G26.

So:
**Initialize eeprom;
M502
M501
M852 <----- Correct spot???
M500

Heat bed
Heat nozzle

**Delta configuration
G28
M665 B70
G33 P3 V2 F5
//M500 Normally I'd do a save here for delta config info? Delta will be saved when m500 below?

**Bed leveling
G29 P1
G29 S1
G29 A
M500

** edit mesh (multiplie iterations) just learned this weekend 😊
G26 B60 H205 F1.75 L0.2 S0.4
G29 P4
G29 S0 <--- should it be S1, to use same mesh as above???

Is that sequence correct as far as getting skew correction working?

The aboves works for me as far as getting printer up and running.
I've added M852 right after eeprom initialization??? Correct?? I'm still getting a 0.0 skews as B4.

For troubleshooting, What commands can I enter right after new firmware to intialize eeprom (G29 Needs eeprom intialization B4 use) and test if skew correction is being calculated?
M502
M501
M582
M500
M503 or M501 to view if working and not 0.0??

I'm similarly unclear on how it works.

I yesterday upgraded from 1.1.4 to 1.1.8 (if it matters I have Geeetech i3 Pro B printer). I have a bit of a skew in my bed, was worse but I managed to reduce it somewhat by disassembling and reassembling the bed but it's still present so when I noticed skew settings in Configuration.h i gave it a try.

After printing test square I got these values

#define XY_DIAG_AC 140.9
#define XY_DIAG_BD 141.4
#define XY_SIDE_AD 100

after flash from Arduino IDE, and M502/M500, I tried M852 and got 0.00. I tried commenting out #define XY_SKEW_FACTOR 0.0 and recompiling and got error on compilation

_'sqrt(1.05173e+5)' is not a constant expression_

so I calculated skew by hand (or better said Excel) I got -0.00354 so I entered this value in XY_SKEW_FACTOR and reflashed. After M502/M500 I again tried M852 and this time instead of 0.00 I got -0.01.
So it seems it stuck, I tried printing another test square but result was the same. No change in skew either for better or for worse.

I again commented out XY_SKEW_FACTOR with my precalculated value and after some experiments managed to compile without that sqrt error. To cut long story short this is how it compiled

#define XY_DIAG_AC 140.90
#define XY_DIAG_BD 141.40
#define XY_SIDE_AD 100.00

I had to include two decimals, I guess it has something to do with variable types in gcc (int, long...).

So i reflashed these updated values and commented out XY_SKEW_FACTOR into my 3D printer, again did M502/M500 and M852 after that returned 0.00, like in the first case.

I just started print on another test square to see if anything changes. I'm even thinking of entering big value for XY_SKEW_FACTOR just to see if it affects anything.

@Solo761 Thank you so much for responding. Seems very similar to my experience.
I had also hand calculated the 1st xy_skew_factor myself last night to test, but then sleep and work today. Didnt get a chance to test it yet. Seems same result, even so.

It seems that last print I did was successfull, AC and BD were the same (cca 141,1).

I only wanted to "fix" XY axis so I left Z commented. If I uncomment _XY_SKEW_FACTOR_ it doesn't work. M852 returns -0.01, but it doesn't alter the skew. If I comment _XY_SKEW_FACTOR_ M852 returns 0.00 but it seems it's actually doing something.

This is my configuration

#define SKEW_CORRECTION

#if ENABLED(SKEW_CORRECTION)
  // Input all length measurements here:
  #define XY_DIAG_AC 140.90
  #define XY_DIAG_BD 141.40
  #define XY_SIDE_AD 100.00

  // Or, set the default skew factors directly here
  // to override the above measurements:
  // #define XY_SKEW_FACTOR -0.00354

  //#define SKEW_CORRECTION_FOR_Z
  #if ENABLED(SKEW_CORRECTION_FOR_Z)
    #define XZ_DIAG_AC 282.8427124746
    #define XZ_DIAG_BD 282.8427124746
    #define YZ_DIAG_AC 282.8427124746
    #define YZ_DIAG_BD 282.8427124746
    #define YZ_SIDE_AD 200
    #define XZ_SKEW_FACTOR 0.0
    #define YZ_SKEW_FACTOR 0.0
  #endif

  // Enable this option for M852 to set skew at runtime
  #define SKEW_CORRECTION_GCODE
#endif

So if I understand you correctly. If you input your measured values you must comment out the respective skew factor lines. That was one of the things I tried.

But I expected to see a calculated skew displayed on startup and with M852, or M503, but its always 0.0 or -0.0.
If I see 0.0, I think:
my printer is perfectly aligned (unlikely)
or
code not working
or
I did something wrong

If I had _XY_DIAG_AC, XY_DIAG_BD, XY_SIDE_AD_ and _XY_SKEW_FACTOR_ defined no skew adjustment happened, although M852 returned value (not the one I entered -0.00354, but rounded to two decimals -0.01). After I commented define for _XY_SKEW_FACTOR_ and left only _XY_DIAG_AC, XY_DIAG_BD_ and _XY_SIDE_AD_ M852 returned 0.00. I tried printing test square anyway and it printed out corrected regardless of 0.00 returned by M852.

I also expected M852 to return calculated value if I don't specify _XY_SKEW_FACTOR_, but if it's not defined maybe it gets calculated from those three values on each print, not on compile time, and stored in that variable. I didn't dig through source code to see exactly how it works.

I just tried to print Commodore 64 cartridge shell, this is where I noticed that my bed is skewed before, top and bottom part couldn't close because of the skew, but now they close perfectly so I guess it really does work.

Try commenting out all three _SKEW_FACTOR_ defines and then try making test print to see if it corrects for you too.

Ok. I understand. Your saying its working in the back ground if commented out skew correction lines. But even from @thinkyhead response

So, the EEPROM had 0, 0, 0 in it.

Just do M502 followed by M852. You'll see the skew has been reset to the factors you set in your configuration. Then, use M500 to save to EEPROM so it will be loaded next time.

I was expecting to see something other then 0.0, if changed my procedure as suggested.

Me too, but... in the end I got it working, although it still shows 0.0. Actually comment in the code says "Enable this option for M852 to set skew at runtime" so from that I'd say M852 only shows value that's set to _SKEW_FACTOR_. If _SKEW_FACTOR_ is uncommented this command will display it's value, if it's commented it's not set so M852 shows 0.00. I don't think there's command to show values from _XY_DIAG_AC, XY_DIAG_BD_ and _XY_SIDE_AD_.

To me real issue is why it didn't correct with manually calculated skew factor as it clearly overrides values we set to _XY_DIAG_AC, XY_DIAG_BD_ and _XY_SIDE_AD_.

The trouble is here

SERIAL_ECHOPAIR(MSG_SKEW_FACTOR " XY: ", planner.xy_skew_factor);
and here
SERIAL_ECHOLNPAIR(" M852 S", LINEAR_UNIT(planner.xy_skew_factor));

which truncate the value to the second decimal place.
They do not round it so if in my case the skew is -0.004047 is returned -0.00 (note the minus)

I did a simple test multiplying the skew by 10,000 and you can clearly see that it is calculated exactly.

SERIAL_ECHOLNPAIR(" M852 S", LINEAR_UNIT(10000 * planner.xy_skew_factor));

Recv: echo: M851 Z-0.20
Recv: echo:Skew Factor:
Recv: echo: M852 S -40.47
Recv: echo:Linear Advance:

Thanks so much @mr-miky - I think this was the problem all along. I bet I never even post here if I saw any correction value other than 0.0.

When a noob finds a problem its so hard for developers to take them seriously. The code is working as @Solo761 suggested, we just didnt see the correction factor, so I thought it wasn't working. I wish @AnHardt tried to help and investigate the issue instead of blowing me off with passive aggressive responses:

How about a M502 to read the programmed settings at least once?

When i wrote my first answer i was not sure if you want to provoke with a silly question.
Now i'm confident you are joking.

@AnHardt Thanks for explaining how to setup the models, that was helpful. But the comments above show you didnt even try it yourself or look into the problem thoroughly.

The trouble is here

SERIAL_ECHOPAIR(MSG_SKEW_FACTOR " XY: ", planner.xy_skew_factor);

and here

SERIAL_ECHOLNPAIR(" M852 S", LINEAR_UNIT(planner.xy_skew_factor));

which truncate the value to the second decimal place. They do not round it so if in my case the skew is -0.004047 is returned -0.00 (note the minus)

Yup... We need to print that with more precision. That floating point number needs to be printed with

SERIAL_PROTOCOL_F(planner.xy_skew_factor, 6);

so for now just to be clear, make the following change ?????

SERIAL_ECHOLNPAIR(" M852 S", LINEAR_UNIT(planner.xy_skew_factor));

to

SERIAL_ECHOLNPAIR(" M852 S", LINEAR_UNIT(10000 * planner.xy_skew_factor));

or just:

SERIAL_PROTOCOL_F(planner.xy_skew_factor, 6);

That will show user correction???

Let's fix it 'right'. It needs to be something like

  SERIAL_ECHO(MSG_SKEW_FACTOR " XY: ");
  SERIAL_ECHO_F(planner.xy_skew_factor, 6);
  SERIAL_ECHO("\n");

Most of the time when a float is printed with high precision, it is terminated with a new line.
We probably should define a SERIAL_ECHONL_F() function.

@Roxy-3D
Thanks for looking at this. Using 1.1.8, now. I'll wait for fix.

It should be updated in both bugfix branches now...

Works nicely in bug fix.....thnks

DId this get fixed? I'm still seeing the same issue...entered all the Skew info, commented out the direct entry of the correction factors...and it still says I have X0Y0Z0 skew (I don't...I can see i don't).

Here's the gcode config...

#define SKEW_CORRECTION

#if ENABLED(SKEW_CORRECTION)
  // Input all length measurements here:
  #define XY_DIAG_AC 279.6
  #define XY_DIAG_BD 283.78
  #define XY_SIDE_AD 199.08

  // Or, set the default skew factors directly here
  // to override the above measurements:
  // #define XY_SKEW_FACTOR 0.0

  #define SKEW_CORRECTION_FOR_Z
  #if ENABLED(SKEW_CORRECTION_FOR_Z)
    #define XZ_DIAG_AC 281.34 //NC 20.06.2018
    #define XZ_DIAG_BD 279.34 //NC 20.06.2018
    #define YZ_DIAG_AC 280.08 //NC 20.06.2018
    #define YZ_DIAG_BD 280.34 //NC 20.06.2018
    #define YZ_SIDE_AD 198.8 //NC 20.06.2018
    //#define XZ_SKEW_FACTOR 0.0
    //#define YZ_SKEW_FACTOR 0.0
  #endif

  // Enable this option for M852 to set skew at runtime
  #define SKEW_CORRECTION_GCODE
#endif

When I put the figures into excel, I gert a calculated AB value of 199.3007, and a Skew factor of
-0.01484...so even if the decimal poiutn thing was the problem - I should still see 0.01?

Confused, and would really like to understand what is going on!

Your Z axis is also skewed? I see you also defined skew correction for Z.

Also, what is your marlin version? I had master branch 1.1.8, which didn't report calculated value with M852, although it works. Bugfix branch had this fixed (and maybe other stuff too) so maybe try with that?

it still says I have X0Y0Z0 skew

Did you do M502, M500 after flashing the new config?

I think this is fixed, but it's still a noob-confuser.

Print model, measure distances.
Enable skew correction (remove "//")
Enter distances.
Optionally, enter manual skew if you have worked it out.

All good so far. But then you upload the firmware and get presented with;

Recv: echo:Skew Factor:
Recv: echo: M852 S0.000000
Recv: ok
[...]

NO, not okay, because it makes you think "skew = 0", and it's ignored your value.

Now I enter ;

Send: M502
Recv: ok
[...]
Send: M500
Recv: ok
[...]
Send: M852
Recv: echo:Skew Factor XY: -0.010280
Recv:
Recv: ok

Yes, yes, now it's okay. Not exactly intuitive though, is it?

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

Was this page helpful?
0 / 5 - 0 ratings