Laser: True grayscale instead of dithering?

@MadHatter OK, I understand. So basically you do what I did, just that you are slower because you reduced laser power, and as you said, the 100% power version failed. But I would predict that if it had worked, it would show the individual PWM dots like my manually created GCode. When I’ll revisit laser in earnest, I most likely will contact Snapmaker support on this.
But after all, great that you created a solution that works with any image, so I’ll tap into that if I need to create “true” grayscale images and do not care about creation times. After all, since the machine works autonomous, any working time is fine in the end, unless you want to do something last minute…

Ah. You know, I forgot or didn’t understand your complaint about the pwm dots before. I actually assumed anything like that would just be where parts of the print successfully burnt and other parts might have needed a little extra power. Hmm… if it is as you say and we are seeing on/off variances of the pwm pulses, that would be a pretty long pwm signal lol. Hmm.

I just inspected your gcode. 10,000mm/min seems pretty fast… what even is the max speed of the machine? I didn’t get a burn at 3000. Maybe my laser focus alignment was off. 2 things I did differently besides the feed rate is I did not turn off the laser each time I changed power with M5 and when I change lines I simply turn the power to 0 M3 P0 S0. The second thing I did was use matching fractional P percentages with my S values. In my tests the S value almost seems to be ignored and can be anything and seems to have the same result but idk if there is truly a difference. Here is a snippet from mine

M3 P100 S255
G1 X138.5
M3 P97.647 S249
G1 X151
M3 P96.471 S246
G1 X160.4
M3 P95.294 S243
G1 X169.8
M3 P94.118 S240
G1 X176
M3 P0 S0
G0 X176 Y195.9
M3 P94.118 S240
G1 X169.8

Here is my nc file if you want to try it with an adjusted feed rate etc

GraySquare_3000hx100.nc
https://littlebox.space/wl/?id=z386yo6c0bhWvQUpds4hFnuzRsqQuEvz

GraySquare_300hx16.nc
https://littlebox.space/wl/?id=ShqJEEPsLfObSilOtIJyfx1sbtLuMZzb

Oh. Found that first print of GraySquare_3000hx100.nc

The failure was that the laser simply didn’t have enough power at a feed rate of 3000 to burn. It did however engrave slightly. I may have been out of focus considering yours burned fine at a feed rate of 10000.

@Tone played around with achievable movment speeds:

So I am not sure what my GCode in the end resulted in in terms af true speed. I assume I was far away from max speeds, since my GCode does 5mm chunks, so accel and deccel settings will basically always kick in.
I’ll try your GCode at some point, but due to time restrictions unfortunately not in the near future. Still, thanks for sharing!!!

On PWM: I’d say I am 99% sure they do stupid software PWM. Depending on which MCU pin they attached the laser driver to, this may or may not be changed to hardware PWM by a head firmware update (never thought about this: Can toolhead firmware be updated through standard means…?). And of course it may be that the laser manufacturer gives upper limits to how fast you may switch the laser on and off. I never digged into the intricacies of laser diodes - can they be driven like normal LEDs? In that case, I’d say kHz PWM should not be a problem, and the MCU should be able to deliver that…

All of this talk got me wondering. My image and my failed print both had some successful burns. I thought about the accel and deccel being the culprit of the burns that were successful like the lines in the 300mm/min x 100% power image in my last post. I ran a test.

G1 F10000

G1 X0
M3 P100 S255
G1 X10
M3 P50 S127.5
G1 X20
M3 P25 S63.75
G1 X30
M3 P50 S127.5
G1 X40
M3 P100 S255
G1 X50
M5

G1 X0
G1 X10
G1 X20
G1 X30
G1 X40
G1 X50

When I ran at 300mm/min, the accel and deccel was negligible but this test very clearly showed that it does indeed stop each time it changes the laser power, but not at all in the second where there is not a command between the moves. This explains why the lines were able to burn in the grey squares but not the rest of the print at 3000 mm/s.

When I was modifying LaserGRBL I noticed it expected to be able to do something like G1 X10 S255 where the adjustment to the laser power was interpreted with the move. I assume this was to avoid this unintended side effect… so on top of the possible PWM problem, we might want to inquire how to better accomplish this or request a change to the firmware to accept these commands. @staff

Anyway I will likely deviate from this to the router tool which is the main reason I bought the machine. Ha.

Aside: Does anyone know if there is a github page, etc for the firmware?

Great finds! The firmware is posted here: FYI:Source code of Snapmaker Firmware. They’ve promised to properly put it on GitHub once they’ve had a chance to make proper documentation.

Setting up Lightburn i run into general questions…

Is there a difference between a CH340 port mentioned in the post of @voidoids on the LightburnForum, and the CH341 downloaded from the snapmaker downloads page ? (or does the 341 have to do with mac…) I get a cu.wchusbserial1410 as port ? Previously having selected the Snapmaker Icon from the machine list.

Is this correct or should i rather go for one of the GBRL icons?

I do not get the homing option.

@MadHatter Hello, and thank you so much for your interest in this matter, it is exactly what my conundrum entails.
I have been away for a few weeks, taking a break from this, and now I see your additions here. Truly wonderful to see the progress you have made so far! Can’t wait to give it a whirl!
But as I was reading this, one concern lingered in the back of my head. Acceleration and desceleration! I noticed the burns on the failed (3000mm/s haha) and recognised them immediately.
I think with higher power, a little more speed and acceleration tweaks, this can indeed go alot faster!

I don’t think we can alter acc/desc setting with gcode, can we? Per line of sintering would start accelerating to top speed, turn off acceleration settings until EOL. If possible…

Would love to pick your brain on this matter…

FYI for @Zet and y’all to see his post Laser dropouts failure which seem to touch on similar findings around acceleration.

@Galduron @halr9000 My assumption is that the laser simply isn’t powerful enough to run that fast, especially for certain materials. My laser was set at 100% power for the failed run. The simple solution is to go slower.

As for the acceleration and deceleration, I don’t believe this is a setting but rather a limitation of the machine. For instance a car might be able to go 200mph, but it might take 30 seconds to reach that speed.

So if your burn only succeeds when the laser is starting and stopping, then that’s a pretty good indication that the burn will only succeed at a lower speed.

It would be nice if the machine could interpret the next movement command without stopping somehow though.

As an aside, I’m tinkering with the CNC module for now so won’t be tinkering with this for a while. Then will probably want to work with the 3D printer for a bit, but I’ll be interested if any of you guys find anything else.

Best of luck!

2 Likes

Hi folks,

remember my assumption above that the Laser does Software-PWM? I think the open sourced firmware supports my assumption:

In Snapmaker2-Modules/Marlin/src/module/laser_head.cpp:

void LaserHead::Init() {
  this->fan_.Init(LASER_FAN_PIN);
[...]
}
[...]
void LaserHead::HandModule(uint16_t func_id, uint8_t * data, uint8_t data_len) {
  uint8_t focus_type;
  switch (func_id) {
    case FUNC_SET_FAN:
      this->fan_.ChangePwm(data[1], data[0]);
      break;
[...]

So it uses the fan class for controlling the laser PWM. Let’s see in Snapmaker2-Modules/Marlin/src/module/laser_head.h where the fan class is defined:

#include "src/device/fan.h"
[...]
class LaserHead : public ModuleBase {
 public:
  void Init();
  void HandModule(uint16_t func_id, uint8_t * data, uint8_t data_len);
  void Loop();
  void EmergencyStop();
  void LaserSaveFocus(uint8_t type, uint16_t foch);
  void LaserReportFocus(uint8_t type);
  Fan fan_;
  SwitchOutput camera_power_;
};

OK, now lets look in Snapmaker2-Modules/Marlin/src/device/fan.cpp:

void Fan::ChangePwm(uint8_t threshold, uint16_t delay_close_time_s) {
  this->delay_close_time_ = delay_close_time_s * 1000;
  if (threshold == 0) {
    this->delay_start_time_ = millis();
    this->delay_close_enadle_ = true;
  } else {
    this->delay_close_enadle_ = false;
    soft_pwm_g.ChangeSoftPWM(this->fan_index_, threshold);
  }
}

And there we have it :frowning: Software-PWM… darn

EDIT: I searched a bit on the internet for spec’s for laser diodes and if they have some limits which may justify slow PWM. On the contrary: It is not unusual to run a laser diode on ~10 kHz PWM. So room for improvement here…

EDIT EDIT: You might wonder why it is “LASER_FAN_PIN” - is this perhaps the routine to control the fan in the laser module? There’s a chance that this is the case, but I do not believe so. There is a) no other function in the module that might set laser power, b) the fan in the laser head would not need PWM control (its either on or off), and c) for the laser head fan you would most likely not need this function:

void LaserHead::EmergencyStop() {
  fan_.ChangePwm(0, 0);
}

On the contrary: Even if the laser emergency-stops, you’d want the cooling fan to keep running until the laser is cooled down to safe levels… So there’s room for me being wrong (there always is :slight_smile: ), but I think it likely that my deduction is sound…

No, it’s hardware pwm from the controller.

Ah, I get it - some of the code is on the module’s MCU, some remains on the main controller. OK, remains the question to what frequency/divider/prescaler is Timer 1 set… But that’s cool, it means that at the point where you’ve figured out how to compile and flash modified firmware, there’s a chance to adjust this!

Thanks for correcting my error!

Hmm… in Snapmaker2-Controller/Marlin/src/HAL/HAL_GD32F1/HAL_LaserPwm_STM32F1.cpp:

void Tim1PwmInit() {
  [...]

	//100HZ  ,255  Level
  #if(0)

  [...] 

  GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
  [...]
  #endif

	TIM_TimeBaseInitStruct.TIM_ClockDivision = 0;
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStruct.TIM_Prescaler = 1862;//959;//1862;//1344;
	TIM_TimeBaseInitStruct.TIM_Period = 255;
[...]

The comment does not bode well - 100Hz. I do not claim I understand all fully, but I’d infer: GPIO speed = 50 MHz, Prescaler 1862, Period 255 → 50.000.000 / 1862 / 255 = ~105 Hz indeed.
But perhaps I should stop writing stupid stuff before I did not fully understand the code…

I agree with 100hz, I’m also not an expert at this

Rather than varying the laser intensity, we could look to vary the dwell time between min/max values per dot to produce a discrete set of tonal colors. I.e. for printing grayscale on cardboard at some laser power level, we could possibly say a min of 2ms dwell (lightest detected burning) - 10ms (black) could then be used to support 8 tonal colors, and when combined with dithering might produce a higher dot density with truer grayscale rendering.

Granted we’d need a new dithering algorithm and then would have to do sample prints to determine min and max dwell times to obtain the number of tonal steps that could be produced, and carry those settings over to the luban processing area.

1 Like

I’m trying your modified version of LaserGRBL but can’t get acceptable results. Can you please tell me what settings should I have in the software to generate a correct nc file?
I’ve set Marlin code variant (is that correct? Cannot find anywhere what Snapmaker is using for laser) and line mode with M4 (as my test with M3 is worser). Please, can you point me in the good direction?

Snapmaker does use Marlin, that is correct. I haven’t tried @MadHatter 's method, so I’ll let him comment on the rest, but if you are looking for “true” grayscale, I would suggest looking at the following thread:

It seems that the problem is that Marlin stops movement when it changes the laser power (as seen in MadHatter’s failed test where only the borders were engraved). @brent113 and @MrWorf have made modified firmware that enables a relatively new feature in Marlin that allows the laser to continue moving while changing power, allowing for more pure grayscale.

I would recommend checking out the thread if you’re interested. And of course, any firmware downloaded and installed from a third party is at your own risk.

Thank you @bobby4718 that was interesting. I could print with LaserGRBL and with Lightburn (using the trial) but both have white banding when laser power changes, like said in that thread.
I’m not so prone thinking to change the firmware for two reasons:

  1. I suppose that warranty will be gone if something will not work as expected
  2. The result of grayscale like generated by both software is while line is moving, generating low resolution in x axis

I was thinking that a better result should be achieved with points using dwell time like Luban is doing BUT modulating the laser power for every point.
That would be waaaaay longer but should be much better results for photos, that’s what I’m searching.

Anyone know of there is a software that can generate that kind of gcode (grayscale using dwell time)? Otherwise I’ll have to write down a software in .net to do it… :wink:

I completely understand not wanting to use non-official firmware. I don’t currently know of software that does what you’re suggesting, but I would be curious if someone else does or if you end up creating your own.