cb028f6ddabe21961602af0fa515ac93ce368444
[heater.git] / case.scad
1 lowres = 0; // fast rendering or fine printing with print-friendly orientation
2
3 eps = 0.01;
4 infty = 300;
5
6 wall = 1.5; // generic wall thickness
7
8 // 18650 is ~18mm diameter, ~65mm length, 
9 batt_diam = 18 + 0.6;
10 batt_len = 65 + 1.5;
11
12 cable_sep = 1;
13
14 // front flat area
15 front_flat_len = batt_len + 4*wall + 2*cable_sep;
16
17 // PCB-related dimensions
18 pcb_len = 36 + 1;       // length of the board
19 pcb_width = 11 + 0.5;   // width of the board
20 pcb_thick = 1.2 + 0.3;  // thickness of the board
21 pcb_comp_h = 2.2;       // height of the components on board
22 pcb_groove = 1;
23
24 body_top_h = 0.35 * batt_diam; // cube-shaped part of the body
25
26 outwire_thick = 2.2;
27 wire_thick = 2.2;
28 wire_sep = 3.5;
29 cable_out_diam = 5.2;
30
31 batt_end_h = wire_sep/2 + wire_thick/2 + 1.5;;
32
33 lid_sep = 0.5; // the lid is made this much smaller to separate from the body
34
35 sw_diam = 2.5 + 0.5;
36 led_diam = 3 + 0.5;
37 sw_xoff =  250 * 25.4/1000; // x offset of microswitches
38 pcb_xoff = 90 * 25.4/1000; // offset of the LED from the middle of the PCB
39
40 prg_len = 10; // programming connector
41 prg_width = 7;
42
43 rear_clip_hole_dist = 10; // distance between the holes in the rear clip
44 rear_clip_aspect = 0.35; // w/h aspect ratio of the ellipse of the rear clip
45
46 module case_body() {
47         hull() {
48                 translate([-batt_len/2-2*wall-cable_sep, -batt_diam/2-wall, 0])
49                         cube([batt_len + 4*wall + 2*cable_sep,
50                                 batt_diam+2*wall, body_top_h]);
51                 difference() {
52                         translate([-batt_len/2-2*wall-cable_sep, 0, 0])
53                                 rotate([0, 90, 0])
54                                 cylinder(r=batt_diam/2+wall,
55                                         h = batt_len + 4*wall + 2*cable_sep);
56                         translate([-infty/2, -infty/2, eps]) cube(infty);
57                 };
58                 translate([-front_flat_len/2,
59                         batt_diam/2 - pcb_width,
60                         -batt_diam/2-2*pcb_comp_h-pcb_thick-wall])
61                         cube([front_flat_len, pcb_width+wall, eps]);
62         };
63         for (x = [-1, 1]) scale([x, 1, 1]) hull() {
64                 for (x0 = [0-wall, 10+wall])
65                         translate([batt_len/2-wall-wire_thick-x0, batt_diam/2, 0])
66                                 rotate([-90, 0, 0]) scale([rear_clip_aspect, 1, 1])
67                                 cylinder(r=batt_diam/2 + 2*wall + wire_thick, h=wall);
68                 };
69 };
70
71 module case() {
72         difference() {
73                 case_body();
74                 // upper cube-shaped part
75                 // rotate([20, 0, 0])
76                 translate([-batt_len/2, -batt_diam/2, 0])
77                         cube([batt_len, batt_diam, batt_diam]);
78
79                 // battery cylinder for the lower part
80                 translate([-batt_len/2, 0, 0])
81                         rotate([0, 90, 0])
82                         cylinder(r=batt_diam/2, h = batt_len);
83
84                 // hole for PCB
85                 translate([-pcb_len/2-pcb_xoff,
86                         batt_diam/2-pcb_width,
87                         -batt_diam/2-pcb_thick - pcb_comp_h])
88                         cube([pcb_len, pcb_width,
89                                 batt_diam/2 + pcb_thick + pcb_comp_h + eps]);
90                 // hole above the PCB
91                 translate([-pcb_len/2-pcb_xoff-wall-2*outwire_thick,
92                         batt_diam/2-pcb_width,
93                         -batt_diam/2-pcb_comp_h])
94                         cube([pcb_len, pcb_width,
95                                 batt_diam/2 + pcb_comp_h + eps]);
96                 // hole under the PCB
97                 translate([-pcb_len/2+pcb_groove-pcb_xoff,
98                         batt_diam/2-pcb_width + pcb_groove,
99                         -batt_diam/2-pcb_thick - 2*pcb_comp_h])
100                         cube([pcb_len-2*pcb_groove, pcb_width-2*pcb_groove,
101                                 batt_diam/2 + pcb_thick + pcb_comp_h + eps]);
102                 // hole for prog connector
103                 translate([pcb_len/2-pcb_xoff-pcb_groove-eps,
104                         batt_diam/2-pcb_width/2-prg_width/2,
105                         -batt_diam/2-pcb_thick - 2*pcb_comp_h])
106                         difference() {
107                                 cube([prg_len+pcb_groove+eps, prg_width,
108                                         batt_diam/2 + pcb_thick + pcb_comp_h + eps]);
109                                 translate([prg_len/2+pcb_groove, -eps, pcb_comp_h])
110                                         cube([prg_len/2+eps, prg_width+2*eps, pcb_thick]);
111                         };
112                 // LED hole
113                 translate([0, batt_diam/2-pcb_width/2, -infty/2]) {
114                         cylinder(r=led_diam/2, h=infty, $fn=6);
115                         translate([sw_xoff, 0, 0])
116                                 cylinder(r=sw_diam/2, h=infty, $fn=6);
117                         translate([-sw_xoff, 0, 0])
118                                 cylinder(r=sw_diam/2, h=infty, $fn=6);
119                 };
120                 // cable outlet
121                 translate([-pcb_xoff-pcb_len/2-outwire_thick-wall, -6, 0])
122                         rotate([40, 0, 0])
123                         scale([2, 1, -1])
124                         cylinder(r=outwire_thick/2, h = infty, $fn=12);
125                 // space under the wire holes for battery contacts
126                 translate([-batt_len/2-2*wall-cable_sep-eps, 0, 0])
127                         difference() {
128                                 rotate([0, 90, 0])
129                                         cylinder(r = batt_diam/2-wall, h = batt_len + 4*wall + 2*cable_sep + 2*eps);
130                                 translate([-infty/2, -infty/2, -batt_end_h])
131                                         cube(infty);
132                         };
133                 // space above the wire holes for battery contacts
134                 translate([-batt_len/2-2*wall-cable_sep-eps, -batt_diam/2, batt_end_h])
135                         cube([batt_len + 4*wall + 2*cable_sep + 2*eps, 
136                                 batt_diam,
137                                 batt_end_h]);
138                 // wire holes for battery contacts
139                 for (x = [-1, 1])
140                 for (y = [-1, 1])
141                         translate([-batt_len/2-wall-eps, x*wire_sep/2, y*wire_sep/2])
142                         rotate([0, 90, 0])
143                                 cylinder(r = wire_thick/2, h = batt_len + 2*wall + 2*eps, $fn=6);
144                 // wire hole from PCB to battery contacts
145                 // translate([-batt_len/2-wall-eps, 0, -batt_diam/2-pcb_comp_h + wire_thick/2])
146                 rotate([40, 0, 0])
147                 translate([-batt_len/2-wall-eps, 0, -batt_diam/2 - wall/2 - wire_thick/2])
148                         rotate([0, 90, 0])
149                                 cylinder(r = wire_thick/2, h = batt_len + 2*wall + 2*eps, $fn=6);
150                 // hole behind the battery contacts
151                 for(x=[1, -1])
152                 scale([x, 1, 1]) translate([batt_len/2+wall, 0, 0]) hull() {
153                         translate([0, -batt_diam/2, 0])
154                                 cube([wall + cable_sep + eps, batt_diam, infty]);
155                         rotate([0, 90, 0])
156                                 cylinder(r = batt_diam/2, h = wall+cable_sep+eps);
157                         translate([0, batt_diam/2 - pcb_width,
158                                 -batt_diam/2-pcb_comp_h-pcb_thick])
159                                 cube([wall + cable_sep + eps, pcb_width, eps]);
160                         translate([cable_sep, batt_diam/2 - pcb_width + 1.5*wall,
161                                 -batt_diam/2-pcb_comp_h-pcb_thick-wall])
162                                 cube([wall + eps, pcb_width-2*wall, eps]);
163                 };
164                 // cable lead to battery contacts
165                 for (x=[1, -1]) scale([x, 1, 1])
166                         rotate([-140, 0, 0])
167                         translate([batt_len/2+wire_thick/2, 0, batt_diam/2-2*wall])
168                                 cylinder(r=wire_thick/2, h = 5);
169                 
170                 // mounting holes
171                 for(x=[-1,1]) scale([x, 1, 1])
172                 translate([batt_len/2-wall-wire_thick, batt_diam/2+2*wall, -batt_diam/2-pcb_thick-2*pcb_comp_h-wall])
173                         vert_torus();
174                         
175                 for (x = [-1, 1]) scale([x, 1, 1]) for (x0 = [0, 10])
176                         translate([batt_len/2-wall-wire_thick-x0, 0, batt_diam/2+wire_thick/2+wall])
177                         rotate([-90, 0, 0])
178                         scale([2,1,1]) cylinder (r=wire_thick/2, h=infty, $fn=16);
179         };
180         // clip barrier
181         for (x = [-1, 1]) scale([x, 1, 1])
182                 translate([batt_len/2+wall-eps, batt_diam/2-pcb_width+wall+lid_sep,
183                         -batt_diam/2-pcb_thick-pcb_comp_h + wall + lid_sep])
184                         cube([cable_sep+eps, pcb_width-2*wall-2*lid_sep, wall]);
185 };
186
187 module lid_body() {
188         translate([-batt_len/2 - wall - lid_sep, -batt_diam/2+lid_sep, -batt_diam/2 -wall])
189                 cube([batt_len + 2*wall + 2*lid_sep, batt_diam-2*lid_sep, batt_diam/2 - batt_end_h + wall - lid_sep]);
190         translate([-batt_len/2 - 2*wall - cable_sep, -batt_diam/2 - wall,
191                 -batt_diam/2-wall])
192                 cube([batt_len + 4*wall + 2*cable_sep, batt_diam + 2*wall,
193                         wall + batt_diam/2 - body_top_h - lid_sep]);
194         // clip behind the battery contacts
195         for(x=[1, -1])
196                 scale([x, 1, 1]) translate([batt_len/2+wall+lid_sep, 0, 0]) hull() {
197                         translate([0, -batt_diam/2+lid_sep, -batt_diam/2])
198                                 cube([wall+cable_sep-lid_sep, batt_diam-2*lid_sep, eps]);
199                         rotate([0, 90, 0])
200                                 cylinder(r = batt_diam/2-lid_sep, h = wall+cable_sep-lid_sep);
201                         translate([0, batt_diam/2 - pcb_width+lid_sep,
202                                 batt_diam/2+pcb_comp_h+pcb_thick-lid_sep])
203                                 cube([wall+cable_sep-lid_sep, pcb_width-2*lid_sep, eps]);
204                         translate([cable_sep+wall/2, batt_diam/2 - pcb_width + 1.5*wall +lid_sep,
205                                 batt_diam/2+pcb_comp_h+pcb_thick+wall/2-lid_sep])
206                                 cube([wall/2-lid_sep, pcb_width-2*wall-2*lid_sep, eps]);
207                 };
208 };
209
210 module lid() {
211         difference() {
212                 lid_body();
213                 translate([-batt_len/2+eps, 0, 0]) rotate([0, 90, 0])
214                         cylinder(r=batt_diam/2, h=batt_len-2*eps);
215                 hull() {
216                         difference() {
217                                 translate([-batt_len/2-cable_sep-wall, 0, 0]) rotate([0, 90, 0])
218                                         cylinder(r=batt_diam/2-wall-lid_sep, h=batt_len+2*wall+2*cable_sep);
219                                 translate([-infty/2, -batt_diam/2, -infty-wire_sep/2-wire_thick/2])
220                                         cube([infty, batt_diam, infty]);
221                         };
222                         translate([-batt_len/2-cable_sep-wall, batt_diam/2-pcb_width+0.5*wall+0.5*lid_sep, batt_diam/2 + pcb_comp_h+pcb_thick-wall-lid_sep])
223                         cube([batt_len + 2*wall + 2* cable_sep, pcb_width-1.5*wall-1.5*lid_sep, eps]);
224                 };
225                 // holes for the mounting clips on the body
226                 for (x = [-1, 1]) scale([x, 1, 1]) hull() {
227                 for (x0 = [0-wall, 10+wall])
228                         translate([batt_len/2-wall-wire_thick-x0, batt_diam/2-lid_sep+eps, 0])
229                                 rotate([-90, 0, 0]) scale([rear_clip_aspect, 1, 1])
230                                 cylinder(r=batt_diam/2 + 2*wall + wire_thick+lid_sep/rear_clip_aspect, h=wall+lid_sep+eps);
231                 };
232         };
233 };
234
235 module vert_torus() {
236         rotate([0, 90, 0])
237         scale([1, 1, 2])
238         rotate_extrude() translate([5, 0, 0]) circle(r=wire_thick/2, $fn=16);
239 };
240
241 if (lowres) {
242         translate([0, 15, 0]) case();
243         translate([0, -15, 0]) rotate([180, 0, 0]) lid();
244 } else {
245         translate([0, 15, batt_diam/2+pcb_thick+2*pcb_comp_h+wall])
246                 case($fn=128);
247         translate([0, -15, batt_diam/2+wall])
248                 lid($fn=128);
249 }
250