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

Добавление ответных элементов для защёлок/винтов

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

На прошлом уроке мы спроектировали консольные защёлки, добавив их на крышку корпуса. Они готовы к работе, но им пока не за что цепляться. Также в одном из предыдущих уроков мы создали бобышки для винтового соединения.

Сегодня мы завершим оба этих механизма, добавив ответные элементы на сопрягаемые детали. В результате у нас будет две полностью готовые к сборке версии корпуса: одна на винтах, другая на защёлках. Мы научимся создавать точные посадочные места как для винтов, используя мощную библиотеку bd_warehouse, так и для спроектированных нами защёлок.

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

Давайте начнём с винтового соединения, так как оно позволит нам познакомиться с очень полезным инструментом для параметрического проектирования.

1. Ответные элементы для винтового соединения

Вместо того чтобы вручную вычислять диаметры отверстий под винты и их головки, мы воспользуемся библиотекой bd_warehouse. Это расширение для build123d, которое содержит параметрические модели стандартизированных компонентов: подшипников, винтов, гаек и т.д. Такой подход, аналогичный импорту готовых модулей в Python, значительно ускоряет разработку и уменьшает вероятность ошибок.

1.1. Установка bd_warehouse

Если вы ещё не установили библиотеку, добавьте её в ваш проект с помощью uv:

uv pip install bd_warehouse

1.2. Создание сквозных отверстий в основании

Предположим, у нас есть крышка с бобышками (lid_with_bosses) и основание (base_final). Наша задача — сделать в основании сквозные отверстия (clearance holes), через которые винты будут свободно проходить и вкручиваться в пилотные отверстия в бобышках. Головка винта должна быть утоплена в основание (countersunk).

Откройте ваш проект (рекомендую сохранить его как enclosure_v11.py) и давайте модифицируем код для создания основания.

FASTENER - PARAMETRIC THREADED FASTENERS (bd_warehouse docs)

Прежде чем мы напишем код, ознакомьтесь с документацией на bd_warehouse, чтобы понять, какие возможности она предоставляет для создания отверстий. Это поможет вам лучше понять код, который мы напишем.

Прочтите раздел 3.4 Custom Holes (стр. 15-20). Особое внимание уделите классу ClearanceHole и его параметрам, таким как fastener, fit и counter_sunk. Этот раздел подробно описывает, как библиотека автоматически создаёт правильные отверстия на основе модели крепежа.

Теперь применим эти знания. Вот как будет выглядеть код для создания основания с правильными отверстиями под винты M3. Предполагается, что у вас уже есть код, создающий base_final (монолитное основание) и boss_locations (GridLocations для размещения бобышек).

# enclosure_v11.py

# ... импорты и параметры ...
from bd_warehouse.fastener import SocketHeadCapScrew, ClearanceHole
from build123d import *

# ... (код для создания pcb_model, base_height, enclosure_dimensions и т.д.) ...

# ================== ПАРАМЕТРЫ КРЕПЛЕНИЯ (ВИНТЫ) ==================
# Определяем, какой винт мы будем использовать
# Длина винта должна быть достаточной, чтобы пройти через основание и войти в бобышку
# base_thickness + (длина резьбы в бобышке)
# Например, 10 мм + 8 мм = 18 мм. Возьмём стандартную длину 20 мм.
fastener_screw = SocketHeadCapScrew(size="M3-0.5", length=20)

# Расположение бобышек/винтов
boss_padding = 10
boss_locations = GridLocations(
    enclosure_dimensions.X - boss_padding * 2,
    enclosure_dimensions.Y - boss_padding * 2,
    2,
    2,
)

# ... (код создания base_final) ...

# ================== МОДИФИКАЦИЯ ОСНОВАНИЯ (ОТВЕРСТИЯ ПОД ВИНТЫ) ==================
with BuildPart() as base_with_holes:
    add(base_final) # Начинаем с существующего основания
    
    # Размещаем кастомные отверстия в тех же местах, что и бобышки
    with Locations(boss_locations):
        # ClearanceHole автоматически создаст сквозное отверстие
        # с углублением под головку винта (т.к. у SocketHeadCapScrew она есть)
        ClearanceHole(fastener=fastener_screw)

base_final_screws = base_with_holes.part

# ... (в блоке визуализации)
# if "show_object" in locals():
#     show_object(base_final_screws, name="base_with_screws")
#     show_object(lid_with_bosses, name="lid_with_bosses") # Предполагается, что эта деталь есть

Ключевые моменты:

  • Мы создаём экземпляр SocketHeadCapScrew, описывая наш винт. bd_warehouse знает все его размеры по стандарту ISO.
  • Мы используем ClearanceHole, передавая ему наш fastener_screw. Объект сам вычисляет нужный диаметр сквозного отверстия и размеры углубления под головку.
  • Параметр depth=None (по умолчанию) означает, что отверстие будет сквозным.
  • Код получается декларативным и чистым. Мы описываем что хотим сделать (отверстие под винт), а не как (диаметры, глубины, булевы операции).

1.3. Pro-Tip: Использование закладных гаек (Captive Nuts)

Вкручивание саморезов в пластик — рабочий, но не самый надёжный метод, особенно если предполагается частая сборка/разборка. Гораздо прочнее использовать стандартный болт и гайку. Чтобы гайка не прокручивалась при затягивании, для неё делают специальное шестигранное гнездо — nut trap.

bd_warehouse делает создание таких гнёзд тривиальной задачей. Вместо бобышек на крышке мы сделаем посадочные места под гайки.

Взгляните на раздел 3.4.1 Captive Nuts (стр. 20) в той же документации LINK.

Давайте модифицируем крышку. Вместо добавления бобышек мы вычтем из неё ClearanceHole с параметром captive_nut=True.

# Пример создания крышки с гнёздами под гайки
from bd_warehouse.fastener import HexNut

# ...
fastener_nut = HexNut(size="M3-0.5", fastener_type="iso4032")
# ...

# Вместо with BuildPart() as lid_with_bosses:
with BuildPart() as lid_with_nut_traps:
    add(lid_final) # Наша полая крышка с фальцем
    
    # Переворачиваемся на внутреннюю сторону крышки
    with BuildSketch(Plane.XY.offset(base_height)):
        with Locations(boss_locations):
            # Создаём гнездо под гайку и сквозное отверстие
            ClearanceHole(fastener=fastener_nut, captive_nut=True)

lid_final_nuts = lid_with_nut_traps.part

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

2. Ответные элементы для защёлок

Теперь вернёмся к защёлкам из предыдущего урока. У нас есть крышка lid_final_with_snaps. Нам нужно сделать в основании (base_final) пазы, за которые будут цепляться крючки защёлок.

3D CAD Rendering of a Two-Part Enclosure with Snap-Fit Mechanism
Пример собранного корпуса, где видны и защёлки на одной части, и ответные пазы на другой. Источник: Formlabs.

Логика здесь проста: мы должны создать "режущий инструмент" (cutting tool) по форме крючка защёлки (с небольшим зазором) и вычесть его из стенки основания.

Продолжим работу в файле enclosure_v11.py, используя код с защёлками из прошлого урока.

2.1. Расчёт геометрии паза

Положение и размер паза полностью определяются геометрией и расположением защёлки.

  • Расположение: Паз должен находиться точно там, где крючок защёлки входит в стенку основания.
  • Размер: Паз должен быть чуть больше крючка, чтобы обеспечить зазор для лёгкого защёлкивания.

Добавим новый параметр для зазора:

# ... после параметров защёлок ...
snap_slot_clearance = 0.3 # Зазор для паза защёлки

2.2. Создание пазов в основании

Мы будем использовать тот же snap_locations, что и для размещения защёлок, но применим его к основанию для создания вырезов.

# ... после создания base_final и snap_part ...

# ================ СОЗДАНИЕ ПАЗОВ В ОСНОВАНИИ ================
with BuildPart() as base_with_slots:
    add(base_final)

    # Размеры "режущего инструмента"
    cutter_width = snap_width + 2 * snap_slot_clearance
    cutter_depth = snap_hook_depth + snap_slot_clearance
    cutter_height = snap_hook_depth * 2 # С запасом, чтобы точно прорезать

    # Создаём режущий инструмент
    cutter = Box(
        length=cutter_width, 
        width=cutter_depth, 
        height=cutter_height,
        align=(Align.CENTER, Align.MIN, Align.MIN)
    )

    # Рассчитываем Y-координату для размещения на внутренней стенке основания
    # Позиционируем режущий инструмент так, чтобы он "врезался" в стенку изнутри
    y_pos_base = enclosure_dimensions.Y / 2 - wall_thickness
    
    # Высота, на которой крючок входит в стенку
    z_pos = base_height - snap_hook_depth / tan(radians(45))

    # Создаём два положения для вырезов
    slot_locations = [
        Location(Vector(0, y_pos_base, z_pos), rotation=Rotation(0, 0, 90)),
        Location(Vector(0, -y_pos_base, z_pos), rotation=Rotation(0, 0, -90)),
    ]

    for loc in slot_locations:
        add(cutter, location=loc, mode=Mode.SUBTRACT)

base_final_snaps = base_with_slots.part

Разбор кода:

  1. Мы создаём Box в качестве режущего инструмента. Его размеры немного больше, чем у крючка защёлки, за счёт snap_slot_clearance.
  2. Мы вычисляем y_pos_base, чтобы расположить режущий инструмент у внутренней стенки основания. align=(Align.CENTER, Align.MIN, Align.MIN) помогает правильно его сориентировать: центр по X, а по Y он будет "расти" наружу, прорезая стенку.
  3. z_pos вычисляется так, чтобы паз оказался на той же высоте, что и зацеп на защёлке.
  4. Мы используем два Location с поворотами на 90 и -90 градусов, чтобы правильно сориентировать cutter вдоль стенок.
  5. В цикле вычитаем cutter из основания.

Теперь обновите блок визуализации:

if "show_object" in locals():
    show_object(base_final_snaps, name="base_with_slots")
    show_object(lid_final_with_snaps, name="lid_with_snaps")

Запустив скрипт, вы увидите основание с аккуратными пазами, идеально совпадающими с защёлками на крышке.

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

Представьте, что после тестовой печати защёлка входит в паз слишком туго. Какой один параметр вы бы изменили в коде, чтобы увеличить зазор и облегчить сборку?

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

Самый простой и правильный способ — увеличить значение параметра snap_slot_clearance. Например, с 0.3 до 0.4. Это параметрически увеличит размеры режущего инструмента (cutter) и, соответственно, размер паза, не требуя изменения остальной логики.

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

  • Мы научились создавать ответные элементы для двух типов соединений: винтового и защёлок.
  • Библиотека bd_warehouse — мощный инструмент для работы со стандартным крепежом, который позволяет писать чистый, декларативный код и избегать ручного расчёта размеров отверстий.
  • Мы освоили профессиональный приём — создание гнёзд для закладных гаек (captive_nut), что значительно повышает надёжность соединения.
  • Для создания ответного паза под сложный элемент (защёлку) удобно использовать простой "режущий инструмент" (Box), размеры и положение которого параметрически связаны с исходным элементом.

Что дальше?

В этом уроке мы использовали "магические числа" для зазоров (например, snap_slot_clearance = 0.3). Хотя это сработало, в реальном мире идеального совпадения размеров не бывает из-за особенностей FDM-печати. В следующем, последнем практическом уроке этого модуля, мы системно подойдём к вопросу допусков (tolerances) и научимся проектировать детали так, чтобы они гарантированно собирались правильно после печати.

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

Sign up