Skip to main content

Someone wanted to learn this too, so Grasp built them a personal learning path.

You can keep exploring this one or create your own

Выбор и реализация механизма соединения деталей корпуса.

Здравствуйте!

На прошлом уроке мы превратили монолитный блок в функциональное основание корпуса, добавив монтажные стойки для печатной платы и вырезы для портов. У нас есть параметрический и готовый к дальнейшей работе final_base.

Сегодня мы делаем финальный шаг в проектировании: реализуем механизм соединения для обеих частей корпуса. Это означает, что мы не только создадим крышку, но и спроектируем элементы, которые будут надежно скреплять ее с основанием.

Мы рассмотрим два популярных подхода:

  1. Винтовое соединение: надежный и классический метод, который мы реализуем с помощью бобышек и винтов. Мы будем использовать специальные библиотеки, чтобы не моделировать крепеж вручную.
  2. Защелки (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)

Винты — это надежно, но иногда хочется, чтобы корпус собирался и разбирался без инструментов. Здесь на помощь приходят защёлки.

Types of Snap-Fit Joints
Существует много видов защёлок. Для нашего корпуса лучше всего подходит консольная (Cantilever), показанная слева вверху.

Проектирование хорошей защёлки требует учета свойств материала (например, PETG или ABS гнутся лучше, чем PLA) и точных допусков. Это более сложная тема, чем винтовое соединение, и требует итеративной печати и доработки.

Принцип работы:

  1. На одной детали (например, на основании) создается гибкий "язычок" (консоль) с крючком на конце.
  2. На другой детали (крышке) делается ответный паз или отверстие.
  3. При сборке язычок изгибается, проходит над стенкой и защелкивается в пазу.

Ваши знания в области физики и математики здесь могут быть очень кстати, так как расчет прочности и упругости такой защёлки — это классическая задача сопромата о изгибе консольной балки.

Design Unbreakable Pins with Perfect Tolerances

Чтобы понять, как проектировать прочные элементы для 3D-печати, такие как штифты или крючки защёлок, посмотрите это видео. Оно объясняет базовые принципы, которые помогут избежать поломки.

Обратите внимание на советы по добавлению скруглений (fillets) в основании элемента для увеличения прочности и фасок (chamfers) для легкого сопряжения деталей. Эти же принципы критически важны и для защёлок.

Реализация защёлок в build123d — интересная задача для самостоятельной проработки. Она потребует создания кастомного эскиза профиля защёлки на боковой стенке и его последующего выдавливания.

Проверьте себя!

Вы решили использовать не винты с головкой под шестигранник (SocketHeadCapScrew), а винты с потайной головкой (CounterSunkScrew). Какие изменения нужно внести в код?

Показать ответ

Изменения будут минимальны, что демонстрирует мощь библиотеки bd_warehouse:

  1. Изменить импорт: from bd_warehouse.fastener import ..., CounterSunkScrew
  2. Изменить создание объекта винта: m3_screw = CounterSunkScrew(size=SCREW_SIZE, length=SCREW_LENGTH)
  3. Функция add_lid_holes продолжит работать без изменений! Параметр counter_sunk=True в ClearanceHole автоматически создаст правильное коническое углубление для потайной головки, используя параметры из объекта m3_screw.

Ключевые выводы

  • Мы спроектировали крышку и основание, которые сопрягаются с помощью выступа-фальца для точного позиционирования.
  • Мы реализовали надежный механизм винтового соединения, используя бобышки и термозакладные втулки.
  • Мы научились использовать библиотеку bd_warehouse для создания параметрического крепежа (HeatSetNut, SocketHeadCapScrew) и соответствующих отверстий (InsertHole, ClearanceHole).
  • Мы обсудили защёлки как альтернативный метод соединения, требующий более глубокой проработки и учета свойств материала.
  • Наш проект теперь состоит из двух полноценных, готовых к экспорту и печати деталей.

Что дальше?

Наш дизайн полностью готов в цифровом виде. Но будет ли он так же хорош в реальности? Точность 3D-принтера, усадка пластика, настройки слайсера — всё это вносит свои коррективы. В следующем уроке мы займемся самым важным этапом перед печатью больших деталей: подготовим и напечатаем тестовые образцы для проверки ключевых допусков, таких как посадка крышки и соединения винтов. Это сэкономит нам массу времени и пластика.

Can't find a good explanation? Sign up and we'll make it for you

Sign up