knob.hs
A pal of mine DJs under the name Syntax Terror.
A while back, he contacted me about printing some replacement dials for his Traktor Kontrol X1 MK2, as these had apparently fallen off during transit.
He sent me a list of possible knob designs from Thingiverse.
Now, I’m broadly of the opinion that the point of having a 3d printer is that you can make custom parts. Thingiverse is great, but if you’re just going to print stuff from Thingiverse all the time, you’d be better off with an Alibaba account.
With this in mind, I thought I’d have a go at designing some custom knobs, instead.
This meant I was able to use the line “I’ve got some knobs here with your name on them”, while we were arranging postage.
While I’m relatively happy with how these came out, I regret not playing around with the bevel radius and number of cuts a little more than I did.
#!/usr/bin/env stack
{- stack script --resolver lts-23.15
--package linear
--package waterfall-cad
--extra-dep waterfall-cad-0.6.3.0
--extra-dep opencascade-hs-0.6.3.0
-}
-- short-description: Tommy's Knobs
-- description: [A pal of mine](https://www.tommyp.org/) DJs under the name [Syntax Terror](https://soundcloud.com/syntax-terrorist).
-- description:
-- description: A while back, he contacted me about printing some replacement dials for his [Traktor Kontrol X1 MK2](https://www.native-instruments.com/en/products/traktor/dj-controllers/traktor-x1/), as these had apparently fallen off during transit.
-- description:
-- description: He sent me a list of possible knob designs from Thingiverse.
-- description:
-- description: Now, I'm broadly of the opinion that the point of having a 3d printer is that you can make _custom parts_.
-- description: Thingiverse is great, but if you're just going to print stuff from Thingiverse all the time, you'd be better off with an Alibaba account.
-- description:
-- description: With this in mind, I thought I'd have a go at designing some custom knobs, instead.
-- description:
-- description: This meant I was able to use the line "I've got some knobs here with your name on them", while we were arranging postage.
-- description:
-- description: While I'm relatively happy with how these came out, I regret not playing around with the bevel radius and number of cuts a little more than I did.
-- image: https://doscienceto.it/blog/photos/knobs-01.jpg
-- image: https://doscienceto.it/blog/photos/traktor_kontrol.jpg
import qualified Waterfall
import Linear
shaft :: Waterfall.Solid
shaft =
let r = 3
h = 20
cutOff = 2
in (Waterfall.scale (V3 r r h) Waterfall.unitCylinder) `Waterfall.difference`
(Waterfall.translate (cutOff *^ unit _y) $ Waterfall.scale (V3 h h (h*3)) $ Waterfall.translate (0.5 *^ unit _y) $ Waterfall.centeredCube)
knob :: Waterfall.Shape -> Waterfall.Solid
knob t =
let rInner = 19/2
h = 19
fillet = Waterfall.roundConditionalFillet (\(V3 _ _ z, V3 _ _ z') -> if z > h/2 && z' > h/2 then Just 5 else Nothing)
cutR = 1.75
cutN = 8
cuts = Waterfall.rotate (unit _z) (pi/cutN) $ mconcat $ take 10 $ iterate (Waterfall.rotate (unit _z) (2*pi/cutN)) $ Waterfall.translate (rInner *^ unit _y) $ Waterfall.scale (V3 cutR cutR (h*3)) $ Waterfall.centeredCylinder
plainCyl = fillet $ Waterfall.scale (V3 rInner rInner h) $ Waterfall.unitCylinder
rOuter = 21/2
baseH = 2
coneS = rOuter + baseH
coneGrad = 0.75
baseCone = Waterfall.scale (V3 coneS coneS (coneS * coneGrad)) $ Waterfall.translate (unit _z) $ Waterfall.rotate (unit _x) pi $ Waterfall.unitCone
base = (Waterfall.scale (V3 rOuter rOuter (h/2)) Waterfall.unitCylinder) `Waterfall.intersection` baseCone
shaft' = Waterfall.translate ((h - 20 - 2) *^ unit _z) $ shaft
tDepth = 0.5
text = Waterfall.translate ((h- tDepth*9) *^ unit _z) $ Waterfall.prism (tDepth *10) t
in (((plainCyl `Waterfall.difference` cuts) `Waterfall.union` base) `Waterfall.difference` shaft') `Waterfall.union` text
font = Waterfall.fontFromSystem "monospace" Waterfall.Regular 5
knobSyntax = knob . (`Waterfall.text` "syntax") <$> font
knobTerror = knob . (`Waterfall.text` "terror") <$> font
main :: IO ()
main = do
let stlRes = 0.05
Waterfall.writeSTL stlRes "knob-syntax.stl" =<< knobSyntax
Waterfall.writeSTL stlRes "knob-terror.stl" =<< knobTerror