Bambu Studio presets management -- utilizing inheritance features

Preset management with Studio is a bit unfortunate (and the whole topic really needs to be addressed separately). Meanwhile the actual underlying preset definition system is quite flexible. If one looks at the provided profiles, like for filaments, one can see that they actually, in most cases, inherit from one another and do not repeat every setting in every definition file. I’ll describe here “briefly” how us users can also utilize this feature. If people are interested in more details, please let me know.

For example there’s an fdm_filament_abs.json, then Bambu ABS @base.json inherits that definition, then the printer and nozzle-specific profiles like Bambu ABS @BBL A1.json, Bambu ABS @BBL A1 0.2 nozzle.json, etc, pull in the “@base” profile as a starting point. At each level of inheritance, only the differences are listed in the more specific files.

The key is the inherits field of each profile, where the name of a parent preset can be listed (has to exactly match the file name of the parent, w/out file extension). Using this in our own user presets requires manual editing and organizing.

Now for us users, in the user/..../filament folder there’s also a base folder (or there should be). (As you probably know the user presets are stored in either user/default or user/###### with your BL user number if you log in for your Studio sessions. And if you log out/log in, all your presets are gone. Personally I created a directory symlink (junction) that points my user # folder to the default folder, to stop that nonsense.)

This base folder is where Studio puts the “custom filaments” you can create starting at the available filament types selection dialog. The parent filament folder is where Studio stores filament presets you save “on the fly” when editing a filament with a project (from where you select the filament).

So if you start with a “core” filament profile which contains most of the settings you need and put that one in base subfolder, then in the parent filament folder your profiles can inherit from this “core.” Unfortunately this key feature isn’t exposed in any way in the Studio UI.

To stay editable in Studio as a filament “custom profile” (where you select available filaments and define new ones), this base should list at least one printer and nozzle type in compatible_printers. Also, this base profile cannot inherit from any other profile (unfortunately), or again it won’t be editable in Studio (though it will still work for using it and any sub-profiles of it). You don’t have to adhere to these limits (especially inheriting from one of the built-in profiles can be really handy), but then you can’t edit it in Studio (for whatever reason, haven’t debugged that yet)

Any custom profiles that inherit from the base can then list whichever printer(s) and nozzle(s) that particular “sub” profile is compatible with. And only the differences from base need to be included in the sub types.

And you might be thinking that it would be cool to use multiple levels of inheritance in our custom profiles. And that’s very true. But there’s a bug/limit in Studio that it cannot find parent profiles in the same folder as the child – the parent has to be in the inner base folder and be imported first. But there’s a workaround by simply creating another base folder inside the existing base folder, which could be done to however many levels you want (it will keep drilling down into base folders until it finds the innermost one and starts loading profiles from there).

Oh, and you can basically ignore the corresponding .info file when creating profiles manually. Leave them be if they’re there already, but they’re not required.


Here’s an example, more or less (this forum ridiculously doesn’t allow .json file type uploads). I’m playing with PEBA Air which acts differently at various print temperatures and flow rates. I wasn’t keen on creating full profiles for each and every variation, for hopefully obvious reasons.

I start with a core profile 2 “base” levels deep:

This is a full filament profile, basically saved from one of Siraya’s example projects they provide, there’s nothing special about it really. But it does list two printers & nozzles as compatible.

Siraya Tech PEBA Air @BBL H2C 0.4 nozzle.json
{
    "activate_air_filtration": [
        "0"
    ],
    "additional_cooling_fan_speed": [
        "0"
    ],
    "chamber_temperatures": [
        "0"
    ],
    "circle_compensation_speed": [
        "200"
    ],
    "close_fan_the_first_x_layers": [
        "1"
    ],
    "compatible_printers": [
        "Bambu Lab H2C 0.4 nozzle",
        "Bambu Lab H2D 0.4 nozzle"
    ],
    "compatible_printers_condition": "",
    "compatible_prints": [],
    "compatible_prints_condition": "",
    "complete_print_exhaust_fan_speed": [
        "70"
    ],
    "cool_plate_temp": [
        "100"
    ],
    "cool_plate_temp_initial_layer": [
        "100"
    ],
    "counter_coef_1": [
        "0"
    ],
    "counter_coef_2": [
        "0.025"
    ],
    "counter_coef_3": [
        "-0.11"
    ],
    "counter_limit_max": [
        "0.05"
    ],
    "counter_limit_min": [
        "-0.04"
    ],
    "default_filament_colour": [
        "#000000"
    ],
    "diameter_limit": [
        "50"
    ],
    "during_print_exhaust_fan_speed": [
        "70"
    ],
    "enable_overhang_bridge_fan": [
        "1"
    ],
    "enable_pressure_advance": [
        "0"
    ],
    "eng_plate_temp": [
        "100"
    ],
    "eng_plate_temp_initial_layer": [
        "100"
    ],
    "fan_cooling_layer_time": [
        "100"
    ],
    "fan_max_speed": [
        "50"
    ],
    "fan_min_speed": [
        "50"
    ],
    "filament_adaptive_volumetric_speed": [
        "0",
        "0"
    ],
    "filament_adhesiveness_category": [
        "0"
    ],
    "filament_change_length": [
        "10"
    ],
    "filament_change_length_nc": [
        "10"
    ],
    "filament_cooling_before_tower": [
        "10",
        "10"
    ],
    "filament_cost": [
        "39.99"
    ],
    "filament_density": [
        "1.22"
    ],
    "filament_deretraction_speed": [
        "nil",
        "nil"
    ],
    "filament_diameter": [
        "1.75"
    ],
    "filament_end_gcode": [
        "; filament end gcode\n"
    ],
    "filament_extruder_variant": [
        "Direct Drive Standard",
        "Direct Drive High Flow"
    ],
    "filament_flow_ratio": [
        "1",
        "1"
    ],
    "filament_flush_temp": [
        "0",
        "0"
    ],
    "filament_flush_volumetric_speed": [
        "0",
        "0"
    ],
    "filament_id": "P7c81eba",
    "filament_is_support": [
        "0"
    ],
    "filament_long_retractions_when_cut": [
        "nil",
        "nil"
    ],
    "filament_max_volumetric_speed": [
        "6",
        "6"
    ],
    "filament_minimal_purge_on_wipe_tower": [
        "15"
    ],
    "filament_notes": "",
    "filament_pre_cooling_temperature": [
        "200",
        "200"
    ],
    "filament_pre_cooling_temperature_nc": [
        "0",
        "0"
    ],
    "filament_prime_volume": [
        "45"
    ],
    "filament_prime_volume_nc": [
        "60"
    ],
    "filament_printable": [
        "3"
    ],
    "filament_ramming_travel_time": [
        "20",
        "20"
    ],
    "filament_ramming_travel_time_nc": [
        "0",
        "0"
    ],
    "filament_ramming_volumetric_speed": [
        "3",
        "3"
    ],
    "filament_ramming_volumetric_speed_nc": [
        "-1",
        "-1"
    ],
    "filament_retract_before_wipe": [
        "nil",
        "nil"
    ],
    "filament_retract_length_nc": [
        "10",
        "10"
    ],
    "filament_retract_restart_extra": [
        "nil",
        "nil"
    ],
    "filament_retract_when_changing_layer": [
        "nil",
        "nil"
    ],
    "filament_retraction_distances_when_cut": [
        "nil",
        "nil"
    ],
    "filament_retraction_length": [
        "0",
        "0"
    ],
    "filament_retraction_minimum_travel": [
        "nil",
        "nil"
    ],
    "filament_retraction_speed": [
        "nil",
        "nil"
    ],
    "filament_scarf_gap": [
        "0%"
    ],
    "filament_scarf_height": [
        "10%"
    ],
    "filament_scarf_length": [
        "10"
    ],
    "filament_scarf_seam_type": [
        "none"
    ],
    "filament_settings_id": [
        "Siraya Tech PEBA Air @BBL H2C 0.4 nozzle"
    ],
    "filament_shrink": [
        "100%"
    ],
    "filament_soluble": [
        "0"
    ],
    "filament_start_gcode": [
        "; filament start gcode\n"
    ],
    "filament_type": [
        "TPU"
    ],
    "filament_velocity_adaptation_factor": [
        "1"
    ],
    "filament_vendor": [
        "Siraya Tech"
    ],
    "filament_wipe": [
        "nil",
        "nil"
    ],
    "filament_wipe_distance": [
        "nil",
        "nil"
    ],
    "filament_z_hop": [
        "nil",
        "nil"
    ],
    "filament_z_hop_types": [
        "nil",
        "nil"
    ],
    "first_x_layer_fan_speed": [
        "0"
    ],
    "from": "User",
    "full_fan_speed_layer": [
        "0"
    ],
    "hole_coef_1": [
        "0"
    ],
    "hole_coef_2": [
        "-0.025"
    ],
    "hole_coef_3": [
        "0.28"
    ],
    "hole_limit_max": [
        "0.25"
    ],
    "hole_limit_min": [
        "0.08"
    ],
    "hot_plate_temp": [
        "70"
    ],
    "hot_plate_temp_initial_layer": [
        "70"
    ],
    "impact_strength_z": [
        "0"
    ],
    "inherits": "",
    "long_retractions_when_ec": [
        "0",
        "0"
    ],
    "name": "Siraya Tech PEBA Air @BBL H2C 0.4 nozzle",
    "no_slow_down_for_cooling_on_outwalls": [
        "0"
    ],
    "nozzle_temperature": [
        "230",
        "230"
    ],
    "nozzle_temperature_initial_layer": [
        "230",
        "230"
    ],
    "nozzle_temperature_range_high": [
        "270"
    ],
    "nozzle_temperature_range_low": [
        "220"
    ],
    "overhang_fan_speed": [
        "100"
    ],
    "overhang_fan_threshold": [
        "95%"
    ],
    "overhang_threshold_participating_cooling": [
        "95%"
    ],
    "pre_start_fan_time": [
        "0"
    ],
    "pressure_advance": [
        "0.02"
    ],
    "reduce_fan_stop_start_freq": [
        "1"
    ],
    "required_nozzle_HRC": [
        "3"
    ],
    "retraction_distances_when_ec": [
        "0",
        "0"
    ],
    "slow_down_for_layer_cooling": [
        "0"
    ],
    "slow_down_layer_time": [
        "8"
    ],
    "slow_down_min_speed": [
        "20"
    ],
    "supertack_plate_temp": [
        "100"
    ],
    "supertack_plate_temp_initial_layer": [
        "100"
    ],
    "temperature_vitrification": [
        "30"
    ],
    "textured_plate_temp": [
        "100"
    ],
    "textured_plate_temp_initial_layer": [
        "100"
    ],
    "version": "2.4.0.70",
    "volumetric_speed_coefficients": [
        "0 0 0 0 0 0",
        "0 0 0 0 0 0"
    ]
}

Then a .6mm nozzle base profile in the folder above it.

It just changes the default flow rate and some plate temperatures (not even sure those are needed yet), but crucially it inherits the parent .4 nozzle profile.

Siraya Tech PEBA Air @BBL H2C 0.6 nozzle.json
{
    "compatible_printers": [
        "Bambu Lab H2C 0.6 nozzle",
        "Bambu Lab H2D 0.6 nozzle"
    ],
    "cool_plate_temp": [
        "80"
    ],
    "cool_plate_temp_initial_layer": [
        "80"
    ],
    "eng_plate_temp": [
        "80"
    ],
    "eng_plate_temp_initial_layer": [
        "80"
    ],
    "filament_flow_ratio": [
        "0.95",
        "0.95"
    ],
    "filament_settings_id": [
        "Siraya Tech PEBA Air @BBL H2C 0.6 nozzle"
    ],
    "hot_plate_temp": [
        "70"
    ],
    "hot_plate_temp_initial_layer": [
        "70"
    ],
    "inherits": "Siraya Tech PEBA Air @BBL H2C 0.4 nozzle",
    "instantiation": "true",
    "name": "Siraya Tech PEBA Air @BBL H2C 0.6 nozzle",
    "supertack_plate_temp": [
        "80"
    ],
    "supertack_plate_temp_initial_layer": [
        "80"
    ],
    "textured_plate_temp": [
        "80"
    ],
    "textured_plate_temp_initial_layer": [
        "80"
    ],
    "version": "2.4.0.70"
}

And at the filaments level I have just the individual temperatures and flow rates and nozzles. They inherit from the parent .4 or .6mm profiles above.

One of the files as an example:

Siraya Tech PEBA Air 250C 76A @BBL H2C 0.4mm.json
{
    "filament_flow_ratio": [
        "0.82",
        "0.82"
    ],
    "filament_settings_id": [
        "Siraya Tech PEBA Air 250C 76A @BBL H2C 0.4mm"
    ],
    "inherits": "Siraya Tech PEBA Air @BBL H2C 0.4 nozzle",
    "name": "Siraya Tech PEBA Air 250C 76A @BBL H2C 0.4mm",
    "nozzle_temperature": [
        "250",
        "250"
    ],
    "nozzle_temperature_initial_layer": [
        "250",
        "250"
    ],
    "version": "2.4.0.70"
}


I know that’s a lot of info, and far from detailed at that, but maybe it helps someone get a grip. If you have any related tricks, please share! If there’s interest in better profile management then I’m open to that conversation as well, as a programmer who could help build a tool or perhaps improve Studio.

Cheers,
-Max

7 Likes

That is a lot, and I plan to go over it again when I can give it more thought.

OrcaSlicer uses the same profile inheritance scheme by default, but you can remove the restrictions for more filament profile options.

You can specify that a User profile works with All printers and nozzles, or a subset of printers. You can also specify that a filament profile applies only to specific processes.

In addition, the current beta, in Developer mode, provides an option to save a complete profile without dependence on an inheritance. This can be helpful if you want to be sure that a profile is not modified because a parent profile changed.

3 Likes

Thanks, I hadn’t noticed that in Orca. Definitely an improvement! I like adding a tab for deps., at first blush anyway.

-Max

Great find! I had already discovered inheritance but never looked into it in more detail. Thank you for taking the time to investigate it and the great explanation.

A related topic that is really implemented terribly is flow dynamics calibration. I really don’t understand why BBL have done it like that. In Orca, the K-value simply is an extra field in the filament profile. I basically have understood how I can calibrate a filament in BambuStudio once and link the saved value to a profile. But I find it so cumbersome, that I didn’t do it since switching back to BambuStudio and instead use the Lidar calibration at the start of each print.
Maybe you know if there is an easier way without creating those extra profiles, e.g. by just editing some files?

Thanks Alex, striving for working smarter and less! :slight_smile:

Here’s what I’ve discovered about PA calibration and the elusive K factor, and what Orca does.

It’s actually summed up rather nicely in a post I found at the Orca GitHub repo, relating to a “adaptive PA” feature they added at some point. The feature is perhaps interesting in its own right, but this last comment explains a bit about how BL printers handle PA differently than other printers.
https://github.com/OrcaSlicer/OrcaSlicer/pull/5609#issuecomment-3745069936

As far as I can tell, the PA value that Orca lets you specify per filament will generate an M900 g-code command, which apparently is a standard way of setting PA (at least in some firmwares). However, in Studio’s code for BL printers, the only time M900 is used is actually during manual flow calibration (that’s how it steps through the different PA rates during the test print). In fact there are specifically comments in the code to not generate M900 commands for actual prints (on BL printers). Because, as per that GitHub post, apparently, the M900 would override some internal magic BL printers do on their own.

The K factor we get after a calibration run is stored on the printer itself. And the printer, apparently, has all the logic to handle it. The Studio code I’m looking at is basically just communicating back and forth with the printer, not storing the calibration values anywhere locally (except some meta data that a calibration was done).

This wasn’t a very deep dive into the matter on my part, so it’s possible I’m missing something, but that seems to be the gist of the story in a nutshell.

-Max

Thanks for the extensive reply!
That contains a lot of information I didn’t know about. I’m especially surprised about avoiding M900. So we want the K-factor stored in the printer :+1:

Do you know of a simpler way for pushing the K-values to the printer? E.g. creating some files in the right place?

That’s a good question, but not that I’ve seen so far.

I can see the commands used to exchange calibration data with the printer in the calibration wizard, stored profiles editor, and AMS material editor (all of which require a printer to be connected). Which are basic JSON-formatted data packets which then disappear into, or emerge from, either BL’s cloud or network plugin for LAN mode.

So in theory I don’t see why staging a calibration data “push” to a printer wouldn’t work, eg. before a print starts, based on a print profile config “K” value. The data sent to the printer is pretty specific as far as the physical nozzle (by serial #) and filament, AMS references… but by the time you’re going to print something all that info should already be known anyway, I think. But there’s no such feature now, and of course it’s quite possible I’m overlooking some reason that might be a bad idea, be “too complicated” to be practical, or just not work for some unknown reason (love it when that happens… lol).

-Max

PS. Actually it could work by basically automating the already-available manual method of setting K value from the AMS/Filaments UI, where you can click a filament, select a nozzle size/type, and set a K factor there (and/or select an existing PA profile). One could specify a PA profile name in a print profile, or just a K factor for the default PA profile, for example, and when sending a print the nozzle size/type would already be known.

To “store” K value I simply add ‘M900 K0.060’ (with the correct value) to filament_start_gcode. Works with X1C, have not tested it with H2D yet.

Hi Jan, did you check out the discussion above? Setting M900 is apparently not the same as K value, and BL printers specifically don’t use that command in g-code generated by Studio.

-M

PS. not doubting your results, just trying to make sense of what works and doesn’t!

Interesting, this same code for the “Dependencies” tab exists in Studio but is disabled (commented out). It has been that way since the first publication on GitHub (4 years ago). I can’t tell what it was like in PrusaSlicer originally because the Studio “fork” didn’t preserve any change history or original authorship (yuck).

I’m guessing it was removed for some reason, but I wonder if that reason is still valid (or anyone even knows/remembers why). Not sure if I should bother with restoring the code, testing, and submitting a patch, if they removed it for a reason. Well… I opened an Issue, so we’ll see where that leads.

Thanks again for pointing that out!

-Max