Skip to content

Commit 72f0744

Browse files
committedNov 13, 2024
Create esp-pcb-40mm
1 parent 5dbf60e commit 72f0744

File tree

6 files changed

+324
-0
lines changed

6 files changed

+324
-0
lines changed
 

‎electronics/esp-pcb-40mm/LICENSE

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
This work is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/4.0/ or send a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.

‎electronics/esp-pcb-40mm/README.md

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# ESPHome 40x40mm PCB mount
2+
3+
![This model is a work in progress][work-in-progress-badge]
4+
[![CC-BY-SA-4.0 license][license-badge]][license]
5+
6+
PCB mount for custom 40x40mm ESPHome PCB designs
7+
8+
![Model render](images/readme/demo.png)
9+
10+
## License
11+
12+
This model is licensed under [Creative Commons (4.0 International License) Attribution-ShareAlike][license].
13+
14+
15+
[license]: http://creativecommons.org/licenses/by-sa/4.0/
16+
[license-badge]: /_static/license-badge-cc-by-sa-4.0.svg
17+
[work-in-progress-badge]: /_static/work-in-progress-badge.svg

‎electronics/esp-pcb-40mm/SConscript

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
Import("env")
2+
b = ModelBuilder(env)
3+
4+
model = "esp-pcb-40mm.scad"
5+
6+
for opts in GenerateOptions(
7+
x=[1, 2, 3], y=[1, 2, 3], screw_x=[(0, ""), (1, "-xscrew")], height=[6, 10]
8+
):
9+
b.STL(
10+
f"esp-pcb-40mm-{opts.x}x{opts.y}-{opts.height}mm{opts.screw_x_fn}.stl",
11+
model,
12+
{
13+
"PCB_X": opts.x,
14+
"PCB_Y": opts.y,
15+
"Height": opts.height,
16+
"Mounting_Screw_Holes_X": opts.screw_x,
17+
},
18+
)
19+
20+
b.Image("demo.png", model, {"Mounting_Screw_Holes_X": 1})
21+
22+
b.add_default_targets()
23+
24+
# vim: ft=python
+282
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,282 @@
1+
/*
2+
* ESPHome 40x40mm PCB mount
3+
* By smkent (GitHub) / bulbasaur0 (Printables)
4+
*
5+
* Licensed under Creative Commons (4.0 International License) Attribution-ShareAlike
6+
*/
7+
8+
/* [Rendering Options] */
9+
Preview_PCB = true;
10+
// Print_Orientation = true;
11+
12+
/* [PCB] */
13+
// 40mm units
14+
PCB_X = 1; // [1:1:3]
15+
16+
// 40mm units
17+
PCB_Y = 1; // [1:1:3]
18+
19+
/* [Size] */
20+
Height = 6; // [5:0.5:20]
21+
Thickness = 2.0; // [1:0.1:5]
22+
Edge_Radius = 0.5; // [0:0.5:1]
23+
Screw_Insert_Diameter = 4.5; // [3:0.1:6]
24+
25+
/* [Features] */
26+
Mounting_Screw_Holes_X = false;
27+
Mounting_Screw_Holes_Y = false;
28+
Mounting_Screw_Hole_Chamfer = false;
29+
Mounting_Screw_Diameter = 4.5;
30+
PCB_Support_Chamfer = 1.5; // [0:0.1:3]
31+
32+
/* [Advanced Options] */
33+
Inner_Holes = true;
34+
35+
module __end_customizer_options__() { }
36+
37+
// Constants //
38+
39+
$fa = $preview ? $fa : 2;
40+
$fs = $preview ? $fs : 0.4;
41+
42+
pcb_grid = 40;
43+
pcb_grid_sep = 2;
44+
corner_radius = 3;
45+
hole_inset = 3;
46+
pcb_hole_d = 3.2;
47+
pcb_thick = 1.6;
48+
49+
hole_d = Screw_Insert_Diameter;
50+
edge_outset = 2;
51+
hole_to_edge = edge_outset + hole_inset;
52+
pcb_hole_clearance = 2.495 + 0.5;
53+
edge_radius = Edge_Radius;
54+
55+
slop = 0.001;
56+
57+
// Functions //
58+
59+
pcb_x = PCB_X * pcb_grid + (PCB_X - 1) * pcb_grid_sep;
60+
pcb_y = PCB_Y * pcb_grid + (PCB_Y - 1) * pcb_grid_sep;
61+
62+
// Modules //
63+
64+
module hull_pair(height) {
65+
slop = 0.001;
66+
hull() {
67+
for (child_obj = [
68+
// Child index, height offset
69+
[0, 0],
70+
[1, height - slop]
71+
]) {
72+
translate([0, 0, child_obj[1]])
73+
linear_extrude(height=slop)
74+
children(child_obj[0]);
75+
}
76+
}
77+
}
78+
79+
module round_3d(radius = edge_radius) {
80+
if (radius == 0) {
81+
children();
82+
} else {
83+
render()
84+
minkowski() {
85+
children();
86+
for (mz = [0, 1])
87+
mirror([0, 0, mz])
88+
cylinder(r1=radius, r2=0, h=radius);
89+
}
90+
}
91+
}
92+
93+
module at_pcb_grid() {
94+
translate([
95+
-(PCB_X - 1) / 2 * (pcb_grid_sep + pcb_grid),
96+
-(PCB_Y - 1) / 2 * (pcb_grid_sep + pcb_grid),
97+
])
98+
for (px = [0:1:PCB_X - 1], py = [0:1:PCB_Y - 1])
99+
translate([px * (pcb_grid + pcb_grid_sep), py * (pcb_grid + pcb_grid_sep)])
100+
union() {
101+
$grid_x = px;
102+
$grid_y = py;
103+
children();
104+
}
105+
}
106+
107+
module at_pcb_holes() {
108+
at_pcb_grid()
109+
union() {
110+
px = $grid_x;
111+
py = $grid_y;
112+
for (hx = [0, 1], hy = [0, 1]) {
113+
edge_x0 = (px == 0 && hx == 0);
114+
edge_x1 = (px == (PCB_X - 1) && hx == 1);
115+
edge_y0 = (py == 0 && hy == 0);
116+
edge_y1 = (py == (PCB_Y - 1) && hy == 1);
117+
inner_x = !(edge_x0 || edge_x1);
118+
inner_y = !(edge_y0 || edge_y1);
119+
inner = (inner_x && inner_y);
120+
if (!inner || (Inner_Holes && inner))
121+
mirror([1 - hx, 0])
122+
mirror([0, 1 - hy])
123+
translate([pcb_grid / 2 - hole_inset, pcb_grid / 2 - hole_inset])
124+
children();
125+
}
126+
}
127+
}
128+
129+
module at_pcb_grid_corners() {
130+
translate([
131+
-PCB_X / 2 * (pcb_grid + pcb_grid_sep),
132+
-PCB_Y / 2 * (pcb_grid + pcb_grid_sep)
133+
])
134+
for (px = [0:1:PCB_X], py = [0:1:PCB_Y]) {
135+
inner = (px > 0 && px < PCB_X) && (py > 0 && py < PCB_Y);
136+
if (!inner || (Inner_Holes && inner))
137+
translate([
138+
px * (pcb_grid + pcb_grid_sep),
139+
py * (pcb_grid + pcb_grid_sep)
140+
])
141+
children();
142+
}
143+
}
144+
145+
module at_base_mount_screws(enable_x=true, enable_y=true) {
146+
screw_offset = Mounting_Screw_Diameter + (pcb_grid + pcb_grid_sep) / 2;
147+
at_pcb_grid() {
148+
if (enable_x && Mounting_Screw_Holes_X) {
149+
if ($grid_x == 0)
150+
translate([-screw_offset, 0])
151+
children();
152+
if ($grid_x == PCB_X - 1)
153+
translate([screw_offset, 0])
154+
children();
155+
}
156+
if (enable_y && Mounting_Screw_Holes_Y) {
157+
if ($grid_y == 0)
158+
translate([0, -screw_offset])
159+
children();
160+
if ($grid_y == PCB_Y - 1)
161+
translate([0, screw_offset])
162+
children();
163+
}
164+
}
165+
}
166+
167+
module pcb() {
168+
color("darkseagreen", 0.5)
169+
linear_extrude(height=pcb_thick)
170+
difference() {
171+
$fs = $preview ? ($fs / 4) : $fs;
172+
offset(r=corner_radius)
173+
offset(r=-corner_radius)
174+
square([pcb_x, pcb_y], center=true);
175+
at_pcb_holes()
176+
circle(d=pcb_hole_d);
177+
}
178+
}
179+
180+
module base_shape() {
181+
offset(r=-edge_radius)
182+
offset(r=hole_to_edge)
183+
offset(r=-hole_to_edge)
184+
square([pcb_x + edge_outset * 2, pcb_y + edge_outset * 2], center=true);
185+
}
186+
187+
module base_cutouts() {
188+
at_pcb_grid()
189+
offset(r=-edge_radius)
190+
offset(r=hole_to_edge * 1.25)
191+
offset(r=-hole_to_edge * 1.25)
192+
square(pcb_grid - (hole_to_edge * 2), center=true);
193+
}
194+
195+
module base_support_quad_shape() {
196+
offset(r=3)
197+
offset(r=-3)
198+
square((hole_inset + pcb_hole_clearance) * 2 + pcb_grid_sep, center=true);
199+
}
200+
201+
module base_supports() {
202+
intersection() {
203+
linear_extrude(height=Height * 2)
204+
base_shape();
205+
translate([0, 0, edge_radius])
206+
// linear_extrude(height=Height - edge_radius * 2)
207+
at_pcb_grid_corners()
208+
hull_pair(Height - edge_radius * 2) {
209+
offset(r=PCB_Support_Chamfer)
210+
base_support_quad_shape();
211+
base_support_quad_shape();
212+
}
213+
}
214+
}
215+
216+
module base_mount_edges() {
217+
offset(r=-hole_to_edge)
218+
offset(r=hole_to_edge)
219+
union() {
220+
base_shape();
221+
for (enable_x = [0, 1])
222+
hull() {
223+
offset(r=(-hole_to_edge - hole_inset))
224+
base_shape();
225+
at_base_mount_screws(enable_x=enable_x, enable_y=!enable_x)
226+
circle(d=Mounting_Screw_Diameter * (Mounting_Screw_Hole_Chamfer ? 3 : 2.25));
227+
}
228+
}
229+
}
230+
231+
module base_body() {
232+
base_supports();
233+
234+
translate([0, 0, edge_radius])
235+
linear_extrude(height=Thickness - edge_radius * 2)
236+
difference() {
237+
union() {
238+
base_shape();
239+
base_mount_edges();
240+
}
241+
base_cutouts();
242+
}
243+
}
244+
245+
module base_holes() {
246+
at_pcb_holes() {
247+
translate([0, 0, -slop])
248+
cylinder(d=hole_d, h=Height + slop * 2);
249+
translate([0, 0, Height - edge_radius])
250+
cylinder(d1=hole_d, d2=hole_d + 2 * edge_radius, h=edge_radius + slop);
251+
translate([0, 0, -slop])
252+
cylinder(d1=hole_d + 2 * edge_radius, d2=hole_d, h=edge_radius + slop);
253+
}
254+
at_base_mount_screws() {
255+
// translate([0, 0, -slop])
256+
translate([0, 0, Thickness])
257+
mirror([0, 0, 1]) {
258+
cylinder(d=Mounting_Screw_Diameter, h=Height + Mounting_Screw_Diameter + slop * 2);
259+
if (Mounting_Screw_Hole_Chamfer)
260+
cylinder(d1=Mounting_Screw_Diameter*2, d2=Mounting_Screw_Diameter, h=Mounting_Screw_Diameter / 2);
261+
}
262+
}
263+
}
264+
265+
module base() {
266+
color("mintcream", 0.9)
267+
render()
268+
difference() {
269+
round_3d()
270+
base_body();
271+
base_holes();
272+
}
273+
}
274+
275+
module main() {
276+
base();
277+
if ($preview && Preview_PCB)
278+
translate([0, 0, Height + slop])
279+
pcb();
280+
}
281+
282+
main();
33.2 KB
Loading
24.2 KB
Loading

0 commit comments

Comments
 (0)