// Addition lookup table for mechanical computation. // This is sort of related to a barrel cam: a needle at position // (x, y) over its top surface can only sink to a depth z that // encodes an arbitrary discretized finite function of x and y. // In this case, the function in question is the truncated 3-bit // sum x+y, interpreting x and y as 3-bit numbers. // Approximation parameters. $fn = 29; epsilon = 0.010; // 10 μm // These are dimensions measured in millimeters that // I can achieve, barely, on the Prusa Mendel // to which I have access. hole_width = 1.7; wall_width = .8; first_layer_height = 0.35; // My Slic3r setting, to avoid aliasing. layer_height = 0.28; z_level_spacing = 3 * layer_height; floor_thickness = first_layer_height + 2*layer_height; skew = 0; // Parameters of the function. x_levels = 8; y_levels = 8; z_levels = 8; function lut_f(x, y) = (x + y) % 8; // Bitwise math library, for when you want to do that. function bit0(x) = x % 2; function bit1(x) = x % 4 - x % 2; function bit2(x) = x % 8 - x % 4; function bit3(x) = x % 16 - x % 8; function nibble_and(x, y) = (bit3(x) ? bit3(y) : 0) + (bit2(x) ? bit2(y) : 0) + (bit1(x) ? bit1(y) : 0) + (bit0(x) ? bit0(y) : 0); function nibble_xor(x, y) = (bit3(x) ? 8 - bit3(y) : bit3(y)) + (bit2(x) ? 4 - bit2(y) : bit2(y)) + (bit1(x) ? 2 - bit1(y) : bit1(y)) + (bit0(x) ? 1 - bit0(y) : bit0(y)); // The model as such starts here. LUT(); bevel_h = 1.5; hole_spacing = hole_width + wall_width; hole_r = hole_width / 2; z_spacing_total = z_level_spacing * (z_levels - 1); height = z_spacing_total + floor_thickness + bevel_h; cube_width = hole_spacing * x_levels - wall_width + 2*wall_width / cos(skew); cube_depth = hole_spacing * y_levels + wall_width; echo("LUT dimensions", cube_width, cube_depth * cos(skew), height); module rhomboid_prism(dimensions, theta) { s = sin(theta); c = cos(theta); multmatrix(m=[[1,s,0,0], // output X from this row [0,c,0,0], // output Y from this row [0,0,1,0], // output Z from this row [0,0,0,1]]) { cube(dimensions); } } module hole(skew, i, j, f) { base_x = i*hole_spacing + wall_width/cos(skew) + hole_r; base_y = j*hole_spacing + wall_width + hole_r; x = base_x + base_y * sin(skew); y = base_y * cos(skew); translate([x, y, floor_thickness + f * z_level_spacing]) cylinder(r=hole_r, h = height*2); translate([x, y, height - bevel_h]) cylinder(r1=hole_r - epsilon, r2=1.414*hole_spacing/2, h=bevel_h + epsilon); } module LUT() { cutoff_bevel_h = (skew > 0 ? .55 : .3) * bevel_h; difference() { rhomboid_prism([cube_width, cube_depth, height], skew); translate([-epsilon, -epsilon, height - cutoff_bevel_h]) { rhomboid_prism([cube_width + 2*epsilon, cube_depth + 2*epsilon, bevel_h * 1], skew); } for (i = [0 : x_levels-1]) { for (j = [0 : y_levels-1]) { echo(i, j, "->", lut_f(i, j)); hole(skew, i, j, lut_f(i, j)); } } } }