Pip-Boy inspired phone holder built around the PINE64 PinePhone
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

304 rader
10 KiB

  1. links_count=6; // [1..20]
  2. include_terminal=true; // [true,false]
  3. export=5; // [0:5]
  4. MODEL_DEMO=0;
  5. MODEL_LINKS=1;
  6. MODEL_CLIP=2;
  7. MODEL_CLIP_RATCHETING=3;
  8. MODEL_CLIP_RATCHETING_A=4;
  9. MODEL_CLIP_RATCHETING_B=5;
  10. //validation=1;
  11. VALIDATE_INTERSECTION=1;
  12. //xray=1;
  13. use <BOSL/transforms.scad>
  14. use <BOSL/shapes.scad>
  15. include <BOSL/constants.scad>
  16. function is_not_export() = is_undef(export) || export == 0;
  17. function is_export() = !is_not_export();
  18. function is_model_strict(m) = is_export() && export == m;
  19. function is_model(m) = is_not_export() || export == m;
  20. function get_link_segment_size() = [15, 30, 5];
  21. function get_link_pin_diameter() = 2;
  22. function get_link_socket_slack() = [1, 4, 1];
  23. function get_link_joiner_arm_size() = [get_link_segment_size().x - 2, 3, segment_size.z];
  24. function get_link_socket_size() = [get_link_segment_size().z,
  25. get_link_segment_size().y - get_link_joiner_arm_size().y*2,
  26. get_link_segment_size().z];
  27. function get_link_clip_size() = [get_link_pin_diameter()*5, get_link_segment_size().y - 5, get_link_segment_size().z];
  28. echo("===============================");
  29. echo(str("Strap length: ", (links_count * get_link_segment_size().x), " mm"));
  30. echo("===============================");
  31. assert(get_link_segment_size().x >= 10, "Link segment is too short.");
  32. assert(get_link_segment_size().z >= (get_link_pin_diameter() + get_link_socket_slack().z + 1), "Link segment is too thin.");
  33. module link(terminal=false) {
  34. segment_size=get_link_segment_size();
  35. module pin() {
  36. h=segment_size.y;
  37. d=get_link_pin_diameter();
  38. back(h/2) xrot(90) cylinder(h=h, d=d, $fn=$preview ? 10 : 30);
  39. }
  40. module pin_socket_area() {
  41. h=segment_size.y-get_link_socket_slack().y;
  42. d=segment_size.z;
  43. back(h/2) xrot(90) cylinder(h=h, d=d, $fn=$preview ? 10 : 30);
  44. }
  45. module pin_socket() {
  46. difference() {
  47. pin_socket_area();
  48. scaleup = [
  49. ((get_link_pin_diameter() + get_link_socket_slack().x) / get_link_pin_diameter()),
  50. ((get_link_pin_diameter() + get_link_socket_slack().y) / get_link_pin_diameter()),
  51. ((get_link_pin_diameter() + get_link_socket_slack().z) / get_link_pin_diameter())
  52. ];
  53. scale(scaleup) pin();
  54. }
  55. }
  56. module joiner() {
  57. gap=2;
  58. arm_size=get_link_joiner_arm_size();
  59. module arm() {
  60. fwd(segment_size.y/2 + arm_size.y/2 - 1) right(arm_size.x/2 - 1) cuboid(arm_size, fillet=1, edges=EDGES_FRONT + EDGES_Y_ALL);
  61. }
  62. module armFront() {
  63. arm();
  64. }
  65. module armBack() {
  66. scale([1, -1, 1]) arm();
  67. }
  68. module armJoiner() {
  69. joiner_size=[arm_size.x-get_link_socket_size().x, segment_size.y, segment_size.z];
  70. right(joiner_size.x/2 + get_link_socket_size().x/2 + gap) cuboid(joiner_size, fillet=1, edges=EDGES_Z_ALL + EDGES_BOTTOM);
  71. }
  72. module socketJoiner() {
  73. joiner_size=[segment_size.x-get_link_socket_size().x+get_link_socket_size().x*0.2,
  74. segment_size.y-4,
  75. segment_size.z];
  76. difference() {
  77. right(joiner_size.x/2 + 4.5) cuboid(joiner_size, fillet=1, edges=EDGES_Z_ALL + EDGES_BOTTOM);
  78. right(segment_size.x) scale([1, 2, 1]) pin_socket_area();
  79. }
  80. }
  81. module terminalArm() {
  82. left(5) {
  83. shift=arm_size.x - get_link_pin_diameter();
  84. right(segment_size.x + shift + gap/2) pin();
  85. right(segment_size.x + gap/2) {
  86. armFront();
  87. armBack();
  88. }
  89. right(arm_size.x - get_link_socket_size().x + gap) armJoiner();
  90. }
  91. }
  92. armFront();
  93. armBack();
  94. armJoiner();
  95. if (terminal) {
  96. terminalArm();
  97. } else {
  98. socketJoiner();
  99. }
  100. }
  101. pin();
  102. joiner();
  103. if (!terminal) {
  104. right(segment_size.x) pin_socket();
  105. }
  106. }
  107. module clip() {
  108. socket_size=get_link_socket_size();
  109. clip_size=get_link_clip_size();
  110. pin_diam=get_link_pin_diameter();
  111. slot_slack=get_link_socket_slack();
  112. size=[clip_size.x+socket_size.x, clip_size.y, clip_size.z];
  113. slot_size=[clip_size.x+slot_slack.x, size.y+1, pin_diam+slot_slack.z];
  114. entry_size=[slot_size.x-5, clip_size.y+1, clip_size.z];
  115. right(clip_size.x/2)
  116. difference() {
  117. cuboid(size, fillet=1);
  118. cuboid(slot_size, fillet=1);
  119. up(entry_size.z/2) cube(entry_size, center=true);
  120. }
  121. }
  122. module clip_ratcheting(ratchet_length=20) {
  123. socket_size=get_link_socket_size();
  124. clip_size=get_link_clip_size();
  125. pin_diam=get_link_pin_diameter();
  126. slot_slack=get_link_socket_slack();
  127. size=[clip_size.x+socket_size.x, clip_size.y, clip_size.z];
  128. slot_size=[clip_size.x+slot_slack.x + 0.2, size.y+1, pin_diam+slot_slack.z];
  129. entry_size=[slot_size.x-5, clip_size.y+1, clip_size.z];
  130. //right(clip_size.x/2)
  131. module hook() {
  132. intersection() {
  133. difference() {
  134. cuboid(size, fillet=1);
  135. cuboid(slot_size, fillet=1);
  136. up(entry_size.z/2) cube(entry_size, center=true);
  137. }
  138. translate([0, -50, -50]) cube([100, 100, 100]);
  139. }
  140. }
  141. module hookRight() {
  142. hook();
  143. }
  144. module hookLeft() {
  145. scale([-1, 1, 1]) hook();
  146. }
  147. wall=2;
  148. tooth_size=[2, 3, 3];
  149. module tooth() {
  150. s=[tooth_size.x, tooth_size.z, tooth_size.y];
  151. up(tooth_size.z/2) xrot(-90) right_triangle(s);
  152. }
  153. module teethFwd() {
  154. tooth_count = ratchet_length/tooth_size.x;
  155. fwd((clip_size.y-wall*2)/2)
  156. right(ratchet_length/2) {
  157. for (i=[1:tooth_count]) {
  158. left(i*tooth_size.x) tooth();
  159. }
  160. cap_size=[ratchet_length, tooth_size.y, 1];
  161. up(tooth_size.z/2 + cap_size.z/2) left(cap_size.x/2) back(tooth_size.y/2) {
  162. difference() {
  163. cube(cap_size, center=true);
  164. translate([0.1, 0.1, 0]) back(tooth_size.y/2) right(ratchet_length/2) zrot(180) tooth();
  165. }
  166. }
  167. }
  168. }
  169. module teethBack() {
  170. scale([1, -1, 1]) teethFwd();
  171. }
  172. module ratchetLeft() {
  173. right(ratchet_length/2) {
  174. difference() {
  175. cube([ratchet_length, clip_size.y, clip_size.z], center=true);
  176. up(wall/2) cube([ratchet_length, clip_size.y-wall*2, clip_size.z], center=true);
  177. right(ratchet_length/2+1) {
  178. slideRailGuide(groove=true);
  179. scale([1,-1,1]) slideRailGuide(groove=true);
  180. }
  181. }
  182. teethFwd();
  183. teethBack();
  184. }
  185. }
  186. ratchet_tooth_count=3;
  187. ratchet_wall=3;
  188. ratchet_slack=0.3;
  189. rail_slack=0.2;
  190. module ratchetTeethFront() {
  191. module ratchetButton() {
  192. size=[8,wall*4,4];
  193. up(size.z+1) fwd(wall*2 - ratchet_wall) cuboid(size, fillet=1, edges=EDGES_FRONT);
  194. up(2) back(ratchet_wall/2) cube([size.x, ratchet_wall, tooth_size.z + size.z], center=true);
  195. }
  196. fwd((clip_size.y-wall*2)/2 - tooth_size.y - ratchet_slack)
  197. left(ratchet_length) {
  198. for (i=[0:ratchet_tooth_count-1]) {
  199. right(i*tooth_size.x) scale([-1,-1,0.8]) tooth();
  200. }
  201. ratchetButton();
  202. }
  203. module ratchetWall() {
  204. up(tooth_size.z/2) left(ratchet_length/2 + wall - wall/2) fwd(clip_size.y/2-wall-tooth_size.y-ratchet_wall/2 - ratchet_slack)
  205. down(wall/2+0.5) cube([ratchet_length + wall, ratchet_wall, tooth_size.z], center=true);
  206. }
  207. ratchetWall();
  208. }
  209. module ratchetTeethBack() {
  210. scale([1,-1,1]) ratchetTeethFront();
  211. }
  212. module ratchetRight() {
  213. left(wall) cube([wall*2, clip_size.y + rail_slack*2, clip_size.z], center=true);
  214. ratchetTeethFront();
  215. ratchetTeethBack();
  216. }
  217. module slideRailGuide(groove) {
  218. size=[ratchet_length, wall, wall];
  219. fwd(clip_size.y/2 + rail_slack)
  220. left(size.x/2) scale(groove?1.5:1) cuboid(size, fillet=0.5);
  221. }
  222. module slideRailLeft() {
  223. size=[ratchet_length, clip_size.y/2 - ratchet_wall*2 - wall - ratchet_slack - tooth_size.y, clip_size.z];
  224. right(size.x/2) cube(size, center=true);
  225. }
  226. module slideRailRight() {
  227. size=[ratchet_length + 3, wall*1.5, clip_size.z];
  228. module railFront() {
  229. fwd(clip_size.y/2 + size.y/2 + rail_slack) left(size.x/2)
  230. cuboid(size, fillet=1, edges=EDGES_FRONT);
  231. slideRailGuide(groove=false);
  232. }
  233. module railBack() {
  234. scale([1, -1, 1]) railFront();
  235. }
  236. railFront();
  237. railBack();
  238. }
  239. if (is_model(MODEL_CLIP_RATCHETING_A) || is_model(MODEL_CLIP_RATCHETING)) {
  240. left(ratchet_length + wall + 1) {
  241. hookLeft();
  242. left(0.1) {
  243. ratchetLeft();
  244. slideRailLeft();
  245. }
  246. }
  247. }
  248. if (is_model(MODEL_CLIP_RATCHETING_B) || is_model(MODEL_CLIP_RATCHETING)) {
  249. ratchetRight();
  250. hookRight();
  251. slideRailRight();
  252. }
  253. }
  254. // Export / Demo / Validation:
  255. segment_size=get_link_segment_size();
  256. if (!is_undef(validation)) {
  257. if (validation==VALIDATE_INTERSECTION) {
  258. intersection() {
  259. right(0*segment_size.x) link();
  260. right(1*segment_size.x) link();
  261. }
  262. intersection() {
  263. right(1*segment_size.x) link();
  264. right(2*segment_size.x) link();
  265. }
  266. }
  267. } else {
  268. intersection () {
  269. if (!is_undef(xray)) {
  270. down(50) cube([100, 100, 100], center=true);
  271. }
  272. union() {
  273. if (is_model(MODEL_CLIP)) {
  274. left(get_link_clip_size().x) clip();
  275. }
  276. if (is_model(MODEL_CLIP_RATCHETING) || is_model(MODEL_CLIP_RATCHETING_A) || is_model(MODEL_CLIP_RATCHETING_B)) {
  277. left(get_link_clip_size().x) clip_ratcheting();
  278. }
  279. if (is_model(MODEL_LINKS)) for (i = [0:links_count-1]) {
  280. terminal=(i==links_count-1) && include_terminal;
  281. right(i*segment_size.x) link(terminal=terminal);
  282. }
  283. }
  284. }
  285. }