Gehäuse-Design und 3D-Druck mit OpenSCAD und ideaMaker

In der Sparte Mikrocontroller / Arduino meiner Website habe ich bereits mein aktuelles Projekt, den Countdown-Wecker vorgestellt.

Nur befindet sich noch alles im Entwicklungsstadium und alle Verbindungen sind auf einem Breadboard gesteckt und die Module liegen lose daneben.


So soll das natürlich nicht bleiben, sondern die Einzelteile sollen fest miteinander verlötet werden und dann in ein Gehäuse kommen, damit der Wecker seinen endgültigen Platz auf meinem Nachttisch einnehmen kann.

Mein Vorgehen dazu ist in der Regel:

Verlöten der Einzelteile

Damit die einzelnen Komponenten steht gute miteinander verbunden sind und sind nicht gleich bei etwa Wackeln aus dem Breadboard rutschen werden sie fest miteinander verlötet. Das hat außerdem den Vorteil, dass das sperrige Breadboard wegfällt und die Einzelteile fast beliebig im Gehäuse arrangiert werden können.

Damit das Arrangieren im Gehäuse klaptt, ist darauf zu achten, dass die Kabel zwischen den Komponenten lang genug sind. Allerdings sollten sie auch nicht zu lang sein, denn die Kabel müssen ja schließlich auch noch im Gehäuse Platz finden - und außerdem wollen wir uns ja nicht ungewollt irgendwelche Spulen basteln, die die Datenübertragung zwischen den Komponenten stören könnten.

Für den Countdown-Wecker sieht das Ergebnis so aus:



Der grüne Knubbel in der Mitte ist übrigens eine kleine Platine, an der GND und +3.3V verteilt werden. Der STM32 besitzt nicht genügend Ausgänge dieser Art, als dass alle Kabel dieser Art diekt am Mikrocontroller angelötet werden könnten. Darum hier also eine kleine Strom-Verteilzentrale.

Bumper für die Module ausdrucken


Damit die Pins der Module nicht den Tisch verkratzen, um die Modulunterseiten zu isolieren und um Kurzschlüsse zu vermeiden und um die Module besser im Gehäuse verbauen zu können, drucke ich mit für jeden Modul einen sogenannten Bumper. Das ist ein kleiner Rahmen, in den das Modul gesteckt werden kann.

Meist drucke ich den Bumper mit einem Boden aus, so dass ich das Modul samt Bumper irgendwo mit doppelseitigem Klebeband oder Klebeknete hin kleben kann. Damit das Modul nicht aus dem Bumper herausfallen kann, auch nicht bei Überkopfmontage, muss es straff im Bumper stecken. Damit den Bumper 0.1 mm breiter zu drucken als das Modul eigentlich ist habe ich hier gute Erfahrungen gemacht.

Für das Designen für den Bumpern nutze ich die Software OpenSCAD. OpenSCAD ist eine kostenlose 3D-Design Software und für Windows, Linux und Mac OS verfügbar. Allerdings verfolgt sie einen etwas anderen Ansatz als die klassischen Design-Tools wie Autodesj Fusion 360, DesignSpark Mechanical, FreeCad, Tinkercad und wie sie alle heißen - bei OpenSCAD wird ein 3D-Objekt nicht mit der Maus gezeichnet, sondern mit einer eigenen Beschreibungssprache umschrieben.

Es handelt sich also um so eine Art Programmiersprache. Man braucht schon ein gerüttelt Maß räumliches Vorstellungsvermögen, um mit OpenSCAD klarzukommen und es darum eher nur für einfachere Objekte zu gebrauchen - zumindest für Anfänger.

Dann hat es aber viele Vorteile: Man kann z. B. Teilobjekte in For-Schleifen wiederholt clonen und in bestimmten Abstand positionieren, anstatt diese einzeln per Maus in einem gewöhnlichen CAD-Programm zu positionieren.

Und da man alles per Text eingibt, muss man bei ähnlichen Objekte nur ein paar Parameter anpassen, um super schnell ein angepasstes Objekt zu rendern.

Genau das habe ich für meine Bumper gemacht. Werfen wir einen Blick auf den OpenSCAD-Code dazu: // genereller Bumper für Platinen. // mit 100% infill drucken breite=23.2; // Breite der Platine laenge=53.7; // Länge der Platine hoehe=1.7; // Dicke der Platine pinhoehe=3; // wieviel stehen unten die Pins über? wandstaerke=1.6; // wie stark sollen die Außenwände sein? auflagebreite=1.5; // wie breit soll die Auflagefläche für die Platine sein? boden=0.4; // 0.0, wenn kein Boden gewünscht union() { difference(){ translate([0,0,0]) { // Außenmaße = Platinenmaße + 5mm auf jeder seite //cube( [54.9, 61.5, 4.0]); cube( [breite+wandstaerke*2, laenge+wandstaerke*2, hoehe+pinhoehe]); } translate([wandstaerke,wandstaerke,pinhoehe]) { // hier wird die Platine reingesteckt (platinenhöhe 1.6 mm) cube( [breite, laenge, hoehe]); } translate([wandstaerke+auflagebreite,wandstaerke+auflagebreite,0]) { // hier ist noch Platz unter der Platine für die Pins bis zum boden = ergibt einen rahmen cube( [breite-auflagebreite*2, laenge-auflagebreite*2, pinhoehe]); } translate([breite/2-4.5+wandstaerke,0,pinhoehe]) { // aussparung für USB an der langen Seite cube( [9, 6, 10]); } } //boden translate([0,0,0]) { // Außenmaße = Platinenmaße + 5mm auf jeder seite cube( [breite+wandstaerke*2, laenge+wandstaerke*2, boden]); } } Hier muss ich nur die Schieblehre rausholen und zweimal am Modul maßnehmen: einmal für die Breite und einmal für die Länge. Diese beiden Werte trage ich dann bei breite= und laenge= ein, drücke F6 und schon habe ich meinen Bumper fertig, den ich gleich als .STL speichern und dann ausdrucken kann.

Die hier verwendeten Anweisungen sind: Das reicht bereits aus, um den gezeigten Bumper auszudrucken. Es gibt aber noch weitere Befehle für Kugeln, Zylinder, Kegelstümpfe und andere Objekte, eine Kurzübersicht findet sich hier.

Design der Gehäuse-Basis

Nachdem alle Module mit Bumpern versorgt sind, geht es an das Design der Gehäuse Basis. Das ist im Prinzip ein großer Block, aus dem Blöcke in der Größe der Module geschnitten werden. Dazu werden die Module samt Bumper ausgemessen und wieder 0.1 mm Toleranz addiert. Das ermöglicht es, die Module von oben hineinzuschieben, wobei diese mit einem Ritsch bis zum Boden hinuntergedrückt werden und da eigentlich von alleine halten. Evtl. muss die Toleranz hier größer gewählt werden. Das kommt auf die Genauigkeit des eingesetzten 3D-Drucker an. Bei meinem Anycubic i3 Mega haben sich 0.1 mm aber als sehr guter Wert herausgestellt.

Für jedes Modul wird ein Block ausgeschnitten, in den es ganz genau hineinpasst. Zwischen den Modulen sollte man immer ein bisschen Wand lassen, damit der Halt gegeben ist. Natürlich muss man auf die Orientierung der Module achten und darf auch nicht vergessen, interne Kabelkanäle auszuschneiden.

Es it sehr wichtig, alles genau auszumessen und sorgfältig zu arbeiten, denn der Druck der Basis hat in diesem Fall über 7 Stunden gedauert. Da möchte man ungern fünf oder mehr mals auf den Ausdruck warten. Das Ergebnis für meinen Countdown-Wecker sieht dann so aus:



Auch hier wieder der OpenSCAD-Code:

wand = 1.6; deckel = 1.6; xxGes=120; yyGes=100; zzGes=40; xGes=0; yGes=0; zGes=0; // Blue Pill xxSTM=26.5; yySTM=57.0; xSTM=5; ySTM=yyGes-yySTM-wand; zSTM=wand; // Blue Pill USB Port xxUSB=10; yyUSB=wand; zzUSB=5; xUSB=xSTM+xxSTM/2-xxUSB/2; yUSB=yyGes-wand; zUSB=3+wand; // Batteriehalter xxBatt=31.9; yyBatt=57.9+5; zzBatt=16; xBatt=xSTM+xxSTM+5; yBatt=yyGes-yyBatt-wand; zBatt=wand; // Einschub für Stand oranger Halter Segmentanzeige xxSegStand=86.1; yySegStand=4.1; zzSegStand=2; xSegStand=wand+15; ySegStand=14.9; zSegStand=wand; // Ausschnitt für die Segmentanzeige in der Front xxSegAnz=61; yySegAnz=8; zzSegAnz=14.5; xSegAnz=xSegStand+14; ySegAnz=0; zSegAnz=zSegStand+2; // Buttonleiste über der Anzeige xxButtons=104.1; yyButtons=27.7; zzButtons=14.5; xButtons=8; yButtons=5; zButtons=zzGes-zzButtons; // Lautsprecher doSpeaker=57; duSpeaker=18.2; zzSpeaker=12.5; xSpeaker=86; ySpeaker=66; difference(){ translate( [xGes,yGes,zGes] ) { // Gesamtblock cube( [xxGes, yyGes, zzGes]); } // vertiefung für STM32, mit Steckdose nach hinten translate ( [xSTM, ySTM, zSTM] ) { cube( [xxSTM, yySTM, zzGes]); } // Aussparung USB-Port translate ( [xUSB, yUSB, zUSB] ) { cube( [xxUSB, yyUSB, zzUSB]); } // Vertiefung Batteriehalter translate ( [xBatt, yBatt, zBatt] ) { cube( [xxBatt, yyBatt, zzGes]); } // Kabelkanal Batt zum STM translate ( [xSTM+xxSTM, yyGes-wand-5, zSTM+5] ) { cube( [10, 5, zzGes]); } // Einschub für Stand oranger Halter Segmentanzeige translate ( [xSegStand, ySegStand, zSegStand] ) { cube( [xxSegStand, yySegStand, zzGes]); } // Darüber frei bis auf Wand translate ( [xSegStand, wand, zSegStand+zzSegStand] ) { cube( [xxSegStand, ySegStand, zzGes]); } // Kabelkanal Segmentanzeige zum STM translate ( [xSegStand-8.7, ySegStand-6, zSegStand] ) { cube( [9, 40, zzGes]); } // Ausschnitt für die Segmentanzeige in der Front translate ( [xSegAnz, ySegAnz, zSegAnz] ) { cube( [xxSegAnz, yySegAnz, zzSegAnz]); } // Buttonleiste über der Anzeige translate ( [xButtons, yButtons, zButtons] ) { cube( [xxButtons, yyButtons, zzGes]); } // Lautsprecher translate ( [xSpeaker, ySpeaker, zzGes-zzSpeaker-deckel-1] ) { cylinder( d1=duSpeaker, d2=doSpeaker, h=zzSpeaker+1, center=false, $fn=36); } // 433 Mhz-Sender und Glückwunschkartenmodul an die Wänder vom Batt-Halter kleben // Platz für das Glückwunschkarten-Modul über STM32 und Batthalter translate ( [xSTM+xxSTM-1, ySTM, wand+zzBatt] ) { cube( [9, 40, zzGes]); } // Ausparung für Deckel mit 1.6mm Stärke translate ( [wand, wand, zzGes-deckel] ) { cube( [xxGes-2*wand, yyGes-2*wand, 2]); } } Hier habe ich zuerst oben alle Maße für die Module definiert (xx, yy, zz) und dessen Positionen im dreidimensionalen Raum (x, y, z). Dann habe ich einen Großen Quader erstellt (120 x 100 x 40 mm) und dann per difference alle Modulschächte daraus ausgeschnitten. Wo was seinen Pltz findet, wird im nachfolgenden Video erläutert. Dort lässt es sich besser erklären.

Dummerweise hatte ich zuerst den Ausschnitt in der Wand links oben vergessen, weil ich dachte, das Glückwunschkartenmodul bekomme ich sicher noch irgendwo unter. Dem war aber nicht so. Ansonsten hatte der Ausdruck aber sehr gut gepasst und da ich nicht einmal 7 Stunden warten wollte, habe ich die Wand einfach mit dem Dremel herusgeschnitten. Ging auch und da es innen ist, sieht man es ja auch nicht.

Weiteres kleines Manko war, dass der Lautsprecher nicht vollständig in dem Kegelstumpf verschwand, sondern oben noch auflag. Da habe ich ein wenig getrickst und einfach das PLA mit einem Düsenfeuerzeug erhitzt, so das es weich wurde. Dann konnte ich den Lautsprecher einsetzen und herunterdrücken. Da nur mit 10% Infill gedruckt habe, gab die Innenstruktur entsprechend nach. Nach ein paar Minuten des Haltens war das PLA wieder fest geworden und der Lautsprecher passte perfekt.

Nachdem alle Module eingesetzt hatte, hatte ich fast Schwierigkeiten, noch alle Kabel unterzubringen, was schließlich doch klaptte. Das Zwischenergebnis sieht dann so aus:



Deckel / Oberseite designen

Nun braucht es natürlich noch ein hübsches Oberteil zur Abdeckung. Dafür habe ich in der Basis extra 1.6 mm Platz nach oben und zu den Seiten freigelassen, um einen Deckel mittig und kantenabschließend einsetzen zu können.

Nun kommt es auf Präzision an, den auf dieses Teil wird man die ganze Zeit schauen. Darum soll es möglichst schön werden. Es werden 6 Aussparungen für die Knöpfe benötigt, eine Kleine für den Lichtsensor und der Lautsprecher soll auch eine Abdeckung bekommen. Diese soll aber bitte schön den Schall durchlassen, schließlich ist es ein Wecker.

Auf die gesamte Größe des Lautsprechers habe ich damit das Plastik verdünnt und außerdem gelocht. Mir gefiele dafür Sechsecke besser als Kreise.

Zuerst habe ich ein großes Loch für den Lautsprecher genommen und den Deckel nur mit einem Layer Höhe, also 0.2 mm gedruckt. Das hat den Vorteil, dass der Druck schon nach 18 Minuten fertig ist. Dann kann ich die Folie anlegen und sehe, ob es schon 100% passt oder ich noch irgendwo korrieren muss. Nach 3 Folien war der Deckel perfekt und konnte auf die gesamte Höhe von 1.4 mm ausgedruckt werden. 0.2 mm habe ich als Luft eingerechnet bzw. als die Höhe, die die Klebeknete ausfüllt, denn der Deckel soll damit aufgeklebt werden. Zur Not bekomme ich ihn dann wieder ab. Hoffentlich zerstörungsfrei, ansonsten wird halt einfach ein neuer gedruckt.



Hier kann das Konzept von OpenSCAD wieder punkten: statt die 95 Löcher für die Lautsprecher einzeln per Maus zu zeichnen und zu positionieren, erledigen das zwei ineinander verschachtelte For-Schleifen. Der Soruce-Code für den Deckel: wand = 1.6; deckel = 1.6; xxGes=120-wand*2-.1; yyGes=100-wand*2-.1; zzGes=1.4; xGes=0; yGes=0; zGes=0; // Lautsprecher doSpeaker=58; xSpeaker=86-wand; ySpeaker=66-wand; // Buttons: Lochraster Abstand für die ersten 5 = 7, rechter :8 dButton=13; yB=16.5; lB=13.3; xB=[lB, lB+7*2.54, lB+2*7*2.54, lB+3*7*2.54, lB+4*7*2.54, lB+4*7*2.54+8*2.54]; dLicht=5.5; xLicht=28.2; yLicht=85.5; dLoch=5; lLoch=xSpeaker-doSpeaker/2+2; hLoch=35; nLoch=10; difference(){ translate( [xGes,yGes,zGes] ) { // Gesamtblock cube( [xxGes, yyGes, zzGes]); } // dünner machen für Lautsprecher translate ( [xSpeaker, ySpeaker, 0] ) { cylinder( d=doSpeaker, h=.8, center=false, $fn=36); } // buttons for (i = [0:5]) { translate ( [xB[i], yB, 0] ) { cylinder( d=dButton, h=2, center=false, $fn=36); } } // Aussparung Lichtsensor translate ( [xLicht, yLicht, 0] ) { cylinder( d=dLicht, h=2, center=false, $fn=36); } // Lochung Lautsprecher for (b = [0:9]) { for (a = [0:nLoch-1]) { x= b%2==0 ? lLoch+a*6+3 : lLoch+a*6;; y=hLoch+b*6; if ( x < 112) { translate ( [x, y, .8] ) { cylinder( d=dLoch, h=2, center=false, $fn=6); } } } } }

Hochzeit von Basis und Deckel

Bevor der Deckel dann fest mit der Basis verklebt wird, teste ich natürlich noch einmal alle Funktionen. Dann kommt der Deckel drauf und der Wecker ist fertig. Noch ein paar Aufkleber unter die Knöpfe, damit ich sie nicht verwechsel und der Countdown-Wecker kann seinen neuen Stammplatz auf meinem Nachttisch einnehmen.



Über den gesamten Vorgang habe ich noch ein Video gemacht, dass mit noch so einigen zusätzlichen Erklärungen aufwarten kann: