// -*- C -*-
+// Hard case for Fairphone 2
+//
+// Copyright 2018 Ian Jackson. There is NO WARRANTY.
+// See below for full licensing and disclaimer.
+//
+// Instructions
+//
+// 1. You will want to git clone this repository.
+//
+// 2. Decide about the notification LED aperture. See the variable
+// led_window_style, below. The default here is "ad-hoc
+// multi-colour", which can produces a translucent (clear-ish)
+// window set into the lid, even on a single-nozzle printer.
+// See "Ad-hoc multi-colour", below.
+//
+// 3. use "make" to generate the necessary files:
+//
+// make -j8 fairphone-case.auto.scads `for f in \
+// HingePrint \
+// LidWindowPrint \
+// LidPrint \
+// OneKeeperPrint \
+// Case \
+// ; do echo fairphone-case,$f.auto.stl; done`
+//
+// 4. Print them. Case and OneKeeperPrint should probably be
+// the same colour.
+//
+// For Lid and LidWindowPrint, if you are doing ad-hoc
+// multi-colour:
+// i. Set up for clear filament
+// ii. Print LidWindowPrint. Wait for it to finish.
+// It won't take long. As soon as it finishes, tell
+// your printer to warm up (so that in fact it does
+// not cool down).
+// iii. Leaving the output so far on the printbed, reload
+// your printer with the main lid colour.
+// iv. Print LidPrint. You can let this go unattended.
+//
+// 5. Assemble the hinge. You will need 4x M2 12mm machine screws
+// and 8x M2 full nuts.
+//
+// Make sure you get the hinge the right way round. If you're not
+// sure, run
+// openscad fairphone-case,DemoHinge.auto.scad
+// to see an assembly diagram.
+//
+// The nuts recess into the hinge. You will want very fine
+// pliers. As you screw each screw in, add the second nut when
+// the screw thread emerges from the first - this will be a
+// locknut. Screw each screw to an appropriate tightness for the
+// hinge stiffness. You want the lid-side hinge to be stiffer as
+// that makes closing the case work better.
+//
+// When you have the stiffness right, tighten the locknuts onto
+// each first nut.
+//
+// 6. In use:
+//
+// - To put the phone in, drop its RH side into the RH side of
+// the case. Then feed the keeper through the small hole.
+// Feed it right through.
+//
+// - The optional prop can be used to prop the phone up (in
+// portrait orientation only right now). See
+// openscad fairphone-case,DemoPropAngles.auto.scad
+//
+// Ad-hoc multi-colour
+//
+// This file is set up to let you make a translucent window using a
+// single-extruder printer, using a "two print run" technique. This
+// works well with our Lulzbot TAZ 5 and Aleph Objects' version of
+// Cura. If you are using a different printer, you may need to
+// adjust the parameters or try a different technique. In particular,
+// initial_layer_thick
+// set so that the window is one layer thick
+// initial_layer_width
+// set so that the slicer draws a rectangle around the whole
+// object, rather than putting a "skirt" or anything inside
+//
+// If you have a dual-extruder printer, you can set led_window_style
+// to 2 and do a single print of LidPrint and LidWindowPrint.
+//
+// Alternatively you can set it to 1 (just a hole) or 0 (no hole).
+//
+// Thanks to Clare Boothby for the ad-hoc multi-colour technique (and
+// the parameters for our Lulzbot TAZ 5 and Aleph Objects's Cura).
+//
+// Other phones
+//
+// It might well be possible to adapt this file for other phones.
+// If you do, let me know how you get on.
+//
+//
+// AUTHORSHIP, COPYRIGHT, LICENCE, AND LACK OF WARRANTY
+//
+// Copyright (C)2018 Ian Jackson.
+//
+// This program for generating a 3D model is free software: you can
+// redistribute it and/or modify it under the terms of the GNU
+// General Public License as published by the Free Software
+// Foundation, either version 3 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public
+// License along with this program. If not, see
+// <http://www.gnu.org/licenses/>.
+//
+// In particular DO NOT BLAME ME IF THIS CASE DOES NOT ADEQUATELY
+// PROTECT YOUR PHONE ! It is your responsibility to decide whether
+// this case will meet your needs.
+
include <utils.scad>
phone = [ 75.0, 145.0 ];
jack_pos = [ 13.83, 8.485 ];
jack_dia = 10.64 + .5; // some jack I had lying around
-led_pos = [ 10.86, 8.58 ];
-led_aperture = 5;
+led_pos = [ 13.98, 10.00 ];
+led_aperture = 9;
led_window_ledge = 0.75; // each side
noisecancelmic_pos = [ 19.54, 7.37 ]; // from rhs
case_th_side = 2;
case_th_lip = 1.2;
+lid_screen_gap_extra = .66;
+
case_struts_count = 6;
case_struts_solid_below = 1.00;
case_struts_solid_above = 0.75;
// exact x posn not very important; must extend past end of keeper
lpp15 = [ lpp14[0],
- epp0[1] - phone_rim_depth + 1/2.5 * case_th_lid ];
+ epp0[1] - phone_rim_depth + 1/2.5 * case_th_lid
+ + lid_screen_gap_extra ];
// ^ beam theory says to maximise force before contact,
// the gap below the `beam' (the lid) must be 1/3
// the thickness (ie the lid thickness) if the beam
module AdhocMultiprintFrame(phase, z0, zs) {
// from z0 to z0 + zs*layer
- extra = phase * 0.65 + 5;
+ extra = phase * (initial_layer_width + multicolour_gap) + 5;
xextra = extra + -epp4[0];
xrange = [ 0, phone_width ] + [-1,+1] * xextra;
yextra = extra + -epp4[0];
module ButtonCoverProfile(){
intersection(){
polygon(concat([ bppM, bppP, bppO, bppJ ],
- (enable_support ? [ bppU, bppV, bppW ] : []),
+ (enable_support && !$button_suppress_over_keeper
+ ? [ bppU, bppV, bppW ] : []),
[ bppL, bppK ]));
hull(){
EdgeProfile();
h = 60);
}
-module SideButton(y, y_ref_sign, l){
+module SideButton(y, y_ref_sign, l, suppress_over_keeper=0){
// y_ref_sign:
// +1 measured from top of actual phone to top of button
// -1 measured from bottom of actual phone to bottom of button
// 0 y is centre of button in coordinate system
$button_l= l;
+ $button_suppress_over_keeper= suppress_over_keeper;
eff_y = y_ref_sign > 0 ? -bumper [1] -y -l/2 :
y_ref_sign < 0 ? (-phone -bumper)[1] +y +l/2 :
y;
}
module Buttons(){
- Flip_rhs(1) SideButton(15.580, +1, 8.9) children(); // power
- Flip_rhs(1) SideButton(48.700, -1, 8.920) children(); // camera
- Flip_rhs(0) SideButton(30.800, +1, 21.96) children(); // volume
+ Flip_rhs(1) SideButton(15.580, +1, 8.9 ) children(); // power
+ Flip_rhs(1) SideButton(48.700, -1, 8.920 ) children(); // camera
+ Flip_rhs(0) SideButton(30.800, +1, 21.96, 1) children(); // volume
Flip_rhs( ) LidButtonishLeg(14, -1) children();
// Flip_rhs(0) LidButtonishLeg(20, +1, 20) children();
}
translate([phone_width/2, -400, kppe[1]])
mirror([1-abs($rhsflip - keeper_side),0,0])
cube([400, 800, 50]);
- if (enable_support)
+ if (enable_support && !$button_suppress_over_keeper)
rotate([-90,90,0])
translate([-400, -400, kppd[1]])
mirror([0,0,1])
translate([led_pos[0], -led_pos[1], lpp13[1]])
mirror([0,0,1])
cylinder(r= nla_r1, h=nla_t);
- LidAdhocMultiprintFrame(0, lpp13[1], -1);
+ LidAdhocMultiprintFrame(0);
}
module LidWindowPrint(){ ////toplevel
module TestSelectLidFrame(){
TestSelectFrame();
translate([led_pos[0], -led_pos[1], -50])
- cylinder(r= nla_r2+2, h=100);
+ cylinder(r= nla_r2+3, h=100);
}
module TestFrameCase(){ ////toplevel
}
}
+module TestSelectTopApertures(){
+ translate([-100, -35, -100])
+ cube([400, 100, 200]);
+ LidAdhocMultiprintFrame(0);
+ LidAdhocMultiprintFrame(1);
+}
+
module TestTopApertures(){ ////toplevel
intersection(){
Case();
TestSelectFrame();
- translate([-100, -35, -100])
- cube([400, 100, 200]);
+ TestSelectTopApertures();
+ }
+}
+
+module TestLidTopAperturesPrint(){ ////toplevel
+ rotate([0,180,0]) intersection(){
+ Lid();
+ TestSelectLidFrame();
+ TestSelectTopApertures();
+ }
+}
+
+module TestLidWindowTopAperturesPrint(){ ////toplevel
+ rotate([0,180,0]) intersection(){
+ LidWindow();
+ TestSelectTopApertures();
}
}
DemoPropAngle(prop_angles[i]);
}
+module DemoSelectAdhocLeftRight(right=0) {
+ translate([phone_width/2, -400, -100]) // , -15, -100 to cross-section
+ mirror([1-right, 0,0])
+ cube([400, 800, 200]);
+}
+
+module DemoLeft(){ ////toplevel
+ color("red") intersection(){ Case(); DemoSelectAdhocLeftRight(); }
+ color("blue") intersection(){ Lid(); DemoSelectAdhocLeftRight(); }
+}
+
module DemoFrame(){ ////toplevel
color("red") TestFrameCase();
color("blue") intersection(){ Lid(); TestSelectLidFrame(); }