Проверка настроек слайсера по срезанному gcode
Интерфейс слайсера показывает то, что вы ввели. Принтер получает то, что осталось после наследования профилей, дефолтов самого слайсера и подстановок в стартовый G-code. Между этими двумя вещами регулярно оказывается пропасть, и единственный способ её увидеть — прочитать срез.
Три вещи, которые видно только там: эффективное значение ключа после всей цепочки наследования; дефолты слайсера для ключей, которых нет ни в одном профиле цепочки; и результат подстановок вида [chamber_temperature] в стартовый G-code.
Уровень 1: конфиг-блок в конце файла
Слайсер дописывает в хвост G-code все эффективные настройки строками ; ключ = значение. Это самый дешёвый и самый надёжный источник.
grep -E '^; (chamber_temperature|enable_pressure_advance|filament_max_volumetric_speed|gap_fill_target|wall_loops|sparse_infill_density) ' plate_1.gcodeТак я поймал у себя ; gap_fill_target = nowhere — ключа не было ни в одном профиле цепочки, значение пришло из дефолта слайсера, и в интерфейсе оно выглядело безобидно.
Полезные строки итогов там же:
; total filament used [g] = 87.90
; estimated printing time (normal mode) = 3h 20m 47s
; total layers count = 300
Именно по ним удобно сравнивать варианты настроек: разница в весе и времени считается без единой напечатанной детали.
Уровень 2: стартовая последовательность
Подстановки в машинном стартовом G-code — отдельный класс ошибок, потому что значение может быть корректным в профиле и потеряться при подстановке. Смотреть первые строки исполняемого блока:
grep -nE '^PRINT_START|^M14[01] |^M19[01] |^M104 |^M140 |^M106' plate_1.gcode | head -12У меня это выглядело так до правки профиля и после:
PRINT_START BED=105 HOTEND=260 CHAMBER=0 EXTRUDER=0 # камера не грелась
PRINT_START BED=105 HOTEND=275 CHAMBER=60 EXTRUDER=0 # после смены базы профиля
Уровень 3: фактические скорости и расход
Заявленные в профиле скорости могут не достигаться — их режет лимит объёмного расхода. Метод разбора и таблица результатов — в Ограничение печати объёмным расходом.
Пакетная проверка вариантов из командной строки
Самое ценное применение — прогнать десяток вариантов настройки и получить вес и время каждого, не трогая интерфейс. У OrcaSlicer для этого есть CLI прямо в бандле приложения (на macOS — исполняемый файл внутри .app/Contents/MacOS/).
Базовый вызов:
OrcaSlicer --datadir "<каталог данных слайсера>" \
--load-settings "machine.json;process.json" \
--load-filaments "filament.json" \
--slice 0 --outputdir . model.stlРезультат — plate_1.gcode в каталоге вывода. Дальше его читают grep-ом, как выше.
Грабли, на которые я потратил час
- Ошибки не печатаются в stdout. На любой проблеме CLI пишет ровно
run found error, exit. Настоящая причина — только в файле из--logfile(плюс--debug 4). Без этого отладка вслепую. - Пользовательские профили не имеют поля
type— CLI падает сunknown config type of file ... in load-settings. Надо добавить его в копию:machine,process,filament. Осторожно: тип профиля печати называетсяprocess, а неprint— наprintта же ошибка, только с именем типа. - Копия профиля вне
--datadirне подтягивает черезinheritsмашинный G-code. Это самая коварная: слайсинг проходит, но со стартовым G-code по умолчанию. Симптом — в срезе нетPRINT_START, зато естьM190 S35, то есть стол греется до непонятных 35 °C. Лечится схлопыванием цепочки наследования в плоский конфиг перед подачей в CLI. - Но ключ
inheritsу машинного профиля надо оставить, даже когда все значения уже явные: проверка совместимости профиля печати с принтером сверяется именно с ним, иначеrun 2652: process not compatible with printer. Плюс вcompatible_printersпрофиля печати должны быть перечислены имена принтера — и своё пользовательское, и вендорское. - Промежуточная ошибка валидации
Relative extruder addressing requires resetting the extruder position at each layer to prevent loss of floating point accuracy. Add "G92 E0" to layer_gcodeозначает ровно то же самое:layer_change_gcodeне унаследовался в копию. - Тип стола обязателен. Без
curr_bed_typeслайсер берёт температуру не того типа поверхности: у меня вместоBED=105(High Temp Plate) уезжалоBED=80(значение для холодной плиты). Настройка живёт в профиле печати. - Имена полей итогов не те, что кажутся. Не
total filament weight [g], а; total filament used [g] =; неtotal estimated time, а; estimated printing time (normal mode) =. Регулярка по неверному имени тихо вернёт «нет данных», и это легко принять за неудачный срез.
Автоматизация сравнения вариантов
Обвязка на питоне: взять плоский конфиг, поменять один ключ, срезать, вытащить вес и время. Так я за несколько минут получил кривую «плотность заполнения против веса и времени» и таблицу «лимит расхода против времени» — обе решили спор о настройках без единой печати.
import json, os, re, subprocess
def slice_variant(base_cfg, overrides, model):
cfg = dict(base_cfg); cfg.update(overrides)
json.dump(cfg, open("var.json", "w", encoding="utf-8"), ensure_ascii=False)
if os.path.exists("plate_1.gcode"):
os.remove("plate_1.gcode")
subprocess.run([BIN, "--datadir", DATADIR, "--debug", "1", "--logfile", "/dev/null",
"--load-settings", "machine.json;var.json",
"--load-filaments", "filament.json",
"--slice", "0", "--outputdir", ".", model],
capture_output=True, timeout=900)
if not os.path.exists("plate_1.gcode"):
return None # срез не удался — смотреть логфайл
t = open("plate_1.gcode", encoding="utf-8", errors="replace").read()
g = re.search(r'(?m)^; total filament used \[g\] = (.*)$', t)
tm = re.search(r'(?m)^; estimated printing time \(normal mode\) = (.*)$', t)
return (float(g.group(1)) if g else None, tm.group(1) if tm else None)Проверку «файл появился» пропускать нельзя: при неудачном срезе в каталоге остаётся plate_1.gcode от предыдущего прогона, и обвязка бодро отрапортует чужими числами. Отсюда os.remove перед запуском.
Тестовую модель проще сгенерировать, чем искать: куб из двенадцати треугольников пишется в бинарный STL в десяток строк. Размер модели подбирать под вопрос — на кубе 20 мм при пяти стенках и крышках по 3 мм от заполнения почти ничего не остаётся, и разница плотностей не проявится; для таких сравнений нужен куб от 60 мм.
Когда это применять
- Перед тем как поверить, что правка профиля вступила в силу — особенно если правился унаследованный ключ.
- При споре «какая настройка лучше» — вес и время считаются точно, а не на глаз.
- При разборе чужого профиля: конфиг-блок среза показывает его целиком и без домыслов.
- После обновления слайсера: дефолты, которых нет в профилях, могут поменяться между версиями, а профиль при этом не менялся.
Источники
- Generic-профиль слайсера теряет машинные настройки — самый частый случай, который ловится именно так
- Ограничение печати объёмным расходом — разбор фактических скоростей по срезу
- klipper_estimator — точная оценка времени печати — уточнение оценки времени, которую печатает слайсер