New lib/skadis-board generator produces a parametric IKEA Skadis-compatible pegboard panel (40mm grid + 20mm offset grid), with standard and dense density modes that both stay accessory-compatible. New raskog-separator project: a customizable RASKOG cart divider whose vertical wall is a Skadis panel, standing on an inverted-T magnetic foot. Magnets glue into pockets that open at the bottom of the flange wings so they sit flush against the basket's steel mesh; size/count/rows configurable.
219 lines
9.9 KiB
OpenSCAD
219 lines
9.9 KiB
OpenSCAD
// ============================================
|
|
// RASKOG Magnetic Skadis Separator
|
|
// ============================================
|
|
// A customizable divider for the IKEA RASKOG cart. The vertical wall is
|
|
// itself an IKEA Skadis pegboard panel, so real Skadis accessories hang on
|
|
// the divider. It stands on a wide magnetic foot whose magnets grab the
|
|
// steel wire-mesh floor of the RASKOG basket to hold the divider in place.
|
|
//
|
|
// The Skadis hole pattern comes from the shared lib/skadis-board generator
|
|
// (40mm grid + 20mm offset grid), with selectable standard/dense density —
|
|
// both stay compatible with off-the-shelf Skadis accessories.
|
|
//
|
|
// Magnets are glued into pockets that open at the BOTTOM of the foot's two
|
|
// flange wings, so each magnet sits flush against the steel mesh for the
|
|
// strongest hold. Pick bigger/more magnets for an even stronger grip.
|
|
//
|
|
// Print standing exactly as modeled (foot flat on the bed, wall up) — it is
|
|
// support-free apart from the few-mm ceiling each magnet pocket bridges over.
|
|
// Use a brim for the tall thin wall if your printer needs one.
|
|
//
|
|
// RASKOG basket interior (measured at the floor; walls taper inward):
|
|
// bottom 288 x 405, middle 284 x 397, top 278 x 389 mm.
|
|
// The default wall_width spans the short axis with clearance for the taper.
|
|
//
|
|
// Coordinate system:
|
|
// Origin (0, 0, 0) = center of the foot footprint, on the basket floor.
|
|
// X = wall length (along the basket axis being divided)
|
|
// Y = thin direction (foot width + wall thickness)
|
|
// Z = up
|
|
|
|
use <../lib/skadis-board/skadis-board.scad>;
|
|
|
|
// ============================================
|
|
// CUSTOMIZABLE PARAMETERS
|
|
// ============================================
|
|
|
|
/* [Separator Wall] */
|
|
// Wall length (X, mm). Default spans the RASKOG short axis with clearance.
|
|
wall_width = 270; // [40:1:400]
|
|
// Skadis board height above the foot (Z, mm)
|
|
wall_height = 80; // [40:1:200]
|
|
// Board thickness (mm). Keep ~5 for Skadis accessory compatibility.
|
|
wall_thickness = 5.0; // [4:0.1:6]
|
|
// Hole pattern: standard Skadis checkerboard, or denser full 20mm grid
|
|
wall_density = "dense"; // [standard, dense]
|
|
// Slot short axis (Skadis nominal 5mm)
|
|
wall_slot_width = 5.0; // [4:0.1:8]
|
|
// Slot long axis (Skadis nominal 15mm)
|
|
wall_slot_height = 15.0; // [10:0.1:25]
|
|
// Countersink at each slot mouth (mm); 0 = sharp slot
|
|
wall_edge_chamfer = 1.0; // [0:0.1:3]
|
|
// Outer board corner radius (mm)
|
|
wall_corner_r = 4; // [0:0.5:15]
|
|
|
|
/* [Magnetic Foot] */
|
|
// Foot flange total width (Y, mm) — the wide base that resists tipping
|
|
foot_flange_w = 34; // [12:1:80]
|
|
// Foot flange height (Z, mm) — must contain the magnet pocket + floor
|
|
foot_flange_h = 6; // [3:0.5:20]
|
|
// Central neck width (Y, mm) — must be >= wall_thickness
|
|
neck_w = 6; // [3:0.5:20]
|
|
// Top of the neck where the wall begins (Z, mm)
|
|
foot_height = 12; // [6:1:40]
|
|
// Chamfer on the foot's bottom edges to avoid an elephant-foot lip (mm)
|
|
foot_edge_chamfer = 1.0; // [0:0.1:4]
|
|
// Concave fillet where the neck meets the flange top (mm) — strength
|
|
join_fillet_r = 2.0; // [0:0.5:8]
|
|
// How far the wall base sinks into the neck for a solid union (mm)
|
|
merge_overlap = 3; // [1:0.1:8]
|
|
|
|
/* [Magnets] */
|
|
// Magnet disc diameter (mm)
|
|
magnet_diameter = 6; // [3:0.5:20]
|
|
// Magnet disc height/thickness (mm)
|
|
magnet_height = 3; // [1:0.5:6]
|
|
// Magnet rows: 2 = one per wing (default, anti-tip), 1 = single offset row
|
|
magnet_rows = 2; // [1, 2]
|
|
// Magnets along the foot in each row
|
|
magnet_per_row = 6; // [1:1:30]
|
|
// Radial clearance around each magnet (glue gap, mm)
|
|
magnet_fit_clear = 0.2; // [0:0.05:0.6]
|
|
// How far the magnet sits above the bottom face (mm) — 0 = flush with the
|
|
// foot bottom for the strongest grip; raise to recess/protect the magnet
|
|
magnet_recess = 0.0; // [0:0.1:3]
|
|
// Distance from the foot ends to the first/last magnet (mm)
|
|
magnet_inset = 18; // [5:1:80]
|
|
|
|
/* [Resolution] */
|
|
$fn = 64;
|
|
|
|
// ============================================
|
|
// DERIVED DIMENSIONS
|
|
// ============================================
|
|
foot_length = wall_width; // foot runs the full length of the wall
|
|
hf = foot_flange_w / 2; // flange half-width (Y)
|
|
nf = neck_w / 2; // neck half-width (Y)
|
|
pocket_r = magnet_diameter / 2 + magnet_fit_clear;
|
|
// Y of each magnet row: centered in the wing region that is clear of the
|
|
// neck-to-flange fillet, so the magnet never collides with the fillet.
|
|
wing_center_y = (nf + join_fillet_r + hf) / 2;
|
|
wall_z = foot_height - merge_overlap; // board base Z (sunk into the neck)
|
|
total_height = wall_z + wall_height; // overall part height (info)
|
|
|
|
// ============================================
|
|
// PARAMETER VALIDATION
|
|
// ============================================
|
|
assert(wall_width > 0 && wall_height > 0, "wall_width and wall_height must be positive");
|
|
assert(wall_thickness >= 4 && wall_thickness <= 6,
|
|
"wall_thickness should be ~5mm for Skadis accessory compatibility");
|
|
assert(foot_flange_w > neck_w, "foot_flange_w must be greater than neck_w");
|
|
assert(neck_w >= wall_thickness, "neck_w must be >= wall_thickness so the wall seats on the foot");
|
|
assert(foot_height > foot_flange_h, "foot_height must be greater than foot_flange_h (the neck rises above the flange)");
|
|
assert(magnet_recess >= 0, "magnet_recess must be non-negative");
|
|
assert(foot_flange_h >= magnet_recess + magnet_height + 0.8,
|
|
"foot_flange_h too small: needs magnet_recess + magnet_height + >=0.8mm cap above the magnet");
|
|
assert(magnet_diameter > 0 && magnet_height > 0, "magnet dimensions must be positive");
|
|
assert(magnet_rows == 1 || magnet_rows == 2, "magnet_rows must be 1 or 2");
|
|
assert(magnet_per_row >= 1, "magnet_per_row must be >= 1");
|
|
assert(magnet_fit_clear >= 0, "magnet_fit_clear must be non-negative");
|
|
assert(wing_center_y - pocket_r >= nf + join_fillet_r,
|
|
"magnet pocket overlaps the neck/fillet — widen the flange or shrink the magnet");
|
|
assert(wing_center_y + pocket_r <= hf - foot_edge_chamfer - 0.5,
|
|
"magnet pocket too close to the flange edge — widen the flange or shrink the magnet");
|
|
assert(2 * magnet_inset < foot_length, "magnet_inset too large for the foot length");
|
|
assert(magnet_per_row == 1
|
|
|| (foot_length - 2 * magnet_inset) >= (magnet_per_row - 1) * (magnet_diameter + 2 * magnet_fit_clear + 2),
|
|
"not enough foot length to fit magnet_per_row pockets without overlap");
|
|
assert(merge_overlap > 0 && merge_overlap < foot_height && merge_overlap < wall_height,
|
|
"merge_overlap must fit within both the neck and the wall");
|
|
assert(foot_edge_chamfer >= 0 && 2 * foot_edge_chamfer < foot_flange_w
|
|
&& foot_edge_chamfer < foot_flange_h,
|
|
"foot_edge_chamfer must fit within the flange");
|
|
assert(join_fillet_r >= 0 && join_fillet_r <= (foot_flange_w - neck_w) / 2
|
|
&& join_fillet_r <= (foot_height - foot_flange_h),
|
|
"join_fillet_r must fit within the flange-to-neck step");
|
|
|
|
// ============================================
|
|
// MAIN ASSEMBLY
|
|
// ============================================
|
|
separator();
|
|
|
|
module separator() {
|
|
union() {
|
|
magnetic_foot();
|
|
translate([-wall_width / 2, -wall_thickness / 2, wall_z])
|
|
skadis_board(
|
|
width = wall_width,
|
|
height = wall_height,
|
|
thickness = wall_thickness,
|
|
density = wall_density,
|
|
slot_w = wall_slot_width,
|
|
slot_h = wall_slot_height,
|
|
edge_chamfer = wall_edge_chamfer,
|
|
corner_r = wall_corner_r);
|
|
}
|
|
}
|
|
|
|
// ============================================
|
|
// COMPONENT MODULES
|
|
// ============================================
|
|
|
|
// Inverted-T foot: a wide flat flange (the basket-floor footprint) with a
|
|
// narrow central neck the wall seats on. Magnet pockets are subtracted from
|
|
// the flange wings. Built by extruding the Y-Z cross-section along X.
|
|
module magnetic_foot() {
|
|
difference() {
|
|
rotate([90, 0, 90]) // map 2D (u,v) -> (Y, Z); extrude along X
|
|
linear_extrude(height = foot_length, center = true)
|
|
polygon(_foot_profile(
|
|
hf = hf, nf = nf, ch = foot_edge_chamfer,
|
|
fh = foot_flange_h, th = foot_height, jf = join_fillet_r));
|
|
magnet_pockets();
|
|
}
|
|
}
|
|
|
|
// 2D cross-section of the foot in the Y-Z plane (first coord = Y, second = Z).
|
|
// Symmetric inverted-T: chamfered bottom flange + concave fillets where the
|
|
// vertical neck meets the flange top.
|
|
function _foot_profile(hf, nf, ch, fh, th, jf, n_arc = 12) =
|
|
let (
|
|
// Left inside fillet: flange top (z=fh) up to neck wall (Y=-nf).
|
|
left_fillet = [
|
|
for (i = [0 : n_arc])
|
|
let (a = -90 + 90 * i / n_arc)
|
|
[(-nf - jf) + jf * cos(a), (fh + jf) + jf * sin(a)]
|
|
],
|
|
// Right inside fillet: neck wall (Y=nf) down to flange top (z=fh).
|
|
right_fillet = [
|
|
for (i = [0 : n_arc])
|
|
let (a = 180 + 90 * i / n_arc)
|
|
[(nf + jf) + jf * cos(a), (fh + jf) + jf * sin(a)]
|
|
]
|
|
)
|
|
concat(
|
|
[[-(hf - ch), 0], [-hf, ch], [-hf, fh]],
|
|
left_fillet,
|
|
[[-nf, th], [nf, th]],
|
|
right_fillet,
|
|
[[hf, fh], [hf, ch], [hf - ch, 0]]
|
|
);
|
|
|
|
// Glue-in magnet pockets: vertical bores opening at the BOTTOM of the flange
|
|
// wings. The magnet is glued in from below, seating against the pocket
|
|
// ceiling magnet_recess above the bottom face; the solid cap above it is
|
|
// what the print bridges over.
|
|
module magnet_pockets() {
|
|
rows_y = (magnet_rows == 2) ? [-wing_center_y, wing_center_y] : [wing_center_y];
|
|
for (y = rows_y)
|
|
for (x = _magnet_x_positions())
|
|
translate([x, y, -1])
|
|
cylinder(h = magnet_recess + magnet_height + 1, r = pocket_r);
|
|
}
|
|
|
|
// Evenly spaced magnet X positions within the inset span (centered if one).
|
|
function _magnet_x_positions() =
|
|
let (span = foot_length / 2 - magnet_inset)
|
|
(magnet_per_row == 1)
|
|
? [0]
|
|
: [ for (i = [0 : magnet_per_row - 1]) -span + 2 * span * i / (magnet_per_row - 1) ];
|