-
-
Notifications
You must be signed in to change notification settings - Fork 5.4k
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
Comments
On Sun, Jan 21, 2018 at 04:03:58AM +0000, GitHub1712 wrote:
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.
It will be very slow if there are a lot of M400 commands in the file.
The M400 command instructs Klipper to completely wait for all activity
on the printer to stop.
If you're seeing an issue without the M400 commands, can you post the
log of a session without the M400 commands (but with the M112)?
…-Kevin
|
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 |
thank you for checking,
so thats a point better working with marlin. Many are attaching laser on 3d
printer. I think set_pin is something that should work fast.
I will try to get it working with extruder commands to controll the laser.
2018-01-21 6:57 GMT+01:00 KevinOConnor <[email protected]>:
… 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
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#133 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/ACA3huaDUQKYO-cPyH3PPFidduWuUWuqks5tMtHUgaJpZM4RlsDc>
.
|
In issue #152 Lucas wrote:
As the title says, the printer stops with a 'timer too close' error.
Now, before anything else, I should mention 2 things:
1. It's not 3d printing. It's laser engraving. I've attached a laser driver to the fan output and control the laser with M106 and M107 (only on and off, no power control)
2. I modified fan.py to make FAN_MIN_TIME = 0.
[...]
So, the thing is, this may not be a klipper bug as I'm using the fan output as something else, but is there a way to achieve what I'm trying to achieve here with klipper? (rapid fan on/off changes)
If not, is there something like a safe min time between pwm events? (less than the default 0.1 s)
Unfortunately, it doesn't seem that there is a simple python-only
solution to make Klipper compatible with laser engravers.
There are two major components in the Klipper system - the host code
and the micro-controller code. The host is responsible for building
the schedule of events and the micro-controller executes that schedule
at the specified times. Right now, the micro-controller is coded so
that it can store a schedule of 100K+ steps in its internal memory.
However, the micro-controller is not written to store more than a
handful of scheduled pin events.
This was done simply because on a traditional 3d-printer there's no
particular need to store more than a few pin changes in memory at a
time (as, stepper motors aside, there are no pins that rapidly and
repeatedly change).
If the laser needs to be able to reliably alter its settings with high
frequency and high predictability, then I suspect the best solution
would be to extend the micro-controller code to create a queue of
scheduled pin events - just as the micro-controller stepper code does.
Then, the host code could fill that queue of scheduled events instead
of its current mechanism (which is to buffer the events on the host
side). This type of change is a bit involved, however. It would
require python code changes, host C code changes, and micro-controller
code changes.
…-Kevin
|
I've been reading some code but I don't think I'm understanding this correctly. 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?
I think I'm getting it wrong :P |
On Tue, Jan 30, 2018 at 11:30:54PM +0000, Lucas wrote:
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?
Yes.
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
Very close. First, run your log through ./scripts/logextract.py (as
described in docs/Debugging.md). That will help cross index some of
the information in the log.
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. Eventually, this slow "drip feed" can't handle the number
of events and the mcu receives a request for a time that is in the
past. That results in a "timer too close" error.
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.
…-Kevin
|
Sorry to bother you again.
I've been fiddling with the code, and have modified the
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.
|
On Sun, Feb 18, 2018 at 01:00:03PM -0800, Lucas wrote:
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'?
It's in mcu.py:MCU_digital_out:set_digital() - it sets the next
requests minclock to the time of the last request. So, serialqueue.c
will not transmit the message until it believes the MCU clock is past
minclock.
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?
The stalled_bytes are the number of bytes that are queued in
serialqueue.c that can not yet be transmitted because their minclock
has yet to be satisfied. These are messages being delayed.
In contrast, the ready_bytes counter is the number of bytes stored in
serialqueue.c that have met the minclock. (These are messages that
are likely to go out in the next few milliseconds.)
- 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.
No - there is only one thread in serialqueue.c. The command queues
are just linked lists of commands to be sent to the MCU. It's done
this way to prioritize messages should there be a situation where
there are more messages to be sent than available bandwidth. So, for
example, if a PWM message needs to be received by clock 101 (a send()
with reqclock=101), a digital_out message needs to be received by
clock 999, and there is limited bandwidth, then we'll send the PWM
message first. Messages can be reordered wrt other command queues,
but messages can not be reordered within a given command queue.
- 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?
We don't release messages by acks. Instead, the code in clocksync.py
calculates a relationship between the MCU clock and the host clock.
The serialqueue.c code uses a conservative version of this host-to-mcu
clock prediction to determine when to release messages so that they
are never received at the MCU prior to their minclock.
…-Kevin
|
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. |
+1 for laser support please https://github.com/gnea/grbl/wiki/Grbl-v1.1-Laser-Mode 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 |
Just checking in, if we are any closer yet? |
I'm not aware of any progress on this topic. I don't have any short term plans to work on this myself. -Kevin |
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). |
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? |
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 |
Is there anyone who has found some solution for laser control? I want to make SLS printer. |
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. |
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 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. |
Cool, I'll wait for the implementation of PWM scheduling then! 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. |
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. |
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. |
I tested #4128 today, works quite well with my setup.
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. 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! |
I would prefer if we could continue discussing the quirks of #4128 inside the merge request. Btw: I love this goofy Hamster in Tuxedo :) |
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.
Edit: |
I would suppose using actual PWM instead of servo-PPM.
|
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. |
An extruder step pin would be ok. The downsides for me are:
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 would be glad if you could submit a working setup, then we can compare the approaches. |
How's it going here? Would love to see the feature in Klipper |
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:
If you want to return to the default master:
Last command just deletes the PR branch. Only needed if you want to. |
You also have to build and flash the firmware to all MCUs, otherwise they won't understand the sync_channel commands. |
Ok i tried it , |
This should not be the case.
This is not true since the |
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. |
See #4128 or on the discourse topic. |
Okay, so this issue is not the single source of progress information anymore, I suppose? Which one do you prefer? Discourse or #4128? |
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). 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. |
I assume this issue is or will be resolved with #6369? |
Yes, it is thought this issue is now resolved. -Kevin |
This ticket is being closed because the underlying issue is now thought to be resolved. Best regards, PS: I'm just an automated script, not a human being. |
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
The text was updated successfully, but these errors were encountered: