// Housing for the handheld particulate sensor. Includes mockups of all the // contents, but note this is just for rough fit. // Set do_build=1 to build. Uncomment whatever should be built on the // bottom. // By Nenad Rijavec // Feel free to use, modify and share as you see fit. module nut_m3( thickness=2.8 ) { linear_extrude( thickness ) circle( 3.6, $fn=6 ) ; } do_build = 0 ; // 9V battery mockup module mockup_9V_battery() { translate( [ 1.5, 1.5, 0 ] ) minkowski() { cube( [ 23.5, 14.5, 46.5 ] ) ; cylinder( 2.5, d=3.0, $fn=40 ) ; } translate( [ 6.9, 8.75, 48.4 ] ) cylinder( 3.8, d = 5.5, $fn = 50 ) ; translate( [ 19.6, 8.75, 48.4 ] ) cylinder( 3.8, d = 9.0, $fn = 6 ) ; } // Plantower PMS1003 sensor mockup module mockup_pms1003() { difference() { union() { cube( [ 64.99, 42.43, 19.8 ] ) ; cube( [ 30.00, 42.43, 22.8 ] ) ; } union() { // cable cavity translate( [ 30.01, 30, 13 ] ) cube( [ 18, 50, 50 ] ) ; // air exhaust translate( [ 10, -1, 14.6 ] ) cube( [ 11, 15, 5.3 ] ) ; // air intake fan opening translate( [ 17, 43, 2+9.4 ] ) rotate( [ 90, 0, 0 ] ) cylinder( 30, d = 18.8, $fn=50 ) ; // screw holes translate( [ -1.425, -1.425, 4 ] ) cylinder( 23, d = 11.0, $fn = 50 ) ; translate( [ 1.425, 1.425, -1 ] ) cylinder( 23, d = 2.2, $fn = 50 ) ; translate( [ 64.99+1.425, 42.43+1.425, 4 ] ) cylinder( 23, d = 11.0, $fn = 50 ) ; translate( [ 64.99-1.425, 42.43-1.425, -1 ] ) cylinder( 23, d = 2.2, $fn = 50 ) ; } } } // 1.8" TFT Display mockup module mockup_display() { // mounting PCB difference() { translate( [ 1.5, 1.5, 0.1 ] ) minkowski() { cube( [ 54, 33, 1 ] ) ; cylinder( 0.1, d = 3, $fn = 50 ) ; } union() { translate( [ 1.5, 1.5, -1 ] ) cylinder( 5, d=2, $fn=30 ) ; translate( [ 55.5, 1.5, -1 ] ) cylinder( 5, d=2, $fn=30 ) ; translate( [ 1.5, 28.5, -1 ] ) cylinder( 5, d=2, $fn=30 ) ; translate( [ 55.5, 28.5, -1 ] ) cylinder( 5, d=2, $fn=30 ) ; } } // screen translate( [ 5.5, 0, 1.2 ] ) cube( [ 46, 36, 3 ] ) ; // plugged in connector, plus a little for wire bending. translate( [ 0.5, 2.3, -24 ] ) cube( [2, 25.4, 24.1 ] ) ; } // Arduino PCB mockup, with arduino and connectors plugged in module mockup_controller() { // PCB base, little extra for wires below cube( [ 60, 40, 4 ] ) ; // Nano board, plugged in, little extra on top for components translate( [ 5, -2, 3.9 ] ) cube( [ 18, 45, 16. ] ) ; // Nano verical 2x3 connector translate( [ 5+9-1.5*2.54, -2, 20.0 ] ) cube( [ 2*2.54, 3*2.54, 10 ] ) ; // Nano USB socket translate( [ 5+9-4, -2+45-8, 20.0 ] ) cube( [ 8, 10, 4 ] ) ; // display and sensor connectors, plugged in // extra space for cables translate( [ 30, 0, 3.9 ] ) cube( [ 20, 40, 25.0 ] ) ; } // switch mockup module mockup_switch() { // body and space for the actual switch on top cube( [ 20, 13, 33.0 ] ) ; // mounting lip translate( [ -1, -1, 27 ] ) cube( [ 22, 15, 2 ] ) ; } housing_x = 109 ; housing_y = 48 ; housing_z = 67 ; h_bottom_z = 42 ; offset_x = -13 ; offset_y = -4 ; offset_z = -4 ; h_top_z = housing_z - h_bottom_z ; h_minkowski_r = 1.5 ; wall_t = 2 ; pcb_base_t = 8.0 ; // housing half - either top or bottom box module housing_half( z, have_posts ) { difference() { intersection() { translate( [ h_minkowski_r, h_minkowski_r, h_minkowski_r ] ) minkowski() { cube( [ housing_x-h_minkowski_r, housing_y-h_minkowski_r, z-h_minkowski_r+5 ] ) ; sphere( h_minkowski_r, $fn = 30 ) ; } translate( [ -5, -5, -5 ] ) cube( [ housing_x+10, //housing_y/2+5, housing_y+10, z+6 ] ) ; } union() { if ( have_posts ) { translate( [ housing_x-wall_t-0.5 , 0.75+housing_y/2,-1 ]) cylinder( z+10, d=3.5, $fn=32 ) ; translate( [ wall_t+2.4 , 0.75+housing_y/2,-1 ]) cylinder( z+10, d=3.5, $fn=32 ) ; } translate( [ h_minkowski_r + wall_t, h_minkowski_r + wall_t, h_minkowski_r + wall_t ] ) minkowski() { cube( [ housing_x-2*wall_t-h_minkowski_r, housing_y-2*wall_t-h_minkowski_r, z ] ) ; sphere( h_minkowski_r, $fn = 30 ) ; } } } if ( have_posts ) { translate( [ housing_x-wall_t-0.5 , 0.75+housing_y/2, wall_t-0.1 ] ) difference() { cylinder( z-wall_t+0.1, d=6.5, $fn=32 ) ; translate( [ 0, 0, -1 ] ) cylinder( z, d=3.5, $fn=32 ) ; } translate( [ wall_t+2.4 , 0.75+housing_y/2, wall_t-0.1 ] ) difference() { cylinder( z-wall_t+0.1, d=6.5, $fn=32 ) ; translate( [ 0, 0, -1 ] ) cylinder( z, d=3.5, $fn=32 ) ; } } height = have_posts ? 25 : 20 ; translate( [ housing_x - 30.5, 0.75* wall_t, 0.75* wall_t ] ) cube( [ wall_t, housing_y - 0.5*wall_t, height ] ) ; } module housing_bottom( ) { difference() { union() { housing_half( h_bottom_z, true ) ; // PCB supports translate( [ wall_t-0.1, wall_t-0.1, wall_t-0.1 ] ) cube( [ 10.5, housing_y/2-wall_t-6.1, 26-wall_t-offset_z ] ) ; translate( [ wall_t-0.1, housing_y/2+7.5, wall_t-0.1 ] ) cube( [ 10.5, housing_y/2-wall_t-6.1, 26-wall_t-offset_z ] ) ; // sensor supports translate( [ wall_t+4.5, wall_t-0.1, wall_t-0.1 ] ) cube( [ 10.5, housing_y-wall_t, 3 ] ) ; translate( [ housing_x-41, wall_t-0.1, wall_t-0.1 ] ) cube( [ 10.5, housing_y-wall_t, 3 ] ) ; } union() { // screw head indentations translate( [ housing_x-wall_t-0.5, 0.75+housing_y/2,-1 ]) cylinder( 4, d=6, $fn=50 ) ; translate( [ wall_t+2.4 , 0.75+housing_y/2,-1 ]) cylinder( 4, d=6, $fn=50 ) ; // air exhaust fan opening translate( [ 17.1-offset_x, 48.5-offset_y, 13.5-offset_z ] ) rotate( [ 90, 0, 0 ] ) cylinder( 32, d = 21.0, $fn=50 ) ; // air intake translate( [ 10-offset_x, -1, 16.6-offset_z ] ) cube( [ 11, 15, 5.3 ] ) ; } } } module housing_top( ) { difference() { union() { housing_half( h_top_z, false ) ; // thicker screw posts to contain the nut slot // posts taper to the bottom translate( [ housing_x-wall_t-0.5, 0.75+housing_y/2, 13 ]) cylinder( 10, d=8, $fn=50 ) ; translate( [ housing_x-wall_t-0.5, 0.75+housing_y/2, wall_t-1]) hull() { cylinder( 12, d1=1, d2=8, $fn=50 ) ; translate( [ 2.5, 0, 0 ] ) cube( [ 1, 1, 12 ] ) ; } translate( [ wall_t+2.4 , 0.75+housing_y/2, 13 ]) cylinder( 10, d=8, $fn=50 ) ; translate( [ wall_t+2.4, 0.75+housing_y/2, wall_t-1]) hull() { cylinder( 12, d1=1, d2=8, $fn=50 ) ; translate( [ -2.5, 0, 0 ] ) cube( [ 1, 1, 12 ] ) ; } } union() { translate( [ housing_x-wall_t-0.5, 0.75+housing_y/2, 16 ]) nut_m3( 3.5 ) ; translate( [ housing_x-wall_t-2.5, 0.75+housing_y/2, 16 ]) nut_m3( 3.5 ) ; translate( [ wall_t+2.4 , 0.75+housing_y/2, 16 ]) nut_m3( 3.5 ) ; translate( [ wall_t+4.4 , 0.75+housing_y/2, 16 ]) nut_m3( 3.5 ) ; // screw holes through thicker posts translate( [ housing_x-wall_t-0.5, 0.75+housing_y/2, wall_t+6 ]) cylinder( h_top_z, d=3.5, $fn=50 ) ; translate( [ wall_t+2.4 , 0.75+housing_y/2, wall_t+6 ]) cylinder( h_top_z, d=3.5, $fn=50 ) ; // LCD opening translate( [ 3.0-offset_x, 2.5-offset_y, -1 ] ) cube( [ 47.5, 37, wall_t+5 ] ) ; // switch opening translate( [ 70.5-offset_x, -offset_y, -1 ] ) cube( [ 21, 14, wall_t+5 ] ) ; // USB port opening translate( [ 4.5-offset_x, -1, 7.5-offset_z ] ) cube( [ 9, wall_t+5, 5 ] ) ; } } // LCD spacer since PCB contacts stick out translate( [ -3.0-offset_x, 1.5-offset_y, wall_t-0.1 ] ) cube( [ 6, 39, 2.1 ] ) ; translate( [ 50.5-offset_x, 1.5-offset_y, wall_t-0.1 ] ) cube( [ 9, 5, 2.1 ] ) ; translate( [ 50.5-offset_x, 36-offset_y, wall_t-0.1 ] ) cube( [ 9, 5, 2.1 ] ) ; } module pcb_base() { width = housing_y- 2 * wall_t - 2 ; difference() { union() { cube( [ 10.5, housing_y/2-wall_t-6.9, pcb_base_t ] ) ; translate( [ 0, housing_y/2+5.3, 0 ] ) cube( [ 10.5, housing_y/2-wall_t-6.9, pcb_base_t ] ) ; translate( [ 55, 0, 0 ] ) cube( [ 23, width, pcb_base_t ] ) ; } union() { translate( [ 3.5, 8, -1 ] ) cylinder( pcb_base_t+2, d=3, $fn=50 ) ; translate( [ 3.5, 8+housing_y/2+5.3, -1 ] ) cylinder( pcb_base_t+2, d=3, $fn=50 ) ; } } translate( [ 6, 0, 0 ] ) cube( [ 4.5, width, pcb_base_t ] ) ; translate( [ 10, width/2-10, 0 ] ) cube( [ 50, 20, pcb_base_t-4 ] ) ; } module pcb_shim() { cube( [ 10,housing_y- 2 * wall_t - 2, 3 ] ) ; } // it jams into walls and bends to hold the display module display_strut() { cube( [ 10, housing_y - 2 * wall_t, 2 ] ) ; } if ( !do_build ) { color( "green" ) { translate( [ 88, 0, 5 ] ) rotate( [ 0, 0, 90 ] ) mockup_9V_battery() ; translate( [ 0, 0, 2 ] ) mockup_pms1003() ; translate( [ 55, 38, 60 ] ) rotate( [0, 0, 180] ) mockup_display() ; translate( [ -5, 0, 28 ] ) mockup_controller() ; translate( [ 68, 29, 37 ] ) mockup_switch() ; } // comment the intersection out to see the whole device // change the intersecting box size and location to see different parts of // the device intersection() { union() { translate( [ offset_x, offset_y, offset_z ] ) housing_bottom() ; translate( [ wall_t+0.5+offset_x, wall_t+0.5+offset_y, 29+offset_z ] ) pcb_base() ; translate( [ offset_x, offset_y+1.5+housing_y,-3+h_bottom_z+h_top_z ]) rotate( [ 180, 0, 0 ] ) housing_top() ; } translate( [ -15, -5, -5 ] ) cube( [ housing_x - 20, housing_y-7, housing_z + 10 ] ) ; } } else { // uncomment whatever should be built //display_strut() ; //pcb_shim() ; //pcb_base() ; housing_bottom() ; //housing_top() ; }