1 module cartridge() 2 { 3 $fn = 50; 4 5 /* Rounding/fillet radius and additional margin of subtracted 6 material. The additional margin helps avoid geometry 7 problems. */ 8 9 rr = 1; 10 ro = rr; 11 extra = 0.1; 12 13 module fillet(r, h) { 14 translate([0, 0, -h/2]) 15 difference() { 16 cube([r + extra, r + extra, h + extra]); 17 cylinder(r = r, h = h); 18 } 19 } 20 21 /* Cartridge dimensions. */ 22 23 width = 89.0; 24 height = 68.5; 25 depth = 16.5; 26 front_depth = 6.5; 27 back_depth = 11.0; 28 29 /* Details. */ 30 31 front_label_width = 83.0; 32 front_label_height = 46.0; 33 front_label_depth = 1.0; 34 front_label_offset_from_bottom = 19.5; 35 36 top_label_width = front_label_width; 37 top_label_height = 11.5; 38 top_label_depth = front_label_depth; 39 top_label_offset_from_front = 2.5; 40 41 groove_width = 2.5; /* how much the groove cuts out of the back */ 42 groove_depth = 1.0; /* how deep the groove goes into each side */ 43 top_groove_width = 1.0; 44 top_groove_depth = 2.0; 45 inner_top_front_cutout_width = 87.0; 46 inner_top_front_cutout_depth = 1.0; 47 inner_top_front_cutout_offset = 2.0; 48 49 back_cavity_width = 68.0; 50 back_cavity_inner_width = 65.0; 51 back_cavity_offset_from_left = 10.5; 52 back_cavity_inner_offset_from_left = 12.0; 53 back_cavity_height = 13.5; 54 back_cavity_inner_height = 12.0; 55 back_cavity_depth = 1.5; 56 57 inner_back_cavity_offset = 1.0; 58 inner_back_cavity_offset_from_left = 2.0; 59 inner_back_slope_offset_from_left = 10.0; 60 inner_back_slope_width = 2.5; 61 inner_back_slope_depth = 2.5; 62 63 inner_back_edge_offset = 2.0; 64 inner_back_edge_width = 69.0; 65 inner_back_edge_height = 3.0; 66 inner_back_edge_depth = 1.5; 67 68 inner_front_edge_offset = 0.5; 69 inner_front_edge_width = 87.0; 70 inner_front_edge_height = 3.0; 71 inner_front_edge_depth = 1.5; 72 73 bottom_from_base = 13.5; 74 75 edge_connector_cutout_front_offset = 1.0; 76 edge_connector_cutout_front_depth = 1.0; 77 edge_connector_cutout_front_width = 15.0; 78 edge_connector_cutout_back_depth = 3.0; 79 edge_connector_cutout_back_width = 57.0; 80 81 /* Side thicknesses. */ 82 83 front = 2; 84 back = 3.5; 85 top = 3; 86 front_left = 1; 87 front_right = 1; 88 back_left = 2; 89 back_right = 2; 90 bottom = 2; 91 92 /* Extra internal features. */ 93 94 pcb_back_support_width = 1.0; 95 pcb_back_support_depth = back_depth - 96 edge_connector_cutout_back_depth; 97 pcb_back_support_height = height - bottom_from_base - top - bottom; 98 99 pcb_front_support_width = 1.0; 100 pcb_front_support_depth = front_depth; 101 pcb_front_support_height = pcb_back_support_height; 102 103 translate([0, -20, 0]) 104 difference() { 105 106 /* The cartridge surfaces. */ 107 108 union() { 109 110 /* Front portion. */ 111 112 translate([0, -front_depth + front / 2, 0]) 113 cube([width, front, height], center = true); 114 translate([-width / 2 + front_left / 2, -front_depth / 2, 0]) 115 cube([front_left, front_depth, height], center = true); 116 translate([width / 2 - front_right / 2, -front_depth / 2, 0]) 117 cube([front_right, front_depth, height], center = true); 118 translate([0, -front_depth / 2, height / 2 - top / 2]) 119 cube([width, front_depth, top], center = true); 120 difference() { 121 translate([0, -front_depth / 2, 122 -height / 2 + bottom / 2 + bottom_from_base]) 123 cube([width, front_depth, bottom], center = true); 124 translate([-width / 2 + edge_connector_cutout_front_offset + 125 edge_connector_cutout_front_width / 2, 126 -edge_connector_cutout_front_depth / 2, 127 -height / 2 + bottom / 2 + bottom_from_base]) 128 cube([edge_connector_cutout_front_width, 129 edge_connector_cutout_front_depth, 130 bottom + extra], center = true); 131 translate([width / 2 - edge_connector_cutout_front_offset - 132 edge_connector_cutout_front_width / 2, 133 -edge_connector_cutout_front_depth / 2, 134 -height / 2 + bottom / 2 + bottom_from_base]) 135 cube([edge_connector_cutout_front_width, 136 edge_connector_cutout_front_depth, 137 bottom + extra], center = true); 138 } 139 140 /* PCB supports. */ 141 142 translate([-edge_connector_cutout_back_width / 2 + 143 pcb_front_support_width / 2, 144 -pcb_front_support_depth / 2, 145 -height / 2 + bottom + bottom_from_base + 146 pcb_front_support_height / 2]) 147 cube([pcb_front_support_width, pcb_front_support_depth, 148 pcb_front_support_height], center = true); 149 150 translate([edge_connector_cutout_back_width / 2 - 151 pcb_front_support_width / 2, 152 -pcb_front_support_depth / 2, 153 -height / 2 + bottom + bottom_from_base + 154 pcb_front_support_height / 2]) 155 cube([pcb_front_support_width, pcb_front_support_depth, 156 pcb_front_support_height], center = true); 157 } 158 159 /* Label insets. */ 160 161 union() { 162 163 /* Front label. */ 164 165 translate([-front_label_width / 2, -front_depth, 166 front_label_offset_from_bottom - height / 2]) 167 cube([front_label_width, front_label_depth, 168 front_label_height]); 169 170 /* Top label. */ 171 172 translate([-top_label_width / 2, 173 -front_depth + top_label_offset_from_front, 174 height / 2 - top_label_depth]) 175 cube([top_label_width, top_label_height, 176 top_label_depth]); 177 } 178 179 /* Inner front edge cavity. */ 180 181 translate([inner_front_edge_width / 2, 182 -front_depth + inner_front_edge_offset, -height / 2]) 183 rotate([0, -90, 0]) 184 linear_extrude(height = inner_front_edge_width) 185 polygon([ 186 [-extra, 0], 187 [0, 0], 188 [inner_front_edge_height, inner_front_edge_depth], 189 [-extra, inner_front_edge_depth], 190 ]); 191 192 /* Inner top cutout for the top of the back portion. */ 193 194 translate([0, -inner_top_front_cutout_depth / 2, height / 2 - 195 inner_top_front_cutout_offset - 196 inner_top_front_cutout_depth / 2]) 197 cube([inner_top_front_cutout_width, 198 inner_top_front_cutout_depth, 199 inner_top_front_cutout_depth], center = true); 200 201 /* Fillets to round off the edges. */ 202 203 union() { 204 205 /* Top left and right rounding. */ 206 207 translate([-width / 2 + ro, -front_depth / 2, height / 2 - ro]) 208 rotate([0, 0, 180]) 209 rotate([90, 0, 0]) 210 fillet(rr, front_depth); 211 translate([width / 2 - ro, -front_depth / 2, height / 2 - ro]) 212 rotate([90, 0, 0]) 213 fillet(rr, front_depth); 214 215 /* Top front rounding. */ 216 217 translate([0, -front_depth + ro, height / 2 - ro]) 218 rotate([0, 0, 180]) 219 rotate([0, -90, 0]) 220 fillet(rr, width); 221 222 /* Edge rounding. */ 223 224 translate([-width / 2 + ro, -front_depth + ro, 0]) 225 rotate([0, 0, 180]) 226 fillet(rr, height); 227 translate([width / 2 - ro, -front_depth + ro, 0]) 228 rotate([0, 0, 270]) 229 fillet(rr, height); 230 } 231 } 232 233 difference() { 234 235 /* The cartridge surfaces. */ 236 237 union() { 238 239 /* Back portion. */ 240 241 translate([0, back_depth - back / 2, 0]) 242 cube([width, back, height], center = true); 243 translate([-width / 2 + back_left / 2, back_depth / 2, 0]) 244 cube([back_left, back_depth, height], center = true); 245 translate([width / 2 - back_right / 2, back_depth / 2, 0]) 246 cube([back_right, back_depth, height], center = true); 247 translate([0, back_depth / 2, height / 2 - top / 2]) 248 cube([width, back_depth, top], center = true); 249 difference() { 250 translate([0, back_depth / 2, 251 -height / 2 + bottom / 2 + bottom_from_base]) 252 cube([width, back_depth, bottom], center = true); 253 translate([0, edge_connector_cutout_back_depth / 2, 254 -height / 2 + bottom / 2 + bottom_from_base]) 255 cube([edge_connector_cutout_back_width, 256 edge_connector_cutout_back_depth, 257 bottom + extra], center = true); 258 } 259 260 /* PCB supports. */ 261 262 translate([-edge_connector_cutout_back_width / 2 + 263 pcb_back_support_width / 2, 264 edge_connector_cutout_back_depth + 265 pcb_back_support_depth / 2, 266 -height / 2 + bottom + bottom_from_base + 267 pcb_back_support_height / 2]) 268 cube([pcb_back_support_width, pcb_back_support_depth, 269 pcb_back_support_height], center = true); 270 271 translate([edge_connector_cutout_back_width / 2 - 272 pcb_back_support_width / 2, 273 edge_connector_cutout_back_depth + 274 pcb_back_support_depth / 2, 275 -height / 2 + bottom + bottom_from_base + 276 pcb_back_support_height / 2]) 277 cube([pcb_back_support_width, pcb_back_support_depth, 278 pcb_back_support_height], center = true); 279 } 280 281 /* Label insets. */ 282 283 union() { 284 285 /* Top label. */ 286 287 translate([-top_label_width / 2, 288 -front_depth + top_label_offset_from_front, 289 height / 2 - top_label_depth]) 290 cube([top_label_width, top_label_height, 291 top_label_depth]); 292 } 293 294 /* Top and side grooves, positioned in the back portion. */ 295 296 union() { 297 298 /* Left groove. */ 299 300 translate([-width / 2 + groove_depth / 2, groove_width / 2, 0]) 301 cube([groove_depth, groove_width, height], 302 center = true); 303 304 /* Right groove. */ 305 306 translate([width / 2 - groove_depth / 2, groove_width / 2, 0]) 307 cube([groove_depth, groove_width, height], 308 center = true); 309 310 /* Top grooves. */ 311 312 translate([0, groove_width / 2, height / 2 - groove_depth / 2]) 313 cube([width, groove_width, groove_depth], 314 center = true); 315 316 translate([0, top_groove_width / 2, 317 height / 2 - top_groove_depth / 2]) 318 cube([width, top_groove_width, top_groove_depth], 319 center = true); 320 } 321 322 /* Back cavity. */ 323 324 intersection() { 325 326 /* From the bottom upwards. */ 327 328 translate([0, back_depth, -height / 2]) 329 linear_extrude(height = back_cavity_height) 330 translate([-width / 2, 0, 0]) 331 polygon([ 332 [back_cavity_offset_from_left, 0], 333 [back_cavity_inner_offset_from_left, 334 -back_cavity_depth], 335 [back_cavity_inner_offset_from_left + 336 back_cavity_inner_width, 337 -back_cavity_depth], 338 [back_cavity_offset_from_left + 339 back_cavity_width, 0] 340 ]); 341 342 /* From left to right. */ 343 344 translate([back_cavity_width / 2, back_depth, -height / 2]) 345 rotate([0, -90, 0]) 346 linear_extrude(height = back_cavity_width) 347 polygon([ 348 [-extra, -back_cavity_depth], 349 [back_cavity_inner_height, 350 -back_cavity_depth], 351 [back_cavity_height, 0], 352 [-extra, 0] 353 ]); 354 } 355 356 /* Inner back cavities. */ 357 358 translate([0, back_depth - inner_back_cavity_offset, -height / 2]) 359 linear_extrude(height = bottom_from_base) 360 translate([-width / 2, 0, 0]) 361 polygon([ 362 [inner_back_cavity_offset_from_left, 0], 363 [inner_back_slope_offset_from_left, 0], 364 [inner_back_slope_offset_from_left + 365 inner_back_slope_width, 366 -inner_back_slope_depth], 367 [inner_back_cavity_offset_from_left, 368 -inner_back_slope_depth] 369 ]); 370 371 translate([0, back_depth - inner_back_cavity_offset, -height / 2]) 372 linear_extrude(height = bottom_from_base) 373 translate([-width / 2, 0, 0]) 374 polygon([ 375 [width - inner_back_slope_offset_from_left, 0], 376 [width - inner_back_cavity_offset_from_left, 0], 377 [width - inner_back_cavity_offset_from_left, 378 -inner_back_slope_depth], 379 [width - inner_back_slope_offset_from_left - 380 inner_back_slope_width, 381 -inner_back_slope_depth] 382 ]); 383 384 /* Inner back edge cavity. */ 385 386 translate([inner_back_edge_width / 2, 387 back_depth - inner_back_edge_offset, -height / 2]) 388 rotate([0, -90, 0]) 389 linear_extrude(height = inner_back_edge_width) 390 polygon([ 391 [-extra, -inner_back_edge_depth], 392 [inner_back_edge_height, -inner_back_edge_depth], 393 [0, 0], 394 [-extra, 0] 395 ]); 396 397 /* Fillets to round off the edges. */ 398 399 union() { 400 401 /* Top left and right rounding. */ 402 403 translate([-width / 2 + ro, back_depth / 2, height / 2 - ro]) 404 rotate([0, 0, 180]) 405 rotate([90, 0, 0]) 406 fillet(rr, back_depth); 407 translate([width / 2 - ro, back_depth / 2, height / 2 - ro]) 408 rotate([90, 0, 0]) 409 fillet(rr, back_depth); 410 411 /* Top back rounding. */ 412 413 translate([0, back_depth - ro, height / 2 - ro]) 414 rotate([0, -90, 0]) 415 fillet(rr, width); 416 417 /* Edge rounding. */ 418 419 translate([width / 2 - ro, back_depth - ro, 0]) 420 fillet(rr, height); 421 translate([-width / 2 + ro, back_depth - ro, 0]) 422 rotate([0, 0, 90]) 423 fillet(rr, height); 424 } 425 } 426 } 427 428 cartridge(); 429