Recommended resources
The freely available resources this lesson will direct you to.
Здравствуйте!
На прошлом уроке мы превратили монолитный блок в функциональное основание корпуса, добавив монтажные стойки для печатной платы и вырезы для портов. У нас есть параметрический и готовый к дальнейшей работе final_base.
Сегодня мы делаем финальный шаг в проектировании: реализуем механизм соединения для обеих частей корпуса. Это означает, что мы не только создадим крышку, но и спроектируем элементы, которые будут надежно скреплять ее с основанием.
Мы рассмотрим два популярных подхода:
- Винтовое соединение: надежный и классический метод, который мы реализуем с помощью бобышек и винтов. Мы будем использовать специальные библиотеки, чтобы не моделировать крепеж вручную.
- Защелки (snap-fit): элегантный метод, не требующий дополнительного крепежа, который мы обсудим как альтернативу.
Наша основная цель — получить две полностью готовые к печати детали, которые точно и надежно соединяются друг с другом.
1. Подготовка: Создание крышки и бобышек
Прежде чем соединять две части, нам нужна вторая часть — крышка (lid). Она должна не просто накрывать основание, а точно входить в него. Для этого мы используем знакомый вам по модулю 4 прием "выступ-фальц" (lip/groove). Мы сделаем на крышке выступ, который будет входить внутрь основания.
Далее, для винтового соединения нам понадобятся "бобышки" (bosses) — цилиндрические столбики в углах основания, в которые будут вкручиваться винты.

Давайте напишем две новые функции: create_enclosure_lid для создания крышки с выступом и add_screw_bosses для добавления бобышек к основанию.
# В файле full_script.py
# ... (в секции ПАРАМЕТРЫ ПРОЕКТА)
LID_HEIGHT = 10.0
LID_LIP_CLEARANCE = 0.2 # Зазор для выступа крышки
SCREW_BOSS_DIAMETER = 8.0
SCREW_BOSS_RADIUS = SCREW_BOSS_DIAMETER / 2
# ... (в секции ФУНКЦИИ-КОНСТРУКТОРЫ)
def create_enclosure_lid(
pcb_width: float,
pcb_length: float,
wall_thickness: float,
side_clearance: float,
lip_clearance: float,
lip_height: float,
lid_thickness: float,
) -> Part:
"""Создает крышку с выступом для посадки в основание."""
inner_width = pcb_width + 2 * side_clearance
inner_length = pcb_length + 2 * side_clearance
outer_width = inner_width + 2 * wall_thickness
outer_length = inner_length + 2 * wall_thickness
with BuildPart() as lid:
# Основная пластина крышки
Box(outer_width, outer_length, lid_thickness)
# Выступ (lip), который входит в основание
lip_width = inner_width - 2 * lip_clearance
lip_length = inner_length - 2 * lip_clearance
with Locations(Vector(0, 0, -lip_height)):
Box(lip_width, lip_length, lip_height)
# Перемещаем начало координат крышки на ее нижнюю плоскость
lid.part.locate(Location(Vector(0, 0, lip_height)))
return lid.part
def add_screw_bosses(
base_part: Part,
wall_thickness: float,
inner_width: float,
inner_length: float,
boss_radius: float,
boss_height: float,
) -> Part:
"""Добавляет бобышки для винтов по углам основания."""
# Координаты центров бобышек
x_pos = (inner_width / 2) + boss_radius
y_pos = (inner_length / 2) + boss_radius
boss_locations = [
(x, y) for x in [-x_pos, x_pos] for y in [-y_pos, y_pos]
]
with BuildPart(base_part) as part_with_bosses:
# Выбираем дно для создания эскиза
bottom_face = part_with_bosses.faces().sort_by(Axis.Z)[0]
with BuildSketch(bottom_face):
with Locations(*boss_locations):
Circle(boss_radius)
extrude(amount=boss_height)
return part_with_bosses.part
2. Магия крепежа: bd_warehouse
Моделировать винты, гайки и отверстия под них вручную — трудоемкая задача. К счастью, для build123d существует библиотека bd_warehouse, которая содержит параметрические модели стандартного крепежа и инструменты для создания правильных отверстий.
Установим ее, если еще не сделали:uv pip install bd_warehouse
Мы будем использовать один из самых надежных методов крепления для 3D-печати: термозакладные втулки (heat-set inserts). Это металлические втулки с резьбой, которые вплавляются в пластик с помощью паяльника и создают очень прочное соединение.
Release ["py310", "py311", "py312", "py313"] Gumyr
Давайте изучим документацию bd_warehouse, чтобы понять, как работать с крепежом. Нас интересует раздел, посвященный созданию отверстий.
Внимательно прочитайте подраздел 'Custom Holes'. Обратите особое внимание на класс InsertHole — он предназначен специально для термозакладных втулок (HeatSetNut). Также посмотрите на класс ClearanceHole, который мы будем использовать для крышки. В справочном разделе ('Reference') можно найти описание класса HeatSetNut и доступные типы.
Реализация отверстий
Теперь, когда мы знаем об инструментах, давайте применим их. Мы модифицируем нашу функцию add_screw_bosses, чтобы она сразу создавала правильные полости для втулок. Затем создадим новую функцию add_lid_holes для крышки.
Мы будем использовать винты M3 (самый популярный размер для таких проектов) и соответствующие им втулки.
# Добавляем импорты в начало файла
from bd_warehouse.fastener import HeatSetNut, SocketHeadCapScrew, ClearanceHole, InsertHole
# ... (в секции ПАРАМЕТРЫ ПРОЕКТА)
# Параметры крепежа
SCREW_SIZE = "M3-0.5" # Стандартный винт M3
HEAT_SET_NUT_TYPE = "M3-0.5-Standard" # Втулка под винт M3
SCREW_LENGTH = 8.0 # Длина винта
# ... (в секции ФУНКЦИИ-КОНСТРУКТОРЫ)
def add_screw_bosses_with_holes(
base_part: Part,
wall_thickness: float,
inner_width: float,
inner_length: float,
boss_radius: float,
boss_height: float,
heat_set_nut: HeatSetNut,
) -> Part:
"""Добавляет бобышки с отверстиями для термозакладных втулок."""
# Расчет координат центров бобышек
x_pos = (inner_width / 2) + boss_radius + wall_thickness
y_pos = (inner_length / 2) + boss_radius + wall_thickness
boss_locations = [
(x, y) for x in [-x_pos, x_pos] for y in [-y_pos, y_pos]
]
with BuildPart(base_part) as part_with_bosses:
# Сначала создаем бобышки
bottom_face = part_with_bosses.faces().sort_by(Axis.Z)[0]
with BuildSketch(bottom_face):
with Locations(*boss_locations):
Circle(boss_radius)
extrude(amount=boss_height)
# Теперь создаем отверстия для втулок в вершинах бобышек
top_faces = part_with_bosses.faces().filter_by(Axis.Z).sort_by(Axis.X, reverse=True).sort_by(Axis.Y, reverse=True)[1:5]
with Locations(*[f.center() for f in top_faces]):
# Используем InsertHole для создания идеального отверстия
InsertHole(fastener=heat_set_nut)
return part_with_bosses.part
def add_lid_holes(
lid_part: Part,
screw: SocketHeadCapScrew,
boss_locations: list[tuple[float, float]]
) -> Part:
"""Добавляет сквозные отверстия с зенковкой под головку винта в крышку."""
with BuildPart(lid_part) as lid_with_holes:
top_face = lid_with_holes.faces().sort_by(Axis.Z)[-1]
with Locations(*[top_face.world_to_local(loc) for loc in boss_locations]):
# ClearanceHole создает сквозное отверстие и зенковку
ClearanceHole(fastener=screw, counter_sunk=True)
return lid_with_holes.part
Обратите внимание, как элегантно bd_warehouse решает задачу:
HeatSetNut(...)создает объект, описывающий втулку.InsertHole(fastener=...)использует этот объект, чтобы вырезать в модели полость нужного диаметра и глубины.- Аналогично
SocketHeadCapScrew(...)иClearanceHole(..., counter_sunk=True)создают в крышке сквозное отверстие для винта и углубление для его шляпки, чтобы она была заподлицо с поверхностью.
3. Сборка и финальный код
Теперь соберем все вместе в главном скрипте.
# full_script.py
# ... (все импорты и параметры как раньше) ...
# ... (все функции-конструкторы) ...
# ----------------- ОСНОВНОЙ СКРИПТ СБОРКИ -----------------
if __name__ == "__main__":
# 1. Рассчитываем ключевые внутренние размеры
enclosure_inner_width = PCB_WIDTH + 2 * SIDE_CLEARANCE
enclosure_inner_length = PCB_LENGTH + 2 * SIDE_CLEARANCE
# 2. Создаем основание (из предыдущего урока)
base = create_enclosure_base( ... )
base_with_standoffs = add_standoffs( ... )
pcb_z_position = WALL_THICKNESS + BOTTOM_CLEARANCE
final_base_body = add_port_cutouts( ... )
# 3. Определяем крепеж из bd_warehouse
m3_heat_set_nut = HeatSetNut(size=HEAT_SET_NUT_TYPE, fastener_type="Hilitchi")
m3_screw = SocketHeadCapScrew(size=SCREW_SIZE, length=SCREW_LENGTH)
# 4. Добавляем бобышки с отверстиями к основанию
base_height = BOTTOM_CLEARANCE + WALL_THICKNESS
final_base = add_screw_bosses_with_holes(
base_part=final_base_body,
wall_thickness=WALL_THICKNESS,
inner_width=enclosure_inner_width,
inner_length=enclosure_inner_length,
boss_radius=SCREW_BOSS_RADIUS,
boss_height=base_height - WALL_THICKNESS, # высота до края стенки
heat_set_nut=m3_heat_set_nut,
)
# 5. Создаем крышку
lid = create_enclosure_lid(
pcb_width=PCB_WIDTH,
pcb_length=PCB_LENGTH,
wall_thickness=WALL_THICKNESS,
side_clearance=SIDE_CLEARANCE,
lip_clearance=LID_LIP_CLEARANCE,
lip_height=LID_HEIGHT / 2,
lid_thickness=WALL_THICKNESS
)
# 6. Добавляем отверстия в крышку
# Координаты бобышек должны совпадать с отверстиями в крышке
boss_x = (enclosure_inner_width / 2) + SCREW_BOSS_RADIUS + WALL_THICKNESS
boss_y = (enclosure_inner_length / 2) + SCREW_BOSS_RADIUS + WALL_THICKNESS
screw_locations = [
Location(Vector(x, y, base_height)) for x in [-boss_x, boss_x] for y in [-boss_y, boss_y]
]
final_lid = add_lid_holes(
lid_part=lid,
screw=m3_screw,
boss_locations=screw_locations
)
# 7. Визуализация и экспорт
pcb = create_pcb_model(PCB_WIDTH, PCB_LENGTH, PCB_HEIGHT)
show_object(final_base, name="base")
show_object(final_lid, name="lid", at=Location(Vector(0,0,base_height)), options={"alpha": 0.7})
show_object(pcb, name="pcb", options={"alpha": 0.6, "color": (0.1, 0.8, 0.2)}, at=Location(Vector(0,0,pcb_z_position)))
final_base.export_stl("enclosure_base.stl")
final_lid.export_stl("enclosure_lid.stl")
4. Альтернатива: Защёлки (Snap-Fit)
Винты — это надежно, но иногда хочется, чтобы корпус собирался и разбирался без инструментов. Здесь на помощь приходят защёлки.

Проектирование хорошей защёлки требует учета свойств материала (например, PETG или ABS гнутся лучше, чем PLA) и точных допусков. Это более сложная тема, чем винтовое соединение, и требует итеративной печати и доработки.
Принцип работы:
- На одной детали (например, на основании) создается гибкий "язычок" (консоль) с крючком на конце.
- На другой детали (крышке) делается ответный паз или отверстие.
- При сборке язычок изгибается, проходит над стенкой и защелкивается в пазу.
Ваши знания в области физики и математики здесь могут быть очень кстати, так как расчет прочности и упругости такой защёлки — это классическая задача сопромата о изгибе консольной балки.
Design Unbreakable Pins with Perfect Tolerances
Чтобы понять, как проектировать прочные элементы для 3D-печати, такие как штифты или крючки защёлок, посмотрите это видео. Оно объясняет базовые принципы, которые помогут избежать поломки.
Обратите внимание на советы по добавлению скруглений (fillets) в основании элемента для увеличения прочности и фасок (chamfers) для легкого сопряжения деталей. Эти же принципы критически важны и для защёлок.
Реализация защёлок в build123d — интересная задача для самостоятельной проработки. Она потребует создания кастомного эскиза профиля защёлки на боковой стенке и его последующего выдавливания.
Проверьте себя!
Вы решили использовать не винты с головкой под шестигранник (SocketHeadCapScrew), а винты с потайной головкой (CounterSunkScrew). Какие изменения нужно внести в код?
Показать ответ
Изменения будут минимальны, что демонстрирует мощь библиотеки bd_warehouse:
- Изменить импорт:
from bd_warehouse.fastener import ..., CounterSunkScrew - Изменить создание объекта винта:
m3_screw = CounterSunkScrew(size=SCREW_SIZE, length=SCREW_LENGTH) - Функция
add_lid_holesпродолжит работать без изменений! Параметрcounter_sunk=TrueвClearanceHoleавтоматически создаст правильное коническое углубление для потайной головки, используя параметры из объектаm3_screw.
Ключевые выводы
- Мы спроектировали крышку и основание, которые сопрягаются с помощью выступа-фальца для точного позиционирования.
- Мы реализовали надежный механизм винтового соединения, используя бобышки и термозакладные втулки.
- Мы научились использовать библиотеку
bd_warehouseдля создания параметрического крепежа (HeatSetNut,SocketHeadCapScrew) и соответствующих отверстий (InsertHole,ClearanceHole). - Мы обсудили защёлки как альтернативный метод соединения, требующий более глубокой проработки и учета свойств материала.
- Наш проект теперь состоит из двух полноценных, готовых к экспорту и печати деталей.
Что дальше?
Наш дизайн полностью готов в цифровом виде. Но будет ли он так же хорош в реальности? Точность 3D-принтера, усадка пластика, настройки слайсера — всё это вносит свои коррективы. В следующем уроке мы займемся самым важным этапом перед печатью больших деталей: подготовим и напечатаем тестовые образцы для проверки ключевых допусков, таких как посадка крышки и соединения винтов. Это сэкономит нам массу времени и пластика.