Архитектура системы#

Справочное описание Sovol Zero как с завода, снятое с работающей машины — файловая система хоста, конфиг Klipper, рантайм MCU, git-remote-ы. Оно нужно под миграцию: точно знать, какое железо и софт в игре и какие куски вендор-специфичные, а какие сток.

Sovol Zero — CoreXY-принтер, индустриализированная производная Voron 0, с областью печати 150×150×150 мм в закрытом корпусе. На нём крутится Klipper на Linux-хосте, который общается с несколькими STM32 MCU по CANbus. Внутренне Sovol зовёт его «SV08 mini» — вендорский пакет прошивки идёт как SV08mini_Update_Package-*.deb, и CAN-голову он делит с SV08 Max — хотя продаётся только как Sovol Zero.

Вычислитель и топология MCU#

Принтер — это Linux-хост плюс три подключённых по CAN STM32 MCU (третий опциональный, под модуль термокамеры).

УзелЖелезоCAN UUIDПрошивка (коммит)Роль
hostAllwinner H616 (64-bit, 1 GB RAM, hostname SPI-XI)Klipper host 8a8b5e8 (1.4.5)Klippy, Moonraker, веб-стек
mcuSTM32H750 (Cortex-M7, мейнборд)0d1445047cdd14d7b18-dirty (собрано 2025-02-10)XY-степперы, Z, нагреватель стола, вентиляторы платы, дисплей
extruder_mcuSTM32F103 (тулхед)61755fe321accc8afd8-dirty = 1.3.7 (собрано 2025-03-10)Экструдер, хотенд, eddy-датчик, акселерометр, обдув детали
hot_mcuSTM32 (модуль термокамеры, опционально)58a72bb93aa4Нагреватель камеры + вентилятор + датчики температуры

Заметки:

  • Хост общается с MCU по CANbus, а не по USB-serial. MCU адресуются по canbus_uuid в printer.cfg.
  • Хост и MCU собраны из разных коммитов (хост 1.4.5, главный MCU 14d7b18, MCU тулхеда 1.3.7, все -dirty). Handshake протокола Klipper совместим, но «версия принтера» — это не одно число: OTA обновляет хост чаще, чем перешивает MCU.
  • Идентичность чипа подтверждается в src/stm32/chipid.c: MCU мейнборда (UUID 0d1445…) — это STM32H750 (дискриминатор 0x8f, собран из .config750), а MCU тулхеда (UUID 61755f…) — STM32F103 (0x80, .config103/stm32f103xe). На диске лежат три сборочных конфига под каждый чип (.config, .config103, .config750). Теги сборки прошивки несут hostname хоста SPI-XI, т.е. прошивка компилируется на самом принтере.
  • Оговорка: вендорский chipid.c не читает аппаратный UID_BASE; он синтезирует CAN-UUID из захардкоженного массива с последним байтом на семейство чипа. Поэтому CAN-UUID вшиты в прошивку, а не уникальны на кристалл — анти-паттерн, который миграция откатывает (mainline читает реальный UID, так что оба MCU поднимаются на новых UUID после перепрошивки).

Почему CAN и почему это не выбор#

То, что линк хост↔тулхед — это CAN, продиктовано разводкой платы, а не опцией Klipper — его не поменять, не переразведя машину:

  • Межплатный кабель (тулхед ↔ мейнборд) — это дифференциальная пара CANH/CANL на PB8/PB9. На F103 эти пины — CAN_RX/CAN_TX (и ремап I2C1), у них вообще нет альтернативной функции USART, так что UART по этому кабелю не пойдёт. Три USART-а F103 сидят на других пинах (USART1 PA9/PA10, USART2 PA2/PA3, USART3 PB10/PB11), и те всё равно уже заняты — PB10/PB11 под software I2C eddy-датчика, PA9/PA10 под драйвер экструдера (DIR) и X-endstop. UART-тулхед на этом кабеле физически невозможен.
  • У F103 нет своего USB; он дотягивается до хоста только через мейнборд. Так что H750 обязан работать в режиме USB-CAN-моста, иначе тулхед недостижим — мост это единственная топология, где видны оба MCU.
  • Это ещё и правильный дизайн: CAN держит шлейф движущегося тулхеда на двух сигнальных проводах плюс питание вместо ~10+ проводов, которые тащил бы прямой (без MCU) тулхед через постоянный изгиб.

Софтовый стек — что форкнуто#

Форкнут только Klipper. Всё остальное — сток upstream, просто на более старых версиях образца 2024-го.

КомпонентИсточникФорк?Версия на принтере
Klipperвнутренняя Gitea SovolДА — вендорский форк8a8b5e8 (1.4.5)
Moonrakergithub.com/Arksine/moonraker.gitНет (сток)v0.9.3-1-g4e00a07
mainsail-configgithub.com/mainsail-crew/mainsail-config.gitНет (сток)v1.2.1
moonraker-timelapsegithub.com/mainsail-crew/moonraker-timelapse.gitНет (сток)v0.0.1-143
crowsnestgithub.com/mainsail-crew/crowsnest.gitНет (сток)v4.1.9-1
moonraker-obicogithub.com/TheSpaghettiDetective/moonraker-obico.gitНет (сток)v2.0.9

История форка Klipper сквошнута (авторство upstream Kevin O'Connor не сохранилось) — непрозрачный вендорский снапшот, а не чистый ребейз. Вендорская дельта от импорта до HEAD — ~715 вставок в хостовом klippy/ и MCU src/. Анализ происхождения патчей разбирает, что изменилось и зачем.

Работающие systemd-сервисы: klipper, moonraker, crowsnest, KlipperScreen, moonraker-obico.

Сторонние Klipper extras (не сток, но и не специфичные для Sovol): gcode_shell_command.py (плагин shell-команд от Arksine, используется макросами OTA/IP).

Система движения#

CoreXY. Агрессивные лимиты, унаследованные от скоростной линии Voron 0:

  • max_velocity: 1200, max_accel: 40000, minimum_cruise_ratio: 0.5, square_corner_velocity: 5.0
  • Z: max_z_velocity: 20, max_z_accel: 500
ОсьДрайверРабочий токStep/dir/enableEndstopПримечания
XTMC5160 (SW-SPI)3.5 APE1 / !PD7 / !PD5^extruder_mcu:PA10rot. dist 40, 16 микрошагов
YTMC5160 (SW-SPI)3.5 APD3 / !PD2 / !PD0^PD1rot. dist 40, 16 микрошагов
ZTMC2209 (UART PA6, addr 3)1.5 APA5 / !PA4 / !PA7probe:z_virtual_endstoprot. dist 4, ходовой винт
ExtruderTMC2209 (UART extruder_mcu:PA12, addr 3)0.8 Aextruder_mcu:PA8/PA9/PA11rot. dist 6.5 (в стиле Orbiter)

XY-моторы крутят TMC5160 на 3.5 A — серьёзные драйверы, под стать высоким ускорениям.

Пробинг и выравнивание стола#

Две разные системы пробинга, обе на MCU тулхеда, обе кормят z_offset_calibration (вендор-онли модуль):

  • Eddy-current (бесконтактная): [probe_eddy_current eddy], датчик ldc1612 на шине I2C i2c2 у extruder_mcu. Офсеты x=-19.8, y=-0.75, z_offset=3.5. Непрерывно сканирует стол, чтобы строить mesh ([bed_mesh] 20×20, bicubic, область 12,12→132,140). Заводская таблица калибровки лежит в блоке SAVE_CONFIG внутри printer.cfg (reg_drive_current=15).
  • Контактная (тензодатчик): вендорский модуль z_offset_calibration использует один датчик нагрузки под столом, чтобы найти контакт сопла со столом (internal_endstop_offset: -0.20). И non_contact_probe, и contact_probe указывают на eddy-датчик; контактный путь — это вендорский тензометрический Z-ноль.
  • Z хоумится через probe:z_virtual_endstop; safe_z_home на 96, 76.2.

Для миграции: текущий upstream покрывает eddy-датчик нативно — probe_eddy_current с METHOD=scan/rapid_scan/tap. Тензодатчик под столом НЕ ложится на upstream load_cell/load_cell_probe/hx71x: его интерфейс — не поток с АЦП, а обычный GPIO-endstop (PD9 — импульс тары, PD10 — триггер контакта), заведённый через community-рецепт конфига — а датчик то есть, то нет по ревизии: v1.0 использовал его для Z-ноля (eddy читал только меш), а v1.1 его выкинул и перевёл Z-ноль на eddy tap. Load-cell-версия какое-то время шла в производстве, так что это не просто рудимент платы v1.0 — но поздние юниты приходят без датчика и без крепёжных отверстий, так что проверь физическую деталь, прежде чем на неё закладываться. Вендорский MCU добавляет кастомные команды (ldc1612_setup_home, query_ldc1612_home_state), у которых нет стокового аналога, так что миграция требует перепрошить MCU из upstream src/ и переписать эти секции конфига.

Термика#

НагревательПинДатчикМаксУправление
Extruderextruder_mcu:PB7кастомная ADC-таблица my_thermistor_e355 °CPID
СтолPD12my_thermistor (100 k)125 °CPID
Камера (опционально)hot_mcu:PA0EPCOS 100K70 °Cwatermark

Проверь медную втулку в хотэнде. Старые ревизии хотэнда шли без неё, и они до сих пор попадаются — в карточке товара втулка есть, а в самом юните может не быть. Это не тонкость: без втулки хитбрейк сидит в радиаторе свободно и заметно болтается. И по теплу это критично — радиатор не снимает тепло с хитбрейка, не работает вообще, термопаста не спасает, ловишь тепловой пробой и пробки. Как опознать: новая версия хотэнда золотистая и с инсертом, старая — простая трубка. Sovol меняет такой хотэнд бесплатно — скажи продавцу, что это снятая с продажи старая версия. Общий тулхед Zero/SV08 Max, касается обоих.

Вентиляторы:

  • [fan_generic fan0] — обдув детали (extruder_mcu:PB0)
  • [fan_generic fan2] — вспомогательный (PE11); [fan_generic fan3] (PE14)
  • [temperature_fan exhaust_fan] — выхлоп термокамеры через угольный фильтр (PB0, watermark, цель 32 °C, tach на PB1)
  • [heater_fan hotend_fan] — хотенд (extruder_mcu:PA6, включается на 45 °C)
  • [heater_fan chamber_fan] (модуль термокамеры, hot_mcu:PA6)

Модуль термокамеры добавляет макросы M141/M191 (задать/ждать температуру камеры) и heater_generic chamber_heater.

Другие датчики#

  • Акселерометр: [lis2dw] на extruder_mcu через software SPI (PB12-PB15), axes_map: x,z,y. Используется [resonance_tester].
  • Филамент: [filament_switch_sensor] на PB2, pause_on_runout: False.

Вендорская засада — input shaper: [resonance_tester] намертво запинен на min_freq: 35, max_freq: 45 — то самое узкое окно поиска, на которое жаловались обзоры принтера, вшитое в поставляемый конфиг, а не только в прошивку. Сохранённый результат: shaper_x = mzv @ 40.2, shaper_y = zv @ 42.6. Mainline-овое чтение LIS2DW чанками из FIFO даёт более чистые трейсы.

Дисплей, LED, UI#

  • [display] — монохромный LCD UC1701 (экран-крутилка), на хедерах EXP1/EXP2 с click-энкодером.
  • [neopixel Screen_Colour] — 3 RGB-светодиода подсветки экрана (EXP1_6).
  • [output_pin main_led] — основной свет в камере (PD13).
  • KlipperScreen.service работает рядом с LCD.
  • Вендорская прошивка показывает числовые «Tip code» / коды ошибок на этом экране (101/103, диапазон shutdown 60+). Этот UI был инвазивно вшит в ядро Klipper; он воспроизведён как опциональный плагин sovol_codes для миграции.

Сеть и удалённый доступ#

  • Moonraker на :7125, Mainsail (nginx, server_name _) на :80, Moonraker-Obico для удалённого доступа.
  • trusted_clients включает диапазоны домашней LAN; cors_domains покрывает *.lan, *.local, хосты mainsail/fluidd.
  • WiFi: если SSID в режиме WPA2/WPA3-transition, старый вендорский WiFi-стек не может завершить SAE, так что профиль надо запинить на wpa-psk. На mainline ОС netplan пинит key-management: "psk" — см. страницу про Armbian.
  • Камера: /dev/video0 через crowsnest/ustreamer ([cam 1], 720×540, MJPEG на :8080). Камера (MGS1, 364d:6366) смонтирована вверх ногами, и аппаратного переворота нет: она не даёт v4l2-контрола переворота, ustreamer не умеет вращать, а вендорские контролы USB Extension Unit — сырые блобы регистров без тумблера переворота — правь на стороне клиента через rotation: 180 в определении вебкамеры Moonraker.

OTA и прошивка MCU#

  • OTA хоста: ~/ota_client.sh (вендорский), запускается макросом _OTA.
  • Прошивка MCU: готовые .bin в ~/printer_data/build/, шьются по CAN по canbus_uuid через bootloader (в стиле Katapult/CanBoot) вендорским flash_can.py (CAN-флешер Klipper — не путать с flashtool.py от Katapult, который использует миграция). Макросы _MCU_UP / _EXTRUDER_MCU_UP / _EXTRA_MCU_UP крутят скрипты обновления для каждого MCU.
  • Следствие для миграции: переход на upstream Klipper означает собрать upstream-прошивку под чип каждого MCU и прошить .bin по CAN, в ногу с хостом — кастомный набор CAN-команд исключает замену только хоста. См. Прошивка MCU.

Резюме по миграции#

Upstream теперь нативно покрывает практически всё специфичное для Sovol железо — eddy-current (probe_eddy_current scan/tap), LED (neopixel), вентиляторы (temperature_fan/heater_fan), оба чипа MCU (stm32f1 под F103 тулхеда, stm32h7 под H750 мейнборда — причём стоковая поддержка H7 новее вендорской), и все input shaper-ы. Форк держится в основном потому, что Sovol появился раньше этих upstream-добавлений. Миграция поэтому — это в основном переписывание конфига + перепрошивка MCU, а не портирование кода, плюс плагин sovol_codes под UI экрана. Единственные по-настоящему вендор-онли хостовые модули — z_offset_calibration.py и probe_pressure.py, и последний не заменяется upstream-овым load_cell_probe: интерфейс тензодатчика — это GPIO-endstop, а не АЦП, который мог бы читать путь hx71x. На поздних юнитах датчика всё равно нет.