Devesh36/orbit-turntable
ORBIT is a USB-C-powered display turntable for photographing jewellery, models and small products. Four-layer ESP32-C3 / ULN2003 PCB, geared stepper, OLED, push encoder, home switch and buzzer, with an enclosed and exploded assembly. Hardware prototype; firmware and physical qualification remain separate.
- Version
- 0.1.1
- License
- unset
- Stars
- 0
mechanics.tsx
import {Fragment} from 'react'
import {jscad} from 'tscircuit'
import {marks} from './wordmarks'
export const boardOffset=[0,-31,0] as const
const dark='#242a32',blue='#2484ff',silver='#bcc4cd'
export function Cyl({r,h,at,n=64}:{r:number,h:number,at:[number,number,number],n?:number}){return <jscad.translate offset={[at[0],at[1],at[2]-h/2]}><jscad.extrudeLinear height={h}><jscad.polygon points={Array.from({length:n},(_,i)=>[r*Math.cos(i*2*Math.PI/n),r*Math.sin(i*2*Math.PI/n)] as [number,number])}/></jscad.extrudeLinear></jscad.translate>}
function RoundBox({w,d,h,r,at}:{w:number,d:number,h:number,r:number,at:[number,number,number]}){return <jscad.hull>{[-1,1].flatMap(x=>[-1,1].map(y=><Fragment key={`${x}/${y}`}><Cyl r={r} h={h} at={[at[0]+x*(w/2-r),at[1]+y*(d/2-r),at[2]]} n={32}/></Fragment>))}</jscad.hull>}
export function Mark({name,x,y,z,color=blue}:{name:keyof typeof marks,x:number,y:number,z:number,color?:string}){return <jscad.colorize color={color}><jscad.translate offset={[x,y,z]}><jscad.extrudeLinear height={0.065}><jscad.union>{marks[name].map((g,i)=><Fragment key={i}>{g.holes.length?<jscad.subtract><jscad.union>{g.outer.map((p,j)=><jscad.polygon key={j} points={p}/>)}</jscad.union><jscad.union>{g.holes.map((p,j)=><jscad.polygon key={j} points={p}/>)}</jscad.union></jscad.subtract>:<jscad.union>{g.outer.map((p,j)=><jscad.polygon key={j} points={p}/>)}</jscad.union>}</Fragment>)}</jscad.union></jscad.extrudeLinear></jscad.translate></jscad.colorize>}
const screws=[[-49,-40],[49,-40],[-46,59],[46,59]] as const
const pcbMounts=[[-17,-53],[38,-53],[-17,-9],[38,-9]] as const
export function Base(){return <jscad.colorize color={dark}><jscad.subtract><jscad.union>
<jscad.subtract>
<jscad.hull><RoundBox w={114} d={134} h={0.1} r={20} at={[0,8,-5.95]}/><RoundBox w={116} d={136} h={24} r={21} at={[0,8,7]}/></jscad.hull>
<RoundBox w={111.2} d={131.2} h={32} r={18.6} at={[0,8,12]}/>
</jscad.subtract>
{screws.map(([x,y])=><Fragment key={`${x}/${y}`}><Cyl r={4} h={23} at={[x,y,7.5]}/></Fragment>)}
{pcbMounts.map(([x,y])=><Fragment key={`${x}/${y}`}><Cyl r={3.4} h={3.2} at={[x,y,-2.4]}/></Fragment>)}
{[-17.5,17.5].map(x=><Fragment key={x}><Cyl r={3.5} h={19.4} at={[x,19,5.7]}/></Fragment>)}
</jscad.union>
{screws.map(([x,y])=><Fragment key={`${x}/${y}`}><Cyl r={1.3} h={26} at={[x,y,8]}/></Fragment>)}
{pcbMounts.map(([x,y])=><Fragment key={`${x}/${y}`}><Cyl r={1.05} h={7} at={[x,y,-1]}/></Fragment>)}
{[-17.5,17.5].map(x=><Fragment key={x}><Cyl r={1.25} h={20} at={[x,19,6]}/></Fragment>)}
{/* Cable hood clearance reaches the recessed USB-C receptacle. */}
<RoundBox w={13.5} d={14} h={6.5} r={1.4} at={[-8,-59,2.8]}/>
{Array.from({length:6},(_,i)=><jscad.cuboid key={i} size={[1.8,13,2]} center={[19+i*4,8,-5.3]}/>)}
</jscad.subtract></jscad.colorize>}
export function Lid(){return <jscad.colorize color={dark}><jscad.subtract><jscad.union>
<jscad.hull><RoundBox w={116} d={136} h={0.1} r={21} at={[0,8,19.15]}/><RoundBox w={113} d={133} h={0.1} r={20} at={[0,8,21.95]}/></jscad.hull>
{/* Bearing seat takes platform loads off the geared motor. */}
<Cyl r={13.2} h={9} at={[0,27,21]}/>
</jscad.union>
<Cyl r={11.1} h={12} at={[0,27,24.5]}/><Cyl r={4.5} h={20} at={[0,27,20]}/>
<RoundBox w={35} d={10.4} h={10} r={1.1} at={[-11,-39,21]}/>
<Cyl r={3.6} h={12} at={[28,-39,21]}/><Cyl r={1} h={12} at={[14,-41,21]}/>
{/* Home switch mounts underneath; lever projects through this slot. */}
<jscad.cuboid size={[16,4,12]} center={[31,27,22]}/>
{screws.map(([x,y])=><Fragment key={`${x}/${y}`}><Cyl r={1.6} h={12} at={[x,y,22]}/><Cyl r={3} h={1.6} at={[x,y,21.7]}/></Fragment>)}
{[-1,0,1].map(i=><Fragment key={i}><RoundBox w={5} d={0.75} h={10} r={0.35} at={[30,-19+i*1.6,21]}/></Fragment>)}
</jscad.subtract></jscad.colorize>}
export function Platter(){return <jscad.colorize color="#c7cdd4"><jscad.union>
<jscad.colorize color='#c7cdd4'><jscad.hull><Cyl r={43} h={0.2} at={[0,27,28.1]} n={128}/><Cyl r={44} h={2} at={[0,27,29.2]} n={128}/><Cyl r={43} h={0.2} at={[0,27,30.9]} n={128}/></jscad.hull></jscad.colorize>
{/* Index lug meets the home lever once per revolution. */}
<jscad.colorize color={blue}><RoundBox w={5} d={5} h={2.8} r={1} at={[35,27,26.6]}/></jscad.colorize>
</jscad.union></jscad.colorize>}
export function Mat(){return <jscad.colorize color="#303842"><Cyl r={42} h={0.8} at={[0,27,31.4]} n={128}/></jscad.colorize>}
export function Coupler(){return <jscad.colorize color={blue}><jscad.subtract><jscad.union><Cyl r={3.98} h={9.3} at={[0,27,20.85]}/><Cyl r={7} h={2.5} at={[0,27,26.75]}/></jscad.union><jscad.subtract><Cyl r={2.6} h={14} at={[0,27,21]}/><jscad.cuboid size={[8,6,16]} center={[0,22.4,21]}/></jscad.subtract></jscad.subtract></jscad.colorize>}
export function Bearing(){return <jscad.union><jscad.colorize color={silver}><jscad.subtract><Cyl r={11} h={7} at={[0,27,22]}/><Cyl r={8.8} h={9} at={[0,27,22]}/></jscad.subtract><jscad.subtract><Cyl r={5.6} h={7} at={[0,27,22]}/><Cyl r={4} h={9} at={[0,27,22]}/></jscad.subtract></jscad.colorize><jscad.colorize color='#53606c'><jscad.subtract><Cyl r={8.8} h={6.6} at={[0,27,22]}/><Cyl r={5.6} h={9} at={[0,27,22]}/></jscad.subtract></jscad.colorize></jscad.union>}
export function Motor(){return <jscad.union>
<jscad.colorize color={silver}><Cyl r={14} h={20} at={[0,19,6]}/><jscad.subtract><RoundBox w={42} d={7} h={0.8} r={3} at={[0,19,15.8]}/>{[-17.5,17.5].map(x=><Fragment key={x}><Cyl r={2.1} h={3} at={[x,19,16]}/></Fragment>)}</jscad.subtract></jscad.colorize>
<jscad.colorize color='#1165ad'><RoundBox w={15} d={8} h={17} r={1.5} at={[0,3,5.5]}/></jscad.colorize>
<jscad.colorize color='#e0e3e6'><jscad.subtract><Cyl r={2.5} h={9} at={[0,27,20.5]}/><jscad.cuboid size={[8,6,12]} center={[0,22.5,20]}/></jscad.subtract></jscad.colorize>
</jscad.union>}
export function Knob(){return <jscad.colorize color="#151a20"><jscad.union><jscad.colorize color='#151a20'><jscad.subtract><jscad.hull><Cyl r={8.5} h={11} at={[28,-39,27.5]} n={48}/><Cyl r={7.8} h={0.2} at={[28,-39,33.8]} n={48}/></jscad.hull><Cyl r={3.05} h={10} at={[28,-39,25]}/></jscad.subtract></jscad.colorize><jscad.colorize color={blue}><Cyl r={7.4} h={0.35} at={[28,-39,33.9]} n={64}/></jscad.colorize><jscad.colorize color='#e4ecf5'><RoundBox w={0.6} d={3.5} h={0.08} r={0.25} at={[28,-35.8,34.12]}/></jscad.colorize></jscad.union></jscad.colorize>}
export function KnobTop(){return <jscad.colorize color={blue}><Cyl r={7.4} h={0.36} at={[28,-39,33.92]}/></jscad.colorize>}
export function KnobIndex(){return <jscad.colorize color="#e4ecf5"><RoundBox w={0.6} d={3.5} h={0.08} r={0.25} at={[28,-35.8,34.16]}/></jscad.colorize>}
export function Display(){return <jscad.colorize color="#122c45"><jscad.cuboid size={[36,12.5,1.2]} center={[-11,-39,18.1]}/></jscad.colorize>}
export function Screen(){return <jscad.colorize color="#060b11"><RoundBox w={33} d={9.2} h={1.2} r={0.5} at={[-11,-39,19.3]}/></jscad.colorize>}
export function ScreenText(){return <jscad.colorize color="#a4daff"><jscad.union><Mark name="screenTitle" x={-11} y={-37.8} z={19.91}/><Mark name="screenSpeed" x={-11} y={-41.3} z={19.91}/></jscad.union></jscad.colorize>}
export function Lens(){return <jscad.colorize color='#318aff'><Cyl r={0.85} h={20} at={[14,-41,12]}/></jscad.colorize>}
export function HomeSwitch(){return <jscad.union><jscad.colorize color='#1b1b1b'><jscad.cuboid size={[12.8,5.8,6.5]} center={[31,27,15.75]}/></jscad.colorize><jscad.colorize color={silver}><jscad.hull><jscad.cuboid size={[1,2,0.35]} center={[24,27,19.6]}/><jscad.cuboid size={[1,2,0.35]} center={[40,27,27.6]}/></jscad.hull></jscad.colorize><jscad.colorize color='#a93624'><jscad.cuboid size={[2,2,2]} center={[35,27,20]}/></jscad.colorize></jscad.union>}
function Wire({points,color,r=0.35}:{points:[number,number,number][],color:string,r?:number}){return <jscad.colorize color={color}><jscad.union>{points.slice(1).map((p,i)=><Fragment key={i}><jscad.hull><jscad.sphere radius={r} center={points[i]} segments={8}/><jscad.sphere radius={r} center={p} segments={8}/></jscad.hull></Fragment>)}</jscad.union></jscad.colorize>}
export function Harness(){return <jscad.union>
{['#2380d0','#ef8ca5','#e8bc36','#e17732','#d64946'].map((color,i)=><Fragment key={color}><Wire color={color} points={[[2.92+i*2.54,-9,8],[3+i,0,8],[3-i*1.5,0,6]]}/></Fragment>)}
{['#d64946','#333333','#e8bc36','#2380d0'].map((color,i)=><Fragment key={color}><Wire color={color} r={0.22} points={[[-11.81+i*2.54,-11,8],[-12+i*1.3,-20,8],[-12+i*1.3,-31,17]]}/></Fragment>)}
<Wire color='#e8bc36' points={[[27.73,-8,8],[38,-2,12],[38,20,15],[31,24,15]]}/><Wire color='#333333' points={[[30.27,-8,8],[40,-2,12],[40,20,15],[33,24,15]]}/>
</jscad.union>}
export function Feet(){return <jscad.colorize color='#16191c'>{[[-38,-40],[38,-40],[-38,55],[38,55]].map(([x,y],i)=><Fragment key={i}><Cyl r={5} h={1.5} at={[x,y,-6.75]}/></Fragment>)}</jscad.colorize>}
export function Fasteners(){return <jscad.colorize color='#252a30'><jscad.union>{screws.map(([x,y])=><Fragment key={`${x}/${y}`}><Cyl r={1.45} h={14} at={[x,y,13]}/><jscad.subtract><Cyl r={2.7} h={1.3} at={[x,y,21.25]}/><jscad.cuboid size={[3.5,0.6,1]} center={[x,y,22]}/><jscad.cuboid size={[0.6,3.5,1]} center={[x,y,22]}/></jscad.subtract></Fragment>)}</jscad.union></jscad.colorize>}
