display-frame.scad (8465B)
1 // Adafruit display and Raspberry Pi Zero wall frame 2 // This consists of 2 parts, the back which mounts to the wall with screws, 3 // holds the Raspberry Pi Zero, and the Adafruit 7" touchscreen display. And 4 // the front bezel/frame which clips into the back. 5 // 6 // Copyright 2023 by Brian C. Lane <bcl@brianlane.com> 7 // All Rights Reserved 8 // 9 // Redistribution and use in source and binary forms, with or without 10 // modification, are permitted provided that the following conditions are met: 11 // 12 // * Redistributions of source code must retain the above copyright notice, 13 // this list of conditions and the following disclaimer. 14 // 15 // * Redistributions in binary form must reproduce the above copyright notice, 16 // this list of conditions and the following disclaimer in the documentation 17 // and/or other materials provided with the distribution. 18 // 19 // * Neither the name of the <ORGANIZATION> nor the names of its contributors 20 // may be used to endorse or promote products derived from this software 21 // without specific prior written permission. 22 // 23 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 24 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 25 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 26 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 27 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 29 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 30 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 31 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 32 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 // 34 // If you have any questions about this license please email bcl@brianlane.com 35 $fn = 30; 36 37 // Adafruit 7" touchscreen display with HDMI and USB connectors 38 displayWidth = 85.5; 39 displayHeight = 154; 40 mountRadius = 2.8/2; 41 corner = [19, 5*mountRadius, 0]; 42 43 44 module display(h=2) { 45 cube([displayWidth, displayHeight, h]); 46 } 47 48 // A latch, place it so the tip slightly overlaps the board to hold it in place 49 // Note that if it is too short and wide it will not flex 50 module latch(r=[0,0,0], h=11) { 51 rotate(r) difference() { 52 union() { 53 cube([4, 2, h]); 54 translate([2, 1, h-4.5]) cylinder(h = 4, r1=1, r2=4); 55 translate([2, 1, h-0.5]) cylinder(h = 1, r1=4, r2=3); 56 } 57 translate([-2, -4, 0]) cube([8, 4, h+4]); 58 translate([-2, -1, 0]) cube([2, 6, h+4]); 59 translate([4, -1, 0]) cube([2, 6, h+4]); 60 } 61 } 62 63 // A smaller latch for the rPi zero 64 module pi_latch_pin(r=[0, 0, 0]) { 65 pin_r = 2.8/2; 66 cylinder(r=pin_r, h=5); 67 cylinder(r=pin_r*1.5, h=3); 68 translate([1, 5.5, 0]) scale([0.5, 0.5, 1]) latch(r=[0, 0, 180], h=7); 69 } 70 71 // rPi zero board with mounting holes 72 module pi_zero() { 73 holes = [[3.5, 3.5], [61.5, 3.5], [3.5, 26.5], [61.5, 26.5]]; 74 r = 2.8/2; 75 difference() { 76 cube([65, 30, 2]); 77 for(pos = holes) { 78 translate([pos[0], pos[1], 0]) cylinder(r=r, h=2); 79 } 80 } 81 } 82 83 // Mounting plate for rPi zero 84 module pi_mount() { 85 mounts = [[3.5, 3.5, 90], [61.5, 3.5, -90], [3.5, 26.5, 90], [61.5, 26.5, -90]]; 86 r = 2.8/2; 87 cube([65+11+11, 30+4+4, 2]); 88 89 for(pos=mounts) { 90 translate([11+pos[0], 4+pos[1], 2]) rotate([0, 0, pos[2]]) pi_latch_pin(); 91 } 92 } 93 94 // Hanger 95 module hanger_hole(depth=2) { 96 cylinder(r=9/2, h=depth); 97 translate([0, 4+5, 0]) cylinder(r=4.5/2, h=depth); 98 translate([-4.5/2, 4, 0]) cube([4.5, 5, depth]); 99 } 100 101 // Single hanger slot on a plate 102 module hanger(width=15, height=20, depth=2) { 103 difference() { 104 cube([width, height, depth]); 105 translate([width/2, (height-15.75+9)/2, 0]) hanger_hole(); 106 } 107 } 108 109 // 2 hanger slots, 90 degrees opposed, common center hole 110 module dual_hanger(base=[20, 20, 2], center=[0, 0, 0], r=[0, 0, 90]) { 111 difference() { 112 cube(base); 113 translate(center+[0, -15.75+9, 0]) { 114 hanger_hole(); 115 rotate(r) hanger_hole(); 116 } 117 } 118 } 119 120 // Diagnostic to help measure between two points and check alignment 121 module measure(p1=[0, 0, 0], p2=[10, 0, 0], r=1, h=1) { 122 #hull() { 123 translate(p1) cylinder(r=r, h=h); 124 translate(p2) cylinder(r=r, h=h); 125 } 126 } 127 128 // A plate with a slot for the front to clip into 129 module latch_plate() { 130 difference() { 131 cube([2, 20, 7]); 132 translate([0, 7, 5]) rotate([-90, 0, 0]) cylinder(r=1, h=6); 133 } 134 } 135 136 module front_latch() { 137 cube([2, 20, 30]); 138 translate([0, 7, 3]) rotate([-90, 0, 0]) cylinder(r=1, h=6); 139 } 140 141 module back_frame1() { 142 143 // Corner pads 144 cube([20, 20, 2]); 145 translate([124-20, 0, 0]) cube([20, 20, 2]); 146 translate([0, 185-35, 0]) cube([20, 20, 2]); 147 translate([124-20, 185-35, 0]) cube([20, 20, 2]); 148 149 // Mounting posts and latches 150 translate(corner+[-9, 0, 0]) cylinder(r=mountRadius, h=26); 151 translate(corner+[-9, 0, 0]) cylinder(r=mountRadius*1.5, h=24); 152 translate(corner+[-10, 0, 2]) cube([2, 6, 8]); 153 translate(corner+[-7, 7, 0]) latch(r=[0, 0, 180], h=28); 154 155 translate(corner+[displayWidth+14, 0, 0]) cylinder(r=mountRadius, h=26); 156 translate(corner+[displayWidth+14, 0, 0]) cylinder(r=mountRadius*1.5, h=24); 157 translate(corner+[displayWidth+14-1, 0, 2]) cube([2, 6, 8]); 158 translate(corner+[displayWidth+16, 7, 0]) latch(r=[0, 0, 180], h=28); 159 160 translate(corner+[-9, 155+1.4, 0]) cylinder(r=mountRadius, h=26); 161 translate(corner+[-9, 155+1.4, 0]) cylinder(r=mountRadius*1.5, h=24); 162 translate(corner+[-10, 155+1.4-6, 2]) cube([2, 6, 8]); 163 translate(corner+[-11, 155+1.4-7, 0]) latch(r=[0, 0, 0], h=28); 164 165 translate(corner+[displayWidth+14, 155+1.4, 0]) cylinder(r=mountRadius, h=26); 166 translate(corner+[displayWidth+14, 155+1.4, 0]) cylinder(r=mountRadius*1.5, h=24); 167 translate(corner+[displayWidth+12+1, 155+1.4-6, 2]) cube([2, 6, 8]); 168 translate(corner+[displayWidth+12, 155+1.4-7, 0]) latch(r=[0, 0, 0], h=28); 169 170 // Diagnostic of the rPi Zero board and mounting holes 171 // translate(corner+[20, 58, 5]) #pi_zero(); 172 173 // rPi Zero mount with holes punched in it 174 difference() { 175 union() { 176 translate(corner+[9, 54, 0]) pi_mount(); 177 translate([10, corner[1]+54, 0]) cube([18, 38, 2]); 178 } 179 translate([20, 80, -0.5]) cylinder(r=15, h=3); 180 translate([60, 80, -0.5]) cylinder(r=15, h=3); 181 translate([85, 80, -0.5]) cylinder(r=15, h=3); 182 } 183 184 // Join the pieces with a frame 185 translate([0, 15, 0]) cube([10, 140, 2]); 186 translate([124-10, 15, 0]) cube([10, 140, 2]); 187 translate([114, 0, 0]) rotate([0, 0, 90]) cube([10, 100, 2]); 188 translate([114, 160, 0]) rotate([0, 0, 90]) cube([10, 100, 2]); 189 190 // Latch plate for front to clip into 191 translate([6, 70, 2]) latch_plate(); 192 translate([3, 70, 2]) cube([1, 20, 10]); 193 translate([124-6, 70, 2]) mirror([1, 0, 0]) latch_plate(); 194 translate([124-4, 70, 2]) cube([1, 20, 10]); 195 196 // Hangers 197 translate([16, 140, 0]) hanger(); 198 translate([92, 140, 0]) dual_hanger(base=[23, 25, 2], center=[8, 14.5, 0], r=[0, 0, -90]); 199 translate([93, 32, 0]) rotate([0, 0, -90]) hanger(height=21); 200 } 201 202 module ell() { 203 cube([10, 1.0, 12]); 204 cube([1.0, 10, 12]); 205 } 206 207 module front_frame() { 208 union() { 209 difference() { 210 translate([0, corner[1]-20, 0]) cube([124, displayHeight+40, 2]); 211 translate(corner-[0, 0, 1]) display(4); 212 } 213 214 translate([6, 70, -29]) mirror([1, 0, 0]) front_latch(); 215 translate([124-6, 70, -29]) front_latch(); 216 217 // Corner registration on display mounting tabs 218 translate(corner+[-9-5.5, -5.5, -12]) ell(); 219 translate(corner+[displayWidth+14-6.5+12, -5.5, -12]) mirror([1, 0, 0]) ell(); 220 translate(corner+[-9-5.5, 155+1.4+5.5, -12]) mirror([0, 1, 0]) ell(); 221 translate(corner+[displayWidth+14-6.5+12, 155+1.4+5.5, -12]) mirror([1, 1, 0]) ell(); 222 } 223 } 224 225 226 // Comment out one or the other before exporting to STL 227 translate([0, 0, -33.5]) #back_frame1(); 228 front_frame();