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 translate([0, -20, 0]) 100 difference() { 101 102 /* The cartridge surfaces. */ 103 104 union() { 105 106 /* Front portion. */ 107 108 translate([0, -front_depth + front / 2, 0]) 109 cube([width, front, height], center = true); 110 translate([-width / 2 + front_left / 2, -front_depth / 2, 0]) 111 cube([front_left, front_depth, height], center = true); 112 translate([width / 2 - front_right / 2, -front_depth / 2, 0]) 113 cube([front_right, front_depth, height], center = true); 114 translate([0, -front_depth / 2, height / 2 - top / 2]) 115 cube([width, front_depth, top], center = true); 116 difference() { 117 translate([0, -front_depth / 2, 118 -height / 2 + bottom / 2 + bottom_from_base]) 119 cube([width, front_depth, bottom], center = true); 120 translate([-width / 2 + edge_connector_cutout_front_offset + 121 edge_connector_cutout_front_width / 2, 122 -edge_connector_cutout_front_depth / 2, 123 -height / 2 + bottom / 2 + bottom_from_base]) 124 cube([edge_connector_cutout_front_width, 125 edge_connector_cutout_front_depth, 126 bottom + extra], center = true); 127 translate([width / 2 - edge_connector_cutout_front_offset - 128 edge_connector_cutout_front_width / 2, 129 -edge_connector_cutout_front_depth / 2, 130 -height / 2 + bottom / 2 + bottom_from_base]) 131 cube([edge_connector_cutout_front_width, 132 edge_connector_cutout_front_depth, 133 bottom + extra], center = true); 134 } 135 } 136 137 /* Label insets. */ 138 139 union() { 140 141 /* Front label. */ 142 143 translate([-front_label_width / 2, -front_depth, 144 front_label_offset_from_bottom - height / 2]) 145 cube([front_label_width, front_label_depth, 146 front_label_height]); 147 148 /* Top label. */ 149 150 translate([-top_label_width / 2, 151 -front_depth + top_label_offset_from_front, 152 height / 2 - top_label_depth]) 153 cube([top_label_width, top_label_height, 154 top_label_depth]); 155 } 156 157 /* Inner front edge cavity. */ 158 159 translate([inner_front_edge_width / 2, 160 -front_depth + inner_front_edge_offset, -height / 2]) 161 rotate([0, -90, 0]) 162 linear_extrude(height = inner_front_edge_width) 163 polygon([ 164 [-extra, 0], 165 [0, 0], 166 [inner_front_edge_height, inner_front_edge_depth], 167 [-extra, inner_front_edge_depth], 168 ]); 169 170 /* Inner top cutout for the top of the back portion. */ 171 172 translate([0, -inner_top_front_cutout_depth / 2, height / 2 - 173 inner_top_front_cutout_offset - 174 inner_top_front_cutout_depth / 2]) 175 cube([inner_top_front_cutout_width, 176 inner_top_front_cutout_depth, 177 inner_top_front_cutout_depth], center = true); 178 179 /* Fillets to round off the edges. */ 180 181 union() { 182 183 /* Top left and right rounding. */ 184 185 translate([-width / 2 + ro, -front_depth / 2, height / 2 - ro]) 186 rotate([0, 0, 180]) 187 rotate([90, 0, 0]) 188 fillet(rr, front_depth); 189 translate([width / 2 - ro, -front_depth / 2, height / 2 - ro]) 190 rotate([90, 0, 0]) 191 fillet(rr, front_depth); 192 193 /* Top front rounding. */ 194 195 translate([0, -front_depth + ro, height / 2 - ro]) 196 rotate([0, 0, 180]) 197 rotate([0, -90, 0]) 198 fillet(rr, width); 199 200 /* Edge rounding. */ 201 202 translate([-width / 2 + ro, -front_depth + ro, 0]) 203 rotate([0, 0, 180]) 204 fillet(rr, height); 205 translate([width / 2 - ro, -front_depth + ro, 0]) 206 rotate([0, 0, 270]) 207 fillet(rr, height); 208 } 209 } 210 211 difference() { 212 213 /* The cartridge surfaces. */ 214 215 union() { 216 217 /* Back portion. */ 218 219 translate([0, back_depth - back / 2, 0]) 220 cube([width, back, height], center = true); 221 translate([-width / 2 + back_left / 2, back_depth / 2, 0]) 222 cube([back_left, back_depth, height], center = true); 223 translate([width / 2 - back_right / 2, back_depth / 2, 0]) 224 cube([back_right, back_depth, height], center = true); 225 translate([0, back_depth / 2, height / 2 - top / 2]) 226 cube([width, back_depth, top], center = true); 227 difference() { 228 translate([0, back_depth / 2, 229 -height / 2 + bottom / 2 + bottom_from_base]) 230 cube([width, back_depth, bottom], center = true); 231 translate([0, edge_connector_cutout_back_depth / 2, 232 -height / 2 + bottom / 2 + bottom_from_base]) 233 cube([edge_connector_cutout_back_width, 234 edge_connector_cutout_back_depth, 235 bottom + extra], center = true); 236 } 237 238 /* PCB supports. */ 239 240 translate([-edge_connector_cutout_back_width / 2 + 241 pcb_back_support_width / 2, 242 edge_connector_cutout_back_depth + 243 pcb_back_support_depth / 2, 244 -height / 2 + bottom + bottom_from_base + 245 pcb_back_support_height / 2]) 246 cube([pcb_back_support_width, pcb_back_support_depth, 247 pcb_back_support_height], center = true); 248 249 translate([edge_connector_cutout_back_width / 2 - 250 pcb_back_support_width / 2, 251 edge_connector_cutout_back_depth + 252 pcb_back_support_depth / 2, 253 -height / 2 + bottom + bottom_from_base + 254 pcb_back_support_height / 2]) 255 cube([pcb_back_support_width, pcb_back_support_depth, 256 pcb_back_support_height], center = true); 257 } 258 259 /* Label insets. */ 260 261 union() { 262 263 /* Top label. */ 264 265 translate([-top_label_width / 2, 266 -front_depth + top_label_offset_from_front, 267 height / 2 - top_label_depth]) 268 cube([top_label_width, top_label_height, 269 top_label_depth]); 270 } 271 272 /* Top and side grooves, positioned in the back portion. */ 273 274 union() { 275 276 /* Left groove. */ 277 278 translate([-width / 2 + groove_depth / 2, groove_width / 2, 0]) 279 cube([groove_depth, groove_width, height], 280 center = true); 281 282 /* Right groove. */ 283 284 translate([width / 2 - groove_depth / 2, groove_width / 2, 0]) 285 cube([groove_depth, groove_width, height], 286 center = true); 287 288 /* Top grooves. */ 289 290 translate([0, groove_width / 2, height / 2 - groove_depth / 2]) 291 cube([width, groove_width, groove_depth], 292 center = true); 293 294 translate([0, top_groove_width / 2, 295 height / 2 - top_groove_depth / 2]) 296 cube([width, top_groove_width, top_groove_depth], 297 center = true); 298 } 299 300 /* Back cavity. */ 301 302 intersection() { 303 304 /* From the bottom upwards. */ 305 306 translate([0, back_depth, -height / 2]) 307 linear_extrude(height = back_cavity_height) 308 translate([-width / 2, 0, 0]) 309 polygon([ 310 [back_cavity_offset_from_left, 0], 311 [back_cavity_inner_offset_from_left, 312 -back_cavity_depth], 313 [back_cavity_inner_offset_from_left + 314 back_cavity_inner_width, 315 -back_cavity_depth], 316 [back_cavity_offset_from_left + 317 back_cavity_width, 0] 318 ]); 319 320 /* From left to right. */ 321 322 translate([back_cavity_width / 2, back_depth, -height / 2]) 323 rotate([0, -90, 0]) 324 linear_extrude(height = back_cavity_width) 325 polygon([ 326 [-extra, -back_cavity_depth], 327 [back_cavity_inner_height, 328 -back_cavity_depth], 329 [back_cavity_height, 0], 330 [-extra, 0] 331 ]); 332 } 333 334 /* Inner back cavities. */ 335 336 translate([0, back_depth - inner_back_cavity_offset, -height / 2]) 337 linear_extrude(height = bottom_from_base) 338 translate([-width / 2, 0, 0]) 339 polygon([ 340 [inner_back_cavity_offset_from_left, 0], 341 [inner_back_slope_offset_from_left, 0], 342 [inner_back_slope_offset_from_left + 343 inner_back_slope_width, 344 -inner_back_slope_depth], 345 [inner_back_cavity_offset_from_left, 346 -inner_back_slope_depth] 347 ]); 348 349 translate([0, back_depth - inner_back_cavity_offset, -height / 2]) 350 linear_extrude(height = bottom_from_base) 351 translate([-width / 2, 0, 0]) 352 polygon([ 353 [width - inner_back_slope_offset_from_left, 0], 354 [width - inner_back_cavity_offset_from_left, 0], 355 [width - inner_back_cavity_offset_from_left, 356 -inner_back_slope_depth], 357 [width - inner_back_slope_offset_from_left - 358 inner_back_slope_width, 359 -inner_back_slope_depth] 360 ]); 361 362 /* Inner back edge cavity. */ 363 364 translate([inner_back_edge_width / 2, 365 back_depth - inner_back_edge_offset, -height / 2]) 366 rotate([0, -90, 0]) 367 linear_extrude(height = inner_back_edge_width) 368 polygon([ 369 [-extra, -inner_back_edge_depth], 370 [inner_back_edge_height, -inner_back_edge_depth], 371 [0, 0], 372 [-extra, 0] 373 ]); 374 375 /* Fillets to round off the edges. */ 376 377 union() { 378 379 /* Top left and right rounding. */ 380 381 translate([-width / 2 + ro, back_depth / 2, height / 2 - ro]) 382 rotate([0, 0, 180]) 383 rotate([90, 0, 0]) 384 fillet(rr, back_depth); 385 translate([width / 2 - ro, back_depth / 2, height / 2 - ro]) 386 rotate([90, 0, 0]) 387 fillet(rr, back_depth); 388 389 /* Top back rounding. */ 390 391 translate([0, back_depth - ro, height / 2 - ro]) 392 rotate([0, -90, 0]) 393 fillet(rr, width); 394 395 /* Edge rounding. */ 396 397 translate([width / 2 - ro, back_depth - ro, 0]) 398 fillet(rr, height); 399 translate([-width / 2 + ro, back_depth - ro, 0]) 400 rotate([0, 0, 90]) 401 fillet(rr, height); 402 } 403 } 404 } 405 406 cartridge(); 407