Improve modularity of cartridge

This commit is contained in:
Nettika 2025-10-05 03:17:17 +00:00
parent d558404c75
commit 561427774a

View file

@ -1,123 +1,281 @@
$fn = $preview ? 32 : 64; $fn = $preview ? 32 : 128;
*rotate([0, -90, -90]) import("/home/nettika/Downloads/8_Track.STL"); // Cartridge base dimensions
*translate([0, 98.6, 21.8]) rotate([-90, 0, -90]) import("/home/nettika/Downloads/Track_Lid.STL");
cartridge_length = 133;
cartridge_width = 102; cartridge_width = 102;
cartridge_length = 133;
cartridge_height = 21; cartridge_height = 21;
wedge_width = 6;
wedge_depth = 16; // Tape guide dimensions
track_inset = 6; tape_guide_width = 6;
foot_inset = 8; tape_guide_depth = 16;
tape_guide_slope = tape_guide_width / tape_guide_depth;
// Track dimensions
track_front_inset = 8;
track_back_inset = 4;
track_side_inset = 6;
track_radius = 1;
track_taper_length = 12;
// Foot dimensions
foot_width = 2.5;
foot_height = 1;
foot_front_inset = 8;
foot_back_inset = 4;
foot_side_inset = 6;
// Fillets
back_vertical_fillet_radius = 4;
side_vertical_fillet_radius = 16;
front_vertical_fillet_radius = 5;
horizontal_fillets_radius = 1;
// Windows on front wall
window_vertical_inset = 2;
window_side_inset = 14;
window_depth = 6; // 13
left_window_width = 20;
right_window_width = 20;
window_gap = 5;
roller_window_depth = 8;
roller_window_offset = 3.5;
// Emulated gap between top and bottom half
gap_height = 1; gap_height = 1;
gap_depth = 0.3; gap_depth = 0.3;
gap_elevation = 9; gap_elevation = 14;
module base_body() { // Grips
minkowski() { grip_wedge_width = 2.5;
translate([0, 0, 1]) linear_extrude(cartridge_height - 2) offset(-1) footprint(); grip_count = 5;
sphere(1);
}
translate([wedge_depth-8, 0, cartridge_height]) {
translate([0, track_inset]) track(cartridge_length-wedge_depth+4);
translate([0, cartridge_width-track_inset]) track(cartridge_length-wedge_depth+4);
}
translate([wedge_depth, foot_inset, -0.5]) foot();
translate([wedge_depth, cartridge_width-foot_inset, -0.5]) foot();
}
module track(l, r=1, taper=12) rotate([0, 90, 0]) { // Tape
cylinder(r1=0, r2=r, h=taper); roller_inset = 0;
translate([0, 0, taper]) cylinder(r=r, h=l-2*taper); roller_radius = 0;
translate([0, 0, l-taper]) cylinder(r1=r, r2=0, h=taper); roller_position = [12, 79.5];
} tape_line_position = [2, 14];
tape_height = 6.4;
module foot(w=2.5) { // NFC Coin
cube([cartridge_length-wedge_depth-2, w, 2]); nfc_coin_depth = 1;
translate([cartridge_length-wedge_depth-2, w, 1]) rotate([90, 90]) cylinder(r=1, h=w); nfc_coin_diameter = 25;
translate([0, w, 1]) rotate([90, 90]) cylinder(r=1, h=w); nfc_coin_tolerance = 0.1;
}
color("salmon") cartridge();
difference() {
base_body(); module cartridge() {
let(inset=2, d=6/*13*/) {
translate([0, 0, inset]) {
translate([0, 14]) cube([d, 20, cartridge_height-inset*2]);
translate([0, 40]) cube([d, 22, cartridge_height-inset*2]);
}
}
translate([0, 0, gap_elevation-(gap_height/2)])
linear_extrude(cartridge_height-gap_elevation+gap_height) {
for(i=[0:2.5:12.5]) {
polygon([
[cartridge_length-5-i, 0],
[cartridge_length-5-i, 1+gap_depth],
[cartridge_length-7.5-i, gap_depth],
[cartridge_length-7.5-i, 0]
]);
polygon([
[cartridge_length-5-i, cartridge_width],
[cartridge_length-5-i, cartridge_width-1-gap_depth],
[cartridge_length-7.5-i, cartridge_width-gap_depth],
[cartridge_length-7.5-i, cartridge_width]
]);
}
}
translate([0, 0, gap_elevation-(gap_height/2)]) linear_extrude(gap_height) {
difference() { difference() {
offset(10) footprint(); base();
offset(-gap_depth) footprint(); windows();
grips();
gap();
undercut();
nfc_coin();
} }
} tape();
translate([0, 0, -gap_height/2 - 2]) linear_extrude(gap_elevation+2) translate([53, cartridge_width-7]) rotate(45) offset(3) square([16, 16]);
} }
color("teal") module base() {
let(h=6.4) { translate([0, 0, horizontal_fillets_radius]) minkowski() {
translate([12, 79.5, (cartridge_height-h)/2]) cylinder(r=10, h); linear_extrude(cartridge_height - 2 * horizontal_fillets_radius)
translate([2, 14, (cartridge_height-h)/2]) cube([10, 65.5, h]); offset(-horizontal_fillets_radius)
footprint();
sphere(horizontal_fillets_radius);
}
tracks();
feet();
} }
module footprint() { module windows() {
difference() { rectangular_windows();
polygon([ roller_window();
[0, wedge_width], }
[0, cartridge_width - wedge_width],
[wedge_depth, cartridge_width], module rectangular_windows() {
[cartridge_length, cartridge_width], translate([
[cartridge_length, 0], 0,
[wedge_depth, 0], window_side_inset,
]); window_vertical_inset
let(r=4) { ]) {
translate([cartridge_length - r, 0]) { window_height = cartridge_height - 2 * window_vertical_inset;
translate([0, r]) fillet(r, a1=90, a2=180); cube([window_depth, left_window_width, window_height]);
translate([0, cartridge_width - r]) fillet(r, a1=0, a2=90); translate([
} 0,
} left_window_width + window_gap,
let(m=wedge_width/wedge_depth, r=20) { ])
translate([wedge_depth + r * tan(atan(m)/2), 0]) { cube([window_depth, right_window_width, window_height]);
translate([0, r]) fillet(r, a1=180, a2=180+atan(m));
translate([0, cartridge_width - r]) fillet(r, a1=0, a2=-atan(m));
}
}
let(m=wedge_depth/wedge_width, r=5) {
translate([r, 0]) {
translate([0, wedge_width + r * tan(atan(m)/2)]) fillet(r, a1=180+atan(1/m), a2=270);
translate([0, cartridge_width - wedge_width - r * tan(atan(m)/2)]) fillet(r, a1=270, a2=360-atan(1/m));
}
}
translate([-8, 76]) circle(r=12);
} }
} }
module fillet(r, d, a1=0, a2=360, p=10) { module roller_window() {
difference() { translate([
-roller_window_depth,
roller_position.y - roller_window_offset,
])
cylinder(h=cartridge_height, r=12);
}
module grips() {
for(i=[0:grip_count-1]) {
translate([cartridge_length - i * grip_wedge_width - back_vertical_fillet_radius, 0]) {
grip_wedge();
translate([0, cartridge_width]) mirror([0, 1]) grip_wedge();
}
}
}
module grip_wedge() {
linear_extrude(gap_elevation)
polygon([ polygon([
[0, 0], [0, 0],
each [for (a=[a1:a2]) [p * sin(a) * r, p * cos(a) * r]], [0, 1 + gap_depth],
[-grip_wedge_width, gap_depth],
[-grip_wedge_width, 0]
]); ]);
circle(r, d); }
module gap() {
translate([0, 0, gap_elevation])
linear_extrude(gap_height)
difference() {
footprint();
offset(-gap_depth) footprint();
}
}
module undercut() {
translate([53, cartridge_width - 7, -foot_height])
linear_extrude(gap_elevation + foot_height)
rotate(45)
offset(3)
square([16, 16]);
}
module tape() {
translate([0, 0, (cartridge_height - tape_height) / 2]) {
roller();
tape_line();
}
}
module roller() {
translate(roller_position)
cylinder(
h=tape_height,
r=10,
);
}
module tape_line() {
translate(tape_line_position)
cube([
window_depth - tape_line_position.x,
roller_position.y - tape_line_position.y,
tape_height
]);
}
module nfc_coin() {
translate([
cartridge_length / 2,
cartridge_width / 2,
cartridge_height - nfc_coin_depth
])
cylinder(
h=nfc_coin_depth + nfc_coin_tolerance,
d=nfc_coin_diameter + 2 * nfc_coin_tolerance,
);
};
module footprint() {
hull() {
translate([
cartridge_length - back_vertical_fillet_radius,
back_vertical_fillet_radius,
]) {
circle(back_vertical_fillet_radius);
// translate([0, cartridge_width - back_vertical_fillet_radius])
// circle(back_vertical_fillet_radius);
}
translate([
cartridge_length - back_vertical_fillet_radius,
cartridge_width - back_vertical_fillet_radius,
]) circle(back_vertical_fillet_radius);
translate([
tape_guide_depth + side_vertical_fillet_radius * tan(0.5 * atan(tape_guide_slope)),
side_vertical_fillet_radius,
]) circle(side_vertical_fillet_radius);
translate([
tape_guide_depth + side_vertical_fillet_radius * tan(0.5 * atan(tape_guide_slope)),
cartridge_width - side_vertical_fillet_radius,
]) circle(side_vertical_fillet_radius);
translate([
front_vertical_fillet_radius,
tape_guide_width + front_vertical_fillet_radius * tan(0.5 * atan(1 / tape_guide_slope)),
]) circle(front_vertical_fillet_radius);
translate([
front_vertical_fillet_radius,
cartridge_width - tape_guide_width - front_vertical_fillet_radius * tan(0.5 * atan(1 / tape_guide_slope)),
]) circle(front_vertical_fillet_radius);
}
}
module tracks() {
track_interval = cartridge_width - 2 * track_side_inset;
translate([track_front_inset, track_side_inset, cartridge_height])
rotate([0, 90, 0]) {
track();
translate([0, track_interval]) track();
}
}
module track() {
track_length = cartridge_length - track_front_inset - track_back_inset;
cylinder(
h=track_taper_length,
r1=0,
r2=track_radius,
);
translate([0, 0, track_taper_length]) cylinder(
h=track_length - 2 * track_taper_length,
r=track_radius,
);
translate([0, 0, track_length - track_taper_length]) cylinder(
h=track_taper_length,
r1=track_radius,
r2=0,
);
}
module feet() {
foot_interval = cartridge_width - 2 * foot_side_inset - foot_width;
translate([foot_front_inset, foot_side_inset, -foot_height]) {
foot();
translate([0, foot_interval, 0]) foot();
}
}
module foot() {
foot_length = cartridge_length - foot_front_inset - foot_back_inset;
translate([foot_height, 0])
cube([
foot_length - foot_height * 2,
foot_width,
foot_height,
]);
intersection() {
cube([
cartridge_length,
foot_width,
foot_height,
]);
union() {
translate([foot_height, foot_width, foot_height])
rotate([90, 90, 0])
cylinder(h=foot_width, r=foot_height);
translate([foot_length - foot_height, foot_width, foot_height])
rotate([90, 90, 0])
cylinder(h=foot_width, r=foot_height);
}
} }
} }