Useful 3D prints for SDIY and electronics

Hitching a ride on this thread rather than start one, since I’m asking just to gauge interest.

You saw how I’ve been making 3D printed panels for my synths? I don’t mention it every time but I make them out of code.

I’m toying with cleaning up my system to turn it into a more user-friendly library than my collection of copy-pasted standalone hacks.

The main value the library would provide is a collection of footprints tested to work well. For example you can see how the pots have retaining notches, or the jacks have a recessed area.

I’m considering also adding simple display objects that won’t be printed giving you a conservative estimate of the footprint of stuff (how big a jack is, how much clearance there is between knobs of a specific diameter).

Now, the code right now is a bit nasty-looking:

import cadquery as cq

# Base panel
panelWidth = 25
panelHeight = 200 
panelThickness = 4.0 
m3Diameter = 3.4
m2Diameter = 2.6
panel = cq.Workplane("XY").box(panelWidth, panelHeight, panelThickness)

# Slots for M3 screws in the corners
panel = (
    panel.faces(">Z")
    .workplane()
    .rect(panelWidth - m3Diameter * 3, panelHeight - 6, forConstruction=True)
    .vertices()
    .slot2D(m3Diameter * 2.5, m3Diameter, 0)
    .cutThruAll()
)

# Holes for switches in horizontal position
switchWidth = 13.2
switchLength = 8.2
switchHoleDiameter = 6
switchDistance = 12
switchX = 7.5
firstSwitchY = 25
switchesLocations = [
    [7.5, 25],
    [7.5, 35],
    [7.5, 45],
    [7.5, 55],
    [7.5, 65],
    [7.5, 75],
    [7.5, 85],
    [7.5, 95],
]
switchY = firstSwitchY
for pos in switchesLocations:
    panel = (
        panel.faces(">Z")
        .vertices("<XY")
        .workplane(centerOption="CenterOfMass")
        .center(switchX, switchY)
        .hole(switchHoleDiameter)
    )
    panel = (
        panel.faces(">Z")
        .vertices("<XY")
        .workplane(centerOption="CenterOfMass")
        .center(switchX, switchY)
        .rect(switchWidth, switchLength)
        .cutBlind(-panelThickness / 2)
    )
    switchY += switchDistance

# Corresponding Holes for LEDs.
ledDiameter = 5.35
ledOffset = 10.5
ledX = switchX + ledOffset
ledY = firstSwitchY
for pos in switchesLocations:
    pos[0] += ledOffset
    panel = (
        panel.faces(">Z")
        .vertices("<XY")
        .workplane(centerOption="CenterOfMass")
        .center(ledX, ledY)
        .hole(ledDiameter)
    )
    ledY += switchDistance

# Reset button
resetPos = [12.5, 125]
resetInnerHole = 6.7
resetOuterHole = 6.7
panel = (
    panel.faces(">Z")
    .vertices("<XY")
    .workplane(centerOption="CenterOfMass")
    .center(resetPos[0], resetPos[1])
    .hole(resetInnerHole)
)

# Holes for jacks
jackDiameter = 10
jackWidth = 16.2
jackLength = jackWidth
jackLocations = [
    [12.5, 145],
    [12.5, 175],
]
for pos in jackLocations:
    panel = (
        panel.faces(">Z")
        .vertices("<XY")
        .workplane(centerOption="CenterOfMass")
        .center(pos[0], pos[1])
        .hole(jackDiameter)
    )
    panel = (
        panel.faces(">Z")
        .vertices("<XY")
        .workplane(centerOption="CenterOfMass")
        .center(pos[0], pos[1])
        .rect(jackWidth, jackLength)
        .cutBlind(-panelThickness / 3)
    )

I’d like to instead provide a simple syntax that’s closer to how you would think of a synth panel, e.g.:

import cadquery as cq

defaultThickness = 4.0
eurorackHeight = 133.35
kosmoHeight = 200.0


################## Helpers


def hp(hp: float) -> float:
    """Converts Horizontal Pitch to millimeters.

    1 HP == 0.2 inches == 5.08 millimeters"""
    return hp * 5.08


################## Panels


def panel(width: float = 100, height: float = 100, thickness: float = defaultThickness):
    """Returns a rectangular panel of arbitrary dimensions."""
    return cq.Workplane("XY").box(width, height, thickness)


def eurorackPanel(width: float = hp(2), thickness: float = defaultThickness):
    """Returns a Eurorack panel. Width best defined in hp().

    A thickness of 4mm minimum is recommended for solidity."""
    return panel(width, eurorackHeight, thickness)


def kosmoPanel(width: float = 25, thickness: float = defaultThickness):
    """Returns a Kosmo (Metric 5U) panel. Widths should be multiples of 25.

    A thickness of 4mm minimum is recommended for solidity."""
    return panel(width, kosmoHeight, thickness)

Quick show of hands:

  • Any interest in using such a system at all? No real knowledge of Python would be required beyond already knowing how to code a little in any language.
  • Are you willing to tolerate an awkward UI if decent instructions are provided? It’d be a Jupyter notebook in your browser or local software (CQ-Editor) that’s a bit rough around the edges.

For example this is what I use:

7 Likes