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

Проектирование портов: USB и Ethernet

Recommended resources

The freely available resources this lesson will direct you to.

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

В прошлом уроке мы разобрались с одной из самых важных концепций в 3D-печати — допусками. Вы научились определять и применять зазоры (clearances), превратив "магические числа" в параметрические переменные вроде TIGHT_FIT_CLEARANCE и LOOSE_FIT_CLEARANCE. Это дало нам уверенность в том, что спроектированные части корпуса соберутся вместе.

Теперь, вооружившись этим знанием, мы можем перейти к созданию функциональных элементов. Цель этого урока — научиться проектировать точные вырезы для портов, таких как USB и Ethernet, на стенках корпуса. Это критически важный шаг, чтобы ваша электроника могла взаимодействовать с внешним миром.

3D-печатный корпус для Raspberry Pi с функциональными вырезами
Корпус для одноплатного компьютера с точно подогнанными вырезами для портов Ethernet, USB и разъема антенны. Это то, чего мы стремимся достичь в этом уроке.

Мы будем использовать уже знакомые вам техники, но применять их для новой задачи: будем выбирать нужную грань корпуса, создавать на ней 2D-эскиз профиля порта и "вырезать" его из стенки.

1. Основной принцип: Эскиз на грани

Ключевой рабочий процесс для создания любого выреза на существующей поверхности состоит из трёх шагов:

  1. Выбрать целевую грань (Face): Нам нужно программно идентифицировать ту стенку корпуса, где будет располагаться вырез.
  2. Создать на ней эскиз (Sketch): На этой грани мы рисуем двумерный профиль будущего отверстия (например, прямоугольник для USB).
  3. Выдавить с вычитанием (Subtractive Extrude): Мы "выдавливаем" этот эскиз сквозь стенку, удаляя материал.

Этот подход является фундаментальным в build123d.

Introductory Examples - Creating Workplanes on Faces

В официальной документации build123d есть отличный пример, иллюстрирующий именно этот процесс. Давайте его изучим.

Найдите раздел '18. Creating Workplanes on Faces'. Обратите внимание на строки кода, где с помощью ex18.faces().sort_by(Axis.Z)[-1] выбирается верхняя грань, на ней создается эскиз with BuildSketch(...), а затем extrude(amount=-thickness, mode=Mode.SUBTRACT) вырезает отверстие.

Как видите, build123d позволяет использовать любую плоскую грань существующего объекта как новую рабочую плоскость. Это невероятно мощный инструмент.

2. Практика: Вырез под порт USB-A

Давайте применим этот принцип на практике. Создадим простой полый короб и вырежем в одной из его стенок отверстие для стандартного порта USB-A.

Для начала, нам нужен базовый корпус. Можете использовать код из предыдущих уроков или этот простой пример:

# enclosure_v13.py
from build123d import *

# ================== ПАРАМЕТРЫ ==================
# Габариты корпуса
enclosure_length = 100
enclosure_width = 80
enclosure_height = 40
wall_thickness = 2

# Допуски (из прошлого урока)
LOOSE_FIT_CLEARANCE = 0.4 # Для свободной посадки

# Размеры порта USB-A (металлический кожух)
usb_a_width = 13.0
usb_a_height = 5.5

# ================== МОДЕЛИРОВАНИЕ ==================
# Создаем монолитный блок
with BuildPart() as enclosure:
    Box(enclosure_length, enclosure_width, enclosure_height)
    
    # Делаем его полым
    offset(amount=-wall_thickness, openings=enclosure.faces().sort_by(Axis.Z)[-1])

    # --- Создание выреза для USB-A ---
    
    # 1. Выбираем целевую грань. 
    #    sort_by(Axis.X)[0] выбирает грань с минимальной координатой X.
    target_face = enclosure.faces().sort_by(Axis.X)[0]
    
    # 2. Создаем эскиз на этой грани
    with BuildSketch(target_face):
        # 3. Рисуем профиль порта с учетом зазора
        Rectangle(
            usb_a_width + LOOSE_FIT_CLEARANCE, 
            usb_a_height + LOOSE_FIT_CLEARANCE
        )
        
    # 4. Выдавливаем эскиз для создания выреза
    extrude(amount=-wall_thickness, mode=Mode.SUBTRACT)

if "show_object" in locals():
    show_object(enclosure.part)

Разбор кода:

  • enclosure.faces().sort_by(Axis.X)[0]: Это ключевая строка для выбора грани.
    • faces() получает список всех граней объекта.
    • sort_by(Axis.X) сортирует их по положению центра вдоль оси X.
    • [0] выбирает первую грань в отсортированном списке, то есть ту, что находится в "минимальном" X (условно, "левая" стенка). Соответственно, [-1] выбрало бы "правую".
  • Rectangle(width + LOOSE_FIT_CLEARANCE, ...): Мы сразу применяем знания из прошлого урока. Чтобы коннектор USB свободно входил, мы делаем отверстие немного больше его физических размеров.
  • extrude(amount=-wall_thickness, mode=Mode.SUBTRACT): Отрицательное значение amount указывает направление "внутрь" детали, а Mode.SUBTRACT предписывает вычесть этот объем из основного тела.

Теперь вы можете запустить этот скрипт и увидеть в OCP CAD Viewer полый короб с аккуратным прямоугольным вырезом.

3. Сложные профили и точное позиционирование

Порты редко располагаются точно по центру стенки. Кроме того, их форма может быть сложнее простого прямоугольника (например, порт Ethernet с выступом под защёлку).

Давайте усовершенствуем наш подход, чтобы разместить вырез в произвольном месте и придать ему более сложную форму.

3.1. Позиционирование с помощью Location

Вместо того чтобы рисовать эскиз по центру грани, мы можем точно его спозиционировать. Допустим, по нашей задумке, центр USB-порта должен находиться на высоте 15 мм от основания корпуса.

# ... (внутри 'with BuildPart() as enclosure')

# Выбираем грань
target_face = enclosure.faces().sort_by(Axis.X)[0]
    
# Создаем эскиз на этой грани
with BuildSketch(target_face):
    # Используем Location для точного позиционирования
    with Locations((0, 15 - enclosure_height / 2, 0)):
        Rectangle(
            usb_a_width + LOOSE_FIT_CLEARANCE, 
            usb_a_height + LOOSE_FIT_CLEARANCE
        )
# ... extrude ...

Объяснение:
Locations создает контекст, в котором все создаваемые объекты смещаются. Координаты (x, y, z) задаются в локальной системе координат грани. Поскольку начало координат грани находится в её центре, нам нужно вычислить смещение относительно него. Если enclosure_height равен 40, то центр грани по Z находится на z=20. Чтобы поднять порт на z=15, нам нужно сместиться на 15 - 20 = -5. Однако BuildSketch работает в 2D, и для вертикальной грани оси могут быть (x, y). В нашем случае для грани на плоскости YZ локальная ось y будет соответствовать глобальной Z. Поэтому мы смещаем по второй координате: (0, 15 - enclosure_height / 2).

Более надежный подход, который вы оцените, имея опыт в программировании — связать позицию выреза с позицией компонента на вашей печатной плате.

Предположим, ваша плата стоит на дне корпуса, а центр USB-порта на плате имеет координаты (x_pcb, y_pcb) относительно угла платы. Тогда вырез на стенке корпуса будет на высоте z_pcb_mount_height + z_port_on_pcb. Этот параметрический подход — залог легко изменяемых и надёжных моделей.

3.2. Создание сложных профилей

А что если нам нужен вырез под порт Ethernet (RJ45)? Его профиль — это, по сути, два прямоугольника.

Лучшая практика — инкапсулировать создание сложного эскиза в отдельную функцию или контекстный менеджер. Это делает код чище и позволяет повторно использовать профиль порта в других проектах.

# Поместим это в начало файла, после импортов

def rj45_port_sketch(clearance: float = 0.0):
    """Создает эскиз для выреза под порт RJ45."""
    # Размеры из стандарта (приблизительные)
    port_width = 16.0
    port_height = 13.5
    latch_width = 8.0
    latch_height = 2.0
    
    # Создаем основной прямоугольник
    with BuildSketch() as rj45:
        # Основной корпус
        Rectangle(port_width + clearance, port_height + clearance, align=(Align.CENTER, Align.MIN))
        # Вырез под защелку снизу
        with Locations((0, (port_height + clearance)/2, 0)):
             Rectangle(latch_width + clearance, latch_height + clearance, mode=Mode.SUBTRACT)
    return rj45

Теперь мы можем использовать эту функцию для создания выреза:

# ... (внутри 'with BuildPart() as enclosure')

# Выбираем другую грань для примера
rj45_face = enclosure.faces().sort_by(Axis.Y)[-1] # "Дальняя" стенка

with BuildSketch(rj45_face):
    with Locations((0, 15 - enclosure_height / 2, 0)):
        add(rj45_port_sketch(clearance=LOOSE_FIT_CLEARANCE))
        
extrude(amount=-wall_thickness, mode=Mode.SUBTRACT)

Такой подход превращает проектирование в работу с высокоуровневыми, самодокументируемыми блоками.

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

Вам нужно создать вырез для круглого разъёма питания (barrel jack) диаметром 7 мм. Вы хотите, чтобы он входил плотно, поэтому решаете использовать TIGHT_FIT_CLEARANCE = 0.2 мм. Вырез должен быть на "правой" стенке корпуса (enclosure_length=100, enclosure_width=80, enclosure_height=40). Какой код вы напишете внутри контекста with BuildPart() as enclosure: для создания этого выреза?

Показать ответ
# Определяем параметры
barrel_jack_diameter = 7.0
TIGHT_FIT_CLEARANCE = 0.2

# 1. Выбираем "правую" грань (с максимальной координатой X)
target_face = enclosure.faces().sort_by(Axis.X)[-1]

# 2. Создаем эскиз на этой грани
with BuildSketch(target_face):
    # 3. Рисуем окружность с учётом плотного зазора
    Circle(radius=(barrel_jack_diameter + TIGHT_FIT_CLEARANCE) / 2)
    
# 4. Вырезаем отверстие
extrude(amount=-wall_thickness, mode=Mode.SUBTRACT)

Ключевые моменты: выбор грани с помощью sort_by(Axis.X)[-1], использование Circle для эскиза, и применение TIGHT_FIT_CLEARANCE к диаметру.

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

  • Основной метод создания вырезов — это выбор грани, создание на ней 2D-эскиза и его "вычитающее" выдавливание (extrude с Mode.SUBTRACT).
  • Для выбора нужной грани удобно использовать фильтрацию и сортировку, например, part.faces().sort_by(Axis.X)[0].
  • Положение выреза на грани можно точно задать с помощью контекста Locations.
  • При проектировании вырезов необходимо всегда учитывать допуски (clearances), чтобы обеспечить правильную посадку коннекторов.
  • Сложные профили портов рекомендуется инкапсулировать в отдельные функции для чистоты и переиспользования кода.

Что дальше?

Сегодня мы научились делать одиночные, но точные вырезы. В следующем уроке мы разовьём эту идею и научимся создавать целые массивы вырезов. Это позволит нам проектировать такие элементы, как вентиляционные решётки, используя уже знакомые нам циклы и паттерны из build123d.

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

Sign up