Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FR] Handle M3/M5 in planner blocks #11576

Closed
SmarteedCS opened this issue Aug 17, 2018 · 36 comments
Closed

[FR] Handle M3/M5 in planner blocks #11576

SmarteedCS opened this issue Aug 17, 2018 · 36 comments
Labels
F: CNC / Laser T: Feature Request Features requested by users.

Comments

@SmarteedCS
Copy link

Hi everyone,
I'm currently trying to setup the firmware for my laser engraver.
It's working pretty good with fan M106 P0 commands, but I thought enabling SPINDLE_LASER_ENABLE can be a good idea to have M3 and M5 commands.
So i remapped my pwm pin to SPINDLE_LASER_PWM_PIN , configured SPINDLE_LASER_POWERUP_DELAY and SPINDLE_LASER_POWERDOWN_DELAY to 5ms ( it has to be as close as possible to 0 ..).
The laser wiring and pin remapping is OK, the laser fire when it has to but each time a M3 or M5 command is executed, a long pause is achieved ( I have nothing to measure this but maybe 200ms ).

I tried V1.1.9 and V2.0 firmware, it's the same behavior for both of them. I even tried to comment all "delay_for_power_down()" and "delay_for_power_up()" call of the gcode_M3_M4 function on marlin_main.cpp and that have no effect.

I will go back to M106 commands, but it can be a really good point if this can be fixed ..

I'm running marlin on ramps 1.4 with atmega2560.

It can be reproduced by running this two different "sample" gcode:

G0 F6000

G0 X50 y50
M3 S50
G0 X60 y60
M5
G0 X50 y60
M3 S50
G0 X60 y50
M5

G0 F6000

G0 X50 y50
M106 P0 S50
G0 X60 y60
M106 P0 S0
G0 X50 y60
M106 P0 S50
G0 X60 y50
M106 P0 S0

@drgrandios
Copy link

I have the same problem - unfortunately this breaks especially grayscale engraving which continuously needs to modify the laser output power.
I also removed the delay_for_power_up/down functions from the source code but this has only a small effect.

Reason for the interrupted moves seems to be the call to "planner.synchronize" - of course, this is necessary to wait for the laser power change until the current moves end. But it leads to stuttering moves (and each time the laser stops moving or is slowed down, it obviously burns a deep mark into the material). This might not be a problem for a spindle, but for a laser it surely is.

In contrast, M106 commands plan the fan power for the next move "block". This should also be the case for M3 commands.

@thinkyhead
Copy link
Member

thinkyhead commented Nov 7, 2018

We have a laser overhaul planned, generalizing to more types of lasers such as those that require a 25KHz base frequency, allowing more freedom in the use of PWM-capable pins, making sure it works well with all our 32-bit boards in addition to AVR, and requiring M452 intentionally selecting laser tool mode.

@drgrandios
Copy link

Maybe this should be commented somewhere here:
http://marlinfw.org/docs/configuration/laser_spindle.html

At the moment it is not a good idea to use the laser/spindle configuration (at least not for an engraving laser). Selecting one of the PWM pins described there, assigning them to a fan pin and using M106 commands is currently the best option.

@thinkyhead
Copy link
Member

The website is also open source. https://github.com/MarlinFirmware/MarlinDocumentation
Go ahead and submit any changes you think would be helpful.

@drgrandios
Copy link

Here you go: MarlinFirmware/MarlinDocumentation#186 ;-)

@manofmanyhats
Copy link

[ If this not the right place to post such a comment - please advise and I will move it ]
I'm trying to setup a new laser system using RAMPS/MEGA2560. The linked page http://marlinfw.org/docs/configuration/laser_spindle.html is a bit confusing to me...
I understand that I can allocate a pin to FAN1_PIN (I would choose D6), and I could then control the output power of my laser PSU by using the M106 P1 Sxxx command. All good so far.
Carrying on reading, I can see that I can define a pin for SPINDLE_LASER_ENABLE_PIN (I would choose D5), and this would go to the enable input of my laser PSU.
It is also suggested that I define a pin for SPINDLE_LASER_PWM_PIN. This is where my confusion lies - Haven't I already defined a pin to use for the PWM in the first step?
Do I need to do this as well?
Thanks

@drgrandios
Copy link

At the moment you should ignore the whole "LASER_SPINDLE..." part. Only use FAN1_PIN and M106 commands.

The laser/spindle options configure M3/M5 commands which are currently broken (at least for laser usage). See initial posts of this issue.

@SmarteedCS
Copy link
Author

SmarteedCS commented Nov 26, 2018

After a bit of work on the software, I finally have a good result with a modified 1.1.9 version. I'm currently able to run a 40w co2 laser engraving pretty small shapes accurately at 6000mm/min.
Here is a description of the changes I made:

  • First, to minimize how much the head stop when engraving fast, I set BLOCK_BUFFER_SIZE to 32.
  • To synchronize fan speed adjustment with block movements, I removed "planner.check_axes_activity();" from Marlin_main.cpp and add planner.buffer_sync_block(); at the end of M106 and M107 command (the function planner.buffer_sync_block(); seems to insert an empty block in the buffer).

I found the function that is called at the end of a block, this is "discard_current_block()" in planner.h.

At first, I called the check_axes_activity(); at the end of this function, but the function seems to do too much and it resulted in quickly stopping the head at each block end. So I wrote a simplified function that only take care of the fans and call it at the end of discard_current_block():

void Planner::UpdateFan(){
    unsigned char axis_active[NUM_AXIS] = { 0 },
                tail_fan_speed[FAN_COUNT];
    if (has_blocks_queued()) {

    #if FAN_COUNT > 0
      for (uint8_t i = 0; i < FAN_COUNT; i++)
        tail_fan_speed[i] = block_buffer[block_buffer_tail].fan_speed[i];
    #endif

  }
  else {
    #if FAN_COUNT > 0
      for (uint8_t i = 0; i < FAN_COUNT; i++) tail_fan_speed[i] = fanSpeeds[i];
    #endif
  }
     #if FAN_MIN_PWM != 0 || FAN_MAX_PWM != 255
      #define CALC_FAN_SPEED(f) (tail_fan_speed[f] ? map(tail_fan_speed[f], 1, 255, FAN_MIN_PWM, FAN_MAX_PWM) : 0)
    #else
      #define CALC_FAN_SPEED(f) tail_fan_speed[f]
    #endif

    #if ENABLED(FAN_SOFT_PWM)
      #if HAS_FAN0
        thermalManager.soft_pwm_amount_fan[0] = CALC_FAN_SPEED(0);
      #endif
      #if HAS_FAN1
        thermalManager.soft_pwm_amount_fan[1] = CALC_FAN_SPEED(1);
      #endif
      #if HAS_FAN2
        thermalManager.soft_pwm_amount_fan[2] = CALC_FAN_SPEED(2);
      #endif
    #else
      #if HAS_FAN0
        analogWrite(FAN_PIN, CALC_FAN_SPEED(0));
      #endif
      #if HAS_FAN1
        analogWrite(FAN1_PIN, CALC_FAN_SPEED(1));
      #endif
      #if HAS_FAN2
        analogWrite(FAN2_PIN, CALC_FAN_SPEED(2));
      #endif
    #endif
}

So that way, if I really understand how planner work, each time a M106 or M107 command is received, a new empty block is added in the block buffer, and at each buffer end, UpdateFan check the new PWM value.

I know that it is a dirty workaround, so if any of you have better idea I will be really happy !! =)

@thinkyhead
Copy link
Member

thinkyhead commented Nov 26, 2018

What problem are you solving with this? The stepper ISR should already be updating the fan (laser) PWM as part of handling a block. The desired fan (laser) power simply has to be set before sending the next move to the planner, and the stepper ISR will set the new PWM value when it gets to that block. The only thing a sync block will do (if not actually being used to update the stepper positions) is to use up time and space in the planner queue.

@SmarteedCS
Copy link
Author

My problem was that the PWM update was not synchronized with the movement. From what I saw on my prints, the laser wasn't fired at the right time resulting in shifting the print at high speed. ( Maybe I have to put this "issue" in another thread ? ).
What I understand is that at high speed, the laser need to be fired at the exact position, so it has to be done when the movement block is completely done and before the next one start. So for me, the action of changing the laser power has to be done between those two action, that's why I tried to insert a "blank" block on M106 and M107 command.
Here is a photo of two tests with and without the workaround :
leworkaroundexplenation
(both are engraved at the same speed )
I don't know if the image is clear but without the workaround, the laser is fired and stopped to late. That's why I thought that movement and PWM updating were not synchronized.

@schme16
Copy link

schme16 commented Jan 2, 2019

Any news on getting the M3/M4 command delays sorted out? or is this a low priority at the moment?

@jeffeb3
Copy link
Contributor

jeffeb3 commented Feb 10, 2019

So, some users in the v1engieering.com forums, have been getting some fuzzy laser results using the fan solution, and they are on a modified version of bugfix-2.0. Ryan tracked it down to a change in Marlin.cpp that only updates the fan speed every 100ms. It's in this commit:
c140007

It went from this:
planner.check_axes_activity();
to this:

  // Limit check_axes_activity frequency to 10Hz
  static millis_t next_check_axes_ms = 0;
  if (ELAPSED(ms, next_check_axes_ms)) {
    planner.check_axes_activity();
    next_check_axes_ms = ms + 100UL;
  }

Reducing the speed of the fan updates seems smart, but not when someone has laser control on there. I think the solution from SmarteedCS was to basically start calling this from other places, which effectively increased the rate of the updates.

So what should the next step be?
a) revert this change and still use the fan stuff for lasers for now
b) Make this code a configuration option, and continue using fans for lasers
c) Make the stop/starting of the M3/M5 commands optional, so if it's a laser, it won't stop just to adjust the laser intensity.
d) Wait for the laser overhaul.

If users just did a) on their own, are there any obvious side effects?

@drgrandios
Copy link

drgrandios commented Feb 13, 2019

I'd love option c) as I am using Marlin on a multi-purpose 3D printer (laser oder 3D print via quick release head). But you would have to rewrite the whole M3/M5 behaviour cause it's completely different than M106.

Or option b) but allow configuration per fan (to be able to configure something like: first fan has the 100ms limitation, second fan is not limited). I guess this would be the easiest change.

@boelle
Copy link
Contributor

boelle commented Feb 20, 2019

@SmarteedCS is the problem still there with latest bugfix 2.0?

@TwatBurglar
Copy link

@drgrandios @SmarteedCS @jeffeb3 @boelle How are you guys driving your laser pin now? M3 or M106 (plus "fast fan update" revert as described above by @drgrandios)?

My other issue is getting more than 1khz on the PWM (laser needs ~20khz) with my Due board - does anyone have some wisdom on this?

@boelle
Copy link
Contributor

boelle commented Mar 6, 2019

@thinkyhead i think we can close this one

@drgrandios
Copy link

@thinkyhead i think we can close this one

Were there any updates on M3/M5 at all in bugfix 2.0?

From my understanding, the initial issue is not fixed at all, just documented. And according to @jeffeb3 bugfix 2.0 even needs modifications to have a working M106...

@boelle
Copy link
Contributor

boelle commented Mar 6, 2019

problem here is also that @SmarteedCS seems to have gone up in smoke or just lost interest in this

and why should marlin work on something where the creator of the issue is not active?

@schme16
Copy link

schme16 commented Mar 7, 2019

@boelle Because it's reasonably clear that others are still hanging on this item? (myself included)
If it helps make sure this doesn't get closed without resolution, I'm happy to test the latest 2.0 bugfix and report back as soon as I can

@TwatBurglar
Copy link

I agree, @schme16 ... this is somewhat of a showstopper for using a Laser - rastering is unusable with stock 2.0 (as evidenced by @SmarteedCS 's pictures above), and vectoring is no picnic - essentially laser power changes are delayed by a random amount between 0 and 100ms (10Hz update rate) - and my steppers can move a couple of mm in 100ms.

I did try @jeffeb3 's planner.check_axes_activity(); change above, and vectoring seems pretty good (haven't tried raster).

@DiverOfDark
Copy link

Obviously on 1 guy who complains and/or creates PR's with fix there are 10 who just struggling silently.
Please, do not close this, and make proper laser support in Marlin! (Or specify in docs that Marlin doesn't support laser engraving, only cutting(?))

Without patches included in this thread laser engraving is just not working in Marlin 2.0.

@InsanityAutomation
Copy link
Contributor

I agree this is something that will need attention. Its on the fringe of what Marlin supports though and is not a high priority item but should remain open until resolved nonetheless. Personally, I would put a target of 2.1 on it, since we want to get all the 32-bit hals stable before worrying about timing sync on a fringe device. No offense to those using it, but its not the primary focus and there are bigger issues.

@manofmanyhats
Copy link

In case anyone is too impatient (like me) for a fix for this, then GRBL: https://github.com/grbl/grbl works well with my laser cutter.

@DiverOfDark
Copy link

Obviously, GRBL would work for laser-only machines, but not for the 3d printer with a laser mounted next to extruder (like some hobbyist including myself did).
I'm just hoping laser engraving would get offical support in Marlin sometime, until then we have to apply patch from SmarteedCS or jeffeb3 manually each time building latest firmware for our printers.

@jeffeb3
Copy link
Contributor

jeffeb3 commented Mar 10, 2019

Even with the change, it's not quite as good as it could be. I think the fan speed code is still picking a fan speed from the future side of the buffer and it's still polling, just much faster. Engraving on wood is a non precise operation, but actually treating laser power as a motion command would be much better. Scaling laser power when motion slows down would be even better.

Someone needs to be interested and capable of doing it. There's no amount of begging that will get it done, unfortunately.

@thinkyhead thinkyhead changed the title Unexpected long pause on M3 M5 commands [FR] Handle M3/M5 in planner blocks Mar 10, 2019
@thinkyhead thinkyhead added the T: Feature Request Features requested by users. label Mar 10, 2019
@thinkyhead thinkyhead added this to the 2.1 milestone Mar 10, 2019
@InsanityAutomation
Copy link
Contributor

jeffeb3 agreed. It's not a minor undertaking since fan control would need quite a bit changed in the case of being set as a laser. One of the reasons my fan as laser feature concept awhile ago was left sitting. It is something on the edge of what I'd like to get done at some point, but too many other things open for people that support my work to go into it any time soon.

@jeffeb3
Copy link
Contributor

jeffeb3 commented Mar 10, 2019

I know almost nothing about the planner, but IMHO, the right way to fix lasers is to get them running on M3/M5 (fan pin or 5V pin, doesn't matter), but not dwell when there is a laser power command. That would be step 2. Step 1 is probably increasing the poll rate on the fan pin just to get things going with M106. Step 3 (are you still with me?) would be to make the laser power act more like a movement axis, and scale the power with the speed.

@MarcelMo
Copy link
Contributor

Wouldn't it be possible to pass S values with G commands ? So these values get written whenever the planned movements are executed ...

@eightheads
Copy link

I have started running into the pausing as well trying to run a TTL control diode laser with the M3/M5 commands. Lots of pausing with the laser still on... Not great for a laser

@thinkyhead
Copy link
Member

Don't use M3/M5. They are not for production use at this time. Use the M106/M107 method. See http://marlinfw.org/docs/configuration/laser_spindle.html

@eightheads
Copy link

That makes things difficult for those of us with TTL controlled lasers that need a 3.3-5v signal.

@jeffeb3
Copy link
Contributor

jeffeb3 commented Sep 17, 2019

You can change the pins to use a 5V pin.

@InsanityAutomation
Copy link
Contributor

Define laser enable pin as FAN1_PIN and the control as the second fan :)

@loadletter
Copy link

Personally to make the M106/M107 method usable with a small laser I've just increased the update rate from 10Hz to 200Hz.

According to #14934 this limit might not even be needed anymore.

@thisiskeithb
Copy link
Member

Since this is added in #22690, I'll close this FR.

@github-actions
Copy link

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.

@github-actions github-actions bot locked and limited conversation to collaborators Aug 28, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
F: CNC / Laser T: Feature Request Features requested by users.
Projects
None yet
Development

No branches or pull requests