diff --git a/readme.md b/readme.md index e0ceb16..725201f 100644 --- a/readme.md +++ b/readme.md @@ -24,24 +24,24 @@ A list of changes classified as breaking, additions or fixes is maintained in [C Axials Jack Rails Box Annotation BOM Ball_bearings KP_pillow_blocks Ring_terminals Butt_box Bezier Clip Batteries LDRs Rockers Cable_grommets Catenary Global - Belts LED_meters Rod Camera_housing Dogbones Polyholes - Blowers LEDs SCS_bearing_blocks Carriers Fillet Rounded_rectangle - Bulldogs Leadnuts SK_brackets Corner_block Gears Sphere - Buttons Light_strips SMDs Door_hinge Hanging_hole Teardrops - Cable_strips Linear_bearings SSRs Door_latch Horiholes - Cameras Magnets Screws Drag_chain Layout - Circlips Mains_sockets Sealing_strip Fan_guard Maths - Components Microswitches Shaft_couplings Fixing_block Offset - DIP Microview Sheets Flat_hinge Quadrant - D_connectors Modules Spades Foot Round - Displays Nuts Spools Handle Rounded_cylinder - Extrusion_brackets O_ring Springs PCB_mount Rounded_polygon - Extrusions Opengrab Stepper_motors PSU_shroud Rounded_right_triangle - Fans PCB Swiss_clips Pocket_handle Sector - Fuseholder PCBs Toggles Press_fit Sweep - Geared_steppers PSUs Transformers Printed_box Thread - Green_terminals Panel_meters Tubings Printed_pulleys Tube - Hot_ends Pillars Variacs Ribbon_clamp + Belts LED_meters Rod Camera_housing Core_xy Polyholes + Blowers LEDs SCS_bearing_blocks Carriers Dogbones Rounded_rectangle + Bulldogs Leadnuts SK_brackets Corner_block Fillet Sphere + Buttons Light_strips SMDs Door_hinge Gears Teardrops + Cable_strips Linear_bearings SSRs Door_latch Hanging_hole + Cameras Magnets Screws Drag_chain Horiholes + Circlips Mains_sockets Sealing_strip Fan_guard Layout + Components Microswitches Shaft_couplings Fixing_block Maths + DIP Microview Sheets Flat_hinge Offset + D_connectors Modules Spades Foot Quadrant + Displays Nuts Spools Handle Round + Extrusion_brackets O_ring Springs PCB_mount Rounded_cylinder + Extrusions Opengrab Stepper_motors PSU_shroud Rounded_polygon + Fans PCB Swiss_clips Pocket_handle Rounded_right_triangle + Fuseholder PCBs Toggles Press_fit Sector + Geared_steppers PSUs Transformers Printed_box Sweep + Green_terminals Panel_meters Tubings Printed_pulleys Thread + Hot_ends Pillars Variacs Ribbon_clamp Tube Hygrometer Pin_headers Veroboard SSR_shroud IECs Pulleys Washers Screw_knob Inserts Wire Socket_box @@ -5574,6 +5574,69 @@ The coordinates of the lowest point on the curve can be retrieved by calling `ca ![catenary](tests/png/catenary.png) +Top + +--- + +## Core_xy +Parameterised Core XY implementation. Draws the belts and provides utilities for positioning the pulleys. + +The belts are positioned according the bottom left "anchor" pulley and the top right drive pulley. +Implementation has the following features: +1. The drive and idler pulleys may be different sizes. +2. The belt separation is parameterised. +3. The separation of the plain and toothed pulleys on the Y carriages is parameterised, in both the X and the Y direction. +4. The drive pulleys may be offset in the X and Y directions. If this is done, extra idler pulleys are added. This +allows flexible positioning of the motors. + +[utils/core_xy.scad](utils/core_xy.scad) Implementation. + +[tests/core_xy.scad](tests/core_xy.scad) Code for this example. + +### Properties +| Function | Description | +|:--- |:--- | +| `coreXY_belt(type)` | Belt type | +| `coreXY_drive_pulley(type)` | Drive pulley type | +| `coreXY_lower_belt_colour(type)` | Colour of the lower belt | +| `coreXY_lower_tooth_colour(type)` | Colour of the lower belt's teeth | +| `coreXY_plain_idler(type)` | Plain idler type | +| `coreXY_toothed_idler(type)` | Toothed idler type | +| `coreXY_upper_belt_colour(type)` | Colour of the upper belt | +| `coreXY_upper_tooth_colour(type)` | Colour of the upper belt's teeth | + +### Functions +| Function | Description | +|:--- |:--- | +| `coreXY_coincident_separation(type)` | Value of x, y separation to make y-carriage pulleys coincident | +| `coreXY_drive_plain_idler_offset(type)` | Offset of plain drive idler pulley | +| `coreXY_drive_pulley_x_alignment(type)` | Belt alignment offset of the drive pulley relative to the anchor pulley | +| `coreXY_drive_toothed_idler_offset(type)` | Offset of toothed drive idler pulley | +| `coreXY_plain_idler_offset(type)` | Offset of y-carriage plain idler | +| `coreXY_toothed_idler_offset(type)` | offset of y-carriage toothed idler | + +### Modules +| Module | Description | +|:--- |:--- | +| `coreXY(type, size, pos, separation, x_gap, plain_idler_offset = 0, upper_drive_pulley_offset, lower_drive_pulley_offset, show_pulleys = false)` | Wrapper module to draw both belts of a coreXY setup | +| `coreXY_belts(type, carriagePosition, coreXYPosBL, coreXYPosTR, separation, x_gap = 20, upper_drive_pulley_offset = [0, 0], lower_drive_pulley_offset = [0, 0], show_pulleys = false)` | Draw the coreXY belts | +| `coreXY_half(type, size, pos, separation_y = 0, x_gap = 0, plain_idler_offset = 0, drive_pulley_offset = [0, 0], show_pulleys = false, lower_belt = false, hflip = false)` | Draw one belt of a coreXY setup | + +![core_xy](tests/png/core_xy.png) + +### Vitamins +| Qty | Module call | BOM entry | +| ---:|:--- |:---| +| 1 | `belt(GT2x6, [ ... ], [10.0078, 11.69], [0, -24.686])` | Belt GT2 x 6mm x 742mm | +| 1 | `belt(GT2x6, [ ... ], [10.0078, 11.69], [0, -24.686])` | Belt GT2 x 6mm x 852mm | +| 7 | `pulley(GT2x16_toothed_idler)` | Pulley GT2 idler 16 teeth | +| 3 | `pulley(GT2x16_plain_idler)` | Pulley GT2 idler smooth 9.63mm | +| 2 | `pulley(GT2x20ob_pulley)` | Pulley GT2OB 20 teeth | +| 8 | `screw(M3_cap_screw, 20)` | Screw M3 cap x 20mm | +| 4 | `screw(M3_grub_screw, 6)` | Screw M3 grub x 6mm | +| 2 | `NEMA(NEMA17M)` | Stepper motor NEMA17 x 40mm | + + Top --- diff --git a/tests/core_xy.scad b/tests/core_xy.scad new file mode 100644 index 0000000..ca549e0 --- /dev/null +++ b/tests/core_xy.scad @@ -0,0 +1,134 @@ +// +// NopSCADlib Copyright Chris Palmer 2020 +// nop.head@gmail.com +// hydraraptor.blogspot.com +// +// This file is part of NopSCADlib. +// +// NopSCADlib is free software: you can redistribute it and/or modify it under the terms of the +// GNU General Public License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// NopSCADlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along with NopSCADlib. +// If not, see . +// + +include <../core.scad> +include <../vitamins/pulleys.scad> +include <../vitamins/screws.scad> +include <../vitamins/stepper_motors.scad> +include <../vitamins/washers.scad> + +include <../utils/core_xy.scad> + + +module coreXY_belts_test() { + coreXY_type = coreXY_GT2_20_16; + plain_idler = coreXY_plain_idler(coreXY_type); + toothed_idler = coreXY_toothed_idler(coreXY_type); + + coreXYPosBL = [0, 0, 0]; + coreXYPosTR = [200, 150, 0]; + separation = [0, coreXY_coincident_separation(coreXY_type).y, pulley_height(plain_idler) + washer_thickness(M3_washer)]; + pos = [100, 50]; + + upper_drive_pulley_offset = [40, 10]; + lower_drive_pulley_offset = [0, 0]; + + coreXY_belts(coreXY_type, + carriagePosition = pos, + coreXYPosBL = coreXYPosBL, + coreXYPosTR = coreXYPosTR, + separation = separation, + x_gap = 10, + upper_drive_pulley_offset = upper_drive_pulley_offset, + lower_drive_pulley_offset = lower_drive_pulley_offset, + show_pulleys = true); + + + translate([coreXYPosBL.x + separation.x/2, coreXYPosTR.y + upper_drive_pulley_offset.y, separation.z/2]) { + // add the upper drive pulley stepper motor + translate([coreXY_drive_pulley_x_alignment(coreXY_type) + upper_drive_pulley_offset.x, 0, -pulley_height(coreXY_drive_pulley(coreXY_type))]) + NEMA(NEMA17M); + + // add the screws for the upper drive offset idler pulleys if required + if (upper_drive_pulley_offset.x > 0) { + translate(coreXY_drive_plain_idler_offset(coreXY_type)) + translate_z(-pulley_offset(plain_idler)) + screw(M3_cap_screw, 20); + translate(coreXY_drive_toothed_idler_offset(coreXY_type)) + translate_z(-pulley_offset(toothed_idler)) + screw(M3_cap_screw, 20); + } else if (upper_drive_pulley_offset.x < 0) { + translate([-pulley_od(plain_idler), coreXY_drive_plain_idler_offset(coreXY_type).y]) + translate_z(-pulley_offset(plain_idler)) + screw(M3_cap_screw, 20); + translate([2*coreXY_drive_pulley_x_alignment(coreXY_type), coreXY_drive_toothed_idler_offset(coreXY_type).y]) + translate_z(-pulley_offset(toothed_idler)) + screw(M3_cap_screw, 20); + } + } + + translate([coreXYPosTR.x - separation.x/2, coreXYPosTR.y + lower_drive_pulley_offset.y, -separation.z/2]) { + // add the lower drive pulley stepper motor + translate([-coreXY_drive_pulley_x_alignment(coreXY_type) + lower_drive_pulley_offset.x, 0, -pulley_height(coreXY_drive_pulley(coreXY_type))]) + NEMA(NEMA17M); + + // add the screws for the lower drive offset idler pulleys if required + if (lower_drive_pulley_offset.x < 0) { + translate([-coreXY_drive_plain_idler_offset(coreXY_type).x, coreXY_drive_plain_idler_offset(coreXY_type).y]) + translate_z(-pulley_offset(plain_idler)) + screw(M3_cap_screw, 20); + translate(coreXY_drive_toothed_idler_offset(coreXY_type)) + translate_z(-pulley_offset(toothed_idler)) + screw(M3_cap_screw, 20); + } else if (lower_drive_pulley_offset.x > 0) { + translate([pulley_od(plain_idler), coreXY_drive_plain_idler_offset(coreXY_type).y]) + translate_z(-pulley_offset(plain_idler)) + screw(M3_cap_screw, 20); + translate([-2*coreXY_drive_pulley_x_alignment(coreXY_type), coreXY_drive_toothed_idler_offset(coreXY_type).y]) + translate_z(-pulley_offset(toothed_idler)) + screw(M3_cap_screw, 20); + } + } + + // add the screw for the left upper idler pulley + translate([coreXYPosBL.x + separation.x/2, coreXYPosBL.y, separation.z]) + screw(M3_cap_screw, 20); + + // add the screw for the right upper idler pulley + translate([coreXYPosTR.x + separation.x/2, coreXYPosBL.y, separation.z]) + screw(M3_cap_screw, 20); + + if (separation.x != 0) { + // add the screw for the left lower idler pulley + translate([coreXYPosBL.x - separation.x/2, coreXYPosBL.y, 0]) + screw(M3_cap_screw, 20); + + // add the screw for the right lower idler pulley + translate([coreXYPosTR.x - separation.x/2, coreXYPosBL.y, 0]) + screw(M3_cap_screw, 20); + } + + translate([-separation.x/2, pos.y + coreXYPosBL.y -separation.y/2, -separation.z/2 + pulley_height(plain_idler)/2]) { + // add the screw for the left Y carriage toothed idler + translate([coreXYPosBL.x, coreXY_toothed_idler_offset(coreXY_type).y, 0]) + screw(M3_cap_screw, 20); + // add the screw for the left Y carriage plain idler + translate([coreXYPosBL.x + separation.x + coreXY_plain_idler_offset(coreXY_type).x, separation.y + coreXY_plain_idler_offset(coreXY_type).y, separation.z]) + screw(M3_cap_screw, 20); + // add the screw for the right Y carriage toothed idler + translate([coreXYPosTR.x + separation.x, coreXY_toothed_idler_offset(coreXY_type).y, separation.z]) + screw(M3_cap_screw, 20); + // add the screw for the right Y carriage plain idler + translate([coreXYPosTR.x - coreXY_plain_idler_offset(coreXY_type).x, separation.y + coreXY_plain_idler_offset(coreXY_type).y, 0]) + screw(M3_cap_screw, 20); + } +} + +if ($preview) + coreXY_belts_test(); diff --git a/tests/png/core_xy.png b/tests/png/core_xy.png new file mode 100644 index 0000000..17dd067 Binary files /dev/null and b/tests/png/core_xy.png differ diff --git a/utils/core_xy.scad b/utils/core_xy.scad new file mode 100644 index 0000000..e9efb72 --- /dev/null +++ b/utils/core_xy.scad @@ -0,0 +1,196 @@ +// +// NopSCADlib Copyright Chris Palmer 2020 +// nop.head@gmail.com +// hydraraptor.blogspot.com +// +// This file is part of NopSCADlib. +// +// NopSCADlib is free software: you can redistribute it and/or modify it under the terms of the +// GNU General Public License as published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// NopSCADlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along with NopSCADlib. +// If not, see . +// + +// +//! Parameterised Core XY implementation. Draws the belts and provides utilities for positioning the pulleys. +//! +//! The belts are positioned according the bottom left "anchor" pulley and the top right drive pulley. +//! Implementation has the following features: +//! 1. The drive and idler pulleys may be different sizes. +//! 2. The belt separation is parameterised. +//! 3. The separation of the plain and toothed pulleys on the Y carriages is parameterised, in both the X and the Y direction. +//! 4. The drive pulleys may be offset in the X and Y directions. If this is done, extra idler pulleys are added. This +//! allows flexible positioning of the motors. +// +include <../core.scad> +include <../vitamins/belts.scad> +include <../vitamins/pulleys.scad> + + +coreXY_GT2_20_20 = ["coreXY_20_20", GT2x6, GT2x20ob_pulley, GT2x20_toothed_idler, GT2x20_plain_idler, [0, 0, 1], [0, 0, 0.5, 1], [0, 1, 0], [0, 0.5, 0, 1] ]; +coreXY_GT2_20_16 = ["coreXY_20_16", GT2x6, GT2x20ob_pulley, GT2x16_toothed_idler, GT2x16_plain_idler, [0, 0, 1], [0, 0, 0.5, 1], [0, 1, 0], [0, 0.5, 0, 1] ]; +coreXY_GT2_16_16 = ["coreXY_16_16", GT2x6, GT2x16_pulley, GT2x16_toothed_idler, GT2x16_plain_idler, [0, 0, 1], [0, 0, 0.5, 1], [0, 1, 0], [0, 0.5, 0, 1] ]; + +function coreXY_belt(type) = type[1]; //! Belt type +function coreXY_drive_pulley(type) = type[2]; //! Drive pulley type +function coreXY_toothed_idler(type) = type[3]; //! Toothed idler type +function coreXY_plain_idler(type) = type[4]; //! Plain idler type +function coreXY_upper_belt_colour(type) = type[5]; //! Colour of the upper belt +function coreXY_upper_tooth_colour(type) = type[6]; //! Colour of the upper belt's teeth +function coreXY_lower_belt_colour(type) = type[7]; //! Colour of the lower belt +function coreXY_lower_tooth_colour(type) = type[8]; //! Colour of the lower belt's teeth + +// used to offset the position of the drive pulley and the y-carriage plain idler pulley +// relative to the anchor pulley so that the belts align properly +function coreXY_drive_pulley_x_alignment(type) = //! Belt alignment offset of the drive pulley relative to the anchor pulley + (pulley_od(coreXY_drive_pulley(type)) - pulley_od(coreXY_toothed_idler(type))) / 2; +function coreXY_coincident_separation(type) = //! Value of x, y separation to make y-carriage pulleys coincident + [ -coreXY_plain_idler_offset(type).x, -(pulley_od(coreXY_plain_idler(type)) + pulley_od(coreXY_toothed_idler(type)))/2, 0 ]; +function coreXY_plain_idler_offset(type) = //! Offset of y-carriage plain idler + [ (pulley_od(coreXY_plain_idler(type)) + pulley_od(coreXY_drive_pulley(type))) / 2 + coreXY_drive_pulley_x_alignment(type), pulley_od(coreXY_plain_idler(type))/2, 0 ]; +function coreXY_toothed_idler_offset(type) = //! offset of y-carriage toothed idler + [ 0, -pulley_pr(coreXY_toothed_idler(type)), 0 ]; +// helper functions for positioning idlers when the stepper motor drive pulley is offset +function coreXY_drive_toothed_idler_offset(type) = //! Offset of toothed drive idler pulley + [ 0, coreXY_drive_pulley_x_alignment(type), 0 ]; +function coreXY_drive_plain_idler_offset(type) = //! Offset of plain drive idler pulley + [ coreXY_plain_idler_offset(type).x, -(pulley_od(coreXY_plain_idler(type)) + pulley_od(coreXY_drive_pulley(type))) / 2, 0 ]; + + +module coreXY_half(type, size, pos, separation_y = 0, x_gap = 0, plain_idler_offset = 0, drive_pulley_offset = [0, 0], show_pulleys = false, lower_belt = false, hflip = false) { //! Draw one belt of a coreXY setup + + // y-carriage toothed pulley + p0_type = coreXY_toothed_idler(type); + p0 = [ size.x / 2, -size.y / 2 - pulley_od(p0_type) / 2 + pos.y - separation_y / 2 ]; + + // bottom right toothed idler pulley + p1_type = p0_type; + p1 = [ size.x / 2, -size.y / 2 ]; + + // bottom left anchor toothed idler pulley + p2_type = p0_type; + p2 = [ -size.x / 2, -size.y / 2 ]; + + // stepper motor drive pulley + p3d_type = coreXY_drive_pulley(type); + p3d = [ -size.x / 2 + coreXY_drive_pulley_x_alignment(type) + drive_pulley_offset.x, + size.y / 2 + drive_pulley_offset.y + ]; + + // toothed idler for offset stepper motor drive pulley + p3t_type = coreXY_toothed_idler(type); + p3t = [ -size.x / 2 + (drive_pulley_offset.x > 0 ? 0 : 2*coreXY_drive_pulley_x_alignment(type)), + size.y / 2 + coreXY_drive_pulley_x_alignment(type) + drive_pulley_offset.y + ]; + + // y-carriage plain pulley + p4_type = coreXY_plain_idler(type); + p4 = [ -size.x / 2 + pulley_od(p4_type) / 2 + pulley_od(p3d_type) / 2 + coreXY_drive_pulley_x_alignment(type) + plain_idler_offset, + -size.y / 2 + pulley_od(p4_type) / 2 + pos.y + separation_y / 2 + ]; + + // plain idler for offset stepper motor drive pulley + p3p_type = p4_type; + p3p = [ drive_pulley_offset.x > 0 ? p4.x : -p0.x - pulley_od(p0_type), + size.y / 2 - pulley_od(p3p_type) / 2 - pulley_od(p3d_type) / 2 + drive_pulley_offset.y + ]; + + // dummy pulleys for y separation + p5_type = p4_type; + p5 = [ pos.x - size.x / 2, -size.y / 2 + pos.y + separation_y / 2 ]; + p6_type = p0_type; + p6 = [ pos.x - size.x / 2, -size.y / 2 + pos.y - separation_y / 2 ]; + + module show_pulleys(show_pulleys) {// Allows the pulley colour to be set for debugging + if (is_list(show_pulleys)) + color(show_pulleys) + children(); + else if (show_pulleys) + children(); + } + + show_pulleys(show_pulleys) { + translate(p0) + pulley_assembly(p0_type); // y-carriage toothed pulley + translate(p1) + pulley_assembly(p1_type); // bottom right toothed idler pulley + translate(p2) + pulley_assembly(p2_type); // bottom left anchor toothed idler pulley + translate(p3d) + hflip(hflip) + pulley_assembly(p3d_type); // top left stepper motor drive pulley + if (drive_pulley_offset.x) { // idler pulleys for offset stepper motor drive pulley + translate(p3t) + pulley_assembly(p3t_type); // toothed idler + translate(p3p) + pulley_assembly(p3p_type); // plain idler + } + translate(p4) + pulley_assembly(p4_type); // y-carriage plain pulley + } + + path0a = [ + [ p0.x, p0.y, pulley_od(p0_type) / 2 ], + [ p1.x, p1.y, pulley_od(p1_type) / 2 ], + [ p2.x, p2.y, pulley_od(p2_type) / 2 ] + ]; + path0b = [ + [ p3d.x, p3d.y, pulley_od(p3d_type) / 2 ], + [ p4.x, p4.y, -pulley_od(p4_type) / 2 ] + ]; + path0c = [ + [ p3t.x, p3t.y, pulley_od(p3t_type) / 2 ], + [ p3d.x, p3d.y, pulley_od(p3d_type) / 2 ], + [ p3p.x, p3p.y, -pulley_od(p3p_type) / 2 ], + [ p4.x, p4.y, -pulley_od(p4_type) / 2 ] + ]; + path0d = [ + [ p3p.x, p3p.y, -pulley_od(p3p_type) / 2 ], + [ p3d.x, p3d.y, pulley_od(p3d_type) / 2 ], + [ p3t.x, p3t.y, pulley_od(p3t_type) / 2 ], + [ p4.x, p4.y, -pulley_od(p4_type) / 2 ] + ]; + path1 = [ // use eps for corner radius to get sharp corners so this part of the belt is deleted by the gap + [ p5.x, p5.y, eps ], + [ p6.x, p6.y, eps ] + ]; + + belt = coreXY_belt(type); + + path0 = drive_pulley_offset.x == 0 ? concat(path0a, path0b) : drive_pulley_offset.x > 0 ? concat(path0a, path0c) : concat(path0a, path0d); + path = separation_y == 0 ? path0 : concat(path0, path1); + + belt(type = belt, + points = path, + gap = [ x_gap + eps, abs(separation_y) + 2 ], + gap_pos = [ pos.x - size.x / 2, pos.y - size.y / 2 + belt_pitch_height(belt) - belt_thickness(belt) / 2 ], + belt_colour = lower_belt ? coreXY_lower_belt_colour(type) : coreXY_upper_belt_colour(type), + tooth_colour = lower_belt ? coreXY_lower_tooth_colour(type) : coreXY_upper_tooth_colour(type)); +} + +module coreXY(type, size, pos, separation, x_gap, plain_idler_offset = 0, upper_drive_pulley_offset, lower_drive_pulley_offset, show_pulleys = false) { //! Wrapper module to draw both belts of a coreXY setup + translate([size.x / 2 - separation.x / 2, size.y / 2, -separation.z / 2]) { + // lower belt + hflip() + explode(25) + coreXY_half(type, size, [size.x - pos.x - separation.x, pos.y], separation.y, x_gap, plain_idler_offset, [-lower_drive_pulley_offset.x, lower_drive_pulley_offset.y], show_pulleys, lower_belt = true, hflip = true); + // upper belt + translate([separation.x, 0, separation.z]) + explode(25) + coreXY_half(type, size, [pos.x, pos.y], separation.y, x_gap, plain_idler_offset, upper_drive_pulley_offset, show_pulleys, lower_belt = false, hflip=false); + } +} + +module coreXY_belts(type, carriagePosition, coreXYPosBL, coreXYPosTR, separation, x_gap = 20, upper_drive_pulley_offset = [0, 0], lower_drive_pulley_offset = [0, 0], show_pulleys = false) { //! Draw the coreXY belts + assert(coreXYPosBL.z == coreXYPosTR.z); + + coreXYSize = coreXYPosTR - coreXYPosBL; + translate(coreXYPosBL) + coreXY(type, coreXYSize, [carriagePosition.x - coreXYPosBL.x + separation.x / 2, carriagePosition.y - coreXYPosBL.y], separation = separation, x_gap = x_gap, plain_idler_offset = 0, upper_drive_pulley_offset = upper_drive_pulley_offset, lower_drive_pulley_offset = lower_drive_pulley_offset, show_pulleys = show_pulleys); +}