WeCreat Lumos Ultra — controller status report never leaves Idle, streams desynchronise on long jobs

I’ve been building a LightBurn device configuration for the WeCreat Lumos Ultra (WeCreat publishes configs for the Vision/Vista/Lumos but not the Ultra) and I think I’ve found a protocol-level problem worth reporting. Everything below is from LightBurn 2.1.04 on a physical machine, and the captures are public:

Setup: Custom GCode device, GCodeFlavor: wecreat, serial at 1,000,000 baud over the machine’s CH340 bridge. LightBurn detects it correctly — “Found WeCreat Device” — and emits WeCreat-specific commands (Exit_Preview_Mode, M41Y1), so the built-in WeCreat support is working as intended.

The observation: the status report’s state field appears to be fabricated.

Every ? returns the same state regardless of what the machine is doing:

<Idle|MPos:2.748,18.237,0.000|FS:0,0|Pn:Z|WCO:0.000,0.000,0.000>

  • MPos is live and correct — it tracks real position, non-integer, mid-motion
  • the state field is always Idle, including during an active job stream
  • FS is always 0,0, never reporting real feed or speed

The sharpest evidence: sending ! (feed hold) mid-job, the controller answers Idle. A machine that has just been told to hold reports itself idle.

Consequence. Long jobs stall part-way through and sit there — no alarm, no disconnect, fan still running. Pressing Pause then Resume (! then ~) restarts the stream from roughly where it stopped. LightBurn reports Stream completed in 0:00 for jobs that visibly take minutes.

That is consistent with LightBurn pacing a stream against a device that claims it is never running and never held.

Why it does real damage: G91.

LightBurn emits fills as relative moves. Measured on one job:

Offset Fill Plain Fill
Moves in G91 relative 1,009 (8.6 %) 9,634 (99.97 %)
Absolute G0 re-anchors 459 2

Plain Fill enters G91 at line 21 and does not leave until line 8,647 — over 8,600 consecutive relative moves with no absolute re-anchor.

So one lost or unacknowledged line shifts everything after it, permanently. I measured a job finishing 2.30 mm outside its own declared ;Bounds: header — arithmetically impossible in a pure G90 job.

It also means the Pause/Resume recovery is itself harmful: a feed hold stops mid-move, and in relative mode any imprecision on resume is inherited by the rest of the job.

What I tried:

  • Query-for-position off, Laser Fire button off, Z axis off, relative-Z only, optimise-Z off (the known fix for WeCreat “Busy after framing”) — no change
  • Transfer mode Synchronous — no change reported
  • Target Buffer Size cannot be changed. Typing 40 reverts to 128, and importing a .lbdev with "TargetBufferSize": 40 still shows 128. Is this clamped by the wecreat flavor? If so it might be worth exposing, or documenting
  • Defining the Raster Move template does not affect G91 — it changes only line formatting

Questions I’d genuinely like answered:

  1. Is there any way to make LightBurn emit fills in absolute coordinates? On a controller with an unreliable stream, G91 converts a recoverable glitch into a ruined workpiece. Even a hidden option would help.
  2. Is Target Buffer Size intentionally fixed for this device class?
  3. Does LightBurn’s WeCreat handling assume a status report that this firmware does not provide?

I’m aware the root cause is likely WeCreat’s firmware, not LightBurn — I’m reporting it to both. But the G91 amplification is the difference between “occasionally stalls” and “occasionally destroys the work”, and that part sits on LightBurn’s side.

Happy to provide the full .gc files, console logs and device profile — they’re all in the repo.

1 Like

Did you see an incremental increase in the GCode output? Did the display match the machine actual position when it finished?

The GCode file (.gc) might show what is wrong, but nothing can be determined about how it got there.

I would be interested in running the Lightburn file (.lbrn2) on my lasers (Sculpfun SF-A9 and S30) to see if I can duplicate your positioning findings. I did not see it on GitHub, so can you attach it to a Reply?

Good questions, and your caution is right — I’ll take it head on.

No, the G-code output is not drifting. I checked this specifically. When I converted Plain Fill.gc from relative to absolute coordinates, the resulting coordinate range matched the file’s own ;Bounds: header exactly — X 48.784–123.216, Y 82.637–125.199, to three decimals across 9,634 moves. LightBurn’s output is internally consistent. The drift is in what got executed, not in what was generated.

You’re also right that the .gc can’t show how it got there. I’d put it this way: the .gc is evidence of the amplifier, not the fault. It shows that 99.97% of a Plain Fill runs in G91 with two absolute re-anchors in the whole job — so any lost line is inherited permanently. It says nothing about why a line goes missing.

On the display question — honest gap. What I measured was the machine’s own MPos report at the end of the run: 2.30 mm below the job’s declared minimum Y. I did not separately compare that against LightBurn’s on-screen position readout. Worth noting the machine’s own reported position had accumulated the same error, which is what you’d expect if it executed a short stream rather than a wrong one.

Your test is the control experiment I can’t run, and I’d really like you to. If the same file runs clean on a Sculpfun — normal GRBL, healthy acknowledgement protocol — that isolates the fault to the WeCreat controller and clears LightBurn’s G91 output of generating anything wrong. If you see drift there too, I’ve misdiagnosed this and I’d want to know.
test-fill.lbrn2 (241.8 KB)

1 Like

@LeeGillie thank you for this extensive report!

We’ve been in contact with WeCreat about the Lumos. Your findings match very closely with what we also discovered and reported to WeCreat.

I’m forwarding your post to our dev working on Lumos support.

2 Likes

About the “Target Buffer Size” changing:

LightBurn reads the buffer size (in bytes) is from the output of $I. Normally GRBL will output a OPT: and return the RX buffer’s byte size there. However if that response is missing, LightBurn defaults to 128 bytes again.

Manually setting the buffer size should override that behavior. We have a fix in place to solve this. (not sure if it already made it to version 2.1.04)

1 Like

@Aaron.F @LeeGillie the buffer on the Lumos Ultra is unfortunately not fully usable. It seems that the buffer to which we send commands through the serial port and the buffer used by the chip executing moves don’t have the same size.

What I found, and it’s easy enough to test to confirm this on your end @LeeGillie, is that if I set the buffer at 127 or bigger, it would just drop moves from the job to process. So yes, I’m aware and discussing with WeCreat how to resolve the issue.

With 127 bytes of buffer, for a galvo machine we’re going to be running “dry” very quickly.

3 Likes

Hi Mike - I replied to your request for the gc file. I don’t think I did it as a direct reply to you, but it is in the thread. My bad. Can you please confirm you received it? Thx - Lee

You did good. Whether you use the posting Reply, or the main one at the bottom, all postings are visible.

This statement, and those following from the Staff point to the laser controller board itself. I did download your file, but given the statements by @Aaron.F and @goeland86 above, I think a test run would prove nothing. I also do not have that font installed. :roll_eyes:

The simplest answer to determine if the gcode has a problem is to go to an online gcode viewer, like ncviewer.com and see if you notice a drift there. If not, it’s the machine having issues, whether firmware or hardware.

On our machine, G91 worked, in that I was able to do a series of fill engraving tests without drift. So I suspect a firmware update not yet released to the public.

Consider that your fill mode is predominantly doing relative movements. And because the serial communication is glitchy, once in a while some data is lost. That’s what we think is happening.
We tried to override positioning to be all absolute via device parameters, but our stuff never made it to the gc. So we have been looking for evidence of stalling (one symptom) and of drift (another symptom) in other generations of WeCreat machine configs. The theory being they will likely have the same com glitches that we see on the Ultra lightburn using serial over USB. MakeIt uploads the job to the machine’s SD card over the USB network interface and lets the controller run it locally, so it never streams over the serial port and never depends on this.

@goeland86 — fair challenge, and let me start by withdrawing my previous post, which was the first thing I have put in this thread that was theory rather than measurement. That was a mistake and I would rather correct it than defend it.

Specifically, what I am taking back:

  • “the serial communication is glitchy, once in a while some data is lost — that’s what we think is happening.” That was a hypothesis stated as though it were established. It is not mine to state. The only actual evidence for dropped data in this thread is yours: that the machine drops moves at a buffer of 127 or larger.
  • “our stuff never made it to the gc.” Vague and unhelpful. What I should have said: I defined the Raster Move template as G1 X{x} Y{y} S{power} F{speed}, saved the G-code, and G91 was still present throughout. So the template does not control relative emission — it controls line formatting only. That is a result, not a failure.
  • The suggestion that other WeCreat generations likely share the same fault. I have no data on any machine but this one. Withdrawn.

Now the ncviewer question, which I should have answered directly.

The generated G-code does not drift. I checked it two ways before posting anything:

  1. I wrote a converter that rewrites the whole fill from relative to absolute. The converted coordinate range matches the file’s own ;Bounds: X48.784 Y82.637 to X123.216 Y125.199 exactly.
  2. The drift measurement never came from the G-code at all. It came from the controller’s own report at end of run: <Idle|MPos:-47.968,-24.663,...>. Through this machine’s confirmed −105 field-centre offset that is Y 80.337, against the job’s own declared minimum of 82.637 — 2.30 mm below it.

So the file says one thing and the machine says another. That is what “the drift is in what got executed” was meant to convey, and I should have shown the numbers instead of asserting it.

The weak edge in that measurement, before anyone else finds it.

That run is not clean. It is a run where I had used Pause/Resume repeatedly to unstick a stall — the console log shows unbalanced ! and ~ — and a feed hold stops mid-move, which in relative mode is itself a drift source. So I cannot separate “dropped move” from “my own recovery attempt” in that particular number.

What I can say is narrower and still holds: a pure G90 job cannot end outside its own declared bounds at all, by construction. Something is accumulating.

I can produce a clean version — run a dense fill, never touch Pause/Resume, abort on stall, and report the final MPos against the declared bounds. If that is useful I will run it this week.

The question I would most like answered, though, is yours:

“On our machine, G91 worked… So I suspect a firmware update not yet released to the public.”

What firmware version does your machine report? Mine identifies as:

[WeCreat Lumos :ver 000240]

If yours differs, that reframes this entire thread. It would mean the behaviour is already fixed and simply has not shipped, and the useful question becomes how owners get that build rather than what is wrong with the controller.

@MikeyH — no argument from me. Your machine is not an Ultra, so a run on it would not be a control, and I should not have left that request hanging. Thank you for downloading it anyway.

I can get you the version string tomorrow, but given that we’re in talks directly with their dev team, I wouldn’t be surprised if we were sent some in-flight firmware that fixed most things, but not all.

Not really, just out of sequence. You posted both, and that is what counts.

Interesting - looks like they have a regression.

Our machine reads WeCreat Lumos :ver 000236 in the console.

goeland86 That’s the opposite of what either of us expected, and it’s the most useful thing anyone has told me yet. 000236 clean, 000240 drifting — the working machine is on the older build.

It also reframes my whole investigation. Everything I’d documented — the fabricated status field, the buffer mismatch, G91 amplification — is a property of the design, and a design doesn’t differ between two units of one model. A version number does.

Holding myself to the same standard I applied to a Flex result yesterday, though: our comparison isn’t matched either. Could you tell me the source, speed and fill type you ran? Mine fail at 12000 mm/min on the 100W MOPA, and a slower job never empties the buffer regardless of firmware. If yours were comparable, “regression” goes from a reasonable reading to a solid one.

I’m asking Ultra owners for version strings alongside their results, so we may be able to bisect this across the community. And I’ve passed the version pair to WeCreat — they have both builds and the changelog between them, so they can settle in minutes what none of us can settle at all.

1 Like

Ah, I was setting my machine to run in mm/s since it’s a galvo, and I was sending it values between 1500 and 2000mm/s on the UV laser. 12000mm/min translates to 200mm/s… So something seems to be bizarre.

We have an in-progress build of LightBurn for WeCreat users, I’m sending you the link in a DM, but we’ll keep the rest of the discussion public here. If anyone else with a WeCreat device wants the in-flight LightBurn version, email support about it. It’s still in early stages, but we’re trying to make sure we have full support for WeCreat machines, and streaming Gcode to them is proving to be an unreliable proposition. WeCreat is also able to test this new Lightburn version to verify it.

I know it does not compare, but I was looking at what the design might be like for outputting the GCode.

I once attended a meeting that had nothing to do with my work assignments. I asked my boss why I was there. He said you never know where the right answer might come from.

1 Like

A correction, and it’s mine to make.

I called the 000236 / 000240 difference a regression, and repeated that in my own documentation. It isn’t one, and I’ve withdrawn it.

WeCreat tells me 000236 is early prototype firmware, from a machine loaned to LightBurn in the first half of this year. It was never released and isn’t distributed. 000240 is the production firmware — what Kickstarter backers received, and their baseline going forward.

So it’s not a shipping build that got worse. It’s a prototype differing from the production build that replaced it, which is a perfectly ordinary thing for a prototype to do.

@goeland86 — the part worth flagging: your reference machine is running firmware no customer has. No criticism intended, it’s just what a six-month-old loan unit means in practice. But it does mean a clean result on yours can’t stand in for a production Ultra, and it probably explains the difference between our two machines better than anything else on the table.

There’s no downgrade path, so the single-variable comparison is off the table for me. What I can still do is run the same fill at 87,000 mm/min on production firmware — you were at 1500–2000 mm/s and I’ve only ever tested at 200 mm/s, so if starvation is the mechanism, going faster should make it worse. I’ll post the result either way.

Still curious what fill type you were using, if you remember — plain Fill or Offset Fill. That’s the last unmatched variable between us.

I was using a normal Fill - not Offset Fill.