dactyl-manuform/src/dactyl_keyboard/dactyl-manuform.clj
2017-03-07 14:52:07 -05:00

486 lines
19 KiB
Clojure
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

(ns dactyl-keyboard.dactyl
(:refer-clojure :exclude [use import])
(:require [scad-clj.scad :refer :all]
[scad-clj.model :refer :all]
[unicode-math.core :refer :all]))
(def nrows 4)
(def ncols 6)
(def lastrow (dec nrows))
(def cornerrow (dec lastrow))
(def α (/ π 12)) ; curvature of the columns
(def β (/ π (if (= nrows 4) 26 36))) ; curvature of the rows
(def centerrow (- cornerrow 1)) ; controls front-back tilt
(def centercol 3) ; controls left-right tilt / tenting
;;;;;;;;;;;;;;;;;
;; Switch Hole ;;
;;;;;;;;;;;;;;;;;
(def keyswitch-height 14.4) ;; Was 14.1, then 14.25
(def keyswitch-width 14.4)
(def sa-profile-key-height 12.7)
(def plate-thickness 4)
(def mount-width (+ keyswitch-width 3))
(def mount-height (+ keyswitch-height 3))
(def single-plate
(let [top-wall (->> (cube (+ keyswitch-width 3) 1.5 plate-thickness)
(translate [0
(+ (/ 1.5 2) (/ keyswitch-height 2))
(/ plate-thickness 2)]))
left-wall (->> (cube 1.5 (+ keyswitch-height 3) plate-thickness)
(translate [(+ (/ 1.5 2) (/ keyswitch-width 2))
0
(/ plate-thickness 2)]))
side-nub (->> (binding [*fn* 30] (cylinder 1 2.75))
(rotate (/ π 2) [1 0 0])
(translate [(+ (/ keyswitch-width 2)) 0 1])
(hull (->> (cube 1.5 2.75 plate-thickness)
(translate [(+ (/ 1.5 2) (/ keyswitch-width 2))
0
(/ plate-thickness 2)]))))
plate-half (union top-wall left-wall (with-fn 100 side-nub))]
(union plate-half
(->> plate-half
(mirror [1 0 0])
(mirror [0 1 0])))))
;;;;;;;;;;;;;;;;
;; SA Keycaps ;;
;;;;;;;;;;;;;;;;
(def sa-length 18.25)
(def sa-double-length 37.5)
(def sa-cap {1 (let [bl2 (/ 18.5 2)
m (/ 17 2)
key-cap (hull (->> (polygon [[bl2 bl2] [bl2 (- bl2)] [(- bl2) (- bl2)] [(- bl2) bl2]])
(extrude-linear {:height 0.1 :twist 0 :convexity 0})
(translate [0 0 0.05]))
(->> (polygon [[m m] [m (- m)] [(- m) (- m)] [(- m) m]])
(extrude-linear {:height 0.1 :twist 0 :convexity 0})
(translate [0 0 6]))
(->> (polygon [[6 6] [6 -6] [-6 -6] [-6 6]])
(extrude-linear {:height 0.1 :twist 0 :convexity 0})
(translate [0 0 12])))]
(->> key-cap
(translate [0 0 (+ 5 plate-thickness)])
(color [220/255 163/255 163/255 1])))
2 (let [bl2 (/ sa-double-length 2)
bw2 (/ 18.25 2)
key-cap (hull (->> (polygon [[bw2 bl2] [bw2 (- bl2)] [(- bw2) (- bl2)] [(- bw2) bl2]])
(extrude-linear {:height 0.1 :twist 0 :convexity 0})
(translate [0 0 0.05]))
(->> (polygon [[6 16] [6 -16] [-6 -16] [-6 16]])
(extrude-linear {:height 0.1 :twist 0 :convexity 0})
(translate [0 0 12])))]
(->> key-cap
(translate [0 0 (+ 5 plate-thickness)])
(color [127/255 159/255 127/255 1])))
1.5 (let [bl2 (/ 18.25 2)
bw2 (/ 28 2)
key-cap (hull (->> (polygon [[bw2 bl2] [bw2 (- bl2)] [(- bw2) (- bl2)] [(- bw2) bl2]])
(extrude-linear {:height 0.1 :twist 0 :convexity 0})
(translate [0 0 0.05]))
(->> (polygon [[11 6] [-11 6] [-11 -6] [11 -6]])
(extrude-linear {:height 0.1 :twist 0 :convexity 0})
(translate [0 0 12])))]
(->> key-cap
(translate [0 0 (+ 5 plate-thickness)])
(color [240/255 223/255 175/255 1])))})
;;;;;;;;;;;;;;;;;;;;;;;;;
;; Placement Functions ;;
;;;;;;;;;;;;;;;;;;;;;;;;;
(def columns (range 0 ncols))
(def rows (range 0 nrows))
(def cap-top-height (+ plate-thickness sa-profile-key-height))
(def row-radius (+ (/ (/ (+ mount-height 1/2) 2)
(Math/sin (/ α 2)))
cap-top-height))
(def column-radius (+ (/ (/ (+ mount-width 2.0) 2)
(Math/sin (/ β 2)))
cap-top-height))
(defn key-place [column row shape]
(let [row-placed-shape (->> shape
(translate [0 0 (- row-radius)])
(rotate (* α (- centerrow row)) [1 0 0])
(translate [0 0 row-radius]))
column-offset (cond
(= column 2) [0 2.82 -4.5]
(>= column 4) [0 -5.8 5.64]
:else [0 0 0])
column-angle (* β (- centercol column))
placed-shape (->> row-placed-shape
(translate [0 0 (- column-radius)])
(rotate column-angle [0 1 0])
(translate [0 0 column-radius])
(translate column-offset))]
(->> placed-shape
(rotate (/ π 12) [0 1 0])
(translate [0 0 24]))))
(def key-holes
(apply union
(for [column columns
row rows
:when (or (.contains [2 3] column)
(not= row lastrow))]
(->> single-plate
(key-place column row)))))
(def caps
(apply union
(for [column columns
row rows
:when (or (.contains [2 3] column)
(not= row lastrow))]
(->> (sa-cap (if (= column 5) 1 1))
(key-place column row)))))
;;;;;;;;;;;;;;;;;;;;
;; Web Connectors ;;
;;;;;;;;;;;;;;;;;;;;
(def web-thickness 3.5)
(def post-size 0.1)
(def web-post (->> (cube post-size post-size web-thickness)
(translate [0 0 (+ (/ web-thickness -2)
plate-thickness)])))
(def post-adj (/ post-size 2))
(def web-post-tr (translate [(- (/ mount-width 2) post-adj) (- (/ mount-height 2) post-adj) 0] web-post))
(def web-post-tl (translate [(+ (/ mount-width -2) post-adj) (- (/ mount-height 2) post-adj) 0] web-post))
(def web-post-bl (translate [(+ (/ mount-width -2) post-adj) (+ (/ mount-height -2) post-adj) 0] web-post))
(def web-post-br (translate [(- (/ mount-width 2) post-adj) (+ (/ mount-height -2) post-adj) 0] web-post))
(defn triangle-hulls [& shapes]
(apply union
(map (partial apply hull)
(partition 3 1 shapes))))
(def connectors
(apply union
(concat
;; Row connections
(for [column (range 0 (dec ncols))
row (range 0 lastrow)]
(triangle-hulls
(key-place (inc column) row web-post-tl)
(key-place column row web-post-tr)
(key-place (inc column) row web-post-bl)
(key-place column row web-post-br)))
;; Column connections
(for [column columns
row (range 0 cornerrow)]
(triangle-hulls
(key-place column row web-post-bl)
(key-place column row web-post-br)
(key-place column (inc row) web-post-tl)
(key-place column (inc row) web-post-tr)))
;; Diagonal connections
(for [column (range 0 (dec ncols))
row (range 0 cornerrow)]
(triangle-hulls
(key-place column row web-post-br)
(key-place column (inc row) web-post-tr)
(key-place (inc column) row web-post-bl)
(key-place (inc column) (inc row) web-post-tl))))))
;;;;;;;;;;;;
;; Thumbs ;;
;;;;;;;;;;;;
(def thumborigin [-23 -34 47])
(defn deg2rad [degrees]
(* (/ degrees 180) pi))
(defn thumb-tr-place [shape]
(->> shape
(rotate (deg2rad 10) [1 0 0])
(rotate (deg2rad -23) [0 1 0])
(rotate (deg2rad -3) [0 0 1])
(translate thumborigin)
(translate [-10 -16 0])
))
(defn thumb-tl-place [shape]
(->> shape
(rotate (deg2rad 10) [1 0 0])
(rotate (deg2rad -23) [0 1 0])
(rotate (deg2rad -3) [0 0 1])
(translate thumborigin)
(translate [-30 -15 -2])))
(defn thumb-mr-place [shape]
(->> shape
(rotate (deg2rad -6) [1 0 0])
(rotate (deg2rad -34) [0 1 0])
(rotate (deg2rad 48) [0 0 1])
(translate thumborigin)
(translate [-29 -40 -13])
))
(defn thumb-ml-place [shape]
(->> shape
(rotate (deg2rad 6) [1 0 0])
(rotate (deg2rad -34) [0 1 0])
(rotate (deg2rad 40) [0 0 1])
(translate thumborigin)
(translate [-51 -25 -12])))
(defn thumb-br-place [shape]
(->> shape
(rotate (deg2rad -16) [1 0 0])
(rotate (deg2rad -33) [0 1 0])
(rotate (deg2rad 54) [0 0 1])
(translate thumborigin)
(translate [-37.8 -55.3 -25.3])
))
(defn thumb-bl-place [shape]
(->> shape
(rotate (deg2rad -4) [1 0 0])
(rotate (deg2rad -35) [0 1 0])
(rotate (deg2rad 52) [0 0 1])
(translate thumborigin)
(translate [-56.3 -43.3 -23.5])
))
(defn thumb-1x-layout [shape]
(union
(thumb-mr-place shape)
(thumb-ml-place shape)
(thumb-br-place shape)
(thumb-bl-place shape)))
(defn thumb-15x-layout [shape]
(union
(thumb-tr-place shape)
(thumb-tl-place shape)))
(def larger-plate
(let [plate-height (/ (- sa-double-length mount-height) 3)
top-plate (->> (cube mount-width plate-height web-thickness)
(translate [0 (/ (+ plate-height mount-height) 2)
(- plate-thickness (/ web-thickness 2))]))
]
(union top-plate (mirror [0 1 0] top-plate))))
(def thumbcaps
(union
(thumb-1x-layout (sa-cap 1))
(thumb-15x-layout (rotate (/ π 2) [0 0 1] (sa-cap 1.5)))))
(def thumb
(union
(thumb-1x-layout single-plate)
(thumb-15x-layout single-plate)
(thumb-15x-layout larger-plate)
))
(def thumb-post-tr (translate [(- (/ mount-width 2) post-adj) (- (/ mount-height 1.15) post-adj) 0] web-post))
(def thumb-post-tl (translate [(+ (/ mount-width -2) post-adj) (- (/ mount-height 1.15) post-adj) 0] web-post))
(def thumb-post-bl (translate [(+ (/ mount-width -2) post-adj) (+ (/ mount-height -1.15) post-adj) 0] web-post))
(def thumb-post-br (translate [(- (/ mount-width 2) post-adj) (+ (/ mount-height -1.15) post-adj) 0] web-post))
(def thumb-connectors
(union
(triangle-hulls ; top two
(thumb-tl-place thumb-post-tr)
(thumb-tl-place thumb-post-br)
(thumb-tr-place thumb-post-tl)
(thumb-tr-place thumb-post-bl))
(triangle-hulls ; bottom two on the right
(thumb-br-place web-post-tr)
(thumb-br-place web-post-br)
(thumb-mr-place web-post-tl)
(thumb-mr-place web-post-bl))
(triangle-hulls ; bottom two on the left
(thumb-bl-place web-post-tr)
(thumb-bl-place web-post-br)
(thumb-ml-place web-post-tl)
(thumb-ml-place web-post-bl))
(triangle-hulls ; centers of the bottom four
(thumb-br-place web-post-tl)
(thumb-bl-place web-post-bl)
(thumb-br-place web-post-tr)
(thumb-bl-place web-post-br)
(thumb-mr-place web-post-tl)
(thumb-ml-place web-post-bl)
(thumb-mr-place web-post-tr)
(thumb-ml-place web-post-br))
(triangle-hulls ; top two to the middle two, starting on the left
(thumb-tl-place thumb-post-tl)
(thumb-ml-place web-post-tr)
(thumb-tl-place thumb-post-bl)
(thumb-ml-place web-post-br)
(thumb-tl-place thumb-post-br)
(thumb-mr-place web-post-tr)
(thumb-tr-place thumb-post-bl)
(thumb-mr-place web-post-br)
(thumb-tr-place thumb-post-br))
(triangle-hulls ; top two to the main keyboard, starting on the left
(thumb-tl-place thumb-post-tl)
(key-place 0 cornerrow web-post-bl)
(thumb-tl-place thumb-post-tr)
(key-place 0 cornerrow web-post-br)
(thumb-tr-place thumb-post-tl)
(key-place 1 cornerrow web-post-bl)
(thumb-tr-place thumb-post-tr)
(key-place 1 cornerrow web-post-br)
(key-place 2 lastrow web-post-tl)
(key-place 2 lastrow web-post-bl)
(thumb-tr-place thumb-post-tr)
(key-place 2 lastrow web-post-bl)
(thumb-tr-place thumb-post-br)
(key-place 2 lastrow web-post-br)
(key-place 3 lastrow web-post-bl)
(key-place 2 lastrow web-post-tr)
(key-place 3 lastrow web-post-tl)
(key-place 3 cornerrow web-post-bl)
(key-place 3 lastrow web-post-tr)
(key-place 3 cornerrow web-post-br)
(key-place 4 cornerrow web-post-bl))
(triangle-hulls
(key-place 1 cornerrow web-post-br)
(key-place 2 lastrow web-post-tl)
(key-place 2 cornerrow web-post-bl)
(key-place 2 lastrow web-post-tr)
(key-place 2 cornerrow web-post-br)
(key-place 3 cornerrow web-post-bl)
)
(triangle-hulls
(key-place 3 lastrow web-post-tr)
(key-place 3 lastrow web-post-br)
(key-place 3 lastrow web-post-tr)
(key-place 4 cornerrow web-post-bl))
))
;;;;;;;;;;
;; Case ;;
;;;;;;;;;;
(defn bottom [height p]
(->> (project p)
(extrude-linear {:height height :twist 0 :convexity 0})
(translate [0 0 (/ height 2)])))
(defn bottom-hull [& p]
(hull p (bottom 10.001 p)))
(defn wall-brace [place1 dx1 dy1 post1 place2 dx2 dy2 post2]
(union
(hull
(place1 post1)
(place1 (translate [0 0 -15] post1))
(place1 (translate [(* dx1 5) (* dy1 5) -4] post1))
(place1 (translate [(* dx1 5) (* dy1 5) -15] post1))
(place2 post2)
(place2 (translate [0 0 -15] post2))
(place2 (translate [(* dx2 5) (* dy2 5) -4] post2))
(place2 (translate [(* dx2 5) (* dy2 5) -15] post2)))
(bottom-hull
(place1 (translate [(* dx1 5) (* dy1 5) -15] post1))
(place1 (translate [0 0 -15] post1))
(place1 (translate [(* dx1 5) (* dy1 5) -15] post1))
(place2 (translate [0 0 -15] post2))
(place2 (translate [(* dx2 5) (* dy2 5) -15] post2)))))
(defn key-wall-brace [x1 y1 dx1 dy1 post1 x2 y2 dx2 dy2 post2]
(wall-brace (partial key-place x1 y1) dx1 dy1 post1
(partial key-place x2 y2) dx2 dy2 post2))
(def case-walls
(union
; back wall
(for [x (range 0 6)] (key-wall-brace x 0 0 1 web-post-tl x 0 0 1 web-post-tr))
(for [x (range 1 6)] (key-wall-brace x 0 0 1 web-post-tl (dec x) 0 0 1 web-post-tr))
(key-wall-brace 0 0 0 1 web-post-tl 0 0 -1 0 web-post-tl)
(key-wall-brace 5 0 0 1 web-post-tr 5 0 1 0 web-post-tr)
; right wall
(for [y (range 0 lastrow)] (key-wall-brace 5 y 1 0 web-post-tr 5 y 1 0 web-post-br))
(for [y (range 1 lastrow)] (key-wall-brace 5 (dec y) 1 0 web-post-br 5 y 1 0 web-post-tr))
(key-wall-brace 5 cornerrow 0 -1 web-post-br 5 cornerrow 1 0 web-post-br)
; left wall
(for [y (range 0 lastrow)] (key-wall-brace 0 y -1 0 web-post-tl 0 y -1 0 web-post-bl))
(for [y (range 1 lastrow)] (key-wall-brace 0 (dec y) -1 0 web-post-bl 0 y -1 0 web-post-tl))
; front wall
(key-wall-brace 3 lastrow 0 -1 web-post-bl 3 lastrow 0.5 -1 web-post-br)
(key-wall-brace 4 cornerrow 0 -1 web-post-bl 4 cornerrow 0 -1 web-post-br)
(key-wall-brace 5 cornerrow 0 -1 web-post-bl 5 cornerrow 0 -1 web-post-br)
(key-wall-brace 3 lastrow 0.5 -1 web-post-br 4 cornerrow 1 -1 web-post-bl)
(key-wall-brace 4 cornerrow 0 -1 web-post-br 5 cornerrow 0 -1 web-post-bl)
; thumb walls
(wall-brace thumb-mr-place 0 -1 web-post-br thumb-tr-place 0 -1 thumb-post-br)
(wall-brace thumb-mr-place 0 -1 web-post-br thumb-mr-place 0 -1 web-post-bl)
(wall-brace thumb-br-place 0 -1 web-post-br thumb-br-place 0 -1 web-post-bl)
(wall-brace thumb-ml-place 0 1 web-post-tr thumb-ml-place 0 1 web-post-tl)
(wall-brace thumb-bl-place 0 1 web-post-tr thumb-bl-place 0 1 web-post-tl)
(wall-brace thumb-br-place -1 0 web-post-tl thumb-br-place -1 0 web-post-bl)
(wall-brace thumb-bl-place -1 0 web-post-tl thumb-bl-place -1 0 web-post-bl)
; thumb corners
(wall-brace thumb-br-place -1 0 web-post-bl thumb-br-place 0 -1 web-post-bl)
(wall-brace thumb-bl-place -1 0 web-post-tl thumb-bl-place 0 1 web-post-tl)
; thumb tweeners
(wall-brace thumb-mr-place 0 -1 web-post-bl thumb-br-place 0 -1 web-post-br)
(wall-brace thumb-ml-place 0 1 web-post-tl thumb-bl-place 0 1 web-post-tr)
(wall-brace thumb-bl-place -1 0 web-post-bl thumb-br-place -1 0 web-post-tl)
(wall-brace thumb-ml-place 0 1 web-post-tr thumb-tl-place -2.5 0 thumb-post-tl)
(wall-brace thumb-tl-place -1 0 thumb-post-tl (partial key-place 0 cornerrow) -1 0 web-post-bl)
(wall-brace thumb-tr-place 0 -1 thumb-post-br (partial key-place 3 lastrow) 0 -1 web-post-bl)
))
(defn on-wall-place [column depth shape]
(key-place column 0
(->> shape
(rotate (+ (* β (- centercol column)) (/ π 12)) [0 -1 0])
(rotate (* α centerrow) [-1 0 0])
(translate [0 (/ mount-height 2) -15])
; (Math/sin (/ α 2)))
)))
; (def test-shape (on-wall-place 1 20 (translate [2.5 15 5] (cube 5 30 10))))
(def test-shape (on-wall-place 1 20 (cube 5 30 10)))
(def teensy-width 20)
(def teensy-height 12)
(def teensy-length 33)
(def teensy-pcb-thickness 1.6)
(def teensy-offset-height 5)
(def usb-cutout
(let [hole-height 6.2
side-radius (/ hole-height 2)
hole-width 10.75
side-cylinder (->> (cylinder side-radius teensy-length)
(with-fn 20)
(translate [(/ (- hole-width hole-height) 2) 0 0]))]
(->> (color [20/255 163/255 163/255 1])
(hull side-cylinder
(mirror [-1 0 0] side-cylinder))
(translate [0 (/ teensy-length 2) (- side-radius)])
(translate [0 0 (- 1)])
(translate [0 0 (- teensy-offset-height)])
(on-wall-place 1 20))))
(spit "repl.scad"
(write-scad (union
key-holes
connectors
thumb
thumb-connectors
case-walls
test-shape
; usb-cutout
; thumbcaps
; caps
)))