Open sn4k3 opened 2 months ago
Some questions:
See this code:
M6054 "2.png";
G0 Z7.2 F8; -> Safe lift, detach from fep + refresh resin
G0 Z0.2 F10; -> Retract to cure the layer at 0.2mm pos
G4 P3000; -> Wait to platform settle
M1400 S255; -> led on
G4 P20000; -> 20s
M1400 S0; -> led off
G4 P3000; -> wait for layer to cooldown
What would be optimal:
M6054 "2.png";
SET_VELOCITY_LIMIT ACCEL=5,500 -> Slow detach but fast stop
G0 Z7.2 F8; -> Safe lift, detach from fep + refresh resin
SET_VELOCITY_LIMIT ACCEL=500,5 -> Fast retract but slow stop
G0 Z0.2 F10; -> Retract to cure the layer at 0.2mm pos
G4 P3000; -> Wait to platform settle
M1400 S255; -> led on
G4 P20000; -> 20s
M1400 S0; -> led off
G4 P3000; -> wait for layer to cooldown
You think the SET_VELOCITY_LIMIT can be improved in that way?
Thank you for your contribution to Klipper. Unfortunately, a reviewer has not assigned themselves to this GitHub Pull Request. All Pull Requests are reviewed before merging, and a reviewer will need to volunteer. Further information is available at: https://www.klipper3d.org/CONTRIBUTING.html
There are some steps that you can take now:
Unfortunately, if a reviewer does not assign themselves to this GitHub Pull Request then it will be automatically closed. If this happens, then it is a good idea to move further discussion to the Klipper Discourse server. Reviewers can reach out on that forum to let you know if they are interested and when they are available.
Best regards, ~ Your friendly GitIssueBot
PS: I'm just an automated script, not a human being.
Interesting, thanks.
I'm curious what your long-term plans are for this work. Are you still working on it? Are there users utilizing this system today?
I didn't see your questions earlier because of the many earlier updates to the PR. I'll try to answer them:
Is there events I can listen for print start/end/pause/cancel?
Unfortunately that is difficult to do with g-code because there isn't an explicit "start of print" nor "end of print" command in g-code. The closest equivalent would be the events generated from the idle_timeout module (see the send_event()
calls in klippy/extras/idle_timeout.py ).
You think this is something I can implement on [output_pin] and benefit other uses, or do it at [msla_display] level?
That sounds like you'll want to implement in a module. You could also look at klippy/extras/pwm_tool.py - as that has emergency cutoff code in it. (Should the host disconnect from the mcu while the gpio is enabled, the mcu will know to transition to an error state and turn off the gpio.)
Would be possible to have a second parameter to define the stop accel?
This was discussed on Discourse. It's possible, but I'd guess it would be simpler to break up the moves and change acceleration between move segments (as you've indicated on Discourse).
I also have a few high-level questions:
G1
and M6054
style g-code commands? I understand the desire for an open text-based format, but I'd have thought more verbose commands something like MOVE_AND_DISPLAY_PICTURE HEIGHT=2.300 FILE="2.png"
would be possible.Thanks again, -Kevin
I'm curious what your long-term plans are for this work.
I plan to maintain it and work with community to attend and lead mSLA forward. Klipper has everything to drive mSLA, only the display image part is missing. I also made it to support other techs and not be "filament" specific. I think Klipper core should go in this direction, abstract rather than specific.
Are you still working on it?
No, I find this PR very stable and everything is ready to be used. I'm printing with confidence and without any failure so far. But will be optimal to have another set of eyes on the code.
Are there users utilizing this system today?
Just me. I converted my printer and throw it a Manta M5P + CM4 to make this proof of concept. Currently printing with it using mainsail.
The Athenna printers (Runs nanoDLP with klipper) also had they sync problem with image and exposure time, they looked my PR and adopted the concept and rewrite my M1400
This was discussed on Discourse. It's possible, but I'd guess it would be simpler to break up the moves and change acceleration between move segments (as you've indicated on Discourse).
Yes, topic was open by me. Is true that 4xG1+SET_VELOCITY does optimize (1s less in my tests) however in future would be a nice to have this and benefit other systems. However not critical for PR.
I'm curious why you plan to use G1 and M6054 style g-code commands? I understand the desire for an open text-based format, but I'd have thought more verbose commands something like MOVE_AND_DISPLAY_PICTURE HEIGHT=2.300 FILE="2.png" would be possible.
mSLA requires lifts before exposure next layer. Here a normal sequence for print layer 1:
;LAYER_START:0
;PositionZ:0.05mm
SET_PRINT_STATS_INFO CURRENT_LAYER=1
BEFORE_LAYER_CHANGE LAYER=1 HEIGHT=0.05 PIXELS=189274 BOUNDS=81.75,46.15,25.2,28.85 AREA=473.185 VOLUME=23.659 MATERIALML=0.0237
M73 P0 R69.88;Set print progress
M1451 F"1.png";Show image
M204 S5;Set acceleration
G1 Z4.05 F600;Z Lift (1)
M204 S100;Set acceleration
G1 Z6.05 F600;Z Lift (2)
G1 Z1.55 F600;Retract (1)
M204 S5;Set acceleration
G1 Z0.05 F600;Retract (2)
G4 P3000;Wait before cure
M1400 S255 P30000;Exposure for 30s
G4 P3000;Wait after cure
SET_PRINT_STATS_INFO CONSUME_MATERIAL=0.0237
AFTER_LAYER_CHANGE
;LAYER_END
You can notice the 4xG1 to perform the lift and retract to detach model from FEP and refresh the resin under it. However this is all setup by user preference, they can opt for just 1 simple lift rather than my optimization with two lifts. There are also situations where we don't want to lift, eg: Cure supports at one exposure time, cure model at other exposure time. Between this two images changes we don't want to lift because they are same layer. Another point is multiple exposure tests and models. There are also users using mSLA printers to fabricate PCBs with high precision.
Regarding that I think MOVE_AND_DISPLAY_PICTURE
is very limited and an extra command that slicers will skip. For that be usable it would need to accept optional HEIGHT1/2 and SPEED1/2, ACCEL1/2, WAIT, and whatever comes next to implement.
I think we should stay with standalone commands for best compatibility and customizable.
Here the parameters users can adjust per layer:
Is there readily available hardware that this code can run on today? That is, can many users buy off-the-shelf hardware and use this support on it, or would users be required to build a printer from scratch.
Any FDM board and a Pi will do it. I have written step by step guide for who want to convert their printer to this firmware: https://github.com/sn4k3/klipper-msla
In my case I have used a Manta M5P + CM4 to make my UNIZ IBEE klipper based.
What software will be used to produce the gcode/png/zip files that are proposed here? Is that software readily available today.
No slicer so far is able to output this zip format with klipper flavor. The current slicers can output zip but with CWS gcode norm. However my software (UVtools) can use any slicer and convert to klipper format. It's a workflow some users already use, They use PrusaSlicer to slice .sl1 and UVtools to convert to their target printer/format.
Here a sample sliced file, PrusaSlicer (SL1) -> UVtools -> Klipper zip
I understand from your description that mSLA firmware is often proprietary. Are there any other popular open source mSLA firmwares at all? Or, is this goal for this to be the basis for the first popular open source mSLA firmware. (Excuse my ignorance here - I have no experience at all with resin based printers.)
There are no popular open-source mSLA firmwares. This is the problem :) Well we have the Prusa SL1 but is not popular along mSLA, also it's a downgrade comparing to FDM none control over printing, it does all internally. So you have no chance to make your custom moves. There are "open-spec" formats, gcode formats, but none is truly open-source. Most consumer printers uses CTB ecosystem. Other share is held by Anycubic then Creality and now Elegoo. None listen to community nor have good firmware, most still not able to control layers individual, lots of problems which I'm tired to patch with my software. There's also the nanoDLP which use klipper but it's a close-source propertary product and have it problems. You can read more about this bad experiences on my repo (One just came today, one didn't even follow own spec) and also the "war" with formats: https://github.com/sn4k3/UVtools/discussions/319 and https://github.com/sn4k3/UVtools/discussions/442
Working with all these formats over years it's an experience I don't wish for anyone. I wonder why is so hard to write a good firmware?
This PR aims to free users from all crappy firmwares monopoly and revindicate the machines under their control. And most important, having the first all-in and good open-source mSLA firmware that allow you to tune and add features to your printer like we do with FDM.
Background
I'm the creator of UVtools, a software dedicated to help and make resin printing sane (mSLA/DLP) with tons of manipulations and checks.
From the past 4 years I've being deal with many mSLA formats available today, I known them in depth, I'm amazed with the fact that mSLA is far behind FDM in slicing features (In fact I could not believe 4 years ago that mSLA was not gcoded and open like FDM). We are very limited to static file formats that only follow a structure with few or none options. The existing gcode printers in this technology can be counted by hand and the ones that exists suffer from bugs or bad performance.
The bad firmwares are ruining the printers "completely", they never listen to community, never fix bugs that in a normal case takes just 1 day to fix and send the patch firmware online. They really don't care, they just flood the market with models and models of machines that many are very decent on it hardware but the firmware make them a crap machine. Companies right now are tied to one or two solutions, which are always locking formats and make the best effort to encrypt and make sure no others can be used.
Myself got asked by a board company what could be done to improve the eco-system. I tell them: Well, make the format open-source and run over gcode... A: That's not possible, our hardware is not capable, parse gcode is very hard, run png's is not possible, not economical, can't be made open-source, bla bla bla. All runaround. The fact is that now they have 4GB boards running linux, is load png still too hard? Is gcode still not possible? 🤦
Then big promises came, open-source boards and format. Guess what? They call themself open-source by just having a repo in github with just a few documentation on the format, which even with the docs we are unsure about the meaning of some fields...
Lies, promises, bad products, and more lies... This is a loop in mSLA with huge lack of vision.
This crappy mindset are ruining the technology and the overall experience. Myself I don't active do nor like resin printing, but I can't just see this and doing nothing when I have to power to change the situation! That lead me to this PR.
What is required run mSLA?
mSLA only need one Z axis, feed image to a screen and lit a UV LED over it. Looping layer by layer and forming a solid piece from cured resin from the lit pixels. FDM is far more complex to build because it motion system. So now you see another point here, why such simple tech is soo hard to implement? The answer is: Drive the displays! Most displays are held, no datasheets no information how to drive it, require custom FPC = custom board. However today most LCDs are HDMI! And you guess it, plug HDMI to PC and send image. Easy!
Why Klipper?
I have been told: Why klipper for that? Thats OP for what you want. Why not using something else? I can't disagree more!
So is Klipper OP for this!? NO! It's just perfect!
Also I think it's time for klipper to embrace other manufacturing processes, it's a win-win and will make klipper richer in capabilities and features.
Hardware
Right now I'm using:
The PR / Implementation
Note that I mark this PR as a draft because I wan't it to be review, it's my first time dealing with klipper sources. In fact I did what most said impossible in just 3 days but had my printer displaying the image using klipper in just one day. This alone means klipper perfect :) So forgive-me If something is not soo well defined.
GCode sample:
Image display
The displays are now connected via HDMI on the Pi. Pi itself let us configure the framebuffer (config.txt) to match the display. So all we need is set correct parameters there. After I created a [framebuffer_display] module into klipper. Which allow us to configure any framebuffer and send buffers/images over there. See framebuffer_display.py I created to be generic and mux, so some may use it for other displays and send pics to a HDMI display. All code is python and it direct address the framebuffer without any external dependencies.
From that I created the [msla_display] which is the keypoint
eg:
type
,model
are just information, not actually used. All other parameters are used to have sane checks but also provide information about the display which is required. thecache
parameter is a smart-feature to cache next layers so buffer is much more fast to send when time comes.The most smart approach to exposure an layer is:
In my implementation before UV LED is turn on, it waits for image buffer send to be completed. A smart feature that most of gcode printers does not have, they never know when buffer is actually completed, in consequence UV LED can be lit before image is present. I really can't understand why, why so hard to make it right? With cache system and direct buffers I manage fast speeds on transfers, not that we really need them, because they way mSLA works with lifts and waits make time to image to complete (In most cases).
Here the results of an 4K buffer, sampled and avg 10 times:
So in normal conditions if image is load from disk it took about 94ms, but if cached it took 3.5ms to be rendered to the display. Pretty good.
Some gcode commands where created to:
M1400: Because UV wavelength goes from 100nm-400nm M1451: Command used by other gcode printers to display the image is M6054, but opt for M1451 to be closer from M1400
Commands are debatable, we should set an standard now.
[virtual_sdcard]
The mSLA requires an image per layer. Some users prints can go up to 4000 layers. Upload folders is a bit messy, the format I think is best it's the Zip file (pngs + gcode) I had to alter the virtual_sdcard.py with some features:
[toolhead.py]
I admit that I had a hard time discovering the [printer] 😅 I have added the property
manufacturing_process
this is required for others interfaces to adapt. Up now all is related to FDM, so interfaces like mainsail would need to know proper process to adapt interface, eg: For mSLA we want to see current layer image that is printing.[printer_stats.py]
Klipper was build around FDM, stats is filament based. Current system is very limited so I rewrote the stats to be universal and more useful. UI's can now render information easier without parse.
filament_used
: Was kept for compatibility and give time for other backends to adapt, but marked as deprecated in favor ofmaterial_used
material_type
: Based ontoolhead.manufacturing_process
this is auto set by klipper, eg:filament
orresin
material_name
: This is set by user viaSET_PRINT_STATS_INFO
, it represents the current printing material, if a material is changed, eg: M600, we can now update it name and display under UI's.material_unit
: The material unit, this is set by klipper but can also be set by user, for filament is set to 'mm', for resin is set to 'ml'. If user is not happy he can change with to 'in' usingSET_PRINT_STATS_INFO
material_total
: The total material print will use, set once on print startmaterial_used
: The used material so far in the print.info.last_material_used
: The last used material, is often the material consumed by last layer.Syntax:
FDM sample:
Print start:
SET_PRINT_STATS_INFO TOTAL_LAYER=1000 MATERIAL_NAME="Generic Orange PLA" MATERIAL_TOTAL=100000
Before layer:SET_PRINT_STATS_INFO LAYER=1
After layer:SET_PRINT_STATS_INFO CONSUME_MATERIAL=100
echo:
100 / 100000 mm
-> This is the used material in mmAdvanced:
Then our
M600
macro can be expanded to show the material to insert.Resin sample:
Print start:
SET_PRINT_STATS_INFO TOTAL_LAYER=1000 MATERIAL_NAME="Generic ABS-Like" MATERIAL_TOTAL=1000
Before layer:SET_PRINT_STATS_INFO LAYER=1
After layer:SET_PRINT_STATS_INFO CONSUME_MATERIAL=1
echo:
1 / 1000 ml
-> This is the used material in mlLaser sample:
Print start:
SET_PRINT_STATS_INFO TOTAL_LAYER=1 MATERIAL_NAME="MDF" MATERIAL_TOTAL=10000
On etch/period:SET_PRINT_STATS_INFO CONSUME_MATERIAL=10
echo:
10 / 10000 mm^2
--> This is the etched / cut areaCNC sample:
Print start:
SET_PRINT_STATS_INFO TOTAL_LAYER=1 MATERIAL_NAME="MDF" MATERIAL_TOTAL=10000
On cut/period:SET_PRINT_STATS_INFO CONSUME_MATERIAL=10
echo:
10 / 10000 mm^3
--> This is the removed material volumeThis are just samples, and uses are not limited to them. UI's can now render better stats without the need of parse nor if's to display stats to other manufacturing processes.
[display]
menu.cfg
anddisplay.cfg
was adjusted to remove some menus if criteria are not match.UVLED
andUVLED pwr
underControl
menu.What's missing
Breaking changes:
None.
Video
(Sorry for the bad quality.)
Sample print file
https://we.tl/t-l9a9fMftQN
WIP
~This is a WIP,~ looking for ideias, improvements but the implementation is working stable.