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

pulseraster branch (for alpha) #69

Open
wants to merge 22 commits into
base: alpha
Choose a base branch
from

Conversation

martinxyz
Copy link
Contributor

This is a complete rewrite of the raster code (firmware) in the alpha branch.

Each raster byte now corresponds to the duration of a single laser pulse. There is a "raster.py" script to process and raster-engrave an image on the command line. There is no GUI yet. (The web interface is broken in the alpha and this PR doesn't fix that.) Results:

raster-script-test

Changes overview:

  • the laser output pin is driven in a different way (new IRQ handler)
  • use of pulse frequency and pulse duration (instead of intensity)
  • new raster data buffer management (only start after data was received)
  • various minor changes and fixes, rewrite of serial raster protocol

Please read the individual commit messages for more explanation.

More testing results: http://log2.ch/laser/raster-testing/

Vector-cutting is expected to work but has not been re-tested yet. (Would be easier to test if the web interface was working.) Known issue: at feedrate 8000 there is an audible bump at the start of each raster line, I think it's a delayed microstep (CPU is overloaded with integer division for the acceleration calculation), no big deal, just don't be alarmed, it's probably not caused by mechanics. It doesn't happen at feedrate 6000.

martinxyz and others added 19 commits November 8, 2015 18:29
SIGNAL(vector)
This is the same as the ISR macro without optional attributes.
Deprecated:
    Do not use SIGNAL() in new code. Use ISR() instead.
And clean up information duplication in driveboard.py.

And yes, this error actually does happen - when the stepper ISR is
called too frequently.
The problem was most visible when engraving small shapes at low power.

This was also causing a rare serial communication problem because the
CPU was overloaded (shortly) by a much too high stepper frequency.
- python style
- don't call __init__() twice
- fix gcc warning
Remove all inline keywords. (Many really long functions were
declared 'inline'.) Enable inlining across files, aka link-time
optimization (-flto). Enable -O2 (which enables inlining) instead
of -Os.

Program size (in the 32K flash):
- 12'064 bytes before this commit
- 12'990 bytes new
- 13'310 bytes new, but without '-flto'
- 30'174 bytes new, but with all 'inline' keywords added back

Duration of stepper IRQ:
- 27.0us before this commit
- 25.2us new
- new serial protocol and buffering for raster data
- new "pixels per mm" setting
  - stepper ISR keeps track of (fractional) distance to next pixel
- raster resolution doesn't have to match the microstep resolution
- raster moves can have any direction/angle now

Raster data is no longer streamed via the serial interrupt while the
move is already in progress. Instead it's expected right after the
"line" command if the new "raster bytes" parameter was used.  The
move is then queued by the planner together with its raster buffer.

The raster buffer is limited to 60 bytes, which will take long enough
to execute to allow the CPU to schedule the next move and combine it
without slowing down while cruising at high speed.

The block buffer size was decreased to make room for 4 raster buffers.
I think this will not become a problem, but if it does, we should
consider to enlarge the serial RX buffer instead, because it buffers
commands with fewer bytes per move and it stores raster data too.

New raster_line() command in driveboard.py to split long raster moves
into smaller ones.
New laser output ISR. Raster bytes now control the duration of
individual laser pulses (exactly one pulse per byte).

The raster execution is now time-based. This relieves the stepper
ISR from sub-microstep calculations, and it allows for more than
one raster byte (and thus laser pulse) per microstep, which is
a requirement for raster-cutting.

The pulse length is more coarse now (32us increments) but the pulse
frequency can be set at very high resolution to compensate.

Serial protocol change: "pulse_frequency" and "pulse_duration" settings
replace the "intensity" setting. The backend still has intensity() as a
convenience API. Its input range is now 0-100 (float) instead of 0-255.

The old pwm-duty-driven code also produced a glitch at the end of
each raster line, when both frequency and duty cycle were lowered at the
same time. This resulted in an unpredictable but very long pulse,
because the duty update is buffered by the timer hardware until the
next duty cycle, while the frequency update is applied instantly.

During acceleration, the power is now regulated by the pulse
frequency only (fixed pulse duration).
The stepper ISR usually takes about 25us to complete, but when
adjust_speed() is called it can take 150us instead.

This is a problem because it can prevent the next stepper ISR from
happening, which effectively alters the number of microsteps per
second, which is bad for time-based raster (and for higher speeds).

This commit shaves off 55us from adjust_speed().

Numbers to compare with:

 4'000 mm/min = 165us between microsteps
 8'000 mm/min =  82us between microsteps
12'000 mm/min =  55us between microsteps
Print commands as they are executed and exit on first error.
They should be prevented in the first place; this is just low-level
protection for peace-of-mind when coding/debugging/experimenting.
Those happen when calling adjust_speed() while stepping at high rates,
say, 8000 mm/min. Not such a big deal because they are infrequent with
about 30 non-delayed microsteps in-between, but for predictable speed
and especially for rastering during acceleration it would be nice to fix.
Firmware's flash.py now calls the backend, to avoid maintaining the same
script twice. (They were already out of sync, too.)
Use air support and do homing.
Bugfix for PIL to numpy array conversion.
Option to generate a preview image.
Options for x and y position offset.
@raydebs
Copy link

raydebs commented Dec 26, 2015

Hey guys and gals,

I just got one of the coolest Christmas presents and I wanted to thank Stefan and Martin for getting raster engraving working!

I am still running the 12.08c hardware hosted on a laptop, and it took me a couple of days of setup and debugging to get it to work, but it does a wonderful job of engraving photos.

I am really looking forward to all the new things I can now do with my lasersaur.

I am running the command-line app Martin put together, and quite like it. It would be nice to have a pretty web UI, but I think I can do things quicker on the command line.

If anyone else is interested, I can submit my mods as a pull request to support older hardware.

Merry Christmas everyone!

Ray

On Dec 18, 2015, at 6:14 AM, Martin Renold [email protected] wrote:

This is a complete rewrite of the raster code (firmware) in the alpha branch.

Each raster byte now corresponds to the duration of a single laser pulse. There is a "raster.py" script to process and raster-engrave an image on the command line. There is no GUI yet. (The web interface is broken in the alpha and this PR doesn't fix that.) Results:

Changes overview:

the laser output pin is driven in a different way (new IRQ handler)
use of pulse frequency and pulse duration (instead of intensity)
new raster data buffer management (only start after data was received)
various minor changes and fixes, rewrite of serial raster protocol
Please read the individual commit messages for more explanation.

More testing results: http://log2.ch/laser/raster-testing/

Vector-cutting is expected to work but has not been re-tested yet. (Would be easier to test if the web interface was working.) Known issue: at feedrate 8000 there is an audible bump at the start of each raster line, I think it's a delayed microstep (CPU is overloaded with integer division for the acceleration calculation), no big deal, just don't be alarmed, it's probably not caused by mechanics. It doesn't happen at feedrate 6000.

You can view, comment on, or merge this pull request online at:

#69

Commit Summary

fix high-power bursts during deceleration
SIGNAL() --> ISR()
add "USART data overrun" error reporting
fix firmware compilation (flash.py)
minor code cleanups
change gcc flags to "-O2 -flto" and remove "inline"
fix problem where homing() is not executed
new raster protocol
new laser code (pulse_frequency and pulse_duration)
stepper.c performance optimization
update flash.py baudrate and slight refactor
laser.c: forbid high frequencies and very short pulses
delayed_microsteps counter (error reporting)
verbose raster_move()
add more firmware constants
raster.py - commandline tool for rastering
remove duplicated build/flash script
firmware binary update
raster.py: bugfix and improvements
File Changes

M backend/build.py (27)
M backend/driveboard.py (348)
M backend/lasersaur.py (2)
A backend/raster.py (247)
A backend/simulation.py (80)
M firmware/LasaurGrbl.hex (1588)
M firmware/src/config.h (15)
M firmware/src/flash.py (170)
A firmware/src/laser.c (103)
A firmware/src/laser.h (33)
M firmware/src/main.c (2)
M firmware/src/planner.c (110)
M firmware/src/planner.h (36)
M firmware/src/protocol.c (71)
M firmware/src/protocol.h (17)
M firmware/src/sense_control.c (32)
M firmware/src/sense_control.h (5)
M firmware/src/serial.c (111)
M firmware/src/serial.h (1)
M firmware/src/stepper.c (107)
M firmware/src/stepper.h (4)
M frontend/app.js (2)
Patch Links:

https://github.com/stefanix/LasaurApp/pull/69.patch
https://github.com/stefanix/LasaurApp/pull/69.diff

Reply to this email directly or view it on GitHub.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants