The real reason of first layer issues, and a solution

Great work and very detailed on the explanation. Issue for me is I understand the words but the process of implementing those words is a much different scenario according to my abilities. It seeems very complex, sure wish I had a first layer that was consistent though.

I have been having first layer issues for a long time now. Printer was great when brand new, then developed a deep dish taco and went to about a 90% printing failure rate. Got sick of that after about a year and started researching and replacing stuff. Strain gauge, build plate, print head cable, nozzle. This all helped a little. The best results came when I changed the way I do bed leveling. I came from an Ender 3 where I had to use the paper method all the time even though it had a CR touch for bed leveling. When I got the K2 Plus I thought I was done with the paper. Wrong. It has bed screws and they do adjust the bed. And you have to use paper. Again. The problem is, I had to develop my own method of doing the paper trick because Creality does not give any tools in the firmware for doing it (as far as I can see). Some people have programmed their own macros for doing it. I tried the bed_ screw&adjust thing, but it was just too complicated to setup and I am not a software developer, so I had to find another way. Then I saw a video on the R3men website https://youtu.be/qKrKXGRXfWs?si=jWD2WmGoVfxbduAE on how to level the bed. I had to download some macros from github. That is within my ability. After running them, my prints now stick. Prints are not perfect, but first layers actually are looking very good.

Interesting thread, I went down pretty much the same rabbit hole with my K2 Plus over the last weeks, but ended up somewhere different.

On my printer the mesh noise itself is small. Two meshes at the same bed temperature, a few hours apart and with the bed fully warmed up, were only 0.006 mm RMS apart. What actually ruined my first layers was the bed still moving:

  • At 70°C my bed is a dome of about 0.15 mm (middle high, corners -0.13 to -0.17). At 100°C it’s quite different again (span 0.245 vs 0.18 at 50°C), so for me one averaged mesh can’t fit every temperature.

  • The stock mesh starts in the middle and spirals outwards, which takes around 4.5 minutes. If the bed isn’t settled, the dome keeps growing during that time and afterwards. Once I had the middle come out +0.06 because the bed was still rising while it was being measured. That print was rough, the next one with a settled bed was perfect.

So my guess is that part of the deviation you measured is thermal drift, not probe noise. rdtsc’s tip to preheat points the same way.

That’s why I wrote a set of macros that hook into the stock firmware (nothing flashed, stock macros keep doing homing, nozzle cleaning, CFS, etc.):

  • Z-offset per material and plate in a config file, optionally per filament in the filament start G-code. No more adjusting by hand before every print, so cloud printing works too.

  • Heat soak before every print, optionally ending once the bed has actually settled.

  • Mesh cache per bed temperature and plate. Before a cached mesh is used, up to 9 points are probed (~30 s). If the bed has only shifted up or down, the difference goes onto the Z-offset. If the shape changed, it measures a new mesh.

  • After a fresh mesh the middle is probed again. If the bed moved during the measurement, that mesh is only used for this one print and not cached.

  • K2_TUNE measures how long your bed needs to settle from cold and sets the soak time and check tolerances from that.

Tested on my K2 Plus with 1.1.6.4 and 1.1.7.0, reported working on a K2 Pro. Feedback welcome: https://github.com/xeladotbe/k2-override-stick

1 Like

Hello xeladotbe, the difference between your approach and mine is that you concentrate on the difference between different meshes whereas I deal with the differences between several measures taken at the same point because I don’t care about a mesh if the measures taken to compute it are false.

As far as I remember (my post is 4 months old), the measures were taken at stable temperatures, This exonerate any thermal drift.

To be sure, I will restart my experience without any heating and will give you the results. I can’t do it right now because I am travelling.

By the way, I am working and printing several times a day, PLA, PETG and TPU, with not a single modification, with the mesh I made 4 months ago.

Hi Jacorbin, thanks for the reply.

Fair point, I only compared whole meshes in my last post. I also checked repeatability at the same point: on my K2 Plus repeated probes at one spot vary by about 0.003 mm, and homing 5 times stayed within ±0.005. So on my printer the single measurements look fine. How much spread did you get?

And you’re right, at a stable temperature the bed doesn’t drift during the measurement. What remains is that the shape is different at each temperature. With the bed fully settled, the middle on mine sits about 0.064 mm higher than the edges at 50°C and about 0.142 mm at 70°C. That’s 0.08 mm difference at the edges, 40% of a 0.2 mm first layer. You can print with one mesh, but the first layer suffers, at least on my bed.

If yours has worked for 4 months with PLA, PETG and TPU, maybe your bed just moves less than mine. If you find the time, I’d be curious how a mesh at 50°C compares to one at 80°C on your printer.

Hi xeladotbe
I will make new measures next week and tell you the result.

Hi xeladothe,

I first made a new set of measurements with a cold machine (unused for a full week in a 20°c environment)
I made 20 rounds of measurements for a 3x3 mesh. This means each of the 9 points was measured 20 times in exactly the same environmental conditions.

The individual standard deviations of the measurements for the 9 points are as follows:

Rear Left 0.019, Rear Middle 0.009, Rear Right 0.018
Middle Left 0.023, Middle Middle 0.022, Middle Right 0.025
Front Left 0.017, Front Middle 0.020, Front Right 0.015

The maximum value for the standard deviation is 0.025. There is an average error of 1 eighth of a 0.2-millimeter layer between the map of the plate and the real plate.

Moreover, the maximum variation range for the 9 points is 0.089, meaning one point (actually the front middle) has an error close to half the standard layer thickness. Largely sufficient to create a blob in the first layer.

To satisfy your curiosity, I am willing to create the meshes you want to compare. Just tell me how many points you want (11x11, 15x15…) ?

Hey Jacorbin,

thanks for taking the time, that’s a lot of probing!

A few questions so I understand the numbers right:

Was the bed heated during the 20 rounds, or completely cold? If it was heating up while you measured, part of the spread could be drift and not noise.

Do the values wander in one direction over the 20 rounds, or do they jump around randomly? The std dev alone doesn’t show that. The 20 raw values for one point (e.g. the middle) would already help.

Did you run BED_MESH_CALIBRATE 20 times or single PROBEs?

The reason I’m asking: on my K2 Plus the noise is a lot smaller. PROBE_ACCURACY in the middle gives me around 0.003, and two 9x9 meshes in a row at print temp differ by about 0.006 RMS. Your 0.02 is 3 to 6 times that. If your probe really scatters that much, averaging several meshes makes sense on your machine, on mine it wouldn’t change much.

About the bigger meshes: thanks, but I don’t think we need them. I already did a 17x17 run with single probes and compared it to the 9x9 mesh. The points between the mesh points weren’t any worse than the mesh points themselves, so the interpolation isn’t the problem.

What would really help to compare: a PROBE_ACCURACY SAMPLES=20 in the middle of the bed, once cold and once at print temp after a soak. Then we’d know if it’s your probe or something else.

1 Like

Hi xeladotbe;
Answers to your questions:

  1. The bed was not heated at all during the 20 rounds. Therefore, no thermal expansion.

  2. Here are the 20 raw probed values for the middle point :

    0.002, 0.035, 0.017, 0.035, 0.025, 0.058, 0.035, 0.025, 0.075, 0.025,
    0.080, 0.027, 0.027, 0.072, 0,090, 0.064, 0.090, 0.072, 0.060, 0.051

BUT, those values cannot be compared because each is the measured distance to a different reference point (the Z recomputed in each round). By definition, we don’t know Z, so its best estimate is the mean of the 9 probed values for that round.

Before any processing, I centered the measures in each round around the average of its 9 values.

The 20 Z averages are

0.034778, 0.048444, 0.045222, 0.040333, 0.039333, 0.037667, 0.040000, 0.037111, 0.054889, 0.032667
0.053000, 0.044222, 0.047556, 0.050333, 0.053333, 0.040778, 0.050778, 0.054000, 0.05000, 0.04800

Therefore, the 20 centered values corresponding to the middle point are:

-0.032778,-0.013444, -0.028222, -0.005333, -0.014333, 0.020333, -0.005000, -0.012111, 0.020111, -0.007667,
0.027000, -0.017222, -0.020556, 0.021667, 0.036667, 0.023222, 0.039222, 0.018000, 0.010000, 0.029000,

  1. I ran BED_MESH_CALIBRATE 20 times

  2. You are right: the “interpolation” is not the problem. Therefore, 9x9 mesg should be enough in that respect. But 17x17 proves better than 9x9 to “extrapolate” on the borders and even more in the corners, where data are missing.

  3. I did not know there was a PROBE_ACCURACY macro (many thanks). I am going to try that tomorrow and let you know the result. Maybe this will show that I need to replace my strain gauge?

,

Hey Jacorbin,

thanks for the raw data, that helps a lot.

I split your 20 rounds into two halves, and it’s not just random scatter, there’s a trend. The middle point averages 0.033 in rounds 1 to 10 and 0.063 in rounds 11 to 20, so it rises about 0.003 per round. Centered your way it’s still -0.008 vs +0.014, and even the mean of all 9 points goes from 0.041 to 0.049.

So even after centering, the middle rises about 0.02 compared to the other points over the run. That looks like a small dome forming, even with the bed off. It’s not the bed heater, but over 20 meshes the motors and electronics still warm the machine up, and the sensor itself can drift too.

On top of that there’s real noise. Within each half the standard deviation is still around 0.017 to 0.020. On my K2 Plus two meshes in a row differ by about 0.006 RMS, so yours is noticeably noisier.

About 17x17 at the borders: Klipper doesn’t extrapolate. Outside mesh_min/mesh_max it just uses the edge value, and the outermost points are in the same place for 9x9 and 17x17. More points only help if the bed bends sharply between the last two rows. When I compared 289 single probes against my 9x9 mesh, the points in between weren’t any worse than the mesh points themselves.

For PROBE_ACCURACY it might be interesting to do two runs in the middle with SAMPLES=20, one with the machine cold and one right after a long series of meshes. If each run is tight but the average moves between the two runs, that would point to drift rather than the sensor. Curious what you get.

One thing to keep in mind: on my printer single PROBE results differ from the BED_MESH_CALIBRATE results by up to about 0.05 at the edges. So PROBE_ACCURACY tells you about the sensor, but not exactly how the mesh behaves.

1 Like

Hey xeladotbe
Progress has been big since yesterday, thanks to your recommendation about PROBE_ACCURACY…

I ran “PROBE_ACCURACY SAMPLES=20” several times at the midpoint, with a cold plate and nozzle. The results are consistent with previous observations, with a range around 0.030 and a standard deviation around 0.006. I considered changing the strain gauge, but following Gemini’s recommendation, I first switched to a brand-new nozzle and ran it again. The results are now completely different, back to something much better: a range around 0.012 and SE 0.002. Gemini’s conclusion is that the nozzle, while “clean”, may have had small plastic residues distorting the measurement.

Then I tested a hot-behavior scenario with the nozzle at 150°C and the plate at 60°C, still using the new nozzle without plastic. I started the “PROBE_ACCURACY SAMPLES=20” once it reached the required temperature and repeated the measurement every 5 minutes for about three hours to check behavior during thermal expansion.

Time measurements at zero time are:
maximum 0.135000, minimum 0.125500, range 0.009500, average 0.131200, median 0.131000, standard deviation 0.002736

Results are as follow :

  1. The range and standard deviation do not change over time, staying respectively around 0.01 and 0.002
  2. The average and median, however, increase steadily with asymptotic behavior towards 0.445.
  3. From an initial 0.1312 (where required temperatures are already reached), it takes:
    5 minutes to reach 0.20
    15 minutes to reach 0.30
    40 minutes to reach 0.40
    45 minutes to reach 0.41
    55 minutes to reach 0.42
    75 minutes to reach 0.43
    110 minutes to reach 0.440
    140 minutes to reach 0.445

From there (2h20’ after the required temperatures are reached), the height starts to slowly oscillate (to the 4th decimal)

From this experiment, I derived the following conclusions:

  1. The mesh has to be built with a very clean nozzle. It is unclear to me how well the standard cleaning procedure keeps the nozzle sufficiently clean every time. This negates the recommendation to build a fresh mesh at every print, which is anyway useless unless the gantry has changed. As far as I am concerned, and given that I keep my mesh “forever”, I will from now on build my mesh with a brand new nozzle.

  2. The mesh has to be built with a stabilized temperature, with small enough thermal expansion during the time window for the measurement. For instance, if you start building a mesh immediately when the temperature target is reached, during a 9x9 mesh (~4 minutes), there’s enough time for thermal expansion to hit (+0.07) during measurement, distorting the result. With a 17x17 mesh (~14 minutes), thermal expansion reaches around 0,17, enough to completely ruin the result. In any case, the “best” mesh is the one where thermal expansion is complete.

  3. It is clear that the conclusions of my initial post are heavily impacted by the fact that the meshes were done without taken into account above points. I am going to redo my measurements and see later.

Last word on the 9x9 against 17x17 (or 41x41 or whatever) mesh: I reserve my position and will come back to you later.

Again, thank you very much for your contribution to my understanding of this difficult issue.

Hey Jacorbin,

nice find with the nozzle! A range of 0.012 and SD 0.002 is about what I see on my K2 Plus, so the strain gauge looks fine.

About the cleaning, I agree with you. I don’t think the stock cleaning gets the nozzle really clean every time. A lot depends on how clean the silicone pads are, once they’re full of old plastic they don’t do much anymore. I’ve also seen small bits of filament fall onto the bed during cleaning, and if one of them ends up under a probe point, that point is off as well.

Your hot test matches what I measured quite well. On my machine at 70C the middle rose about 0.20 within the first 40 minutes, at 50C it settled after about 25 minutes. Your much longer tail up to 140 minutes is something I see too. Once the bed itself has settled, the whole thing keeps creeping up by about 0.002 mm per minute, I assume from the frame and chamber warming up.

One thing I’d add: a single point in the middle can’t tell apart two different effects. One part of the rise is the whole bed moving up evenly. That doesn’t change the mesh shape at all, it only shifts Z, and a fresh Z home or a small offset correction before the print takes care of it. The other part is the bed doming, the middle rising more than the edges. Only that part really distorts the mesh. On my bed at 70C the corners rose only about 0.04 while the middle rose 0.20, so for me most of it was dome. If you repeat your test with one corner as well (or a quick 3x3 every few minutes), you’d see how much of your 0.31 is dome and how much is the whole bed moving.

On the dome itself, I’m currently trying something on the hardware side. The plate is held by four M4 screws that sit in the carrier without any play, so when it heats up it can’t really expand sideways and bows up in the middle instead. My idea is to keep one corner fixed with the M4 screw and use M3 screws in the other three, so the plate has a bit of room to grow away from the fixed corner. The screws and new knobs are ready, I just need to melt in the threaded inserts and then the test can start. I’ll report back once I know whether it reduces the dome.

It also helps to know that the K2 measures the mesh starting from the middle and then works outwards in a spiral. If the bed is still moving, the outer points end up measured later than the middle, so the error ends up mostly at the edges and corners.

That’s also why I don’t build a fresh mesh for every print. My macros (the k2-override-stick I mentioned earlier in this thread) keep one mesh per bed temperature and plate, and before each print they only check 9 points to see whether the shape still matches. If only the height differs, that difference goes onto the Z offset. So we pretty much ended up at the same conclusion: measure once, properly, with a settled bed.

If you don’t feel like doing all that by hand again, the K2_TUNE macro in there does basically your experiment automatically. It probes the middle 10 times cold for the noise, then heats the bed and probes the middle every minute and the 4 corners every 5 minutes until the shape stops changing. At the end it shows the settling time, how the dome developed and suggested soak times and tolerances. The nozzle stays cold during it, and it stops after 45 minutes by default (MAX_MINUTES= changes that), so it won’t catch your long slow creep, but that only affects the height anyway.

Looking forward to your new measurements.

1 Like

Hey [xeladotbe]
Perfect!
Many thanks for the K2_TUNE macro, which I didn’t know about. I’ll definitely use it next time I need to do it again.
For now, I want to check whether my mesh average stuff is still needed after the dispersion improvement.
Then, I built 5 different meshes with the brand-new nozzle without plastic, and I am going to test them in isolation with 350x350 first layers.
I’ll let you know the result.
About the hardware, I personally never understood why we are given 4 screws to set up a plane. On my first printer (Twotrees) years ago, I could avoid using the rear screws and install a single one in the middle rear, and most of my first-layer problems were gone. Interestingly, the Bambu Lab P2S (I bought one for my grandchildren) has three lead screws, with one in the middle rear. That’s how they achieve a fully automated mesh setup.
Since my TwoTrees experience, I always avoid tightening one of the screws, counting only on the three others to set up the best possible horizontal plane. I leave the last corner free, and if it’s not close to the plane, so be it, because any attempt to bring it onto the plane will fail and introduce useless additional torsion constraints on the plate.
See you later …

Hey xeladotbe,

Final statement on that subject.

From my last post, the progress toward closing that subject was quick and straightforward.

The first mesh I built with the brand-new nozzle, after two hours of heat soaking, produced a perfect 350x350 first layer. So I didn’t need any additional meshes to average.

The purpose of my initial post was to find a workaround to correct the too-large variance in the Z measure, which I thought caused the high number of complaints about poor first layers.

Thanks to your contribution, I realized no workaround is needed because the large variance isn’t a hardware characteristic; it’s an artifact of the measure itself.

If you use a perfectly clean nozzle and allow sufficient heat-soaking time beforehand, you can build a good-enough mesh in a single step.

This is a giant step for me, and I want to THANK YOU for it.

When I have time, I will add a more complete statement to the initial post. For now, I have a lot to do with my “forever” mesh. In the meantime, anybody interested in the subject can reach this final conclusion.

Bye