Пример #1
0
 def make_reservation(self):
     vss = self.get_ventscrews_a()
     sr = CQ().box(self.reserve_xy,
                   self.reserve_xy,
                   self.reserve_h,
                   centered=(True, True, False))
     sr = sr.translate(
         (0, 0, -self.pcb_thickness - self.pcb_spacer_h - self.cu_base_t))
     wires = CQ().box(self.wire_slot_depth,
                      2.54 * 20,
                      2.54 * 2,
                      centered=(False, True, False)).translate(
                          (-self.reserve_xy / 2, 0,
                           self.wire_slot_z + self.pcb_thickness / 2))
     wiresA = wires.translate((0, self.wire_slot_offset, 0))
     wiresB = wires.translate((0, -self.wire_slot_offset, 0))
     sr = sr.cut(wiresA).cut(wiresB).add(vss)
     # these next two lines are very expensive (and optional)!
     sr = sr.add(self.get_pcb())
     #sr = CQ().union(sr)
     return sr
Пример #2
0
    def mkwalls(
        aso: cadquery.Assembly,
        height: float,
        cshift,
        extents,
        hps,
        zbase: float,
    ):
        """the chamber walls"""
        name = "walls"
        color = cadquery.Color("GRAY55")
        thickness = 12
        inner = (extents[0] - 2 * thickness, extents[1] - 2 * thickness)
        inner_shift = cshift
        outer_fillet = 2
        inner_fillet = 6
        chamfer = 0.75

        nut = HexNut(size="M5-0.8", fastener_type="iso4033")  # HNN-M5-A2
        flat_to_flat = math.sin(60 * math.pi / 180) * nut.nut_diameter + 0.25

        gas_fitting_hole_diameter = 20.6375  # 13/16"
        gas_fitting_recess = 6.35
        gas_fitting_flat_to_flat = 22.22 + 0.28
        gas_fitting_diameter = 25.66 + 0.34

        back_holes_shift = 45
        back_holes_spacing = 27
        front_holes_spacing = 75

        fitting_step_xy = (
            3, 15)  # dims of the little step for the vac fitting alignment
        fitting_step_center = (-fitting_step_xy[0] / 2 + inner[0] / 2 +
                               cshift[0], extents[1] / 2 -
                               fitting_step_xy[1] / 2 - thickness)
        wp = CQ().workplane(offset=zbase).sketch()
        wp = wp.push([cshift
                      ]).rect(extents[0], extents[1],
                              mode="a").reset().vertices().fillet(outer_fillet)
        wp = wp.push([inner_shift]).rect(inner[0], inner[1], mode="s").reset()
        dummy_xy = (fitting_step_xy[0], inner[1])
        dummy_center = (fitting_step_center[0], 0)
        wp = wp.push([dummy_center]).rect(
            *dummy_xy,
            mode="a")  # add on a dummy bit that we'll mostly subtract away

        wp = wp.finalize().extrude(height).edges("|Z").fillet(inner_fillet)

        sub_xy = (40, inner[1] - fitting_step_xy[1])
        sub_center = (-sub_xy[0] / 2 + inner[0] / 2 + cshift[0],
                      -fitting_step_xy[1] / 2)
        wp2 = CQ().workplane(offset=zbase).sketch().push([sub_center
                                                          ]).rect(*sub_xy,
                                                                  mode="a")
        wp2 = wp2.finalize().extrude(height).edges("|Z").fillet(inner_fillet)
        wp = wp.cut(wp2)

        # wp = CQ().workplane(offset=zbase).sketch()
        # wp = wp.push([cshift]).rect(extents[0], extents[1], mode="a").reset().vertices().fillet(outer_fillet)
        # wp = wp.push([inner_shift]).rect(inner[0], inner[1], mode="s")  # .reset().vertices().fillet(inner_fillet)
        # wp = wp.finalize().extrude(height)
        wp: cadquery.Workplane  # shouldn't have to do this (needed for type hints)

        wall_hardware = cq.Assembly(None, name="wall_hardware")

        # corner holes (with nuts and nut pockets)
        wp = wp.faces(">Z").workplane(
            **u.copo, offset=-nut.nut_thickness).pushPoints(hps).clearanceHole(
                fastener=nut,
                fit="Close",
                counterSunk=False,
                baseAssembly=wall_hardware)
        wp = wp.faces(">Z").workplane(**u.copo).sketch().push(hps[0:4:3]).rect(
            flat_to_flat, nut.nut_diameter, angle=45).reset().push(
                hps[1:3]).rect(flat_to_flat, nut.nut_diameter,
                               angle=-45).reset().vertices().fillet(
                                   nut.nut_diameter /
                                   4).finalize().cutBlind(-nut.nut_thickness)

        # chamfers
        wp = wp.faces(">Z").edges(">>X").chamfer(chamfer)

        # gas holes with recesses
        wp = wp.faces("<X").workplane(**u.cobb).center(
            back_holes_shift,
            0).rarray(back_holes_spacing, 1, 2,
                      1).hole(diameter=gas_fitting_hole_diameter,
                              depth=thickness)
        # wp = wp.faces("<X").workplane(**u.cobb).center(back_holes_shift, 0).sketch().rarray(back_holes_spacing, 1, 2, 1).rect(gas_fitting_diameter, gas_fitting_flat_to_flat).reset().vertices().fillet(gas_fitting_diameter / 4).finalize().cutBlind(-gas_fitting_recess)
        wp = wp.faces("<X").workplane(**u.cobb).center(
            back_holes_shift, 0).sketch().rect(
                2 * gas_fitting_diameter / 2 + back_holes_spacing,
                gas_fitting_flat_to_flat).reset().vertices().fillet(
                    gas_fitting_diameter / 4).finalize().cutBlind(
                        -gas_fitting_recess)  # unify the back holes
        wp = wp.faces(">X").workplane(**u.cobb).rarray(
            front_holes_spacing, 1, 2,
            1).hole(diameter=gas_fitting_hole_diameter, depth=thickness)
        wp = wp.faces(">X").workplane(**u.cobb).sketch().rarray(
            front_holes_spacing, 1, 2,
            1).rect(gas_fitting_diameter,
                    gas_fitting_flat_to_flat).reset().vertices().fillet(
                        gas_fitting_diameter /
                        4).finalize().cutBlind(-gas_fitting_recess)

        # that's part number polymax 230X2N70
        o_ring_thickness = 2
        o_ring_inner_diameter = 230
        ooffset = 17  # two times the o-ring path's center offset from the outer edge of the walls

        # cut the lid o-ring groove
        wp = wp.faces(">Z").workplane(**u.cobb).mk_groove(
            ring_cs=o_ring_thickness,
            follow_pending_wires=False,
            ring_id=o_ring_inner_diameter,
            gland_x=extents[0] - ooffset,
            gland_y=extents[1] - ooffset,
            hardware=wall_hardware)

        # cut the base o-ring groove
        wp = wp.faces("<Z").workplane(**u.cobb).mk_groove(
            ring_cs=o_ring_thickness,
            follow_pending_wires=False,
            ring_id=o_ring_inner_diameter,
            gland_x=extents[0] - ooffset,
            gland_y=extents[1] - ooffset,
            hardware=wall_hardware)

        # get pipe fitting geometry
        a_pipe_fitting = u.import_step(
            wrk_dir.joinpath(
                "components",
                "5483T93_Miniature Nickel-Plated Brass Pipe Fitting.step"))
        a_pipe_fitting = a_pipe_fitting.translate(
            (0, 0, -6.35 - gas_fitting_recess))
        pipe_fitting_asy = cadquery.Assembly(a_pipe_fitting.rotate(
            axisStartPoint=(0, 0, 0), axisEndPoint=(0, 0, 1), angleDegrees=30),
                                             name="one_pipe_fitting")

        # move the pipe fittings to their wall holes
        wppf = wp.faces(">X").workplane(**u.cobb).center(
            front_holes_spacing / 2, 0)
        pipe_fitting_asy.loc = wppf.plane.location
        wall_hardware.add(pipe_fitting_asy, name="front_right_gas_fitting")
        wppf = wppf.center(-front_holes_spacing, 0)
        pipe_fitting_asy.loc = wppf.plane.location
        wall_hardware.add(pipe_fitting_asy, name="front_left_gas_fitting")
        wppf = wp.faces("<X").workplane(**u.cobb).center(
            back_holes_shift + back_holes_spacing / 2, 0)
        pipe_fitting_asy.loc = wppf.plane.location
        wall_hardware.add(pipe_fitting_asy, name="rear_left_gas_fitting")
        wppf = wppf.center(-back_holes_spacing, 0)
        pipe_fitting_asy.loc = wppf.plane.location
        wall_hardware.add(pipe_fitting_asy, name="rear_right_gas_fitting")

        # get bonded washer geometry, part 229-6277
        bonded_washer = u.import_step(
            wrk_dir.joinpath("components", "hutchinson_ljf_207242.stp"))
        bonded_washer = bonded_washer.rotate(axisStartPoint=(0, 0, 0),
                                             axisEndPoint=(0, 1, 0),
                                             angleDegrees=90).translate(
                                                 (0, 0, 1.25))
        bonded_washer_asy = cadquery.Assembly(bonded_washer,
                                              name="one_bonded_washer")

        # move bonded washers to their wall holes
        washer_thickness = 2.5
        wpbw = wp.faces(">X").workplane(**u.cobb,
                                        offset=-thickness -
                                        washer_thickness).center(
                                            -front_holes_spacing / 2, 0)
        bonded_washer_asy.loc = wpbw.plane.location
        wall_hardware.add(bonded_washer_asy, name="front_right_bonded_washer")
        wpbw = wpbw.center(front_holes_spacing, 0)
        bonded_washer_asy.loc = wpbw.plane.location
        wall_hardware.add(bonded_washer_asy, name="front_left_bonded_washer")
        wpbw = wp.faces("<X[-5]").workplane(**u.cobb).center(
            -back_holes_shift - back_holes_spacing / 2, 0)
        bonded_washer_asy.loc = wpbw.plane.location
        wall_hardware.add(bonded_washer_asy, name="rear_right_bonded_washer")
        wpbw = wpbw.center(back_holes_spacing, 0)
        bonded_washer_asy.loc = wpbw.plane.location
        wall_hardware.add(bonded_washer_asy, name="rear_left_bonded_washer")

        aso.add(wall_hardware.toCompound(),
                name="wall_hardware",
                color=cadquery.Color(hardware_color))

        # passthrough details
        pcb_scr_head_d_safe = 6
        n_header_pins = 50
        header_length = n_header_pins / 2 * 2.54 + 7.62  # n*0.1 + 0.3 inches
        support_block_width = 7
        pt_pcb_width = 2 * (support_block_width / 2 +
                            pcb_scr_head_d_safe / 2) + header_length
        pt_pcb_outer_depth = 8.89 + 0.381  # 0.35 + 0.15 inches
        pt_pcb_inner_depth = 8.89 + 0.381  # 0.35 + 0.15 inches
        pt_center_offset = 28.65  # so that the internal passthrough connector aligns with the one in the chamber

        # make the electrical passthrough
        pt_asy = cadquery.Assembly(
        )  # this will hold the passthrough part that gets created
        # pcb_asy = cadquery.Assembly()  # this will hold the pcb part that gets created
        pcb_asy = None  # dont generate the base PCB (will probably later import the detailed board model)
        hw_asy = cadquery.Assembly(
        )  # this will hold the pcb part that gets created
        ptt = 5.5  # passthrough thickness, reduce a bit from default (which was half wall thickness) to prevent some thin walls close to an o-ring gland
        wp = wp.faces("<X").workplane(**u.cobb).center(
            -pt_center_offset,
            0).make_oringer(board_width=pt_pcb_width,
                            board_inner_depth=pt_pcb_inner_depth,
                            board_outer_depth=pt_pcb_outer_depth,
                            wall_depth=thickness,
                            part_thickness=ptt,
                            pt_asy=pt_asy,
                            pcb_asy=pcb_asy,
                            hw_asy=hw_asy)
        # insert passthrough into assembly
        for asyo in pt_asy.traverse():
            part = asyo[1]
            if isinstance(part.obj, cadquery.occ_impl.shapes.Solid):
                aso.add(part.obj, name=asyo[0], color=color)
        if pcb_asy is not None:
            # insert pcb into assembly
            for asyo in pcb_asy.traverse():  # insert only one solid object
                part = asyo[1]
                if isinstance(part.obj, cadquery.occ_impl.shapes.Solid):
                    aso.add(part.obj,
                            name=asyo[0],
                            color=cadquery.Color("DARKGREEN"))
        # insert hardware into assembly
        aso.add(hw_asy.toCompound(), name="passthrough hardware")

        # add in little detailed PCB
        a_little_pcb = u.import_step(
            wrk_dir.joinpath("components", "pt_pcb.step")).translate(
                (0, 0, -pcb_thickness / 2))  # shift pcb to be z-centered
        little_pcb = cadquery.Assembly(a_little_pcb.rotate(
            axisStartPoint=(0, 0, 0), axisEndPoint=(0, 1, 0),
            angleDegrees=90).rotate(axisStartPoint=(0, 0, 0),
                                    axisEndPoint=(0, 0, 1),
                                    angleDegrees=90),
                                       name="small detailed pcb")
        asys["squirrel"].add(little_pcb,
                             loc=wp.plane.location,
                             name="little pcb")

        # for the vac chuck fittings
        rotation_angle = -155  # degrees
        vac_fitting_wall_offset = extents[
            1] / 2 - thickness - inner_fillet - 4  # mounting location offset from center
        wp = wp.faces(">X").workplane(**u.cobb).center(
            vac_fitting_wall_offset,
            0).tapHole(vac_fitting_screw, depth=thickness + fitting_step_xy[0])
        vac_chuck_fitting = cadquery.Assembly(a_vac_fitting.rotate(
            axisStartPoint=(0, 0, 0),
            axisEndPoint=(0, 0, 1),
            angleDegrees=rotation_angle),
                                              name="outer_wall_vac_fitting")
        aso.add(vac_chuck_fitting,
                loc=wp.plane.location,
                name="vac chuck fitting (wall outer)")

        nwp = wp.faces(">X").workplane(**u.cobb,
                                       invert=True,
                                       offset=thickness +
                                       fitting_step_xy[0]).center(
                                           vac_fitting_wall_offset, 0)
        vac_chuck_fitting = cadquery.Assembly(a_vac_fitting.rotate(
            axisStartPoint=(0, 0, 0),
            axisEndPoint=(0, 0, 1),
            angleDegrees=-rotation_angle),
                                              name="inner_wall_vac_fitting")
        aso.add(vac_chuck_fitting,
                loc=nwp.plane.location,
                name="vac chuck fitting (wall inner)")

        aso.add(wp, name=name, color=color)  # add the walls bulk
Пример #3
0
    def _makeNegative(center):
        """
        Generates the pocket shape we'll be cutting out
        """

        # the connector pocket's dimensions
        pocket_w = connector_width + con_clearance * 2
        pocket_l = con_len + con_clearance * 2
        pocket_d = connector_height + con_clearance

        # find the source thing's thickness at the cut point
        swiss = CQ(self.plane).add(self.findSolid())
        cheese = CQ(self.plane).add(self.findSolid()).pushPoints(
            [center]).circle(0.5).cutThruAll()
        core = swiss.cut(cheese)
        this_thikness = u.find_length(core, along="normal", bb_method=False)

        min_thickness = pocket_d + min_gp_connector_pocket_spacing + gp_depth

        # check that it's thick enough here
        if this_thikness < min_thickness:
            raise (ValueError(
                f"The part is too thin (thickness = {this_thikness}) at {center} to cut the PCB pocket"
            ))

        # make a box to subtract from
        start_box = CQ("XY").box(100,
                                 100,
                                 this_thikness,
                                 centered=(True, True, False))

        # make a simple pocket that we'll use for the chamfer operation
        result = start_box.faces("<Z").rect(pocket_w,
                                            pocket_l).cutBlind(pocket_d)

        # chamfer the connector edge
        result = result.faces("<Z").edges("not(<X or >X or <Y or >Y)").chamfer(
            chamfer_length)

        # now make the undercut pocket
        CQ.undercutRelief2D = u.undercutRelief2D
        result = result.faces("<Z").workplane().undercutRelief2D(
            pocket_l, pocket_w, diameter=r * 2, angle=90,
            kind=kind).cutBlind(pocket_d)

        # cut out the glue pocket
        slot_width = c.pcb_thickness + 2 * gp_buffer
        slot_len = pcb_len + slot_width
        result = result.faces(">Z").workplane().slot2D(
            slot_len, slot_width, angle=90).cutBlind(-gp_depth)

        # cut out the pcb passthrough slot
        slot_width = c.pcb_thickness + 2 * pcb_clearance
        slot_len = pcb_len + slot_width
        result = result.faces(">Z").workplane().slot2D(slot_len,
                                                       slot_width,
                                                       angle=90).cutThruAll()

        # invert the geometry and rotate the negative
        negative = start_box.cut(result)
        negative = negative.rotate((0, 0, 0), (0, 0, 1), angle)
        to_cut = negative.findSolid().locate(center)
        to_cut = to_cut.mirror("XY")
        return to_cut