znlgis 博客

GIS开发与技术分享

第12章:实战案例:机械结构与 3D 打印零件

1. 实战目标

本章以一个“带盖电子小盒”为案例,综合使用参数、模块、布尔、孔位、螺丝柱、圆角板和命令行导出。案例不追求复杂外观,而强调工程结构的可复用写法。

2. 需求定义

假设需求:

  • 外壳外尺寸可配置。
  • 底壳开口向上,有固定壁厚。
  • 四角有 M3 螺丝柱。
  • 盖板有对应通孔。
  • 侧面有一个线缆孔。
  • 可分别导出底壳、盖板和装配预览。
  • 尺寸默认按 FDM 打印,单位毫米。

3. 参数区

$fn = 48;

part = "assembly"; // "base", "lid", "assembly"
box_size = [90, 55, 28];
wall = 2.4;
lid_thickness = 3;
corner_r = 5;
screw_d = 3.2;
screw_post_d = 9;
clearance = 0.3;

参数应集中在文件顶部,让用户不用阅读全部几何也能修改规格。

4. 圆角矩形工具

module rounded_rect_2d(size = [40, 20], r = 4) {
    hull() {
        for (x = [-size[0]/2+r, size[0]/2-r])
            for (y = [-size[1]/2+r, size[1]/2-r])
                translate([x,y]) circle(r = r);
    }
}

module rounded_box_solid(size = [60,40,20], r = 4) {
    linear_extrude(height = size[2], center = true)
        rounded_rect_2d([size[0], size[1]], r);
}

这里使用二维 hull 后拉伸,性能比三维圆角更可控。

5. 螺丝柱孔位

function screw_positions(size, inset) = [
    [-size[0]/2+inset, -size[1]/2+inset],
    [ size[0]/2-inset, -size[1]/2+inset],
    [ size[0]/2-inset,  size[1]/2-inset],
    [-size[0]/2+inset,  size[1]/2-inset]
];

把孔位写成函数可以让底壳和盖板共用,避免孔位不一致。

6. 底壳主体

module base_shell() {
    difference() {
        rounded_box_solid(box_size, corner_r);
        translate([0,0,wall])
            rounded_box_solid([box_size[0]-2*wall, box_size[1]-2*wall, box_size[2]], max(corner_r-wall, 1));
        translate([0, -box_size[1]/2, 3]) rotate([90,0,0])
            cylinder(h = wall + 1, d = 10, center = true);
    }
}

开腔时内部切除体向上偏移,保留底板厚度。线缆孔作为侧面圆柱切除。

7. 螺丝柱

module screw_posts() {
    post_h = box_size[2] - wall - lid_thickness;
    for (p = screw_positions(box_size, 10))
        translate([p[0], p[1], -box_size[2]/2 + wall + post_h/2])
            difference() {
                cylinder(h = post_h, d = screw_post_d, center = true);
                cylinder(h = post_h + 1, d = screw_d, center = true);
            }
}

螺丝柱要考虑打印方向和强度。孔径是否需要攻丝、热熔铜螺母或自攻螺丝,应根据工艺调整。

8. 底壳总成

module base() {
    union() {
        base_shell();
        screw_posts();
    }
}

实际项目还可以加入加强筋、卡扣、定位台阶和倒角。

9. 盖板

module lid() {
    difference() {
        translate([0,0,box_size[2]/2 + lid_thickness/2 + clearance])
            rounded_box_solid([box_size[0], box_size[1], lid_thickness], corner_r);
        for (p = screw_positions(box_size, 10))
            translate([p[0], p[1], box_size[2]/2 + lid_thickness/2 + clearance])
                cylinder(h = lid_thickness + 1, d = screw_d, center = true);
    }
}

盖板与底壳之间使用 clearance 留出装配间隙。若要隐藏螺丝头,可加入沉孔或沉头。

10. 装配与导出

module assembly() {
    color("lightgray") base();
    color("skyblue", 0.6) lid();
}

if (part == "base") base();
else if (part == "lid") lid();
else assembly();

命令行:

openscad -D 'part="base"' -o base.stl box.scad
openscad -D 'part="lid"' -o lid.stl box.scad
openscad -D 'part="assembly"' -o assembly.png --imgsize=1200,800 box.scad

11. 打印前检查

  • 壁厚是否是喷嘴宽度的合理倍数?
  • 螺丝柱是否太细或太高?
  • 孔径是否包含打印收缩补偿?
  • 线缆孔是否需要倒角或圆角?
  • 盖板是否有足够间隙?
  • 是否需要避免大面积悬垂?
  • 底面是否平整放置在打印平台?

12. 扩展练习

  1. 为盒体添加 USB-C 开口。
  2. 增加热熔铜螺母孔。
  3. 盖板增加沉头螺丝孔。
  4. 添加内部 PCB 固定柱。
  5. text 添加型号和方向标识。
  6. 创建 smallmediumlarge 三种规格。
  7. 增加 quality 参数控制导出精度。