2022-06-01 08:29:44 +02:00
|
|
|
/*************************************************************************
|
|
|
|
* Hülle für die u23-Spielekonsole. *
|
|
|
|
* Rückseite. *
|
|
|
|
* *
|
|
|
|
* Author: Shy *
|
|
|
|
* License: CC0 *
|
|
|
|
*************************************************************************/
|
|
|
|
|
2024-01-22 11:40:28 +01:00
|
|
|
include <lib/colors.scad>;
|
|
|
|
include <lib/edge.scad>;
|
2022-06-01 08:29:44 +02:00
|
|
|
|
|
|
|
/* Höhe wichtiger Bauteile:
|
|
|
|
*
|
|
|
|
* NRF-Modul:
|
|
|
|
* H: ~ 15 mm
|
|
|
|
*
|
|
|
|
* USB Port:
|
|
|
|
* GCT USB4105-GF-A
|
|
|
|
* H: 3.31 mm
|
|
|
|
* B: 8.94 mm / 9.58 mm
|
|
|
|
* L: 7.53 mm
|
|
|
|
*
|
|
|
|
* Klinkennuchse:
|
|
|
|
* CUI SJ1-3523N
|
|
|
|
* H: 6 mm
|
|
|
|
* B: 12 mm
|
|
|
|
* L: 14 mm
|
|
|
|
*
|
|
|
|
* RJ-45 Buchse:
|
|
|
|
* RJMG1BD3B8K1ANR
|
|
|
|
* H: 13.35 mm
|
|
|
|
* B: 15.75 mm
|
|
|
|
* L: 21.72 mm
|
|
|
|
*
|
|
|
|
* Vibrationsmotor:
|
|
|
|
* Jinlong Z4KC1B1051202
|
|
|
|
* H: 4.5 mm
|
|
|
|
* B: 4.6 mm
|
|
|
|
* L: 15.6 mm
|
|
|
|
*
|
|
|
|
* CF-Kartenadapter:
|
|
|
|
* Hirose DM3AT-SF-PEJM5
|
|
|
|
* H: 1.6 mm
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Default slim (Schrauben: M3, 16mm).
|
|
|
|
*
|
|
|
|
* space = 8;
|
|
|
|
* border_height = 4;
|
|
|
|
* nut_sink = 6;
|
|
|
|
* side_recess = 0;
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* Default full (Schrauben: M3, 25mm).
|
|
|
|
*
|
|
|
|
* space = 15;
|
|
|
|
* border_height = 8;
|
|
|
|
* nut_sink = 4;
|
|
|
|
* side_recess = 4;
|
|
|
|
*/
|
|
|
|
|
2024-01-18 13:20:00 +01:00
|
|
|
// Abgerundete Außenkanten.
|
2024-01-19 20:17:44 +01:00
|
|
|
rounded_edges = false;
|
2024-01-10 01:09:39 +01:00
|
|
|
|
2024-01-18 13:20:00 +01:00
|
|
|
// Abgeschrägte Außenkanten.
|
2024-01-19 20:17:44 +01:00
|
|
|
beveled_edges = true;
|
2024-01-18 13:20:00 +01:00
|
|
|
|
2024-01-10 01:09:39 +01:00
|
|
|
// Strukturen zur Stützung der Buttons auf der Vorderseite.
|
|
|
|
button_support = true;
|
|
|
|
|
|
|
|
// Strukturen zur Stützung der Analog Sticks.
|
|
|
|
stick_support = true;
|
|
|
|
|
2024-01-21 15:20:10 +01:00
|
|
|
// Öffnung über dem I²C-Anschluss.
|
2024-01-11 19:59:07 +01:00
|
|
|
i2c_port = true;
|
|
|
|
|
2024-01-21 15:20:10 +01:00
|
|
|
// Gewindeeinsatz statt Mutter.
|
2024-01-10 01:09:39 +01:00
|
|
|
threaded_insert = false;
|
2022-06-01 08:29:44 +02:00
|
|
|
|
|
|
|
// Dicke der Decke.
|
2023-12-19 15:20:12 +01:00
|
|
|
top = 1;
|
2022-06-01 08:29:44 +02:00
|
|
|
|
|
|
|
// Höhe des Innenraumes.
|
|
|
|
space = 8;
|
|
|
|
|
2024-01-10 01:09:39 +01:00
|
|
|
// Höhe des Randes. (Empfehlung: space/2.)
|
2022-06-01 08:29:44 +02:00
|
|
|
border_height = 4;
|
|
|
|
|
2024-01-10 01:09:39 +01:00
|
|
|
// Aussparungen über den Befestigungslöchern an den Seiten.
|
|
|
|
side_recess = 0;
|
|
|
|
|
2022-06-01 08:29:44 +02:00
|
|
|
// Höhe der Verstrebungen.
|
|
|
|
struts = 2;
|
|
|
|
|
|
|
|
// Dicke der Aufhängungen an der Vorderkante.
|
2023-12-19 15:20:12 +01:00
|
|
|
loop_strength = 3.5;
|
2022-06-01 08:29:44 +02:00
|
|
|
|
|
|
|
// Durchmesser der Bohrungen.
|
|
|
|
drill = 3.4;
|
|
|
|
|
|
|
|
// Durchmesser der Bohrschäfte.
|
|
|
|
drill_shaft = 7.4;
|
|
|
|
|
|
|
|
// Tiefe der Versenkung für die Mutter.
|
|
|
|
nut_sink = 6.0;
|
|
|
|
|
|
|
|
// Schlüsselweite der Mutter (M3 = 5.5 + Spiel).
|
|
|
|
wrench_size = 5.8;
|
|
|
|
|
|
|
|
// Durchmesser der Mutter von Kante zu Kante.
|
|
|
|
nut_size = wrench_size * 2 / sqrt(3);
|
|
|
|
|
|
|
|
// Position der Bohrungen.
|
|
|
|
drill_pos = [
|
|
|
|
[10, 10],
|
|
|
|
[10, 90],
|
|
|
|
[140, 10],
|
|
|
|
[140, 90],
|
|
|
|
];
|
|
|
|
|
|
|
|
// Höhe, die der USB-Port benötigt.
|
|
|
|
limit_usb = 3.4;
|
|
|
|
|
|
|
|
// Höhe, die die Klinkenbuchse benötigt.
|
|
|
|
limit_audio_jack = 6.5;
|
|
|
|
|
|
|
|
// Soll ein nRF24-Modul verbaut werden?
|
|
|
|
nrf_module = false;
|
|
|
|
|
|
|
|
// Höhe, die das nRF24-Modul benötigt.
|
|
|
|
limit_nrf = 15;
|
|
|
|
|
|
|
|
// Höhe, die der Vibrationsmotor benötigt.
|
|
|
|
limit_vib = 7.5;
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************
|
|
|
|
* Überprüfe Parameter auf Fehler. *
|
|
|
|
*************************************************************************/
|
|
|
|
|
|
|
|
// Achte auf die Höhe ausgewählter Bauteile.
|
|
|
|
if ((space - border_height) < limit_usb) {
|
|
|
|
if ($preview) {
|
|
|
|
// Zeige den Platz, den der USB-Port braucht.
|
|
|
|
color(color_warning)
|
2023-12-19 15:20:12 +01:00
|
|
|
translate([40, 92.35, space + top - limit_usb])
|
2022-06-01 08:29:44 +02:00
|
|
|
cube([9, 8, limit_usb]);
|
|
|
|
} else {
|
|
|
|
assert((space - border_height) >= limit_usb,
|
|
|
|
"USB-Port hat zu wenig Platz!");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (nrf_module && (space < limit_nrf)) {
|
|
|
|
if ($preview) {
|
|
|
|
// Zeige den Platz, den das nRF24-Modul braucht.
|
|
|
|
color(color_warning)
|
2023-12-19 15:20:12 +01:00
|
|
|
translate([101.25, 81.75, top])
|
2022-06-01 08:29:44 +02:00
|
|
|
cube([29.5, 15.75, limit_nrf]);
|
|
|
|
} else {
|
|
|
|
assert(space >= limit_nrf,
|
|
|
|
"nRF24-Modul hat zu wenig Platz!");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************
|
|
|
|
* Einzelteile *
|
|
|
|
*************************************************************************/
|
|
|
|
|
|
|
|
// Schaft für die Schrauben.
|
|
|
|
module screw_shaft() {
|
2023-12-19 15:20:12 +01:00
|
|
|
translate([0, 0, top])
|
2022-06-01 08:29:44 +02:00
|
|
|
cylinder(h = space, r = drill_shaft/2, $fn=32);
|
|
|
|
// Verdickung, um die Versenkung zu kompensieren.
|
|
|
|
if(nut_sink > 0 && !threaded_insert) {
|
2023-12-19 15:20:12 +01:00
|
|
|
translate([0, 0, top])
|
2022-06-01 08:29:44 +02:00
|
|
|
cylinder(h = nut_sink, r = (nut_size + drill_shaft - drill)/2, $fn=32);
|
|
|
|
intersection() {
|
2023-12-19 15:20:12 +01:00
|
|
|
translate([0, 0, top + nut_sink])
|
2022-06-01 08:29:44 +02:00
|
|
|
cylinder((nut_size + drill_shaft - drill)/2, (nut_size + drill_shaft - drill)/2, 0, $fn=32);
|
|
|
|
// Begrenzt die Höhe.
|
2023-12-19 15:20:12 +01:00
|
|
|
cylinder(r = (nut_size + drill_shaft - drill)/2, h = top + space, $fn=32);
|
2022-06-01 08:29:44 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Bohrung für die Schrauben.
|
|
|
|
module screw_drill() {
|
2023-12-19 15:20:12 +01:00
|
|
|
cylinder(h=space + top, r=drill/2, $fn=24);
|
2022-06-01 08:29:44 +02:00
|
|
|
// Versenkung für die Mutter.
|
|
|
|
if(nut_sink > 0 && !threaded_insert) {
|
|
|
|
cylinder(h=nut_sink, r=nut_size/2, $fn=6);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Ausschnittobjekt mit zweifach gerundeten Ecken.
|
|
|
|
// depth = Tiefe
|
|
|
|
// widht = Weite
|
|
|
|
// h1 = Höhe links oben
|
|
|
|
// h2 = Höhe rechts oben
|
|
|
|
// bevel = Größe der Rungungen
|
|
|
|
module cutout(depth=4, width=8, h1=2, h2=2, bevel=1) {
|
|
|
|
|
|
|
|
// Addiere 0.01 um im Vorschaumodus Artefakte zu reduzieren.
|
|
|
|
height = $preview ? max(h1, h2) + 0.01 : max(h1, h2);
|
|
|
|
assert (width >= bevel * 2);
|
|
|
|
$fn = 24;
|
|
|
|
|
|
|
|
rotate([90, 0, 0]) {
|
|
|
|
hull() {
|
|
|
|
translate([0, max(height * 0.75, bevel), 0])
|
|
|
|
cube([width, height/2, depth], center=true);
|
|
|
|
|
|
|
|
translate([-width/2 + bevel, bevel, 0])
|
|
|
|
cylinder(h=depth, r=bevel, center=true);
|
|
|
|
|
|
|
|
translate([width/2 - bevel, bevel, 0])
|
|
|
|
cylinder(h=depth, r=bevel, center=true);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Zeichne Rundung nach links außen, falls die Höhe ausreicht.
|
|
|
|
if (h1 >= bevel * 2) {
|
|
|
|
translate([-width/2 - bevel, h1 - bevel, 0])
|
|
|
|
// Linke Kante.
|
|
|
|
difference() {
|
|
|
|
translate([0, 0, -depth/2])
|
|
|
|
cube([bevel, bevel, depth]);
|
|
|
|
cylinder(h=depth, r=bevel, center=true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Zeichne Rundung nach rechts außen, falls die Höhe ausreicht.
|
|
|
|
if (h2 >= bevel * 2) {
|
|
|
|
translate([width/2 + bevel, h2 - bevel, 0])
|
|
|
|
difference() {
|
|
|
|
translate([-bevel, 0, -depth/2])
|
|
|
|
cube([bevel, bevel, depth]);
|
|
|
|
cylinder(h=depth, r=bevel, center=true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Aussparungen am Rand der Konsole.
|
|
|
|
module border_cutouts() {
|
|
|
|
// Aussparung an der Klinke-Buchse.
|
|
|
|
if (space - border_height < limit_audio_jack) {
|
|
|
|
diff = limit_audio_jack - (space - border_height);
|
|
|
|
|
|
|
|
translate([63, 91, border_height - diff])
|
|
|
|
cutout(depth=20, width=14, h1=diff, h2=diff);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Aussparung am Vibrationsmotor.
|
|
|
|
if (space - border_height < limit_vib) {
|
|
|
|
diff = limit_vib - (space - border_height);
|
|
|
|
|
2022-06-07 16:56:26 +02:00
|
|
|
// Größe und Position durch Versuch.
|
|
|
|
translate([119, 2 - 0.1 + 15.6/2, border_height - diff])
|
|
|
|
cutout(depth=36, width=4.6 + 3.4, h1=diff, h2=diff);
|
2022-06-01 08:29:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Aussparungen am Rand neben den seitlichen Befestigungslöchern.
|
|
|
|
if (side_recess > 0) {
|
|
|
|
// Die Aussparungen sollten nicht niedriger sein als die Verstrebungen.
|
|
|
|
recess = min(side_recess, border_height - struts);
|
|
|
|
|
|
|
|
// Aussparung auf der linken Seite.
|
|
|
|
translate([5, 67, border_height - recess])
|
|
|
|
rotate([0, 0, 90])
|
|
|
|
cutout(
|
|
|
|
depth=4,
|
|
|
|
width=20,
|
|
|
|
bevel=recess / 2,
|
|
|
|
h1=recess,
|
|
|
|
h2=recess);
|
|
|
|
|
|
|
|
// Aussparung auf der rechten Seite.
|
|
|
|
translate([150 - 5, 67, border_height - recess])
|
|
|
|
rotate([0, 0, 90])
|
|
|
|
cutout(
|
|
|
|
depth=4,
|
|
|
|
width=20,
|
|
|
|
bevel=recess / 2,
|
|
|
|
h1=recess,
|
|
|
|
h2=recess);
|
|
|
|
|
|
|
|
// Bei einer effektiven Höhe der Aussparungen > 2 schrägen wir eine
|
|
|
|
// Seite ab.
|
|
|
|
if (recess > 2) {
|
|
|
|
|
|
|
|
multmatrix([
|
|
|
|
[1, 0, 0, 0],
|
|
|
|
[0, 1, -1, border_height - recess ],
|
|
|
|
[0, 0, 1, 0]
|
|
|
|
]) {
|
|
|
|
|
|
|
|
// Linke Seite.
|
|
|
|
translate([5, 67, border_height - recess])
|
|
|
|
rotate([0, 0, 90])
|
|
|
|
cutout(
|
|
|
|
depth=4,
|
|
|
|
width=20,
|
|
|
|
bevel=recess / 2,
|
|
|
|
h1=recess,
|
|
|
|
h2=recess);
|
|
|
|
|
|
|
|
// Rechte Seite.
|
|
|
|
translate([150 - 5, 67, border_height - recess])
|
|
|
|
rotate([0, 0, 90])
|
|
|
|
cutout(
|
|
|
|
depth=4,
|
|
|
|
width=20,
|
|
|
|
bevel=recess / 2,
|
|
|
|
h1=recess,
|
|
|
|
h2=recess);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Die äußeren Teile: Front und Ränder.
|
|
|
|
module outer() {
|
|
|
|
// Decke.
|
|
|
|
color(color_top)
|
2023-12-19 15:20:12 +01:00
|
|
|
linear_extrude(height=top) {
|
2022-06-01 08:29:44 +02:00
|
|
|
import("./svg/back top.svg");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Rand.
|
2023-12-19 15:20:12 +01:00
|
|
|
translate([0, 0, top]) {
|
2022-06-01 08:29:44 +02:00
|
|
|
// Schneide Aussparungen aus dem Rand.
|
|
|
|
difference() {
|
|
|
|
union() {
|
|
|
|
// Oberer Rand.
|
|
|
|
color(color_border1)
|
|
|
|
linear_extrude(height = border_height) {
|
|
|
|
import("./svg/back borders.svg");
|
|
|
|
}
|
|
|
|
// Unterer Rand.
|
|
|
|
color(color_border2)
|
|
|
|
translate([0, 0, border_height]) {
|
|
|
|
linear_extrude(height=space-border_height) {
|
|
|
|
import("./svg/back borders lower.svg");
|
|
|
|
}
|
|
|
|
}
|
2024-01-21 11:21:59 +01:00
|
|
|
|
|
|
|
// Bei abgerundeten Ecken sehen schärfere Kanten neben dem
|
|
|
|
// RJ45-Stecker besser aus.
|
|
|
|
color(color_border1)
|
|
|
|
if (beveled_edges || rounded_edges) {
|
|
|
|
translate([67, 98, -top])
|
|
|
|
cube([2, 2, top+border_height]);
|
|
|
|
translate([93.25, 101, -top])
|
|
|
|
cube([1, 1, top+space]);
|
|
|
|
}
|
2022-06-01 08:29:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
render() border_cutouts();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Verstrebungen.
|
|
|
|
color(color_struts)
|
2023-12-19 15:20:12 +01:00
|
|
|
translate([0, 0, top]) {
|
2022-06-01 08:29:44 +02:00
|
|
|
linear_extrude(height=struts) {
|
|
|
|
import("./svg/back struts.svg");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Aufhängungen.
|
|
|
|
color(color_special)
|
|
|
|
translate([0, 0, 0]) {
|
2023-12-19 15:20:12 +01:00
|
|
|
linear_extrude(height=max(loop_strength, top)) {
|
2022-06-01 08:29:44 +02:00
|
|
|
import("./svg/back loops.svg");
|
|
|
|
}
|
|
|
|
}
|
2024-01-19 20:17:44 +01:00
|
|
|
|
|
|
|
// Stützen für die Buttons.
|
|
|
|
if (button_support) {
|
|
|
|
color(color_struts)
|
|
|
|
translate([0, 0, top]) {
|
|
|
|
linear_extrude(height=struts) {
|
|
|
|
import("./svg/back pillars struts.svg");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
color(color_special)
|
|
|
|
translate([0, 0, top]) {
|
|
|
|
linear_extrude(height=space) {
|
|
|
|
import("./svg/back pillars.svg");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-06-01 08:29:44 +02:00
|
|
|
|
|
|
|
// Stützen für die Analog sticks.
|
|
|
|
if (stick_support) {
|
|
|
|
color(color_struts)
|
2023-12-19 15:20:12 +01:00
|
|
|
translate([0, 0, top]) {
|
2022-06-01 08:29:44 +02:00
|
|
|
linear_extrude(height=struts) {
|
|
|
|
import("./svg/back sticks struts.svg");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
color(color_special)
|
2023-12-19 15:20:12 +01:00
|
|
|
translate([0, 0, top]) {
|
2022-06-01 08:29:44 +02:00
|
|
|
linear_extrude(height=space - 2) {
|
|
|
|
import("./svg/back sticks pillars.svg");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
color(color_special)
|
2023-12-19 15:20:12 +01:00
|
|
|
translate([0, 0, top + space - 2]) {
|
2022-06-01 08:29:44 +02:00
|
|
|
linear_extrude(height=2) {
|
|
|
|
import("./svg/back sticks pillars top.svg");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-01-20 08:50:59 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************
|
|
|
|
* Die Hülle. *
|
|
|
|
*************************************************************************/
|
|
|
|
|
|
|
|
module body_back() {
|
|
|
|
if (rounded_edges || beveled_edges) {
|
2024-01-21 15:20:10 +01:00
|
|
|
edge_modifier(beveled_edges, "./svg/back outline.svg") {
|
|
|
|
outer();
|
2024-01-20 08:50:59 +01:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
outer();
|
|
|
|
}
|
|
|
|
|
2022-06-01 08:29:44 +02:00
|
|
|
// Schäfte für die Bohrungen.
|
|
|
|
color(color_drills)
|
|
|
|
for (i = [0:3]) {
|
|
|
|
translate([drill_pos[i][0], drill_pos[i][1], 0])
|
|
|
|
screw_shaft();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-11 19:59:07 +01:00
|
|
|
// Bohrungen und andere Durchbrüche.
|
2022-06-01 08:29:44 +02:00
|
|
|
difference() {
|
|
|
|
body_back();
|
|
|
|
union() {
|
2024-01-11 19:59:07 +01:00
|
|
|
// Platzierung der Bohrungen.
|
2022-06-01 08:29:44 +02:00
|
|
|
// Bei einem Gewindeeinsatz wird die Decke nicht durchbohrt.
|
2023-12-19 15:20:12 +01:00
|
|
|
floor = threaded_insert ? top : 0;
|
2022-06-01 08:29:44 +02:00
|
|
|
for (i = [0:3]) {
|
|
|
|
translate([drill_pos[i][0], drill_pos[i][1], floor])
|
|
|
|
screw_drill();
|
|
|
|
}
|
2024-01-11 19:59:07 +01:00
|
|
|
|
|
|
|
// I2C-Anschluss.
|
|
|
|
if (i2c_port) {
|
|
|
|
translate([0, 0, -0.1])
|
|
|
|
linear_extrude(height=top + 0.2) {
|
|
|
|
import("./svg/back top i2c.svg");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-01 08:29:44 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|