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

SET_PIN not usable for laser engraving #133

Closed
GitHub1712 opened this issue Jan 21, 2018 · 48 comments
Closed

SET_PIN not usable for laser engraving #133

GitHub1712 opened this issue Jan 21, 2018 · 48 comments
Labels
enhancement resolved Issue is thought to now be fixed

Comments

@GitHub1712
Copy link

GitHub1712 commented Jan 21, 2018

Using SET_PIN for laser raster engraving is very slow.
Same code runs much faster on marlin using m42 instead of SET_PIN.
Attached gcode to test.
Removing m400 will make execution asynchronous.

klippy.log

KlipperRasterTest.zip

@KevinOConnor
Copy link
Collaborator

KevinOConnor commented Jan 21, 2018 via email

@KevinOConnor
Copy link
Collaborator

It's worth noting that the SET_PIN command was not intended as a mechanism for high speed updates. A SET_PIN command has a minimum time of 100ms - if multiple commands are sent within a smaller window, then the subsequent commands will be delayed so that each pin setting is active for at least 100ms.

This behavior is due to how commands are buffered between host and micro-controller. Things like step times are buffered on the micro-controller, and hundreds of thousands of them can be queued. However, pin updates have a very small queue on the micro-controller (no more than 1 update) and instead most of the queuing is done on the host. So, there would need to be development work necessary to make high speed arbitrary pin updates with precise timing work.

-Kevin

@GitHub1712
Copy link
Author

GitHub1712 commented Jan 21, 2018 via email

@KevinOConnor
Copy link
Collaborator

KevinOConnor commented Jan 30, 2018 via email

@KevinOConnor KevinOConnor changed the title SET_PIN slow SET_PIN not usable for laser engraving Jan 30, 2018
@lucashpandolfo
Copy link

I've been reading some code but I don't think I'm understanding this correctly.
Let's see. For each pin a oid object containing the pin info is created in the MCU. This oid object is the one being queued/scheduled (at least it holds a timer) and thus it cannot be scheduled more than once?

Is that it?

So when my log shows things like the thing below and tries to schedule the same pin 4 times in a row it messes something up?

Sent 95 13602.031433 13602.030873 14: seq: 14, schedule_soft_pwm_out oid=4 clock=2274294805 value=256
Sent 96 13602.045151 13602.044631 13: seq: 15, schedule_soft_pwm_out oid=4 clock=2274534805 value=0
Sent 97 13602.061034 13602.060474 14: seq: 16, schedule_soft_pwm_out oid=4 clock=2274774805 value=256
Sent 98 13602.075648 13602.075128 13: seq: 17, schedule_soft_pwm_out oid=4 clock=2275570795 value=0

I think I'm getting it wrong :P

@KevinOConnor
Copy link
Collaborator

KevinOConnor commented Jan 30, 2018 via email

@lucashpandolfo
Copy link

Sorry to bother you again.

As earlier, the way I would address it would be to allow more than one
scheduled event to be stored in the mcu, thus avoiding the slow "drip
feed" issue.

I've been fiddling with the code, and have modified the schedule_digital_out command, so now it's possible to schedule several events of this type. It works, but...

Because the mcu schedule_soft_pwm_out command can only schedule one
event at a time, the host will only send one event at a time to the
mcu. The host waits until the last event is finished before sending
the next.

This is what has been bothering me for the past few days. I can now have several commands of this type scheduled, but it won't do anything different because of this limit. Where in the code is that 'send only one event at a time and wait for the response'?

I think the problem is that I'm not understanding how the serialqueue works.

Some questions that may (or may not) help me understand.

  • What does the stalled_bytes of serialqueue means?
  • I see there are 4 alloc_command_queue (endstop, digital_out, pwm and adc). Each one of this queues have their own bg thread, and each one takes turns writing to the serial_fd in turns. Does it really work that way? I fell I'm misundestanting/missing something.
  • In the micro controller, command_find_block reads the serial port messages and then sends the ack inmediatly back to the host. So the host code could never know when said command finished executing. Is this correct?

@KevinOConnor
Copy link
Collaborator

KevinOConnor commented Feb 19, 2018 via email

@KenDodman
Copy link

Has there been a solution at all for this? I've been using klipper as is for cutting for abit now, and find its works ok under 300mm/min but would love to run at 10 times that speed.

@petervanderwalt
Copy link

+1 for laser support please

https://github.com/gnea/grbl/wiki/Grbl-v1.1-Laser-Mode
https://github.com/Smoothieware/Smoothieware/tree/edge/src/modules/tools/laser

Some important features that's must have

Proportional laser (M4 mode in grbl, on by default in smoothie) scales PWM power according to acceleration to prevent darker burns during (ac/de)celleration
G0=laseroff move, G1=laseronmove (Makes gcode generator more efficient, no need for m3/m5 on every segment / change etc
PWM freq configurable (we found that between various diode drivers and CO2 driver, it helps to tweak pwm freq for a better linear response. CO2 PSUs seem to like a 1khz, whereas some of the chinesier diode drivers need 30khz, etc)

@petervanderwalt
Copy link

Just checking in, if we are any closer yet?

@KevinOConnor
Copy link
Collaborator

I'm not aware of any progress on this topic. I don't have any short term plans to work on this myself.

-Kevin

@ghost
Copy link

ghost commented Aug 19, 2018

How about changing the interface between host CPU and MCU/s with 2 x SPI for fast communication ? Another way might be porting the MCU code on the CPU as process or on a co-processor. Allwinner H3 (Orange Pi, NanoPi NEO , ...) has AR100 co-processor and this seems to be done in LinuxCNC + Orange Pi project (https://github.com/orangecnc), ARISC firmware for making a real-time GPIO manipulations (https://github.com/orangecnc/h3_arisc_firmware).

@ghost
Copy link

ghost commented Dec 29, 2019

Does this mean that if only one pin change is issued, this pin change will occur immediately after the previous move has finished, but any subsequent pin change will occur at least 100 ms later?

I need to send out one pulse at a very precise position within the g-code, without interrupting the rest of the g-code. Is that possible?

@KevinOConnor
Copy link
Collaborator

The current code supports scheduling of pin updates at very precise times. However, it does not support queuing of multiple updates on the micro-controller - thus one can write python code to arrange for a pin to be set at an arbitrary time, but in practice the next update has to be ~100ms or so in the future.

-Kevin

@webers89
Copy link

Is there anyone who has found some solution for laser control? I want to make SLS printer.
I have an idea that may be it would be possible to connect laser ON/OFF pin to extruders Enable PIN? How fast can it change PIN state? Does it still has this 100 ms limitation?
Then it would be necessary to add code that extruder is disabled after each move or each time when G0 command is received and activated each time when extruder is moved (E values).

@Cirromulus
Copy link
Contributor

A faster PIN-Operation on any digital out pin is possible on this experimental branch, but be aware that it will not be continued (more on that at #3338 and #3515).

@webers89
Copy link

webers89 commented Mar 26, 2021

I am converting stepper pulses to analog voltage and then I am using arduino to calculate necessary power to PWM range.

Arduino sketch reads FAN pwm output from Klipper and using map function based of extruders step pulses adjusts power.
Additionally if there is any signal in extruder it activates digital output which controls lasers ON/OFF signal.

@Cirromulus
Copy link
Contributor

Completely different idea: How fast can the pins on the host be controlled? I could wire the laser power input directly to the Pi and output the PWM signal there, but if the same restrictions apply to the host driver, that won't work.

I suppose that the PI will be able to drive this pretty fast, but never as accurate as the MCU can do it.
This is why realtime-tasks are not done by the klipper host software, but scheduled.

The best solution imo would be to implement something like Marlin has, where laser power can be specified per move, so the output power is automatically adjusted to acceleration. They call it "inline laser power" and I had spectacular results with it:

This is on my roadmap. This will not only add a proportionality, but also reduce the GCODE-bottleneck.

Currently, I am finalizing #3995, after that comes the integration of fast pwm scheduling.
I don't think that there is a need for overcomplicating things when our Klipper/MCU combination is well capable of everything we need. Judging by the benchmarks, I am confident that laser updates can reach the range of 100k-500k updates per second, surpassing every other printer/laser-firmware I know of.

@TazerReloaded
Copy link

Cool, I'll wait for the implementation of PWM scheduling then!
I already wrote my own little "slicer" for images, so syntax adjustments are not an issue (still working on minimizing GCode output).

Might build a little ATtiny-based step-to-pwm-converter if I have time, but configuring an additional extruder also takes up lots of pins, I'll have to check if I have enough.

@kingjamez
Copy link

Completely different idea: How fast can the pins on the host be controlled? I could wire the laser power input directly to the Pi and output the PWM signal there, but if the same restrictions apply to the host driver, that won't work.

I suppose that the PI will be able to drive this pretty fast, but never as accurate as the MCU can do it.
This is why realtime-tasks are not done by the klipper host software, but scheduled.

The best solution imo would be to implement something like Marlin has, where laser power can be specified per move, so the output power is automatically adjusted to acceleration. They call it "inline laser power" and I had spectacular results with it:

This is on my roadmap. This will not only add a proportionality, but also reduce the GCODE-bottleneck.

Currently, I am finalizing #3995, after that comes the integration of fast pwm scheduling.
I don't think that there is a need for overcomplicating things when our Klipper/MCU combination is well capable of everything we need. Judging by the benchmarks, I am confident that laser updates can reach the range of 100k-500k updates per second, surpassing every other printer/laser-firmware I know of.

IMO, if this is able to implemented, there will be no better option for laser engravers / cutters. Almost every engraving system today is limited by processor speed. I was in the middle of building an arudino based Z-axis height to PWM converter, but will also now wait for this to arrive. I'm not (yet) able to develop on Klipper, but will be a happy tester when needed. I've got both a Co2 laser and a diode laser.

@Cirromulus
Copy link
Contributor

I'm not (yet) able to develop on Klipper, but will be a happy tester when needed. I've got both a Co2 laser and a diode laser.

I would be happy if you could test #4128. Questions regarding the Hardware-Setup and in general are welcome, so that we can adapt the how-to file to being more understandable.

@TazerReloaded
Copy link

I tested #4128 today, works quite well with my setup.
Hardware:

  • Raspberry Pi 3B, default clock
  • BTT SKR 1.4 100MHz
  • Some generic 1.3W diode laser with PWM input

Fastest feed rate I tested so far was 50mm/s, resolution 0.1mm. Above that I sometimes get "Timer too close", but I'm not sure when exactly, going to test that the next days.
So far the results are very promising:
IMG_20210420_214124185

You can also try my image to GCode converter here if you want. 100% JS, no server-side code, feel free to download and modify the script!

@Cirromulus
Copy link
Contributor

I would prefer if we could continue discussing the quirks of #4128 inside the merge request.
I will update some fixes that may reduce the problems on other systems.

Btw: I love this goofy Hamster in Tuxedo :)

@fedetony
Copy link

fedetony commented Jun 4, 2021

You can emulate a Laser PWM better with a servo than with an extruder. Stepper motors are controlled with number of pulses, yet for servo control the Frequency of the signal is fixed and the duty cycle varies.
"Servos accept a common control signal, a square wave with a repeat frequency of 20ms and an on period of 1ms (5%) to 2ms (10%). It is the width of the on pulse that indicates what angle the servo should be at." info from here
Just notice that the servo will be running at 50Hz PWM

[servo Laser_servo]
pin: yourpin
#   PWM output pin controlling the servo. This parameter must be
#   provided.
maximum_servo_angle: 1000
#   The maximum angle (in degrees) that this servo can be set to. `The`
#   default is 180 degrees.
#   Put here your Desired Range (laser Grbl 1.1 uses S1000 as default)
minimum_pulse_width: 0.001
#   The minimum pulse width time (in seconds). This should correspond
#   with an angle of 0 degrees. The default is 0.001 seconds.
maximum_pulse_width: 0.199 
#   The maximum pulse width time (in seconds). This should correspond
#   with an angle of maximum_servo_angle. The default is 0.002
#   seconds.
# 99%, give it 1ms loss
initial_angle: 0
#   Initial angle (in degrees) to set the servo to. The default is to
#   not send any signal at startup.
#initial_pulse_width:
#   Initial pulse width time (in seconds) to set the servo to. (This
#   is only valid if initial_angle is not set.) The default is to not
#   send any signal at startup.

Edit:
after running it it had the following error: :(
Recv: // Option 'maximum_pulse_width' in section 'servo laser_servo' must be below 0.02 Recv: // Once the underlying issue is corrected, use the "RESTART" Recv: // command to reload the config and restart the host software. Recv: // Printer is halted Recv: !! Option 'maximum_pulse_width' in section 'servo laser_servo' must be below 0.02 Recv: ok
yet works with:
minimum_pulse_width: 0.0001
maximum_pulse_width: 0.0199

@Cirromulus
Copy link
Contributor

You can emulate a Laser PWM better with a servo than with an extruder.

I would suppose using actual PWM instead of servo-PPM.
PPM is built to always have an on- and off-position, so neither all-zero nor full power would be reachable this way.
The output_pin section is built for that.
E.g.:

[output_pin TOOL]
pin: !ar9       # use your fan's pin number
pwm: True
cycle_time: 0.001
shutdown_value: 0

@DickyMcCockpants
Copy link

DickyMcCockpants commented Jan 14, 2022

I must beg the question, why not use an extruder step pin? It would be an ideal drop-in replacement and would be higher resolution than traditional pwm since it would function like a one bit DAC sampling up to your max "step rate", which should be in the khz range while maintaining perfect synchronization with position axis.

In your G-code you would set the extruder axis position for laser cutting moves based on the strength of laser cut desired and distance of the move to compute an E value approximating the total power disbursed during the move. The motion control of klipper should evenly apply the total power across the move. (Turn off pressure advance! Using relative extrusion would probably be smart.)

I haven't worked with lasers much but I think if you set the extruder stepper pulse time to match the laser's pwm/pulse requirements it should generate an appropriate signal.

To sum up my point, an 8 bit avr ramps board will have no problem driving an extruder stepper pin at over 50khz while doing the same on the coordinated x and y axis steppers. (I was able to run my delta at 170mm/s at 400s/mm so ~68khz on 4 simultaneous axis, with just 3 axis it could probably even run faster, although the few lasers I looked at maxed out around 9khz.)

If you wanted to do true pulse width output the square stepping option used for tmc drivers could be used if it was modified to always set the signal low when stopping, but I think for fast pulsing diode types ("fiber laser") the traditional fixed time, adjustable frequency ("dumb" stepper) pulse output is ideal.

@Cirromulus
Copy link
Contributor

An extruder step pin would be ok. The downsides for me are:

  • No plug and play: A hardware translation from the "kind-of-ppm" to PWM would be necessary
  • No easy to use software: Existing laser CAM softwares (I know of) export either M3 or G0 Sx format. A sophisticated post processing step would be necessary
  • (Personally) I find it weird mis-using the Stepper pins when conceptually the MCU is able to drive a PWM-Pin with the benefit of added safety features
  • My PR already works for most workloads (OK, I agree this is a weak point)

I don't know about the square driving of TMC-drivers. But all Lasers I know have a fixed powersupply with TTL control, anyway.

I haven't worked with lasers much but I think if you set the extruder stepper pulse time to match the laser's pwm/pulse requirements it should generate an appropriate signal.

I would be glad if you could submit a working setup, then we can compare the approaches.

@HWiese1980
Copy link

How's it going here? Would love to see the feature in Klipper

@Sineos
Copy link
Collaborator

Sineos commented Mar 31, 2022

@bk227865
Copy link

bk227865 commented May 20, 2022

Do i need to install updated firmware to try this out ? Or just checkout from git

@Sineos
Copy link
Collaborator

Sineos commented May 21, 2022

Do i need to install updated firmware to try this out ? Or just checkout from git

You would need to "cherry pick" the PR. Got to your klipper folder and issue following commands:

git fetch origin pull/4128/head:pr-4128
git checkout pr-4128
sudo service klipper restart

If you want to return to the default master:

git checkout master
git branch -D pr-4128

Last command just deletes the PR branch. Only needed if you want to.

@TazerReloaded
Copy link

You also have to build and flash the firmware to all MCUs, otherwise they won't understand the sync_channel commands.
If you go back to master, just build and flash the firmware from master again.
Moonraker should be compatible for some time, if not you'll have to checkout an older version there too, roughly matching the time this PR was last updated.

@bk227865
Copy link

bk227865 commented May 22, 2022

Ok i tried it ,
Would my assertion be correct that i cannot change the cycle_time component anymore ?
Even on non "high throughput" pins ?
something like "SET_PIN PIN=BEEPER_pin VALUE=0.5" works,
but if i do "SET_PIN PIN=BEEPER_pin VALUE=0.5 CYCLE_TIME=0.002" it locks up.
That would break my M300 macro :(

@Cirromulus
Copy link
Contributor

Cirromulus commented May 22, 2022

Would my assertion be correct that i cannot change the cycle_time component anymore ?

This should not be the case.
My changes only affect the pin in high throughput Mode.
Can you provide a logfile and Info about your Setup in the PR's issue? Also, did you Re-Flash your MCU to rule everything out? (#4128)

You also have to build and flash the firmware to all MCUs, otherwise they won't understand the sync_channel commands

This is not true since the queue_pwm commands were already merged. The only way the reflash is needed is when between the head of my PR and Master were additional changes made to the MCU Code. (which is possible, though. I do not follow the Master too close currently).

@HWiese1980
Copy link

Okay, since it has been a while since you posted last here, @Cirromulus, would you mind giving a short status report on this issue? Would be greatly appreciated.

@Cirromulus
Copy link
Contributor

See #4128 or on the discourse topic.
Feel free to try out the PR and report your success (or, hopefully not but more interestingly, bugs) to the PR discussion. This will help gaining more traction.

@HWiese1980
Copy link

Okay, so this issue is not the single source of progress information anymore, I suppose? Which one do you prefer? Discourse or #4128?

@Cirromulus
Copy link
Contributor

Well, klipper has grown to be a big project with many people. This Issue is the single most old one here - so policies changed during its lifetime.

Comments here should regard this actual issue. (What is needed, alternative solutions, general interest in having this feature).
I am personally involved as I propose one solution - the Pull Request #4128.
Topics discussed there should be focused on the code change itself, meaning the technique and the way it was implemented. Especially bug or success reportings should go there.

General discussions, as in "Where do we want to go from there" and "What software do you use for generating G-Code of Lasers, what Macros/Printers" should be done in the discourse topic, as this is more in a conversational/forum context.

@c---
Copy link

c--- commented Jan 19, 2024

I assume this issue is or will be resolved with #6369?

@KevinOConnor
Copy link
Collaborator

Yes, it is thought this issue is now resolved.

-Kevin

@KevinOConnor KevinOConnor added the resolved Issue is thought to now be fixed label Jan 19, 2024
Copy link

This ticket is being closed because the underlying issue is now thought to be resolved.

Best regards,
~ Your friendly GitIssueBot

PS: I'm just an automated script, not a human being.

rogerlz added a commit to Piezoid/klipper that referenced this issue Jan 28, 2024
@github-actions github-actions bot locked and limited conversation to collaborators Jul 24, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement resolved Issue is thought to now be fixed
Projects
None yet
Development

Successfully merging a pull request may close this issue.