2022-06-01 08:29:44 +02:00
|
|
|
/*************************************************************************
|
|
|
|
* Hülle für die u23-Spielekonsole. *
|
|
|
|
* Vorderseite. *
|
|
|
|
* *
|
|
|
|
* Author: Shy *
|
|
|
|
* License: CC0 *
|
|
|
|
*************************************************************************/
|
|
|
|
|
|
|
|
include <colors.scad>;
|
|
|
|
|
|
|
|
/* Höhe wichtiger Bauteile:
|
|
|
|
*
|
|
|
|
* Display:
|
|
|
|
* Z320IT010
|
|
|
|
* L: 54 mm
|
|
|
|
* B: 77.4 mm
|
|
|
|
* H: 2.4 mm
|
|
|
|
* Davon LCD:
|
|
|
|
* L: 48.6 mm
|
|
|
|
* B: 64.8 mm, mit 3.35 mm Abstand zum rechten Rand
|
|
|
|
*
|
|
|
|
* Kurzhubtaster Pads:
|
|
|
|
* PTS645SL50-2 LFS
|
|
|
|
* H Taster: 5 mm
|
|
|
|
* H Gehäuse: 3.45 mm
|
|
|
|
* D Taster: 3.5 mm
|
|
|
|
*
|
|
|
|
* Kurzhubtaster unten:
|
|
|
|
* PTS645SK43SMTR92 LFS
|
|
|
|
* H Taster: 4.3 mm
|
|
|
|
* H Gehäuse: 4.3
|
|
|
|
* D Taster: 3.5 mm
|
|
|
|
*
|
|
|
|
* Schalter an der Schulter:
|
|
|
|
* D2FS-FL-N-A
|
|
|
|
* H: 5.8 mm
|
|
|
|
* B: 12.8 mm
|
|
|
|
*
|
|
|
|
* Analog Stick:
|
|
|
|
* Alps RKJXV1224005
|
|
|
|
* H Gehäuse: 10.8 mm
|
|
|
|
* H bis Gelenk: 12.46 mm
|
|
|
|
* L: 21.3 mm
|
|
|
|
* B: 17.8 mm
|
|
|
|
* Der Kern ist ein Quadrat mit 13.15 mm Kantenlänge.
|
|
|
|
* Anschlag 7 mm von der Platine.
|
|
|
|
*/
|
|
|
|
|
2024-01-18 13:20:00 +01:00
|
|
|
// Abgerundete Außenkanten.
|
2024-01-19 20:17:44 +01:00
|
|
|
rounded_edges = false;
|
2022-06-01 08:29:44 +02: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
|
|
|
|
2023-12-30 00:23:11 +01:00
|
|
|
// Aussparungen für den linken Analog-Stick.
|
|
|
|
analog_stick_l = true;
|
|
|
|
|
|
|
|
// Aussparungen für den rechten Analog-Stick.
|
2024-01-06 21:26:44 +01:00
|
|
|
analog_stick_r = false;
|
|
|
|
|
|
|
|
// LEDs am unteren Rand.
|
|
|
|
led_bottom = true;
|
|
|
|
|
|
|
|
// Y-LED.
|
|
|
|
led_y = true;
|
|
|
|
|
|
|
|
// LED-Pegel.
|
|
|
|
led_gauge = true;
|
|
|
|
|
|
|
|
// LED Logo.
|
|
|
|
led_logo = true;
|
|
|
|
|
2022-06-01 08:29:44 +02:00
|
|
|
// Dicke der Decke.
|
2023-12-19 15:20:12 +01:00
|
|
|
top = 1.0;
|
2022-06-01 08:29:44 +02:00
|
|
|
|
|
|
|
// Höhe des Innenraumes.
|
|
|
|
space = 7;
|
|
|
|
|
|
|
|
// Höhe des oberen Randes.
|
|
|
|
border_height = 4;
|
|
|
|
|
|
|
|
// Höhe der Verstrebungen.
|
|
|
|
struts = 2;
|
|
|
|
|
2023-12-29 21:08:12 +01:00
|
|
|
// Display (X, Y, Weite, Höhe).
|
|
|
|
display = [42.5, 24, 68.5, 52];
|
|
|
|
|
2022-06-01 08:29:44 +02:00
|
|
|
// Durchmesser der Bohrungen.
|
|
|
|
drill = 3.4;
|
|
|
|
|
|
|
|
// Durchmesser der Bohrschäfte.
|
|
|
|
drill_shaft = 7.4;
|
|
|
|
|
|
|
|
// Position der Bohrungen.
|
|
|
|
drill_pos = [
|
|
|
|
[10, 20],
|
|
|
|
[10, 100],
|
|
|
|
[140, 20],
|
|
|
|
[140, 100],
|
|
|
|
];
|
|
|
|
|
|
|
|
// Dicke der Basis der Aktionsbuttons.
|
|
|
|
button_action_base = 1;
|
|
|
|
|
|
|
|
// Dicke der Basis der Systembuttons.
|
|
|
|
button_system_base = 2;
|
|
|
|
|
|
|
|
// Tatsächliche Höhe der Taster unter den Aktionsbuttons.
|
|
|
|
button_action_size = 5;
|
|
|
|
|
|
|
|
// Tatsächliche Höhe der Taster unter den Systembuttons.
|
2022-06-04 18:09:37 +02:00
|
|
|
button_system_size = 4.5;
|
2022-06-01 08:29:44 +02:00
|
|
|
|
|
|
|
// Spiel der Buttons zwischen Taster und Decke.
|
|
|
|
button_clearance = 0.2;
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************
|
|
|
|
* Überprüfe Parameter auf Fehler. *
|
|
|
|
*************************************************************************/
|
|
|
|
|
|
|
|
//assert(space >= trigger_switch_height + button_trigger_base,
|
|
|
|
// "Die Höhe reicht nicht für die Schultertasten!");
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************
|
|
|
|
* Einzelteile *
|
|
|
|
*************************************************************************/
|
|
|
|
|
|
|
|
// Durchbrüche in der Front.
|
|
|
|
module top_cutouts() {
|
2023-12-29 21:08:12 +01:00
|
|
|
// Display.
|
|
|
|
// Berechne X/Y-Koordinaten vom linken oberen Rand der Platine.
|
|
|
|
translate([150 - display[2]/2 - display.x, 110 - display[3]/2 - display.y, (top + struts)/2])
|
|
|
|
minkowski() {
|
|
|
|
cube([display[2] - 2, display[3] - 2, 0.01], true);
|
|
|
|
cylinder(top + struts, 2, 1, true, $fn=16);
|
|
|
|
}
|
|
|
|
|
2022-06-01 08:29:44 +02:00
|
|
|
// LEDs am unteren Rand.
|
|
|
|
if (led_bottom) {
|
2023-12-19 15:20:12 +01:00
|
|
|
linear_extrude(height=top) {
|
2022-06-01 08:29:44 +02:00
|
|
|
import("./svg/front led bottom.svg");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// LED-Pegel.
|
|
|
|
if (led_gauge) {
|
2023-12-19 15:20:12 +01:00
|
|
|
linear_extrude(height=top) {
|
2022-06-01 08:29:44 +02:00
|
|
|
import("./svg/front led gauge.svg");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Y-LED.
|
|
|
|
if (led_y) {
|
2023-12-19 15:20:12 +01:00
|
|
|
linear_extrude(height=top) {
|
2022-06-01 08:29:44 +02:00
|
|
|
import("./svg/front led y.svg");
|
|
|
|
}
|
|
|
|
}
|
2022-06-07 18:00:34 +02:00
|
|
|
|
|
|
|
// Power LED.
|
|
|
|
if (led_logo) {
|
2023-12-19 15:20:12 +01:00
|
|
|
linear_extrude(height=top) {
|
2022-06-07 18:00:34 +02:00
|
|
|
import("./svg/front led power logo.svg");
|
|
|
|
}
|
|
|
|
} else {
|
2023-12-19 15:20:12 +01:00
|
|
|
linear_extrude(height=top) {
|
2022-06-07 18:00:34 +02:00
|
|
|
import("./svg/front led power.svg");
|
|
|
|
}
|
|
|
|
}
|
2022-06-01 08:29:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Platzsparendere Stützen für die Bohrungen am oberen Rand.
|
|
|
|
module screw_support(width, length) {
|
2023-12-19 15:20:12 +01:00
|
|
|
translate([0, 0, top + (space / 2)])
|
2022-06-01 08:29:44 +02:00
|
|
|
cube([width, length, space], center=true);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Bohrung für die Schrauben.
|
|
|
|
module screw_drill() {
|
2024-01-10 00:30:06 +01:00
|
|
|
// Die "$preview"-Bedingung reduziert Feher bei der Vorschau.
|
|
|
|
cylinder(h=space + top + ($preview ? 0.2 : 0), r=drill/2, $fn=24);
|
2022-06-01 08:29:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Maske für Stellen, an denen der Rand nicht ganz auf der Platine aufliegen
|
|
|
|
// kann.
|
|
|
|
module border_pcb_cutouts() {
|
|
|
|
// Vibrator.
|
|
|
|
translate([28, 10 + 1, -1.5])
|
|
|
|
cube([6, 1, 1.5]);
|
2022-06-07 17:23:14 +02:00
|
|
|
|
|
|
|
// Batteriefach.
|
|
|
|
translate([47.5 - 2, 10 + 1, -1.5])
|
|
|
|
cube([4, 1, 1.5]);
|
2022-06-01 08:29:44 +02:00
|
|
|
}
|
|
|
|
|
2024-01-20 08:50:59 +01:00
|
|
|
// Kleine Streben zwischen Decke und Rand.
|
|
|
|
module border_strut(width, length, height) {
|
|
|
|
x = width/2;
|
|
|
|
y = length/2;
|
|
|
|
|
|
|
|
polyhedron(points = [
|
|
|
|
[-x, -y, 0],
|
|
|
|
[x, -y, 0],
|
|
|
|
[x, y, 0],
|
|
|
|
[-x, y, 0],
|
|
|
|
[-x, y, height],
|
|
|
|
[x, y, height]
|
|
|
|
], faces = [
|
|
|
|
[0, 1, 2, 3],
|
|
|
|
[1, 5, 2],
|
|
|
|
[2, 5, 4, 3],
|
|
|
|
[3, 4, 0],
|
|
|
|
[0, 4, 5, 1]
|
|
|
|
]);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2022-06-01 08:29:44 +02:00
|
|
|
// 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/front top.svg");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Oberer Rand.
|
|
|
|
color(color_border1)
|
2023-12-19 15:20:12 +01:00
|
|
|
translate([0, 0, top]) {
|
2022-06-01 08:29:44 +02:00
|
|
|
linear_extrude(height = border_height) {
|
|
|
|
import("./svg/front borders.svg");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Unterer Rand.
|
|
|
|
color(color_border2)
|
2023-12-19 15:20:12 +01:00
|
|
|
translate([0, 0, top + border_height]) {
|
2022-06-01 08:29:44 +02:00
|
|
|
difference() {
|
|
|
|
linear_extrude(height=space - border_height) {
|
|
|
|
import("./svg/front borders lower.svg");
|
|
|
|
}
|
|
|
|
// Stellen, an denen der Rand nicht ganz auf der Platine aufliegen
|
|
|
|
// kann.
|
|
|
|
translate([0, 0, space - border_height])
|
|
|
|
border_pcb_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/front struts.svg");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-29 21:08:12 +01:00
|
|
|
// Verstrebung um das Display herum.
|
|
|
|
// Berechne X/Y-Koordinaten vom linken oberen Rand der Platine.
|
|
|
|
color (color_struts)
|
|
|
|
translate([150 - display[2]/2 - display.x, 110 - display[3]/2 - display.y, (top + struts)/2])
|
|
|
|
minkowski() {
|
|
|
|
cube([display[2] - 2, display[3] - 2, 0.01], true);
|
|
|
|
cylinder(top + struts, 4, 3, true, $fn=16);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Verstärkungen für die Analog-Sticks.
|
2023-12-30 00:23:11 +01:00
|
|
|
if (analog_stick_l) {
|
|
|
|
color(color_struts)
|
|
|
|
translate([0, 0, top]) {
|
|
|
|
linear_extrude(height = struts) {
|
|
|
|
import("./svg/front analog stick l struts.svg");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (analog_stick_r) {
|
2023-12-29 21:08:12 +01:00
|
|
|
color(color_struts)
|
|
|
|
translate([0, 0, top]) {
|
|
|
|
linear_extrude(height = struts) {
|
2023-12-30 00:23:11 +01:00
|
|
|
import("./svg/front analog stick r struts.svg");
|
2023-12-29 21:08:12 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-18 13:20:00 +01:00
|
|
|
// Zusätzliche Verstrebungen zwischen Decke und Rand.
|
|
|
|
if (rounded_edges || beveled_edges) {
|
|
|
|
color(color_struts)
|
|
|
|
for (pos = [
|
|
|
|
// [x, y, rotation, länge]
|
|
|
|
[37, 107.5, 0, 3],
|
|
|
|
[45, 107.5, 0, 3],
|
|
|
|
[63, 107.5, 0, 3],
|
|
|
|
[71, 107.5, 0, 3],
|
|
|
|
[79, 107.5, 0, 3],
|
|
|
|
[87, 107.5, 0, 3],
|
|
|
|
|
|
|
|
[147.5, 85, 270, 3],
|
|
|
|
[148, 78.5, 270, 2],
|
|
|
|
[148, 71.5, 270, 2],
|
|
|
|
[147.5, 65, 270, 3],
|
|
|
|
[147.5, 57, 270, 3],
|
|
|
|
[148, 49, 270, 2],
|
|
|
|
[148, 41, 270, 2],
|
|
|
|
|
|
|
|
[109, 12.5, 180, 3],
|
|
|
|
[94, 12.5, 180, 3],
|
|
|
|
[56, 12.5, 180, 3],
|
|
|
|
[41, 12.5, 180, 3],
|
|
|
|
[26, 12.5, 180, 3],
|
|
|
|
|
|
|
|
[5, 36, 90, 2],
|
|
|
|
[5, 44, 90, 2],
|
|
|
|
[5, 52, 90, 2],
|
|
|
|
[5, 60, 90, 2],
|
|
|
|
[2.5, 84, 90, 3],
|
|
|
|
]) {
|
|
|
|
translate([pos[0], pos[1], top])
|
|
|
|
rotate([0, 0, pos[2]])
|
|
|
|
border_strut(1.6, pos[3], pos[3]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-01 08:29:44 +02:00
|
|
|
}
|
|
|
|
|
2024-01-20 08:50:59 +01:00
|
|
|
// Maske, um angerundete oder abgeschrägte Außenkanten zu schneiden.
|
|
|
|
module edge_cut() {
|
|
|
|
minkowski() {
|
|
|
|
linear_extrude(height=0.1) {
|
|
|
|
import("./svg/front outline.svg");
|
|
|
|
}
|
2022-06-01 08:29:44 +02:00
|
|
|
|
2024-01-20 08:50:59 +01:00
|
|
|
$fn = $preview ? 4 : 8;
|
|
|
|
if (beveled_edges) {
|
|
|
|
// Abgeschrägte Kanten.
|
|
|
|
cylinder(h=4, r1=1.5, r2=0);
|
|
|
|
} else {
|
|
|
|
// Abgerundete Kanten.
|
|
|
|
// Dafür generieren wir im folgenden einen konkaven Kegel.
|
|
|
|
union() {
|
|
|
|
curve = [1.34, 1.07, 0.84, 0.63, 0.46, 0.32, 0.2, 0.11, 0.05, 0.01, 0];
|
|
|
|
for (i = [0:len(curve)-2]) {
|
|
|
|
translate([0, 0, i*0.5])
|
|
|
|
cylinder(h=0.5, r1=curve[i], r2=curve[i+1]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-06-01 08:29:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************
|
|
|
|
* Die Hülle. *
|
|
|
|
*************************************************************************/
|
|
|
|
|
|
|
|
module casing_front() {
|
|
|
|
difference() {
|
2024-01-18 13:20:00 +01:00
|
|
|
if (rounded_edges || beveled_edges) {
|
2024-01-19 20:17:44 +01:00
|
|
|
difference() {
|
2022-06-01 08:29:44 +02:00
|
|
|
union () {
|
|
|
|
outer();
|
|
|
|
}
|
|
|
|
|
2024-01-19 20:17:44 +01:00
|
|
|
translate([0, 0, -0.1])
|
2024-01-20 08:50:59 +01:00
|
|
|
edge_cut();
|
2022-06-01 08:29:44 +02:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
outer();
|
|
|
|
}
|
|
|
|
|
2024-01-10 00:30:06 +01:00
|
|
|
// Vergrößere das zu substrahierende Objekt, um Darstellungsfehler
|
|
|
|
// in der Voransicht zu vermeiden.
|
2022-06-01 08:29:44 +02:00
|
|
|
if ($preview) {
|
|
|
|
translate([0, 0, -0.1])
|
2024-01-10 00:30:06 +01:00
|
|
|
resize([0, 0, top + struts + 0.4])
|
2022-06-01 08:29:44 +02:00
|
|
|
top_cutouts();
|
|
|
|
} else {
|
|
|
|
top_cutouts();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Halterungen für die Aktionsbuttons.
|
|
|
|
// Begrenzung nach oben.
|
|
|
|
color(color_buttons)
|
2023-12-19 15:20:12 +01:00
|
|
|
translate([0, 0, top]) {
|
2022-06-01 08:29:44 +02:00
|
|
|
linear_extrude(height = space - button_action_size - button_action_base - button_clearance) {
|
|
|
|
import("./svg/front button action upper.svg");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Führung für die Aktionsbuttons.
|
|
|
|
color(color_buttons)
|
2023-12-19 15:20:12 +01:00
|
|
|
translate([0, 0, top]) {
|
2022-06-01 08:29:44 +02:00
|
|
|
// Wir ziehen die Führungen zwei Millimeter tiefer, um auf der sicheren
|
|
|
|
// Seite zu sein.
|
|
|
|
linear_extrude(height = space - button_action_size + 2) {
|
|
|
|
import("./svg/front button action lower.svg");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Halterungen für die Systembuttons.
|
|
|
|
// Begrenzung nach oben.
|
|
|
|
color(color_buttons)
|
2023-12-19 15:20:12 +01:00
|
|
|
translate([0, 0, top]) {
|
2022-06-01 08:29:44 +02:00
|
|
|
linear_extrude(height = space - button_system_size - button_system_base - button_clearance) {
|
|
|
|
import("./svg/front button system upper.svg");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Führung für die Systembuttons.
|
|
|
|
color(color_buttons)
|
2023-12-19 15:20:12 +01:00
|
|
|
translate([0, 0, top]) {
|
2022-06-01 08:29:44 +02:00
|
|
|
linear_extrude(height = space - button_system_size) {
|
|
|
|
import("./svg/front button system lower.svg");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Schäfte für die Bohrungen.
|
|
|
|
color(color_drills)
|
|
|
|
for (i = [0:3]) {
|
|
|
|
// Die normalen Bohrungen am unteren Rand.
|
2024-01-17 01:12:52 +01:00
|
|
|
translate([drill_pos[i].x, drill_pos[i].y, 0])
|
|
|
|
screw_shaft();
|
2022-06-01 08:29:44 +02:00
|
|
|
}
|
|
|
|
|
2023-05-02 13:40:40 +02:00
|
|
|
// Schacht für den Lichtsensor.
|
|
|
|
color(color_struts)
|
2023-12-19 15:20:12 +01:00
|
|
|
translate([0, 0, top]) {
|
2023-05-02 13:40:40 +02:00
|
|
|
linear_extrude(height = space) {
|
|
|
|
import("./svg/front well.svg");
|
|
|
|
}
|
|
|
|
}
|
2022-06-01 08:29:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Plazierung der Bohrungen.
|
|
|
|
difference() {
|
|
|
|
casing_front();
|
2024-01-10 00:30:06 +01:00
|
|
|
|
|
|
|
// Bedingtes translate um Fehler bei der Vorschau auszubessern.
|
|
|
|
translate([0, 0, $preview ? -0.1 : 0])
|
2022-06-01 08:29:44 +02:00
|
|
|
union() {
|
|
|
|
for (i = [0:3]) {
|
|
|
|
translate([drill_pos[i][0], drill_pos[i][1], 0])
|
|
|
|
screw_drill();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Die Löcher für die Analog-Sticks.
|
2023-12-30 00:23:11 +01:00
|
|
|
if (analog_stick_l) {
|
2024-01-10 00:30:06 +01:00
|
|
|
linear_extrude(height = space * ($preview ? 1.2 : 1)) {
|
2023-12-30 00:23:11 +01:00
|
|
|
import("./svg/front analog stick l.svg");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (analog_stick_r) {
|
2024-01-10 00:30:06 +01:00
|
|
|
linear_extrude(height = space * ($preview ? 1.2 : 1)) {
|
2023-12-30 00:23:11 +01:00
|
|
|
import("./svg/front analog stick r.svg");
|
2022-06-01 08:29:44 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|