Skip to content

Conversation

@amini-allight
Copy link

I've been trying to use your GOO format export fork to get Prusa Slicer working with my ELEGOO Saturn 3 Ultra. Initially the files it generated failed to print and created a flat pancake adhered to either the FEP screen at the bottom of the tank or the build plate. I investigated the differences between the files generated by your exporter and those created by CHITUBOX and VoxelDance and found there were four differences:

  • header_info:aa_level being non-zero in Prusa exports
  • layer_definition::pause_lift_distance_mm being zero in Prusa exports
  • header_info::bottom_exposure_time_s being set to the duration of a typical layer exposure, not the bottom layer exposure, in Prusa exports
  • header_info::advance_mode_layer_definition being true in Prusa exports

I did a series of test prints changing each these values to the values found in known-good files and found that the bottom two must be changed to get a successful print. The top two have no obvious effect.

This pull request changes those bottom two values: header_info::bottom_exposure_time_s is now set to the correct bottom exposure time value and header_info::advance_mode_layer_definition is now constant false.

The new value for header_info::bottom_exposure_time_s should be better in all cases but, from my reading of the GOO format standard, changing header_info::advance_mode_layer_definition like this may have unintended side effects via causing the values written into the layer definitions to be ignored. You might know more about this than I do.

I have done a test print using the code provided here and I can confirm it prints, at least on the Saturn 3 Ultra.

Felix-Rm and others added 11 commits February 22, 2024 13:39
Create header and source files for GOO format and add them to the build
system. Register GOOWriter and GOOReader classes in SLAArchiveFormatRegistry.
Add exposure, timing, lift and retract specific options to SLAMaterialConfig and the material tab.
These parameters are needed for generating .goo output files and were
not yet present in the slicer. The lift and retract options are
prefixed with 'sla_' to avoid conflict with e.g. 'retract_speed' from
FFF printing.
Adds GOORLERasterEncoder for encoding the 'Data size', 'Image data' and
'Delimiter' parts of the 'Layer content' segment in goo files.
Add implementations for the required SLAArchiveWriter virtual functions.
This adds full support for generating goo files including thumbnails and
inclusion of slicer, printer and profile names in the output file.

Note that GOOReader is not yet implemented. Usage of GOOReader will
result in an error message in the console.
MSVC compiler was ignoring [[gnu::packed]]. This commit adds macros to
add the compiler specific attributes.
MSVC was complaining about designated struct initializers in c++17. This
commit replaces designated initializers with member-wise
initialization. This change should probably be reversed once PrusaSlicer
moves on to c++20.

The use of capturing structured bindings was also removed in 'libslic3r/SLA/RasterBase.cpp'.
Generation of multi-option lines for lift and retract parameters was moved
into a lambda to reduce code duplication and make future optionalizing
of the parameters easier.
This allows for SLA printers without tilt mechanisms to be added. Time
estimation code will also be able to switch between estimations based
on tilt and estimations based on lift and retract by checking for the
presence of tilt configuration.
This commit adds time estimate calculation based on lift and retract.
Calculation with these parameters gets triggered if tilt parameters
are set to null (N/A) in the SLA printer tab.

It also adds a `Time estimate correction` field in the `Corrections`
section of the SLA printer tab to account for processing delays of the
selected printer.
The algorithm used for checksum generation is not explicitly specified
in the .goo format spec and was implemented wrong until now. The printer
ignores the checksum so this wasn't a problem. This implementation is
now equivalent to the one used in UVTools.
…r exposure value to fix broken prints on ELEGOO Saturn 3 Ultra
@Felix-Rm
Copy link
Owner

Thanks for contributing! The code has only been tested on Mars printers up until now, so getting some feedback for Saturn printers is quite valuable.

The current value of header_info::bottom_exposure_time_s is definitely wrong and should be replaced with the value you provided.

Regarding the change to header_info::advance_mode_layer_definition I am a bit more hesitant:
Forcing the printer to use the slicer generated layer times and heights definitely allows for better control. The exposure time set in the layer_definition is also currently a correctly calculated one. So if the printer is actually using the values from the layer_definition, like the header_info::advance_mode_layer_definition flag description in the .goo spec suggests, the bug in the header_info::bottom_exposure_time_s shouldn't even have manifested. This is definitely the case for the Mars printers. Maybe the Saturn printers behave differently for some reason.

Could you please confirm that the current (buggy) version of the code actually results in the printer only using the normal exposure times instead of fading from initial_exposure_time to exposure_time. If so, this behaviour would differ from Mars printers and should then probably be handled in a special way for Saturn printers.

Thanks for also highlighting the differences in the other two values. The anti-aliasing level currently reflects the actual value used in the layer rasterizer. I believe this value is not even used by the printer in any way and is purely for information purposes.
The layer_definition::pause_lift_distance_mm together with the layer_definition::pause_at_layer flag should be integrated with Prusas actual pause on layer height functionality, but this is currently unimplemented. I will add it to the todo list in the PR on the Prusa repo.

@amini-allight
Copy link
Author

Could you please confirm that the current (buggy) version of the code actually results in the printer only using the normal exposure times instead of fading from initial_exposure_time to exposure_time.

I'd be happy to but I'm not quite sure how to test this. Should I time the actual layers with a stopwatch while the printer is running or is there a better way?

@Felix-Rm
Copy link
Owner

I'd be happy to but I'm not quite sure how to test this. Should I time the actual layers with a stopwatch while the printer is running or is there a better way?

Yes, timing the first 3-4 layers with a stopwatch is how I have been testing it on my printer. This should be enough to verify that the first layer uses initial_exposure_time and that there is some kind of (non abrupt) transition towards exposure_time.

Thanks again for your help!

@amini-allight
Copy link
Author

Sorry for the delay, I've been busy and getting this version of Prusa to compile seems to get steadily harder the more time passes. But more importantly, I got some very interesting results!

  • I printed a test cube .goo file exported with the known-bad version of Prusa (e.g. 6f4de42, your last commit to goo-format-support-dev).
  • header_info::bottom_exposure_time_s was 3.5.
  • header_info::advance_mode_layer_definition was 1.
  • layer_definition::exposure_time_s for layer 0 was 35.
  • The print failed, adhering to the FEP at the bottom of the tank.
  • The measured times for the first 14 layers were roughly:
    • 30 seconds
    • 29 seconds
    • 28 seconds
    • 24 seconds
    • 22 seconds
    • 19 seconds
    • 15 seconds
    • 13 seconds
    • 10 seconds
    • 6 seconds
    • 3 seconds
    • 3 seconds
    • 3 seconds
    • 3 seconds

I seemingly undercounted most of the layer times slightly because the initial time should have been 35 seconds and the final stabilized time should have been 3.5 seconds, but that doesn't effect the conclusion. This is clearly the curve from the layer_definition structures, the sharp drop from 9.8 seconds at layer 8 to 6.65 seconds at layer 9 to 3.5 seconds at layer 10 is clearly visible.

I think what this must mean is using header_info::advance_mode_layer_definition = 1 on Saturn printers does cause them to read from the layer definitions but something else about this code path is bugged or Saturn printers interpret the layer_definition structure fields differently to Mars printers in some undocumented way.

When header_info::advance_mode_layer_definition = 0 I assume it uses the values from header_info (per the specification), which would explain why header_info::bottom_exposure_time_s needed to be fixed as well to get a successful print.

Do you want me to go ahead and add an additional flag to fix this? I could probably do the pause fields at the same time.

@Felix-Rm
Copy link
Owner

Thank you for the testing!

I do agree that the printer is using the correct exposure times. I have plotted the values you provided and they seem to align quite well (to a margin of human timing error) with what we would expect.

chart

Your theory that something else is wrong seems possible. I have again checked for any differences between the data in the header_info and layer_definitions. As all values (apart from pause and position related ones) in the layer_definitions have their equivalent initial and normal counterparts in the header_info, I am also quite confident they are set correctly. The only possible difference I can think of, is that we don't interpolate the lift speeds and distances (as we possibly should do). But I am sceptical if this alone would cause prints to fail.

As a side note:
Comparing your print settings to the ones I am currently using it seems possible that your initial exposure time is just too short. In my profiles these times are usually set to more than one minute (normal exposure time after fade is around 3 seconds as you have also set). On the other hand these times are largely dependent on the light source, initial layer height and the used resin, so this might just be different with your setup. Although it would be interesting to see how close the print is to actually sticking to the plate instead of the FEP (by printing with increased initial exposure time).

I do still consider adding a "use header info data" checkbox to the printer settings (or even a hidden option via the printer config file) as a bit of a hack. I don't think we are at the point yet, but if that is the only way to fix this issue I think it would still be a positive addition.

Can you observe any other differences in printer behaviour between advance_mode_layer_definition on or off? Maybe printing with a higher initial exposure time as suggested above could also give us some more insight. I do understand if you don't want to risk any more failed prints (as possibly tearing the FEP and having to replace it is quite a pain), but if you could do some more research it would be much appreciated. I will also try to do some testing on my Mars 3 Max to check if I can find any differences.

Regarding your build issues and fixes:
I currently have a rebase of the goo-format-support-dev branch to PrusaSlicer 2.8 (fixing the current merge conflicts with upstream) on my local machine. If it is okay with you I would add the fix of bottom_exposure_time_s to this rebase and include you as a contributor to the respective commit.

I also have a local branch which adds config presets for Elegoo SLA Printers and Anycubic ABS-like resin to PrusaSlicer (saving users of having to manually add them), as well as a new autobuild branch which should be able to provide full binary builds for all future upstream releases. If you would be so kind to add your config for the Saturn 3 Ultra as a comment to this gist, I could also include it in the builds. The autobuild branch should be up and running by end of next week.

@amini-allight
Copy link
Author

Regarding lift speed and distance: I just compared my test cube .GOO files from CHITUBOX and Prusa side-by-side: neither of them interpolates the lift speed and distance. It might be better practice to do so (I don't know enough about printers to weigh in on this) but it's not the cause of the print failures otherwise CHITUBOX prints would also be failing.

Regarding exposure times: I currently have SUNLU High Tough Black resin loaded and the exposure times are known good for that resin: I was printing successfully with it using my fixed version of Prusa Slicer. I forget exactly where I got them but I'm fairly sure the numbers come from an official SUNLU publication. Additionally when I first discovered this problem I was using ELEGOO's official resin with their official settings which they publish for every resin and printer combination.

Regarding further tests: I'm not keen to run failed prints again because of the danger to the FEP (I broke it at least once while doing my original testing) but I will do so if we need another specific test to distinguish between two hypotheses. However I have had an idea for a test that only requires a successful print. Do you think it's possible that the problem is the exposure time interpolation curve? The main difference between the two states of header_info::advance_mode_layer_definition that I can see is where the initial exposure time → normal exposure time interpolation curve is calculated. I will try to do a successful print with the known-good version of Prusa and time the layers to see what curve the printer chooses for itself.

Regarding rebasing: Go ahead and include my contribution in that commit.

Regarding printer config: I'll get you my Saturn 3 Ultra config but do keep in mind it will fail for anyone who tries to use it unless we add that secret "use header info data" flag to the printer config files. I think in the absence of any clarification either from the upcoming test or from ELEGOO about what's going on here adding that flag is the best solution. I will contact ELEGOO about this if the test I described above doesn't reveal the issue.

@Felix-Rm Felix-Rm force-pushed the goo-format-support-dev branch from 6f4de42 to c0b70c8 Compare September 30, 2024 17:37
@amini-allight
Copy link
Author

amini-allight commented Oct 3, 2024

We have results!

I ran a print with header_info::advance_mode_layer_definition = 0 and timed the layers until it stabilized at the normal exposure time. Here I've plotted the Prusa-generated exposure times (in blue) vs. the measured printer-generated exposure times (in orange):

printer curves

Putting aside measurement errors there's a massive difference here. The printer chooses to hold the bottom exposure time for the first 12 layers. After that it declines to the normal exposure time using the same linear interpolation and slope as Prusa.

Adding a special flag to identify a specific printer configuration as a Saturn and then output .GOO files with this altered behavior should be enough to fix the problem.

@Felix-Rm
Copy link
Owner

Felix-Rm commented Oct 3, 2024

Results indeed!
This definitely explains why the prints with the PrusaSlicer curve kept failing for you.

Looking at the code it is now also painfully obvious why the Saturns curve looks the way it does. With the current implementation we are setting both header_info::bottom_layers and header_info::transition_layers to PrusaSlicers internal SLAPrintObjectConfig::faded_layers. So the printer first holds the initial exposure for header_info::bottom_layers and then performs the fade for header_info::transition_layers.
As the printer is obviously correct here, I don't think this should be fixed with a Saturn specific flag.

Going forward, I briefly considered the option to set header_info::bottom_layers to 1 or even 0 and just keep the header_info::transition_layers. But this is arguably a bad solution, as it resulted in print failures on your printer with the recommended exposure times.

The more proper solution would be just to add a "Bottom layers" input field in the "Print Settings" tab. The exposure time calculation in the layer_definition would also have to be adjusted to match the printers behavior, as well as the time estimate code. One problem arising with this solution is that this option would only be used when exporting to the .goo format. So ideally this input field would be disabled when using other export formats. Regardless of this small implementation issue, I still believe this is the option we should go with.
What do you think would be the best option?

Somewhat of topic:
As you have probably noticed, I rebased the goo-format-support-dev branch onto the version_2.8.1 release of PrusaSlicer to get rid of the merge conflicts that were present. In the process I also corrected the bottom_exposure_time_s mistake as discussed. This inadvertently has made a bit of a mess of this PR, so before any further development your "forked branch" would also need to be rebased onto mine.

Regarding the build issues you mentioned before: The autobuild workflow is also working and has already produced PrusaSlicer binaries for version_2.8.1 with the .goo support and printer configs included. You could look into using the resources at Felix-Rm/prusaslicer-autobuild in your fork or even locally while developing. (The autobuild workflow is part of the last two commits on master. Syncing your fork should also enable them in your repo.)

The current PR that is open on the PrusaSlicer repo has also been part of a discussion (issue prusa3d#13306) regarding the naming of these extra SLA print options. Going forward this should also be considered and some communication with the maintainer of PR prusa3d#10531 might be of value.

@amini-allight
Copy link
Author

I think the "bottom layers" setting in the GUI sounds like a much better solution than any sort of special toggle/flag as it accurately reflects the structure of the underlying file.

Should I close this pull request? One change has been added as part of your rebase and the other turns out to be unnecessary now we understand better what the underlying problem really is, so I'm not sure what purpose if any it still serves.

Regarding my fork, is there any other work you want me to do? I could correct the pause lift distances if that hasn't already been done, or add the bottom layers setting.

@Felix-Rm
Copy link
Owner

Felix-Rm commented Oct 4, 2024

Sounds good. I will close this PR as it has been mainly implemented in 8d2ee78.

For the "Bottom layers" and "Pause lift distance" features I will open new issues where we can discuss further details. You are of cause invited to work on these issues if you want to.

Thanks again for all the research work you did to get us to this point!

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