rushabhcodes/desk-fidget-counter
A desk knob assembly combining a circuit board with PETG-printed mechanical parts and vendor CAD-modeled hardware.
- Version
- 5.6.1
- License
- MIT
- Stars
- 0
mechanical/fit.py
# SPDX-License-Identifier: MIT
"""Engineering fit budget using catalogue facts and user-authorized estimates."""
import math
def evaluate(p):
b=p['bearing'];m=p['bearing_mount'];f=p['fit_budget'];c=p['pcb_capture']
diameter_error=f['printed_fit_diameter_error']+f['bearing_diameter_error']
inner=b['id']-p['bearing_stem_od'];outer=p['bearing_pocket_id']-b['od']
eccentricity=(inner+outer+2*diameter_error)/2
print_xy=eccentricity+f['lid_alignment_error']+2*f['printed_surface_error']
pcb_play=(2.7+f['pcb_hole_diameter_error']-(c['peg_diameter']-f['printed_fit_diameter_error']))/2
pcb_xy=eccentricity+f['lid_alignment_error']+f['printed_surface_error']+pcb_play+f['smt_position_error']
gap_min=c['compressed_pad_height']-f['pcb_thickness_error']-f['relative_print_z_error']
gap_max=c['compressed_pad_height']+f['pcb_thickness_error']+f['relative_print_z_error']
foam_min=c['uncompressed_pad_height']*(1-c['pad_thickness_tolerance_fraction'])
foam_max=c['uncompressed_pad_height']*(1+c['pad_thickness_tolerance_fraction'])
compression_min=foam_min-gap_max+c['adhesive_thickness']-.01
compression_max=foam_max-gap_min+c['adhesive_thickness']+.01
sagitta=p['encoder']['track_radius']-math.sqrt(p['encoder']['track_radius']**2-2**2)
radial_slot=(3-p['encoder']['track_thickness'])/2-pcb_xy-sagitta
margin_width=f['bearing_width_error']+f['relative_print_z_error']
values={
'PCB_peg_min_diametral_clearance_mm':2.7-f['pcb_hole_diameter_error']-c['peg_diameter']-f['printed_fit_diameter_error'],
'maximum_bearing_radial_eccentricity_mm':eccentricity,
'fixed_print_to_rotor_xy_budget_mm':print_xy,
'PCB_to_rotor_xy_budget_mm':pcb_xy,
'PCB_maximum_in_plane_play_mm':pcb_play,
'bezel_to_rotor_remaining_radial_clearance_mm':.8-print_xy,
'optical_fork_remaining_radial_clearance_mm':radial_slot,
'optical_slot_remaining_vertical_beam_margin_mm':.9-.1-.15-f['pcb_thickness_error']-f['relative_print_z_error']-f['moving_z_check'],
'screen_glass_remaining_axial_clearance_mm':p['display']['glass_relief_mm']-.1-f['relative_print_z_error'],
'foam_minimum_compression_mm':compression_min,
'foam_maximum_compression_percent':100*compression_max/foam_max,
'foam_nominal_compression_percent':100*(c['uncompressed_pad_height']-c['compressed_pad_height']+c['adhesive_thickness'])/c['uncompressed_pad_height'],
'USB_plug_to_rotor_min_vertical_clearance_mm':p['knob_bottom_z']-f['moving_z_hardware_check']-p['usb_access']['axis_z']-p['usb_access']['plug_height_mm']/2,
}
for key,value in values.items():assert value>0,(key,value)
assert values['foam_maximum_compression_percent']<60,'Engineering compression criterion, not a supplier operating rating'
assert print_xy<=f['moving_xy_print_check']+1e-8
assert pcb_xy<=f['moving_xy_pcb_check']+1e-8
assert abs(f['moving_z_print_check']-f['bearing_width_error']-f['relative_print_z_error'])<1e-8
assert abs(f['moving_z_hardware_check']-f['bearing_width_error']-f['pcb_thickness_error']-f['relative_print_z_error'])<1e-8
return {'basis':'Catalogue boundaries plus explicitly accepted engineering approximations; calibrated print target, not measured process capability.','assumptions':f,'results':{k:round(v,4) for k,v in values.items()},'all_running_margins_positive':True,'push_fit':{'nominal_stem_clearance_mm':inner,'nominal_pocket_clearance_mm':outer,'diameter_uncertainty_mm':diameter_error,'calibration_required':True,'physical_retention_verified':False},'physical_tests':'Not performed; first-build checks remain documented in validation/BRINGUP.md.'}
