/* Improved Auto Coin Sorter V7.41 */ /* - Customizer syntax error fixed */ /* - Coin-roll and "classic" slot versions */ /* - Custom currency support re-introduced */ /* - New contoured back */ /* - Front tube rack retaining edge */ /* - Basebox can be printed upright now */ /* - Includes NIS Israeli New Shekel */ /* - Includes NOK Norwegian Krone */ /* - Includes RON Romanian Leu */ /* - Includes TWD New Taiwan Dollar */ /* - Includes TRY Turkish Lira */ /* - Includes XPF CFP Franc */ /* by Bikecyclist */ /* https://www.thingiverse.com/Bikecyclist */ /* */ /* Version History */ /* */ /* Improved Auto Coin Sorter V7.3 */ /* - Scale placement more accurate */ /* - Includes IDR Indonesian Rupiah */ /* - Includes INR Indian Rupee */ /* - Includes ISK Icelandic Krona */ /* - Includes MXN Mexican Peso */ /* - Includes SGD Singapore Dollar */ /* by Bikecyclist */ /* https://www.thingiverse.com/Bikecyclist */ /* Improved Auto Coin Sorter V7.2 */ /* - New internal logic for coin selection */ /* - Includes ARS Argentine Peso */ /* - Includes AUD Australian Dollar */ /* - Includes BRL Brazilian Real */ /* - Includes CLP Chilean Peso */ /* - Includes CZK Czech Koruna */ /* - Includes DKK Danish Krone */ /* - Includes HKD Hong Kong Dollar */ /* - Includes HUF Hungarian Forint */ /* - Includes JPY Japanese Yen */ /* by Bikecyclist */ /* https://www.thingiverse.com/Bikecyclist */ /* */ /* Improved Auto Coin Sorter V7.1 */ /* - Includes GBP British Pound */ /* - Includes RUB Russian Ruble */ /* - Unused "other" option removed from selection */ /* by Bikecyclist */ /* https://www.thingiverse.com/Bikecyclist */ /* */ /* Improved Auto Coin Sorter V7 */ /* https://www.thingiverse.com/thing:3467834 */ /* - Includes Features from Compact Version */ /* - Coin roll support looks at more details */ /* - Coin tube base chamfered (anti-elephant) */ /* - Coin tube base bottom marked with index number */ /* - New style of base box backside pattern added */ /* - Topboard tolerance added */ /* - Increased topboard rim height */ /* - Extra height for right end of vertical guard */ /* - Support for "other coins" dropped */ /* by Bikecyclist */ /* https://www.thingiverse.com/Bikecyclist */ /* */ /* Improved Auto Coin Sorter V6 */ /* - Interim version, never released */ /* by Bikecyclist */ /* https://www.thingiverse.com/Bikecyclist */ /* */ /* Improved Auto Coin Sorter V5 */ /* https://www.thingiverse.com/thing:3421345 */ /* - Obsolete image decoration code removed */ /* - Unused dovetail code removed */ /* - Unused box/tube emptier code removed */ /* by Bikecyclist */ /* https://www.thingiverse.com/Bikecyclist */ /* */ /* Remixed from */ /* */ /* Compact Improved Auto Coin Sorter */ /* https://www.thingiverse.com/thing:3338193 */ /* by Bikecyclist */ /* https://www.thingiverse.com/Bikecyclist */ /* */ /* Customized Auto Coin Sorter PLN */ /* (No longer on Thingiverse) */ /* by Seveneq */ /* https://www.thingiverse.com/Seveneq */ /* */ /* Improved Auto Coin Sorter V4.1, V4, V3, V2, V1 */ /* https://www.thingiverse.com/thing:3203049 */ /* by Bikecyclist */ /* https://www.thingiverse.com/Bikecyclist */ /* */ /* Sorteador Monedas Mexicanas */ /* https://www.thingiverse.com/thing:3204506 */ /* by morenot3131 */ /* https://www.thingiverse.com/morenot3131 */ /* */ /* Coin sorter for UK coins (inc new £1) */ /* https://www.thingiverse.com/thing:2498200 */ /* by mabbog */ /* https://www.thingiverse.com/mabbog */ /* */ /* Auto Coin Sorter for All Currencies */ /* https://www.thingiverse.com/thing:499177 */ /* by Youngcat */ /* https://www.thingiverse.com/youngcat */ /* */ /* Customized versions of Youngcat's Coin Sorter */ /* for the following currencies: */ /* */ // ARS // https://www.thingiverse.com/thing:1955336 // by // https://www.thingiverse.com/charly3darg // // AUD // https://www.thingiverse.com/thing:1073586 // by // https://www.thingiverse.com/Sadiablo // // BRL // https://www.thingiverse.com/thing:958842 // by // https://www.thingiverse.com/igcefa // // CLP // https://www.thingiverse.com/thing:1869330 // by // https://www.thingiverse.com/yutroc // // CZK // https://www.thingiverse.com/thing:1616408 // by // https://www.thingiverse.com/Tomas_Halbych // // DKK // https://www.thingiverse.com/thing:1032447 // by // https://www.thingiverse.com/Nonbeliever // // HKD // https://www.thingiverse.com/thing:1681392 // by // https://www.thingiverse.com/g2david // // HUF // https://www.thingiverse.com/thing:1025395 // by // https://www.thingiverse.com/thebence98 // // IDR // https://www.thingiverse.com/thing:2166484 // by // https://www.thingiverse.com/rizkypratama // // INR // https://www.thingiverse.com/thing:2034732 // by // https://www.thingiverse.com/Neeraja // // JPY // https://www.thingiverse.com/thing:1717615 // by // https://www.thingiverse.com/miettal // // NIS // https://www.thingiverse.com/thing:2152362 // by // https://www.thingiverse.com/Esh_Robotics // // NOK // https://www.thingiverse.com/thing:1024392 // by // https://www.thingiverse.com/RolBerg // // RON // https://www.thingiverse.com/thing:2109232 // by // https://www.thingiverse.com/szilveszter // // TWD // https://www.thingiverse.com/thing:1671027 // by // https://www.thingiverse.com/osmiumtpe // // XPF // https://www.thingiverse.com/thing:1821933 // by // https://www.thingiverse.com/M2orea /* [General] */ // Choose a currency you use. currency = 8; // [-1:Custom - Define Coins in Custom Currency Tab, 0:ARS - Argentine Peso, 1:AUD - Australian Dollar, 2:BRL - Brazilian Real, 3:CAD - Canadian dollar, 4:CHF - Swiss Franc, 5:CLP - Chilean Peso, 6:CZK - Czech Koruna, 7:DKK - Danish Krone, 8:EUR - Euro, 9:GBP - British Pounds, 10: HKD - Hong Kong Dollar, 11: HUF - Hungarian Forint, 12:IDR - Indonesian Rupiah, 13:INR Indian Rupee, 14: ISK - Icelandic Krona, 15:JPY - Japanese Yen, 16:MXN - Mexican Peso, 17: NIS - Israeli New Shekel, 18: NOK - Norwegian Krone, 19:PEN - Peruvian Sol, 20:PLN - Polish Zloty, 21: RON - Rumanian Leu, 22:RUB - Russian Ruble, 23:SEK - Swedish Krona, 24:SGD - Singapore Dollar, 25:THB - Thai Baht, 26:TRY - Turkish Lira, 27:TWD - New Taiwan Dollar, 28:USD - US dollar, 29:XFP - CFP Franc] // Choose Coin Roll vs. Classic Slot Version coin_roll_version = 1; // [1: Coin Roll Version, 2:Classic Slot Version] // How much height to add to the default for the shortest tube? In millimeters: tube_extra_height = 0; // [-100:150] // How much extra topboard length for placing the coins on the sorter? (In percent of the total topboard length.): extra_topboard_length_pct = 14; // [0:30] extra_topboard_length = extra_topboard_length_pct * 0.01; // Style of vertical guard guard_style = "Front_and_back"; // [Front_and_back:Front and back guard rails, Front_guard: Front guard rail only] // How much extra height on the right hand side of the guard rail? In millimeters: extra_guard_height = 15; // [0:30] // Topboard bottom rim height. (Holds topboard on.) topboard_rim = 15; //[10:25] // Which parts would you like to see? part = "all_unassembled"; // [all_assembled:All parts assembled, all_unassembled:All parts unassembled, basebox:Base box only,topboard:Top board only, tuberack:Tube rack only, tubes:Tubes only] /* [Custom Currency] */ // Enter ISO 4217 code for custom currency - see https://en.wikipedia.org/wiki/ISO_4217#Active_codes custom_currency_code = "ABC"; // Diameter of largest coin (0 to skip this coin) coin_01_dia = 10.01; // Thickness of largest coin coin_01_th = 1.01; // Number of coins in a coin tube (for this coin) coin_01_n = 25; // Diameter of 2nd largest coin (0 to skip this coin) coin_02_dia = 9.01; // Thickness of this coin coin_02_th = 1.01; // Number of coins in a coin tube (for this coin) coin_02_n = 25; // Diameter of 3rd largest coin (0 to skip this coin) coin_03_dia = 8.01; // Thickness of this coin coin_03_th = 1.01; // Number of coins in a coin tube (for this coin) coin_03_n = 25; // Diameter of 4th largest coin (0 to skip this coin) coin_04_dia = 7.01; // Thickness of this coin coin_04_th = 1.01; // Number of coins in a coin tube (for this coin) coin_04_n = 50; // Diameter of 5th largest coin (0 to skip this coin) coin_05_dia = 0.00; // Thickness of this coin coin_05_th = 1.01; // Number of coins in a coin tube (for this coin) coin_05_n = 50; // Diameter of 6th largest coin (0 to skip this coin) coin_06_dia = 0.00; // Thickness of this coin coin_06_th = 1.01; // Number of coins in a coin tube (for this coin) coin_06_n = 50; // Diameter of 7th largest coin (0 to skip this coin) coin_07_dia = 0.00; // Thickness of this coin coin_07_th = 1.01; // Number of coins in a coin tube (for this coin) coin_07_n = 50; // Diameter of 8th largest coin (0 to skip this coin) coin_08_dia = 0.00; // Thickness of this coin coin_08_th = 1.01; // Number of coins in a coin tube (for this coin) coin_08_n = 50; // Diameter of 9th largest coin (0 to skip this coin) coin_09_dia = 0.00; // Thickness of this coin coin_09_th = 1.01; // Number of coins in a coin tube (for this coin) coin_09_n = 50; // Diameter of 10th largest coin (0 to skip this coin) coin_10_dia = 0.00; // Thickness of this coin coin_10_th = 1.01; // Number of coins in a coin tube (for this coin) coin_10_n = 50; // Enter default length of shortest tube default_shortest = 75; /* [Hidden] */ all_coins = [ ["ARS", [26.00, 25.00, 24.00, 19.00], [ 2.15, 2.00, 1.75, 1.35], [ 25, 25, 50, 50], 95], // Source: Wikipedia ["AUD", [ 31.65, 28.65, 25.00, 23.60, 20.50, 19.41], [ 2.80, 2.50, 3.00, 2.00, 2.80, 1.30], [ 25, 25, 25, 50, 25, 50], 90], ["BRL", [ 27, 25, 23.50, 23, 22, 22, 21, 20], [ 1.95, 2.25, 1.40, 2.85, 1.65, 1.20, 1.20, 2.23], [ 25, 25, 50, 25, 50, 50, 50, 50], 80], ["CAD", [28.00, 27.13, 26.50, 23.88, 21.20, 19.05, 18.03], [ 1.80, 1.95, 1.75, 1.58, 1.76, 1.45, 1.22], [ 25, 25, 50, 50, 50, 50, 50], 90], ["CHF", [31.45, 27.40, 23.20, 21.05, 19.15, 18.20, 17.15], [ 2.35, 2.15, 1.15, 1.65, 1.45, 1.25, 1.25], [ 25, 25, 50, 50, 50, 50, 50], 75], ["CLP", [ 26.94, 25.52, 23.5, 21.08], [ 2.00, 2.00, 2.33, 1.46], [ 25, 25, 25, 50], 75], ["CZK", [ 27.50, 26, 24.5, 23, 21.5, 20], [ 2.55, 2.55, 2.55, 1.85, 1.85, 1.85], [ 25, 25, 25, 50, 50, 50], 90], ["DKK", [ 28.5, 27.00, 24.5, 23.35, 21.5, 20.25], [ 2.0, 2.35, 1.8, 2.3, 1.55, 1.6], [ 25, 25, 50, 25, 50, 50], 90], ["EUR", // 2.00 0.50 1.00 0.20 0.05 0.10 0.02 0.01 [25.75, 24.25, 23.25, 22.25, 21.25, 19.75, 18.75, 16.25], [ 2.20, 2.38, 2.33, 2.14, 1.67, 1.93, 1.67, 1.67], [ 25, 20, 25, 40, 50, 40, 50, 50], 80], ["GBP", [28.5, 27.5, 25.9, 24.5, 23.5, 21.4, 20.3, 18.0], [2.5, 1.78, 2.03, 1.85, 3.15, 1.7, 1.65, 1.70], [ 25, 25, 25, 50, 25, 50, 50, 50], 90], ["HKD", [ 28, 27.00, 25.5, 24, 22.50, 19, 17.5], [ 2.03, 3.26, 1.95, 3, 1.72, 1.52, 1.15], [ 25, 25, 25, 25, 50, 50, 50], 95], ["HUF", [ 28.3, 27.4, 26.3, 24.8, 23.8, 21.2], [ 2, 1.7, 1.9, 1.3, 2.2, 1.3], [ 25, 50, 50, 50, 50, 50], 95], ["IDR", [ 27.2, 25, 24, 23], [ 2.3, 2.1, 1.5, 1.9], [ 25, 25, 50, 50], 90], ["INR", [ 28, 25, 23, 22], [ 1.8, 1.4, 2.5, 1.3], [ 25, 25, 25, 50], 70], // Source: Wikipedia ["ISK", // 10 100 5 50 1 [27.50, 25.50, 24.50, 23.00, 21.50], [ 1.78, 2.25, 1.75, 2.60, 1.66], [ 25, 25, 25, 25, 50], 70], ["JPY", [26.5, 23.5, 22.6, 22.0, 21.0, 20.0], [ 1.8, 1.5, 1.7, 1.5, 1.7, 1.5], [ 25, 50, 50, 50, 50, 50], 90], ["MXN", [ 32, 28, 25.5, 23, 21, 17], [ 2.15, 2.00, 1.75, 1.95, 1.8, 1.7], [ 25, 25, 50, 50, 50, 50], 90], ["NIS", [ 26, 24, 23, 22, 21.6, 18], [ 1.6, 2.4, 2.2, 1.5, 2.3, 2.1], [ 25, 25, 25, 50, 25, 50], 90], ["NOK", [ 27.5, 26, 24, 21], [ 2.2, 2, 2, 1.7], [ 25, 25, 25, 50], 80], ["PEN", [25.50, 24.38, 23.00, 22.30, 22.00, 20.50, 18.00], [ 1.65, 2.13, 1.26, 2.07, 1.65, 1.26, 1.26], [ 25, 25, 50, 50, 50, 50, 50], 90], ["PLN", [24.00, 23.00, 21.50, 20.50, 19.50, 18.50, 17.50, 16.50, 15.50], [ 2.00, 1.70, 2.00, 1.70, 1.40, 1.70, 1.40, 1.70, 1.40], [ 25, 25, 25, 50, 50, 50, 50, 50, 50], 75], ["RON", [ 23.7, 20.35, 18.13, 16.75], [ 1.82, 1.75, 1.6, 1.57], [ 25, 25, 25, 50], 80], ["RUB", [25.08, 23.17, 22.10, 20.56, 19.47, 17.55], [ 1.90, 1.84, 2.25, 1.40, 1.45, 1.23], [ 25, 25, 25, 50, 50, 50], 70], ["SEK", [23.75, 22.50, 20.50, 19.50], [ 1.97, 1.79, 1.79, 2.90], [ 25, 25, 25, 25], 70], // Source: Wikipedia ["SGD", // 1.00 0.50 0.20 0.10 0.05 [24.65, 23.00, 21.00, 18.50, 16.75], [ 2.50, 2.45, 1.72, 1.38, 1.22], [ 25, 25, 50, 50, 50], 90], ["THB", [26.00, 24.05, 22.05, 20.01], [ 2.16, 2.13, 1.48, 1.38], [ 20, 20, 50, 50], 70], // Source: Wikipedia ["TRY", // 1.00 0.50 0.25 0.10 0.05 0.01 [26.15, 23.85, 20.50, 18.50, 17.50, 16.50], [ 1.90, 1.90, 1.65, 1.65, 1.65, 1.35], [ 25, 25, 50, 50, 50, 50], 85], ["TWD", [ 28, 26, 22 , 20], [ 2.4, 1.9, 1.6, 1.6], [ 25, 25, 50, 50], 85], ["USD", // 0.50 1.00 0.25 0.05 0.01 0.10 [30.61, 26.50, 24.26, 21.21, 19.05, 17.91], [ 2.15, 2.00, 1.75, 1.95, 1.55, 1.35], [ 20, 25, 40, 40, 50, 50], 75], ["XFP", [ 33, 31, 29.89, 28.48, 27.02, 23.95, 23], [ 2.37, 2.24, 1.98, 2.14, 1.76, 1.84, 1.43], [ 25, 25, 25, 25, 50, 50, 50], 80] ]; echo (all_coins [currency]); // // Hidden Obsolescent Parameters // // Choose a pattern for the back side. pattern = "no"; // [no:Solid with contoured back, chncoin:Chinese ancient coin pattern, mesh:Mesh pattern] // If a back side pattern is selected, should it be filled in? patternfill = "yes"; // [yes:filled-in back, no:open back] // Choose the desired mesh thickness. In millimeters: mesh_thickness = 0.8; // // MAIN // height = currency>=0? tube_extra_height + all_coins [currency][4]: tube_extra_height + default_shortest; other_coins_d_t = [ [coin_01_dia, coin_01_th, coin_01_n], [coin_02_dia, coin_02_th, coin_02_n], [coin_03_dia, coin_03_th, coin_03_n], [coin_04_dia, coin_04_th, coin_04_n], [coin_05_dia, coin_05_th, coin_05_n], [coin_06_dia, coin_06_th, coin_06_n], [coin_07_dia, coin_07_th, coin_07_n], [coin_08_dia, coin_08_th, coin_08_n], [coin_09_dia, coin_09_th, coin_09_n], [coin_10_dia, coin_10_th, coin_10_n] ]; coins = currency>=0? [ all_coins [currency][1], all_coins [currency][2], all_coins [currency][3] ] : [ [for (i=other_coins_d_t) if(i[0] > 0) i[0]], [for (i=other_coins_d_t) if(i[0] > 0) i[1]], [for (i=other_coins_d_t) if(i[0] > 0) i[2]] ]; coins_d = coins[0]; coins_thickness = coins[1]; coins_n = coins [2]; enable_box = (part == "all_assembled" || part == "all_unassembled" || part == "basebox"); enable_mesh = (pattern != "no" && pattern != "slim"); enable_top_board = (part == "all_assembled" || part == "all_unassembled" || part == "topboard"); enable_tubes = (part == "all_assembled" || part == "all_unassembled" || part == "tubes") && (coin_roll_version == 1); enable_tuberack = (part == "all_assembled" || part == "all_unassembled" || part == "tuberack"); enable_tuberack_scale = true; assembled = (part != "all_unassembled"); lay_flat = (part != "all_assembled" && part != "all_unassembled"); // Thickness of back-side fill-in (if selected) min_wall_thickness = 0.3; // Thickness of tube walls th_tubewall = 0.5; // Tolerance between tubes and tuberack tol_tuberack = 0.25; guard_corner_radius = 5; sorter_min_height = height; board_thickness = 2.0; // This also implies wall thickness board_left_padding = 1; board_right_padding = 1; board_primary_slope = 16; board_secondary_slope = 15; horizontal_guard_width = 3; coin_padding = 0.4; coin_padding_top_board = 0.25; nozzle_size = 0.4; nozzle_size_upbound = 0.41; tuberack_shorter = 5; tuberack_front_back_cut = 2; tuberack_base_thickness = 4.0; tuberack_back_thinner = 1; tuberack_scale_depth = 0.4; tuberack_scale_height = 0.8; tuberack_padding = 0.5; // Applies to tuberack retaining ledge horizontally and vertically tuberack_retaining_ledge_height = tuberack_base_thickness - tuberack_padding; unassembled_top_board_lift = 45; unassembled_tuberack_lift = 20; unassembled_tubes_lift = 40; topboard_bigger = 1.6; $fa = 6; // default: 12 $fs = 1; // default: 2 coin_count = len(coins_d); coin_max_index = coin_count - 1; board_length = (board_left_padding + board_right_padding + sum_coins_d() + coin_padding * coin_count * 2 + board_thickness * (coin_count + 3)); board_width = coins_d[0] + coin_padding + board_thickness * 3; slope_height = tan(board_secondary_slope) * board_width + tan(board_primary_slope) * board_length; sorter_max_height = sorter_min_height + slope_height + board_thickness; echo("box length:", board_length); //echo("board_width:", board_width); echo("box min height:", sorter_min_height); echo("box max height:", sorter_max_height); //projection (cut = true) translate ([0, 0, -80]) main(); module main() { top_board_lift = assembled ? 0 : unassembled_top_board_lift; tuberack_lift = assembled ? 0 : unassembled_tuberack_lift; tubes_lift = assembled ? 0 : unassembled_tubes_lift; if (lay_flat) { main_impl_flat(top_board_lift, tuberack_lift, tubes_lift); } else { main_impl(top_board_lift, tuberack_lift, tubes_lift); } } module main_impl(top_board_lift=0, tuberack_lift=0, tubes_lift=0) { if (enable_box) { base_box(false); } if (enable_top_board) { translate([0, 0, top_board_lift]) top_board(); } if (enable_tuberack) { translate([0, 0, tuberack_lift]) tuberack(); } if (enable_tubes) { translate([0, 0, tubes_lift]) tubes(); } } module main_impl_flat(top_board_lift=0, tuberack_lift=0, tubes_lift=0) { if (enable_box) { if (!enable_mesh) base_box(false); else rotate([-90, 0, 0]) base_box(false); } if (enable_top_board) { translate([0, 0, top_board_lift]) untransform_top_board(sorter_min_height) top_board(); } if (enable_tuberack) { translate([0, 0, tuberack_lift]) tuberack(); } if (enable_tubes) { translate([0, 0, tubes_lift]) tubes(); } } // // BASE BOX // // Component: the box. module base_box() { render(convexity=4) difference() { union() { box_empty(); } if (enable_mesh) { board_back_hollow(board_thickness * 1.5); } } if (enable_mesh) { intersection() { board_back_mesh(); union() { board_back_hollow(); box_back_fill(); } *if (patternfill == "yes") box_empty (); } // Closed backside if (patternfill == "yes") translate ([0, box_size()[1], 0]) rotate ([-90, 0, 0]) linear_extrude (min_wall_thickness, convexity = 2) projection (cut = false) rotate ([90, 0, 0]) box_empty (); } else { box_back_fill(); } } function box_size(fatter=0, thicker=0, altitude=0, fronter=0, taller=0) = [board_length + fatter*2 + thicker*2, board_width + fatter*2 + thicker*2 + fronter, sorter_max_height + fatter*2 + thicker*2 + taller]; module box_move(fatter=0, thicker=0, altitude=0, fronter=0, taller=0) { translate([-fatter-thicker, -fatter-thicker-fronter, altitude-fatter-thicker]) { children(); } } module box_empty() { cut_top_side() { difference () { box_empty_tall(); translate ([4 * board_thickness, board_thickness + 0.01, board_thickness]) cube ([box_size () [0] - 8 * board_thickness - board_left_padding - board_right_padding, box_size () [1], box_size() [2]]); } difference () { translate ([0, -board_thickness, 0]) cube ([box_size ()[0], board_thickness + tuberack_front_cut_y(), tuberack_retaining_ledge_height]); linear_extrude(height = tuberack_retaining_ledge_height + 0.01, center=false, convexity=2) offset (tuberack_padding) tuberack_base_2(); } } } module box_empty_tall(fatter=0, thicker=0, altitude=0) { difference() { box_outer_solid_tall(fatter, thicker, altitude); box_inner_solid_tall(fatter, thicker, altitude); } } module box_outer_solid_tall(fatter=0, thicker=0, altitude=0, fronter=0, taller=0) { box_move(fatter, thicker, altitude, fronter, taller) { cube(box_size(fatter, thicker, altitude, fronter, taller)); } } module box_inner_solid_tall(fatter=0, thicker=0, altitude=0) { box_outer_solid_tall( fatter - board_thickness - thicker, thicker, altitude, board_thickness + thicker + 0.1, board_thickness + thicker + 0.1); } module board_back_hollow(thicker=0) { xyz = box_size(fatter = -board_thickness - thicker); cut_top_side(altitude = -thicker) box_move(fatter = -board_thickness - thicker) translate([0, xyz[1] + thicker/2, 0]) { cube([xyz[0], board_thickness + thicker, xyz[2]]); } } module box_back_fill(thicker=0) { cut_top_side(altitude = -thicker) { box_back_fill_tall(); } } module box_back_fill_tall(wall_only = true) { linear_extrude(height=sorter_max_height, center=false, convexity=8) translate([0, coin_padding*2]) if (wall_only) { intersection () { offset (board_thickness) difference () { square ([box_size() [0], box_size () [1] - board_thickness - coin_padding * 2 - 0.01]); tuberack_back_contour (); } tuberack_back_contour (); } } else tuberack_back_contour (); } module tuberack_back_contour () { difference() { polygon(tuberack_cut_back_complete()); for (i = [0 : coin_max_index]) coin_hole_plain(i); } } // Transformation: cut the right, left, back and front side. module cut_sides(fatter=0, thicker=0) { intersection() { union() { children(); } box_outer_solid_tall(fatter, thicker, taller=sorter_max_height); } } module cut_top_side(fatter=0, thicker=0, altitude=0) { difference() { union() { children(); } top_side(sorter_min_height + fatter + altitude); } } // // MESH // module board_back_mesh() { diag_len = sqrt(board_length * board_length + sorter_max_height*sorter_max_height); if (pattern == "mesh") { board_back_mesh_grids( mesh_thickness, 15, ceil(diag_len / 15) + 1, 45, [board_length / 2, board_width * 0.7, sorter_max_height / 2], "y", board_width); } else if (pattern == "chncoin") { board_back_mesh_ancient_coins( mesh_thickness, 18, ceil(diag_len / 18 / 2) + 2, [board_length / 2, board_width * 0.7, sorter_max_height / 2], "y", board_width); } } module mesh_extrude( center=[0,0,0], normal_direction="z", height=10, convexity=10) { translate(center) { rotate(normal_direction=="x" ? [0,90,0] : normal_direction=="y" ? [-90,0,0] : [0,0,0]) { linear_extrude(height, center=true, convexity=convexity) { children(); } } } } module board_back_mesh_grids( thickness, gap, count, rotate_angle=0, center=[0,0,0], normal_direction="z", height=10) { length = (thickness + gap) * (count - 1) + thickness; mesh_extrude(center, normal_direction, height, convexity=8) rotate([0, 0, rotate_angle]) translate([-length/2, -length/2]) { for (i = [0 : count - 1]) { translate([(thickness + gap) * i, 0]) { square([thickness, length]); } translate([0, (thickness + gap) * i]) { square([length, thickness]); } } } } module board_back_mesh_ancient_coins( thickness, radius, count, center=[0,0,0], normal_direction="z", height=10) { sqrt2 = sqrt(2); mesh_extrude(center, normal_direction, height, convexity=8) translate([-sqrt2 * radius * (count - 1) / 2, -sqrt2 * radius * (count - 1) / 2]) { for (i = [0 : count - 1]) for (j = [0 : count - 1]) { translate([sqrt2 * radius * i, sqrt2 * radius * j]) { render(convexity=2) difference() { circle(r=radius + thickness / 2); circle(r=radius - thickness / 2); } } } } } // // TOP BOARD // // Component: the solid board on top (topboard) module top_board() { difference() { // the board itself union () { cut_sides() transform_top_board(sorter_min_height) cube([board_length*2, board_width*2, board_thickness]); difference () { transform_top_board(sorter_min_height) translate ([0, 0, -topboard_rim + board_thickness - 0.01]) linear_extrude (topboard_rim) offset (topboard_rim/2) scale ([1.05 + extra_topboard_length, 1.05, 1]) projection (cut = false) cut_sides() transform_top_board(sorter_min_height) cube([board_length*2, board_width*2, board_thickness]); cut_sides() transform_top_board(sorter_min_height) cube([board_length*2, board_width*2, board_thickness]); topboard_bottom_cutout (); } } // holes and cuts for (i = [0 : coin_max_index]) { coin_hole(i, bigger_r=coin_padding_top_board-coin_padding); slope_cut_for_coin(i, bigger_r=coin_padding_top_board-coin_padding); } } difference () { union () { vertical_guard(); if (guard_style == "Front_and_back") translate ([0, board_width, board_width * sin (board_secondary_slope)]) vertical_guard(); } topboard_bottom_cutout (); } horizontal_guard(); } // Negative component: Basebox-sized hole in topboard bottom module topboard_bottom_cutout () { translate ([-topboard_bigger/2, -topboard_bigger/2, 0.01]) resize ([box_size ()[0] + topboard_bigger, box_size ()[1] + topboard_bigger, box_size ()[2]]) hull () base_box (false); } // Component: the guard on top of the top board. module vertical_guard() { intersection() { translate ([0, 0, -2 * guard_corner_radius]) rotate ([-90, 0, 0]) linear_extrude (board_thickness) offset (guard_corner_radius) offset (-guard_corner_radius) projection (cut = false) rotate ([90, 0, 0]) difference() { intersection() { cube([board_length * (1 + extra_topboard_length), board_thickness, sorter_max_height * 2]); top_side(sorter_min_height + board_thickness - 0.1); } translate ([0, 0, 10]) top_vertical_guard (sorter_min_height + board_thickness * 2, extra_guard_height); } } } // Component: the guard crossing the holes. module horizontal_guard() { // should be similar to top_board() cut_sides() transform_top_board(sorter_min_height) { cube([board_length*2, horizontal_guard_width + board_thickness, board_thickness]); } } // Submodule: the upper solid box that is rotated the same as the top board. module top_side(altitude = 0) { // rotate it and raise it transform_top_board(altitude) { // a big box translate([-board_length/2, -board_width/5, 0]) { cube([board_length*2, board_width*2, sorter_max_height]); } } } // Submodule: the vertical guard cutter that is rotated the same as the top board. module top_vertical_guard(altitude = 0, right_hand_altitude = 0) { // rotate it and raise it transform_top_board(altitude) { // a big box translate([0, -board_width/5, 0]) { hull () { cube([0.01, board_width*2, sorter_max_height]); translate([0.8 * board_length, 0, 0]) cube([0.01, board_width*2, sorter_max_height]); } hull () { translate([0.8 * board_length, 0, 0]) cube([0.01, board_width*2, sorter_max_height]); translate([2 * (1 + extra_topboard_length) * board_length, 0, 2 * right_hand_altitude]) cube([0.01, board_width*2, sorter_max_height]); } } } } // Transformation: do the rotation. module transform_top_board(lift_z=0) { translate([0, 0, lift_z]) { rotate(a=board_secondary_slope, v=[1, 0, tan(board_primary_slope)]) rotate([0, -board_primary_slope, 0]) { children(); } } } module untransform_top_board(lift_z=0) { rotate([0, board_primary_slope, 0]) rotate(a=-board_secondary_slope, v=[1, 0, tan(board_primary_slope)]) { translate([0, 0, -lift_z]) { children(); } } } // // COIN CUT // // Submodule: the coin holes. module coin_hole(n, bigger_r=0) { translate([coin_center_x(n), coin_center_y(n), board_thickness+0.1]) { cylinder(h = sorter_max_height, r = coins_d[n] / 2 + coin_padding + bigger_r); } } // Submodule: the coin holes, in a plain. module coin_hole_plain(n) { translate([coin_center_x(n), coin_center_y(n)]) { circle(coins_d[n] / 2 + coin_padding); } } // Submodule: the solid tube, in a plain. module coin_hole_plain_thicker(n) { translate([coin_center_x(n), coin_center_y(n)]) { circle(coins_d[n] / 2 + coin_padding + board_thickness); } } // Submodule: the slope cuts. module slope_cut_for_coin(n, bigger_r=0) { render(convexity=2) { intersection() { // the (too big) actual slope cut transform_top_board(sorter_min_height) { a = board_primary_slope; th = board_thickness; cut_length = coins_d[n] * 1.5; move_x = coin_left_x(n+1) - cut_length; cut_length_rotated = cut_length / cos(a); move_x_rotated = move_x / cos(a) + th * tan(a) + 1; translate([move_x_rotated, 0, 0]) { // move rightwards // make a triangle-box rotate([0, -atan(th / cut_length_rotated), 0]) { cube([cut_length_rotated * 2, board_width, th * 2]); } } // translate, move rightwards } // transform_top_board // limiting box translate([coin_center_x(n), 1, 0]) { cube([coins_d[0], coin_top_y(n) - 1 + bigger_r, sorter_max_height]); } } } } // // COIN TUBE RACK // // Component: the tuberack. module tuberack() { linear_extrude(height=tuberack_base_thickness+0.01, center=false, convexity=2) tuberack_base_2(); difference() { translate([0, 0, tuberack_base_thickness]) tuberack_body_3(); if (enable_tuberack_scale) translate([0, 0, tuberack_base_thickness + 1.5]) // +1.5 compensates for tube bottom thickness tuberack_scales(); translate([0, -1, sorter_min_height - tuberack_shorter]) rotate([0, -board_primary_slope, 0]) cube([board_length * 2, board_width * 2, sorter_max_height]); } } // Submodule: the "last coins" and the tube connecting part. module tuberack_base_2() { polygon(concat( [[tuberack_cut_x_x(0)[0], tuberack_front_cut_y()], [tuberack_left_x(), tuberack_front_y()], [tuberack_left_x()+tuberack_back_thinner, tuberack_back_y()]], tuberack_cut_back_xys(), [[tuberack_right_x()-tuberack_back_thinner, tuberack_back_y()], [tuberack_right_x(), tuberack_front_y()], [tuberack_cut_x_x(coin_max_index)[1], tuberack_front_cut_y()]])); } // Submodule: the tube connecting part subtracted by coin holes. module tuberack_base_3() { difference() { tuberack_base_2(); for (i = [0 : coin_max_index]) if (coin_roll_version == 1) offset (th_tubewall + tol_tuberack) coin_hole_plain(i); else coin_hole_plain(i); } } module tuberack_body_3() { linear_extrude(height=sorter_max_height, center=false, convexity=2) tuberack_base_3(); } module tuberack_scales() { for (i = [0 : coin_max_index]) { render(convexity=2) { interval = (coins_thickness[i] > 1.5 ? 1 : 2); for (j = [interval : interval : sorter_max_height/coins_thickness[i]]) { translate([coin_center_x(i), tuberack_front_cut_y() - 1, j * coins_thickness[i] - tuberack_scale_height / 2]) { length_offset = (j%10==0 ? 3 : j%2==0 ? 1 : -0.5); cube([tuberack_cut_half_width(i) + length_offset, tuberack_scale_depth + 1, tuberack_scale_height]); } } } } } // // COIN TUBES // // Component: the tubes module tubes() { translate([0, 0, tuberack_base_thickness]) for (i = [0 : coin_max_index]) color ("green") coin_tube (i); } // Submodule: the coin tube module coin_tube (n) { translate([coin_center_x(n), coin_center_y(n)]) difference () { make_coin_tube (coins_d[n] + 2 * coin_padding, coins_thickness [n], coins_n [n]); translate ([0, 0, -0.01]) n_die (n + 1, 0.8 * 1/sqrt (2) * (coins_d [n]/2 - 2)); } } cylinders = [[0], [5], [1, 9], [1, 5, 9], [1, 3, 7, 9], [1, 3, 5, 7, 9], [1, 3, 4, 6, 7, 9], [1, 3, 4, 5, 6, 7, 9], [1, 2, 3, 4, 6, 7, 8, 9], [1, 2, 3, 4, 5, 6, 7, 8, 9]]; dots = [[0, 0], [-1, -1], [0, -1], [1, -1], [-1, 0], [0, 0], [1, 0], [-1, 1], [0, 1], [1, 1]]; module n_die (n, r) { if (n > 0 && n < 10) for (i = cylinders [n]) translate (r * dots [i]) cylinder (d = 2, h = 1); else if (n == 10) for (i = [1, -1]) translate ([i * r/2 * sqrt (2), i * r/2 * sqrt (2)]) n_die (5, r/2); } module make_coin_tube (d_coin, h_coin, n_coins) { translate ([0, 0, 1]) difference () { hull () { translate ([0, 0, -1]) cylinder (d = d_coin, h = 0.5 + (n_coins + 0.5) * h_coin); cylinder (d = 2 * th_tubewall + d_coin, h = 0.5 + (n_coins + 0.5) * h_coin); } translate ([0, 0, 0.5]) cylinder (d = d_coin, h = 0.5 + (n_coins + 0.5) * h_coin + 0.01); } } // // FUNCTIONS // // Accumulated coins' diameters. function sum_coins_d(first_n=coin_count) = first_n <= 0 ? 0 : coins_d[first_n - 1] + sum_coins_d(first_n - 1); // Coin positions. function coin_center_x(n) = coin_left_x(n) + coins_d[n] / 2; function coin_left_x(n) = board_left_padding + sum_coins_d(n) + coin_padding * (2 * n + 1) + board_thickness * (n + 2); function coin_center_y(n) = coins_d[n] / 2 + coin_padding + board_thickness; function coin_top_y(n) = coin_center_y(n) + coins_d[n] / 2 + coin_padding; function coin_bottom_y(n) = coin_center_y(n) - coins_d[n] / 2 - coin_padding; // Tube cuts. function tuberack_left_x() = board_thickness + coin_padding; function tuberack_right_x() = board_length - board_thickness - coin_padding; function tuberack_front_y() = coin_padding; function tuberack_back_y() = board_width - board_thickness - coin_padding; function tuberack_front_cut_y() = coin_bottom_y(0) + tuberack_front_back_cut; function tuberack_cut_half_width(n) = sqrt(pow(coins_d[n] / 2 + coin_padding + board_thickness, 2) - pow(coins_d[n] / 2 + coin_padding - tuberack_front_back_cut, 2)); function tuberack_cut_x_x(n) = [coin_center_x(n) - tuberack_cut_half_width(n), coin_center_x(n) + tuberack_cut_half_width(n)]; function tuberack_cut_back_xy_xy(n) = [[coin_center_x(n) - tuberack_cut_half_width(n), coin_top_y(n) - tuberack_front_back_cut], [coin_center_x(n) + tuberack_cut_half_width(n), coin_top_y(n) - tuberack_front_back_cut]]; function tuberack_cut_back_xys(first_n=coin_count) = first_n <= 0 ? [] : concat(tuberack_cut_back_xys(first_n - 1), tuberack_cut_back_xy_xy(first_n - 1)); function tuberack_cut_back_complete() = concat([[tuberack_left_x()+tuberack_back_thinner, tuberack_back_y()]], tuberack_cut_back_xys(), [[tuberack_right_x()-tuberack_back_thinner, tuberack_back_y()]]); // Tube connections. function tuberack_height_at(x) = sorter_min_height - tuberack_shorter - tuberack_base_thickness + x * tan(board_primary_slope); function tuberack_x_height_at(x, z_delta=0) = [x, tuberack_height_at(x) + z_delta]; function tuberack_connection_height(n) = sorter_min_height - tuberack_shorter - tuberack_base_thickness + ( n == 0 ? 0: coin_center_x(n-1) * tan(board_primary_slope));