UVJ format / Open (M)SLA format #687
Replies: 8 comments 12 replies
-
Correct.
It can, like other formats UVtools create a new layer in same position Z, UVJ defines A good and future proof format should be gcode + png images. Forget about weak microcontrollers, microprocessors with Linux and added functions and capabilities are the way to go, even if it adds a little more cost. Just like we see on FDM, most people add a Pi to have octoprint and other features, that is more expensive than provide a final board that is able to do that from start. Pixels vs Vectors: There is one format that UVtools supports that use vectors: SVGX. However, I see no advantage on that. It will support other printers but who wants to print a file sliced with given settings for a given resin profile? That's a user error. Even on FDM I never dare to print other's .gcode even if is for the same printer brand and material, not because I don't trust the file but because I don't trust the settings which are never optimal, same goes otherwise. So, in the end people should always slice their own to guarantee the best settings and success and then having a vector that should be converted to image after all is not a bonus. Also, if you go vector forget about AA or get ready to have a mess in the vectors due the brightness change. |
Beta Was this translation helpful? Give feedback.
-
UVJ 1.0 Proposal - Vendor Neutral MSLA FormatFeel free to comment, suggest alternatives or additional keys etc. As I realized, @sn4k3 / Tiago has extended silently the UVJ format as proposed by @ezrec / Jason by following new settings:
which implies the 2nd stage of build-plate movement, beside the peeling motion. I support this addition. I propose following addition:
Any .uvj which has not the |
Beta Was this translation helpful? Give feedback.
-
I highly recommend that the format version number follows the “semver” spec, specifically:
See https://semver.org/ for the general guidelines. The “Vendor” keys should be in a vendor block that can be added to any section, further wrapped by the vendor name, ie: …. |
Beta Was this translation helpful? Give feedback.
-
A few questions of clarification for @ezrec & @sn4k3 : Two Stages of Motion
Now, what is the common practice here, as If Lift vs RetractWhat is the reason to differentiate between One Stage of Motion@sn4k3: When Preview Tiny & Huge@ezrec in your samples you indicated
Is this some guidance of size, or how shall we define tiny vs huge in pixels, and the aspect ratios? Also, the files are optional? Suggested recommendation: "if previews are generated, make background transparent" or so. How to deal with additional files?To adapt @ezrec "Vendor" for
Thoughts? |
Beta Was this translation helpful? Give feedback.
-
To be honest; my comments on those fields were best guesses at the time - I neglected to do any experiments to verify my assumptions.
|
Beta Was this translation helpful? Give feedback.
-
Hello everyone, author of https://github.com/nviennot/turbo-resin File formatI would much prefer that we don't use PNG. I've measured the ROM footprint, and it's ~20KB. Not a huge deal, but the RAM footprint is massive: 50KB due to the decompression algorithm. It's awful. It can be done, but there's not going to be much left for the rest of the firmware (e.g., things like wifi support). As a point of comparison, the ROM footprint for the CTB format is 0.3KB, and PWMA 0.3KB. So that's a pretty massive difference. Color depthWe want to support at the very least 4-bit color depth. Note that it'd be nice to support people who want to use the 3D printer as a way to make circuit-boards. MasksThings that are helpful when calibrating a new printer+resin is to do multiple exposures. Sending a 4K (or 8K) image to the LCD takes a long time, like 10secs at times, depending how well the image compresses. Maybe we want to have the ability to apply a given mask as an overlay, but that's something the FPGA driving the LCD panel should be able to understand. And it's hard to write a custom firmware for that. Still, we should allow the file format to eventually specify masks. G-codeI think it's a good idea to use g-code. We could be specifying the acceleration/speed settings in a more standardized format. Maybe masks would be applied via a g-code command like "MXXX mask.png" or maybe "MXXY (x1,y1,x2,y2)" as a rectangle coordinate. Also, I'd like the possibility to implement a force sensor in the printer (like https://blog.honzamrazek.cz/2022/01/prints-not-sticking-to-the-build-plate-layer-separation-rough-surface-on-a-resin-printer-resin-viscosity-the-common-denominator/) which is used by the firmware to decide on the correct build plate movement. The maximum "pressure" could be defined by g-code. All the json-like parameters per-layer is wrong in my opinion. It doesn't compose well. We can't make experiments. Having different speeds is silly. What if I want 3? G-code is the answer. |
Beta Was this translation helpful? Give feedback.
-
OSLA: Powerful, Requirement for Labeling Capabilities for Firmware/Device@nviennot the OSLA definition I glanced over, here my thoughts:
The definition is powerful, but with it also makes it hard(er) to support, and labeling what exactly is supported in a firmware/device is required. And the slicers need to know which devices are capable which features of OSLA. The idea to use a load cell to increase print speed as you wrote me by email, is there something the file format needs to support (UVJ or OSLA), or this is mainly a firmware feature [measure area exposed, and combine Z-motions with load cell measurement]? |
Beta Was this translation helpful? Give feedback.
-
@Spiritdude reached out to me via Twitter to express my opinion on the topic. TBH, I haven't read the discussion. But I have been thinking about programming MSLA machines for a long time in past, and I came up with the following proposal (it is commented example program). I abandoned the idea of building a custom driver electronics recently, so I decided to share it publically: # There are line comments denoted by '#'. There is no other type of comment.
# There is a mandatory language type and version specification
language MSLALang version=1
# Then there can be a list of parameters that the user can set before starting
# the print. Parameters marked as mutable can be adjusted during runtime.
param baseExposure type=number default=2 min=0 max=10 mutable=true
param bottomExposure type=number default=20
param baseLayerCount type=number default=5
# We can also have constants that make it easy for humans to understand what's
# going on
const layerHeight type=number value=0.05
# A few words about types: There are two built-in types: number and string.
# Additional drivers can implement a new types. Usually that would be an image
# that we can project on the screen. However, you cannot reference these types
# from the MSLA language.
# A program in the MSLA language is just a set of function and procedures. One
# of the procedures must be called main. This is the procedure where the
# evaluation of the program starts.
#
# Most of the procedures are built-in or they are imported from other modules.
# Functions are expressions – they take arguments and return a value. They can
# invoke other functions, but they cannot invoke procedures. The functions
# cannot be recursive.
#
# Basically function are "just" named expressions.
#
# We distinguish two types: number and string. The strings can be formatted.
fun exposureTime(layerNumber: number) -> number:
if layerNumber <= baseLayerCount
then bottomExposure
else baseExposure
# This is an example of a function that returns a layer slice name as a string
fun layerSliceName(layerNumber: number) -> string:
"layerImage_${layerNumber}"
# Procedures are non-recursive subprograms that take arguments and perform
# actions on the machine.
#
# Each line is a single invocation of another procedure. The procedures take
# arguments via name=value. If the value should be computed, it has to be
# enclosed inside the argument evaluation section ${}
proc layerCycle(layerNumber: number):
reportLayerStart layerNumber
moveAbs Z=(${layerHeight * (layerNumber + 1)})
# The retrieve function retrieves a slice image from the program archive.
showPattern pattern=(retrieve (layerSliceName layerNumber))
startExposure
wait (exposureTime layerNumber)
machinePeelCycle
reportLayerEnd layerNumber
# Each program starts with a procedure main:
proc main():
home
moveAbs Z=0
for i in 1..5000:
layerCycle(layerNumber)
moveSafeZ
message "Print completed"
# You might be wondering - why such restrictions? Well, the language is designed
# to be decidable. We can decide if the program halts, we can simulate it and
# never run into an infinite loop. This is essential as we want to make precise
# time estimates and simulations of the printing process.
# To make the language useful, we should define a mandatory procedures for given
# types of machines. An example of such mandatory procedure is, e.g.,
# machinePeelCycle. It is a built-in procedure that peels a layer. Every machine
# has it. Dumb machines will just wait and lift; smart machines will use, e.g.,
# a force sensor to peel. Having the minimal set of required procedures allows
# you to write portable programs. However, if you know that you target a
# specific machine, you can use machine-specific procedures.
# The language is designed to be powerful, hackable and human readable, however,
# it comes at the cost that post-processing tools, such as UVTools, will have
# hard time interpreting the programs and modyfing them. However, the question
# is if using a post-processing is a good path in a long term anyways and if all
# the functionality UVTools offer shouldn't be migrated into a custom
# open-source slicer. |
Beta Was this translation helpful? Give feedback.
-
I tried to find information for the UVJ format, beside the source code of UVtools. I found a brief description at https://github.com/ezrec/uv3dp/tree/master/uvj - it seems as if @ezrec defined the format?
What UVJ is missing is the ability to expose multiple images at the same Z, e.g. multi exposure support, which is helpful when printing calibration pieces in one go to find best print settings for a resin or environmental condition (like temperature).
Gathering Thoughts
I'm in the midst to gather my thoughts on a Open (M)SLA format, something like .SL1 or .UVJ, but with multi-exposure support:
main.gcode
which describes the entire print process using G-code:G1 Z{lift_distance}
the firmware would be still in charge of some settingsM356
code alike Marlin'sM355
M1200 I"img0001.png"
Goals
Pixels vs Vectors
For now I tend to think in terms of pixels per exposure image, but in order to support SLA as well, images could be also vector-based (exterior and interior polygons).
The advantage of vector based images would be to a model slice once, and have it print on different SLA or MSLA machines.
Burden on Firmware/Controller
The simplest is the RLE format to pack pixels, like the CTB or PW* formats do, but each machine needs its own format - the burden on the controller and firmware is minimal, just unpacking pixels for the LCD to expose UV light.
The unpack of PNG exposure images is a bigger task, as it requires
libpng
to support the many formats (bw, gray, rgb(a) and packing methods), not sure about runtime RAM requirements involved.To rasterize polygons with holes is no easy task for a microcontroller, the complexity direct relates to required RAM as in data structures and/or stacksize involved.
Which leads to the requirement on the controller, a small Atmel running Marlin vs RPi/SBC which runs Linux, which easily can rasterize vector slices, and those many 32bit ARM controllers in between.
Thoughts, Comments, Links
Constructive thoughts, comments and links to useful resources are appreciated.
Beta Was this translation helpful? Give feedback.
All reactions