//
// 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.
+// 2. <deleted>
//
// 3. use "make" to generate the necessary files:
//
// make -j8 fairphone-case.auto.scads `for f in \
-// HingePrint \
-// LidWindowPrint \
+// HingeLeverPrint \
// LidPrint \
// OneKeeperPrint \
// Case \
// 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. After placing the parts in the appropirate
+// relative placement:
//
-// 5. Assemble the hinge. You will need 4x M2 12mm machine screws
-// and 8x M2 full nuts.
+// Use long bit of wire to ensure holes are lined up and proper
+// Cut four short bits of wire, using above as a guage
//
-// 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.
+// Push two short bits into two holes on same side
+// Use long bit of wire to ensure properly in holes
+// Keep that side up so they don't fall out!
//
-// 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.
+// For each of the two holes
+// Use 20-30cm hunk of 2.85mm PLA
+// Use gas flame to melt end until it catches fire (!)
+// Remove from flame, wave to extinguish, and quickly:
+// Dab end onto where hole is
+// As it congeals, use sidecutters to cut off by hole
//
-// When you have the stiffness right, tighten the locknuts onto
-// each first nut.
+// Repeat for two holes on other side
+// When cool, file down rough edges
//
// 6. In use:
//
// 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.
//
// AUTHORSHIP, COPYRIGHT, LICENCE, AND LACK OF WARRANTY
//
-// Copyright (C)2018 Ian Jackson.
+// Copyright (C) 2018-2022 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
include <utils.scad>
include <funcs.scad>
-phone = [ 75.0, 145.0 ];
+phone = [ 75.86, 162.0 ];
prop_buildout_less = 3;
enable_support = 1;
-led_window_style = 3;
+led_window_style = 0;
// 0: no window
// 1: simply an opening
// 2: opening with separate cover model, for printing in clear (two colour)
initial_layer_width = 0.750; // ^ needed for mode 3 only
multicolour_gap = 0.15; // each side
-phone_cnr_rad = 6.0;
-phone_rim_depth = 0.80; // includes allowance for a screen protector
+phone_cnr_rad = 7.0; // actuall 8.mumble, but smaller is fine
+phone_rim_depth = 0.01; // includes allowance for a screen protector
button_cutout_depth = 9;
-phone_edge_thick = 9.0;
-phone_total_thick = 12.0;
-phone_backside_slope_inner = 1.5; // larger means shallower
-phone_backside_slope_outer = 1.0; // larger means shallower
+phone_edge_thick = 11.25;
-camera_pos_tl = [ 6.450, 12.750 ]; // measured from tl corner
-camera_pos_br = [ 22.300, 37.600 ]; // tl/br as seen from back
+camera_pos_tl = [ 5.600, 5.750 ]; // from tl corner (as seen from back)
+camera_edge_rad = 9.750 + 0.700;
+camera_sz = 32.920 + .750 + 1.000;
+// this is disabled, FP4 doesn't have one
jack_pos = [ 13.83, 8.485 ];
jack_dia = 10.64 + .5; // some jack I had lying around
-led_pos = [ 13.98, 10.00 ];
+// this led stuff, is irrelevant, we have disabled it as it doesn't have one
+led_pos = []; // [ 13.98, 10.00 ];
led_aperture = 9;
led_window_ledge = 0.75; // each side
-noisecancelmic_pos = [ 19.54, 7.37 ]; // from rhs
+noisecancelmic_pos = [ 15.08 + .720, 4.35 ]; // from rhs, from top edge
noisecancelmic_dia = 4.00;
-//fingerpushhole_dias = [ 15, 18 ];
+mainmic_pos = [ 21.0, 4.65 ]; // from lhs, from top edge
+mainmic_dia = 4.00;
+
+lhshole_pos = [ phone[1]/2 + 0.40, 4.35 ];
+
fingerpushhole_dias = [];
+//fingerpushhole_dias = [ 15, 18 ]; // this is for testing
lanyard_half_dia = 1.15;
lanyard_entry_rel_breadth = 2;
-lanyard_channel_len = 15;
-rearspeaker_pos_bl = [ 12.64, 18.72 ];
-rearspeaker_size = [ 3.76, 7.36 ];
+lanyard_channel_len = 8;
+//rearspeaker_pos_bl = [ 12.64, 18.72 ];
+//rearspeaker_size = [ 3.76, 7.36 ];
+
+bottomspeaker_size = [ 11.35, 1.90 ] + [1,1] * 0.5;
+bottomspeaker_pos = [ 17.55, 5.17 ]; // from rhs, from top
-microusb_above = 3.27 - 0.25;
-microusb_below = 0.0;
-microusb_width = 16.12 + 1.25;
+microusb_above = 1.64 - 0.25;
+microusb_below = 2.42;
+microusb_width = 12.16 + 2.0 + 1.25;
case_th_bottom = 2.5;
case_th_lid = 3.0;
-case_th_side = 2.3;
+case_th_side = 2.6;
case_th_lip = 1.2;
lid_screen_gap_extra = .66;
keeper_gap_z_bot = 0.75;
keeper_gap_x = 0.25;
keeper_gap_x_holes = 0.75;
+keeper_fatter = 0.45;
+keeper_fatter_hole = 1.20;
+keeper_stubbier = 0.0;
keeper_side = 0; // 0 = lhs; 1 = rhs
lid_lip = 1.75;
lid_edgepart_width = 5.0;
lid_buttoncover_thick = 1.3;
-lid_buttoncover_reinf = 0.65;
+lid_buttoncover_reinf = 0.95;
foldover_gap = 0.50;
foldover_lever_gap = 0.50;
// properties of the hinge fasteners
-hingescrew_shaft_dia = 2.0 + 0.25; // M2 x 12mm machine screw
-hingescrew_shaft_len = 12;
+hingescrew_shaft_dia = 1.600 + 0.45; // beading wire
+hingescrew_shaft_len = 10;
hingescrew_fasteners_extra_thick = 0.40;
// ^ amount of thread protruding if everything was completely nominal
// and we are using two nuts
hinge_x_postscrew_gap = 0.75;
hinge_x_arms_gap = 0.35;
hinge_r_arms_gap = 0.55;
+hinge_over_nut_plate = -0.50; // bodge apropos slope
-rearspeaker_gap = [ 2.0, 2.0 ]; // each side
+// there isn't one of these, speaker is by hinge
+// rearspeaker_gap = [ 2.0, 2.0 ]; // each side
thumbrecess_depth = 1.3;
thumbrecess_width = 16.5;
$button_leg_only = false;
$suppress_forward_holes = false;
+$suppress_hinge = false;
// ---------- calculated ----------
+phone_total_thick = phone_edge_thick;
+
phone_width = (phone + bumper*2)[0];
phone_height = (phone + bumper*2)[1];
lid_buttoncover_gap = lid_gap_x;
lid_buttoncover_overlap = case_th_lip + keeper_gap_z_top;
-phone_backside_slope_thick = phone_total_thick - phone_edge_thick;
-
//prop_lidrecess_depth = case_th_lid - prop_recess_under;
//prop_nose_len = case_th_lid - prop_recess_under;
//prop_recess_width = prop_main_th / cos(prop_max_angle) + prop_backfwd_gap;
-//lid_lip_overlap_width xxx bad name = ;
-//lid_lip_inner_slope = [ 5, 5 ]; // xxx
-
epp0 = [0,0];
epp1 = [0, -phone_edge_thick];
-epp2i = epp1 + phone_backside_slope_thick * [ phone_backside_slope_inner, -1 ];
-epp2o = epp1 + phone_backside_slope_thick * [ phone_backside_slope_outer, -1 ];
+epp2i = epp1; // conflated for FP4
+epp2o = epp2i;
epp3 = epp2i + [10, 0];
epp5 = epp0 + [0,1] * (keeper_th_z + keeper_gap_z_top + case_lip);
epp4 = epp5 + [-1,0] * case_th_side;
+ hingescrew_fasteners_extra_thick);
hex26 = hex23 + hingescrew_nut_thick * 2/3;
-echo(hex20, hex21, hex22, hex23, hex24);
-// 6, 10.8725, 10.9975, 13.74, 18.75
-module chk(act,exp) {
- if (abs(act-exp) > 1e-9) echo("WRONG", act, exp);
- else echo("ok", act);
-}
-chk(hex20, 6);
-chk(hex21, 10.8725);
-chk(hex22, 10.9975);
-chk(hex23, 13.74);
-chk(hex24, 18.75);
+//echo(hex20, hex21, hex22, hex23, hex24);
+//// 6, 10.8725, 10.9975, 13.74, 18.75
+//module chk(act,exp) {
+// if (abs(act-exp) > 1e-9) echo("WRONG", act, exp);
+// else echo("ok", act);
+//}
+//chk(hex20, 6);
+//chk(hex21, 10.8725);
+//chk(hex22, 10.9975);
+//chk(hex23, 13.74);
+//chk(hex24, 18.75);
lid_fold_clearance_skew =
(lpp10[1] - hppB[1]) /
ly_r = lanyard_half_dia / 2;
ly_rc = ly_r * 2;
-ly_theta = -atan2vector(epp2i - epp1);
-ly_o = epp2i + 3 * ly_r * unitvector2d(epp1 - epp2i);
+ly_theta = 90;
+ly_o = epp2i + 3 * ly_r * [0,1];
max_case_bottom_edge_thickness =
- case_th_bottom
- + sin(ly_theta) * (epp2i-epp2o)[0];
+ case_th_bottom;
ly_q_z = -(ly_rc + ly_r);
ly_re = max_case_bottom_edge_thickness - (-ly_q_z);
}
}
-module KeeperProfile(slant=0){
+module KeeperProfile(fatter=0, slant=0, stubbier=0){
use_e = kppe + [0,-1] * slant * keeper_inner_width / keeper_slant_slope;
- polygon([use_e, kppd, kppc, kppb, kppa, kppf]);
+ polygon([use_e + [+1,-1] * fatter,
+ kppd + [ 0,-1] * fatter - stubbier * [1,0],
+ kppc - stubbier * [1,0],
+ kppb,
+ kppa + stubbier * [0,1],
+ kppf + [+1, 0] * fatter + stubbier * [0,1]
+ ]);
}
module EdgeProfile(){
}
polygon([ epp5 + [0,10],
epp1,
- epp2i,
epp3 + [10,0] ]);
}
}
[phone_width, -phone_height] + [-1,+1] * phone_cnr_rad);
}
-module CaseAperture(pos, dia, $fn) {
+module CaseAperture(pos, dia, $fn, topbottom=0) {
theta = 180/$fn;
- translate([ pos[0] + bumper[0],
+ translate([ bumper[0],
-epp2i[0],
- -pos[1] ])
+ 0 ])
+ rotate([0,0, 90*topbottom])
+ translate([ pos[0] * (topbottom>0 ? -1 : +1), 0, -pos[1] ])
rotate([-90, theta, 0])
cylinder(r = dia/2 / cos(theta),
h = 60);
}
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, 1) children(); // volume
- Flip_rhs( ) LidButtonishLeg(14, -1) children();
-// Flip_rhs(0) LidButtonishLeg(20, +1, 20) children();
+ Flip_rhs(1) SideButton(30.320, +1, 22.960 ) children(); // volume
+ Flip_rhs(1) SideButton(64.220, +1, 14.500 ) children(); // power
+ Flip_rhs(1) LidButtonishLeg(14, -1) children();
+ Flip_rhs(0) LidButtonishLeg(21, -1) children();
+ Flip_rhs(0) LidButtonishLeg(38, +1) children();
+ Flip_rhs(0) LidButtonishLeg(14, +1) children();
}
module Struts(x_start, z_min, th){
children();
}
-module MicroUSB(){
+module MicroUSBEtc(){
Flip_bot(1){
rotate([90,0,0])
mirror([0,0,1])
}
}
+module OrdinaryBottomEdgeApertures(){
+ Flip_bot(1)
+ CaseAperture(mainmic_pos, mainmic_dia, 8);
+
+ Flip_bot(1) Flip_rhs(1) {
+ linextr_y_xz(-epp2i[0], 60)
+ hull()
+ for (x= [-1,+1]) {
+ translate([ -bottomspeaker_pos[0], -bottomspeaker_pos[1] ] +
+ [ 0.5 * x * bottomspeaker_size[0] - bottomspeaker_size[1],
+ 0 ])
+ rotate(360/16)
+ circle(r = bottomspeaker_size[1], $fn = 8);
+ }
+ }
+}
+
module OrdinaryRearApertures(){
// rear speaker
- OrdinaryRearAperture(1,1, rearspeaker_pos_bl)
- rectfromto(-rearspeaker_gap,
- rearspeaker_size + rearspeaker_gap);
+ // OrdinaryRearAperture(1,1, rearspeaker_pos_bl)
+ // rectfromto(-rearspeaker_gap,
+ // rearspeaker_size + rearspeaker_gap);
+}
+module NotInTestFrameRearApertures(){
// finger hole to remove phone
if (len(fingerpushhole_dias))
- OrdinaryRearAperture(1,0, [ fingerpushhole_dias[0]/2 + epp2i[0],
+ OrdinaryRearAperture(0,0, [ fingerpushhole_dias[0] + epp2i[0],
phone[1]/2 ])
scale(fingerpushhole_dias)
circle(r= 0.5 );
module RearCameraAperture(){
Flip_rhs(1)
mirror([0, 0, 1])
+ translate([0,0,0])
+ hull() // there is some kind of bug if hull() is done in 2D here!
linear_extrude(height = 20)
mirror([0, 1, 0])
translate(bumper)
- rectfromto(camera_pos_tl, camera_pos_br);
+ translate(camera_pos_tl)
+ for (xy = [ [0,0], [0,1], [1,0] ]) {
+ translate(
+ camera_edge_rad * [1,1] +
+ xy * (camera_sz - camera_edge_rad * 2)
+ )
+ circle(r = camera_edge_rad);
+ }
}
module HingeLidProfile(){
circleat(epp2o, case_th_bottom);
circleat(hppB + [10,0], hp_r1);
}
- polygon([epp5, epp1, epp2i, epp3, bppL]);
+ polygon([epp5, epp1, epp3, bppL]);
}
}
for (s = [-1,+1]) {
c = s > 0 ? hppT : hppB;
translate(c)
- mirror([0,0,s>0])
+ mirror([0,0, s>0 ? 1 : 0])
rotate(s<0 ? -40 : 0)
hull()
for (x=[-20,20])
Flip_rhs(1-keeper_side) intersection(){
rotate([90, 0, 0])
linear_extrude(height = phone_height + phone_cnr_rad * 2)
- KeeperProfile(1);
+ KeeperProfile(fatter=0, slant=1);
// outline of the whole case, to stop it protruding
translate([0,0, -25])
}
// hinge
- HingePortion(hex20, hex21) HingeBaseProfile();
+ if (!$suppress_hinge)
+ HingePortion(hex20, hex21) HingeBaseProfile();
// buildout for prop recess
if (prop_caserecess_buildout_r > 0) Flip_rhs(1)
rotate([90, 0, 0])
linear_extrude(height = phone_height + phone_cnr_rad * 2)
minkowski(){
- KeeperProfile();
+ KeeperProfile(fatter=keeper_fatter_hole);
rectfromto([ -keeper_gap_x, -keeper_gap_z_bot ],
[ keeper_gap_x_holes, +keeper_gap_z_top ]);
}
// apertures along top edge
if (!$suppress_forward_holes) {
- CaseAperture(jack_pos, jack_dia, 8);
+ // CaseAperture(jack_pos, jack_dia, 8);
Flip_rhs(1)
CaseAperture(noisecancelmic_pos, noisecancelmic_dia, 8);
}
+ CaseAperture(lhshole_pos, noisecancelmic_dia, 8, 1);
+
+ OrdinaryBottomEdgeApertures();
OrdinaryRearApertures();
+ NotInTestFrameRearApertures();
- MicroUSB();
+ MicroUSBEtc();
// gaps for the lid's hinge arms
- HingePortion(hex20 - hinge_x_arms_gap,
- hex21 + hinge_x_arms_gap)
- minkowski(){
+ if (!$suppress_hinge) {
+ HingePortion(hex20 - hinge_x_arms_gap,
+ hex21 + hinge_x_arms_gap)
+ minkowski(){
HingeLidProfile();
circle(r= hinge_r_arms_gap, $fn= 8);
}
- // screw holes in the hinge arms
- HingeScrews();
+ // screw holes in the hinge arms
+ HingeScrews();
+ }
// thumb recess
ThumbRecessApply(epp4[1])
HingeLeverOuterProfile();
// space for the screws
- HingePortion(hex26, hex24)
- HingeLeverInnerProfile();
+// HingePortion(hex26, hex24)
+// HingeLeverInnerProfile();
// recesses for the nuts
- HingePortion(hex23, hex26+1)
- HingeLeverNutProfile();
+// HingePortion(hex23, hex26+1)
+// HingeLeverNutProfile();
// bores for the screws
HingeScrews();
- // space for the charging cable
- MicroUSB();
- Flip_hinge() MicroUSB();
+ // space for the charging cable and speaker and micc apertures
+ hull() {
+ for (x = [-1,+1]) {
+ multmatrix([[ 1,0,
+
+ x
+ * ( (hex24 + hinge_over_nut_plate) -
+ (phone_width/2 - microusb_width/2)
+ )
+ / ( (epp0[1] - microusb_above)
+ -
+ (hppB[1] - hp_r2) ),
+
+ x * (epp0[1] - microusb_above)
+
+ ],
+ [ 0,1,0, 0 ],
+ [ 0,0,1, 0 ]]) {
+ union(){
+ MicroUSBEtc();
+ Flip_hinge() MicroUSBEtc();
+ }
+ }
+ }
+ }
}
}
translate([0, -phone_cnr_rad, 0])
rotate([90, 0, 0])
linear_extrude(height = phone_height - phone_cnr_rad * 2)
- KeeperProfile();
+ KeeperProfile(fatter=keeper_fatter, stubbier=keeper_stubbier);
}
module OneKeeperPrint(){ ////toplevel
linear_extrude(height=200)
rectfromto(include, inside_br - include);
}
+
+ for (i= [1,2]) {
+ translate([ 0, -phone[1] * i/3, 0 ])
+ cube(center=true, [1000, 4, 100]);
+ }
}
module TestSelectLidFrame(){
TestSelectFrame();
- translate([led_pos[0], -led_pos[1], -50])
+ if (len(led_pos))
+ translate([led_pos[0], -led_pos[1], -50])
cylinder(r= nla_r2+3, h=100);
}
}
module DemoFrame(){ ////toplevel
- color("red") TestFrameCase();
- color("blue") intersection(){ Lid(); TestSelectLidFrame(); }
- color("black") HingeScrews();
- %HingeLever();
+ color("red") render() TestFrameCase();
+ color("blue") render() intersection(){ Lid(); TestSelectLidFrame(); }
+ color("black") render() HingeScrews();
+ %render() HingeLever();
}
module DemoLanyardCutout(){ ////toplevel
}
module DemoHingedFrame(){ ///toplevel
- color("red") TestFrameCase();
+ color("red") render() TestFrameCase();
translate([0,0, -2*hp_k])
- color("blue") intersection(){ Lid(); TestSelectLidFrame(); }
+ color("blue") render() intersection(){ Lid(); TestSelectLidFrame(); }
Flip_hinge(){
- color("orange") HingeLever();
- color("black") HingeScrews();
+ color("orange") render() HingeLever();
+ color("black") render() HingeScrews();
}
}