Здравствуйте!
На прошлом уроке мы создали параметрическую модель печатной платы — нашего «цифрового двойника». Мы поместили её внутрь корпуса, чтобы визуализировать компоновку. Теперь плата «парит» в воздухе на дне основания. Наша задача — спроектировать для неё надёжную опору.
Цель этого урока — спроектировать монтажные стойки (standoffs). Это цилиндрические или многогранные выступы, которые поднимаются со дна корпуса и служат опорой для печатной платы. Они обеспечивают зазор для компонентов на нижней стороне платы, улучшают вентиляцию и являются основой для будущего крепления.

Мы продолжим следовать принципу проектирования «сверху вниз» (top-down design): вместо того чтобы вычислять координаты стоек заново, мы получим их напрямую из созданной нами модели печатной платы.
1. Подготовка и новые параметры
Давайте скопируем наш предыдущий файл enclosure_v5.py и назовем его enclosure_v6.py. В этом файле мы и будем работать.
Для проектирования стоек нам понадобятся два новых параметра. Добавьте их в ваш скрипт, например, после параметров платы.
# enclosure_v6.py
# ... после параметров PCB ...
# ================== ПАРАМЕТРЫ СТОЕК (STANDOFFS) ==================
# Высота стойки, определяет зазор между платой и дном корпуса
standoff_height = 6.0
# Внешний диаметр стойки
standoff_diameter = 7.0
Высота standoff_height в 6 мм создаст достаточный зазор для большинства компонентов, монтируемых на обратной стороне платы. Диаметр в 7 мм обеспечит стойке необходимую прочность.

2. Программное извлечение координат
Ключевая идея этого урока — не дублировать информацию. Координаты монтажных отверстий уже определены в нашей модели the_pcb. Нам лишь нужно их оттуда извлечь.
build123d позволяет запрашивать геометрические элементы объекта. Мы можем получить все рёбра (edges) нашей модели платы, отфильтровать из них только круговые (рёбра монтажных отверстий) и затем получить координаты их центров.
Это делается очень элегантно с помощью list comprehension — конструкции, которая вам хорошо знакома из Python.
Добавьте следующий код в раздел ВИЗУАЛИЗАЦИЯ после создания the_pcb:
# ... в разделе ВИЗУАЛИЗАЦИЯ ...
# Создаем плату, используя параметры
the_pcb = create_pcb(...)
# Программно получаем центры монтажных отверстий из модели платы
# 1. Выбираем все рёбра (edges)
# 2. Фильтруем те, что являются окружностями (is_circular)
# 3. Создаем список векторов с их центрами
hole_centers = [edge.center() for edge in the_pcb.edges().filter_by(Edge.is_circular)]
# hole_centers теперь содержит список Vector(x, y, z) для каждого отверстия
# Например: [Vector(40.75, 24.5, 0.0), Vector(-40.75, 24.5, 0.0), ...]
Таким образом, если вы измените параметры расположения отверстий в create_pcb, код для создания стоек автоматически адаптируется, так как он напрямую зависит от геометрии the_pcb.
3. Создание стоек с помощью Locations
Теперь, имея список центров hole_centers, мы можем создать стойки. Мы могли бы сделать это в цикле, но в build123d есть более идиоматичный способ — контекстный менеджер Locations. Он позволяет применить одну и ту же операцию (в нашем случае, создание цилиндра) в нескольких точках пространства.
- Создадим новый
BuildPartдля наших стоек. - Используем
with Locations(*hole_centers):, чтобы указать, где будут создаваться объекты. Звёздочка*здесь распаковывает наш список векторов в отдельные аргументы дляLocations. - Внутри контекста создаём один
Cylinder.build123dавтоматически создаст его копии во всех указанных точках.
# ... после получения hole_centers ...
# Создаем четыре стойки как единую деталь (Compound)
with BuildPart() as standoffs:
with Locations(*hole_centers):
Cylinder(
radius=standoff_diameter / 2,
height=standoff_height,
align=(Align.CENTER, Align.CENTER, Align.BOTTOM) # Выравниваем по нижнему основанию
)
# standoffs.part теперь содержит 4 цилиндра, расположенных в нужных XY координатах,
# но пока что на плоскости Z=0.
Обратите внимание на align=(Align.CENTER, Align.CENTER, Align.BOTTOM). Это выравнивает цилиндры так, чтобы их основание находилось на плоскости Z=0. Это упростит их последующее позиционирование.
4. Интеграция стоек в основание корпуса
На данный момент у нас есть два отдельных объекта: base_with_lip (основание) и standoffs.part (стойки). Нам нужно объединить их.
- Позиционирование стоек: Стойки должны начинаться от «пола» основания. Мы уже вычисляли Z-координату пола в прошлом уроке:
floor_z = -enclosure_height / 2 + wall_thickness. - Объединение: После перемещения стоек на нужную высоту мы можем просто «сложить» их с основанием с помощью оператора
+.
# ... после создания стоек ...
# Вычисляем Z-координату "пола" основания
floor_z = -enclosure_height / 2 + wall_thickness
# Перемещаем стойки на пол основания
positioned_standoffs = standoffs.part.moved(Location(Vector(0, 0, floor_z)))
# Добавляем стойки к основанию
base_with_standoffs = base_with_lip + positioned_standoffs
Готово! base_with_standoffs теперь является монолитной деталью, включающей в себя и стойки.
5. Финальная сборка и проверка
Последний штрих — обновить положение самой печатной платы. Она больше не лежит на дне, а опирается на верхушки стоек.
Новая Z-координата центра платы будет равна: координата пола + высота стойки + половина толщины платы.
Обновите код визуализации:
# ... в конце файла, в разделе ВИЗУАЛИЗАЦИЯ ...
# Новая Z-позиция для центра платы
pcb_z_pos = floor_z + standoff_height + pcb_thickness / 2
if "show_object" in locals():
# Отображаем основание со стойками
show_object(base_with_standoffs, name="Base with Standoffs")
# Отображаем крышку (смещена для наглядности)
show_object(lid_with_groove.moved(Location(Vector(0, 0, 15))), name="Lid with Groove")
# Отображаем плату, размещенную на стойках
show_object(the_pcb.moved(Location(Vector(0, 0, pcb_z_pos))), name="PCB on Standoffs")
Запустите скрипт enclosure_v6.py. Вы должны увидеть, как печатная плата аккуратно лежит на четырёх стойках, а её монтажные отверстия идеально совпадают с центрами этих стоек.
Проверьте себя!
Предположим, для лучшей фиксации платы вы хотите, чтобы стойки были не цилиндрическими, а шестигранными.
Задание: Как изменить код в блоке with BuildPart() as standoffs:, чтобы создать шестигранные стойки вместо цилиндрических? Диаметр вписанной в шестигранник окружности должен быть равен standoff_diameter.
Показать решение
Вместо Cylinder нужно использовать комбинацию BuildSketch и extrude. Внутри эскиза мы нарисуем шестигранник с помощью RegularPolygon.
# Заменяем блок создания стоек на этот:
with BuildPart() as standoffs:
with Locations(*hole_centers):
# Создаем эскиз на плоскости XY
with BuildSketch() as standoff_sketch:
RegularPolygon(
radius=standoff_diameter / 2, # Это радиус описанной окружности
side_count=6
)
# Выдавливаем эскиз вверх
extrude(amount=standoff_height)
# Примечание: RegularPolygon по умолчанию использует радиус описанной окружности.
# Если требуется радиус вписанной, его можно рассчитать: inscribed_radius = circumscribed_radius * cos(pi / side_count)
# или использовать Polygon и задать вершины вручную, но RegularPolygon проще.
Весь остальной код останется без изменений, что еще раз демонстрирует гибкость и модульность такого подхода.
Ключевые выводы
- Мы спроектировали монтажные стойки, которые точно соответствуют монтажным отверстиям на печатной плате.
- Мы применили мощный приём: программное извлечение геометрических данных (
.edges().filter_by()) из одной детали для управления созданием другой. - Мы использовали контекстный менеджер
Locationsдля эффективного создания повторяющихся элементов. - Мы обновили положение платы, чтобы она корректно отображалась на созданных опорах.
Что дальше?
Наша плата теперь имеет опору, но никак не закреплена на ней. Если перевернуть корпус, она просто выпадет. В следующем уроке мы решим эту проблему: создадим в стойках пилотные отверстия для саморезов, которые будут надёжно фиксировать плату на месте.