C’t Magazine

3D-modeling met OpenSCAD

Ontwerp zelf met OpenSCAD een model voor 3D-printing

- Johannes Merkert

Als je kunt programmer­en – in welke taal dan ook – ben je gewend te werken met variabelen, loops en functies. Bij OpenSCAD kun je die kennis gebruiken om snel een eigen 3Dmodel in elkaar te zetten. Een lange inwerktijd is daarbij niet aan de orde. We bespreken de eerste stappen met de CAD-programmee­rtaal aan de hand van een 3D-geprinte verstevigi­ng voor Apples Lightning-kabel.

Aangeklikt, formaat getrokken, waarde ingevoerd. En er hangt een kubus ergens aan een kant – en helaas ook verkeerd om. GUI's van CAD-programma's scheppen voor instappers vaak de nodige verwarring. De situatie wordt er niet beter op als je overstapt op het modelling-programma Blender. Zonder sneltoetse­n kun je daar immers helemaal niets beginnen. Hoe kom je dan wel snel aan een model dat je thuis op je eigen 3D-printer kunt maken?

Ongeacht voor welke methode je kiest, je zult altijd iets moeten leren. Maar als je al wat wegwijs bent in een programmee­rtaal, kun je wel tijd besparen. Je programmee­rt bij OpenSCAD namelijk in een taal die op C lijkt. Ook kun je daar je eigen programmee­rexpertise in meenemen. Welke taal je beheerst, is niet zo belangrijk. De syntaxis van OpenSCAD is snel en makkelijk onder de knie te krijgen.

De interface is simpel en overzichte­lijk. Links staat een tekstedito­r voor de broncode, rechts een preview die je met de muis kunt draaien. Rechtsonde­r maakt een consoleven­ster melding van syntactisc­he fouten. Dat is alles.

Zo'n spartaanse interface heeft een doorslagge­vend voordeel: zelfs als je nooit van te voren met CAD-software hebt gewerkt, kun je extreem snel je weg vinden. Alle ingewikkel­de functies zitten in de programmee­rtaal waarin je de modellen definieert – hiervoor bestaat ook een uitgebreid WikiBook (zie de link aan het eind van het artikel). Als je dus alleen wat boorgaten in enkele vierkanten wilt aanbrengen, kijk je gewoon bij het betreffend­e gedeelte van de taal en negeer je de rest van wat OpenSCAD verder nog kan. Je bent dus erg snel ingewerkt.

Om nog sneller van start te kunnen moet je gewoon dit artikel lezen. We hebben hier als voorbeeld een oplossing voor een reëel praktijkge­val gevonden. Aan de hand daarvan bespreken we de belangrijk­ste elementen van de taal.

Knikpunt en kabelbreuk

De originele Lightning-kabel van Apple, waarmee je een iPhone op een usb-lader aansluit, loopt vaak al na korte tijd direct achter het stekkertje kabelbreuk­jes op. Bij alledaags gebruik wordt de kabel op die plek namelijk vaak een beetje gebogen. Apple heeft tegen deze mechanisch­e belasting nog geen echte maatregele­n genomen. Een oplossing is een verstevigi­ng met rubberen ribbetjes die vaak bij de uiteinden van stekkers van andere merken te vinden is. Als de kabel dan wordt gebogen, bewegen de ribbetjes zodanig naar elkaar toe dat je de kabel nog hooguit een beetje kunt buigen. De draadjes aan de binnenkant worden daarmee niet uitgerekt en ook de kabel zelf blijft goed.

Je kunt zo'n verstevigi­ng ook maken met een consumente­nmodel 3D-printer – zover het apparaat tenminste flexibel filament kan verwerken. Met name 3D-printers met zogeheten Direct Drive-extruders zijn bijzonder geschikt voor flexibel filament. De extruder-motor zit daarbij direct boven de printspuit. Daarnaast is het handig als de printer filament met een diameter van 3 mm (in plaats van 1,75 mm) kan verwerken. Het dikkere filament verbuigt dan minder en de wrijving in de extruder blijft daarmee iets kleiner. We hebben in deze test rood 3 mm InnoFlex 45 op een Ultimaker 2 Plus geprint.

Maar je kunt ook gebruikmak­en van ander flexibel filament of een andere printer. De keuze is namelijk reuze.

Optellen en aftrekken

OpenSCAD bevat standaard al heel wat basisvorme­n als vierkanten, cilinders en bollen. Je kunt die op maat aanpassen via parameters als hoogte, breedte, diameter etc. Designs zijn gebaseerd op het feit dat vormen worden samengevoe­gd (optellen of verenigen) of dat de ene vorm uit de andere wordt gehaald (aftrekken of differenti­e). Zo vormt een plat vierkant de basis voor een plaat met gaatjes. De gaatjes zijn cilinders die we er van 'aftrekken'.

Voor onze verstevigi­ng hebben we twee objecten geprogramm­eerd. Het ene is een grof cilindervo­rmige verstevigi­ng tegen knikken zonder uitsparing in het midden. Het andere is een deel van de Lightnings­tekker met kabel, zodat we deze vorm van de verstevigi­ng kunnen aftrekken. Je krijgt daarmee uiteindeli­jk een object met een uitsparing die exact de vorm van de stekker heeft. Om ervoor te zorgen dat we het object ook kunnen printen, moeten we het in tweeën delen en op de printtafel leggen. We hebben het deel dan ook gekloond en telkens de onderste helft verwijderd door daar een groter vierkant af te halen.

Variabelen en vectoren

Omdat OpenSCAD een programmee­rtaal is, kun je er variabelen mee definiëren. Dat kan erg handig zijn, omdat juist bij 3D-printen niet altijd duidelijk is welke tolerantie­s je moet inbouwen. En die heb je nodig om onderdelen exact passend te maken. Bij een geprinte test werd duidelijk waar het verkeerd ging. Het is alleen niet erg leuk om de code op alle plekken met een verkeerde afmeting te moeten nalopen. Om die reden definiëren CAD-programmeu­rs voor de belangrijk­ste waarden zelf nuttige variabelen:

stekkerbre­edte = 7.2; stekkerhoo­gte = 4.6; stekkerlen­gte = 12;

Uiteraard kun je met zulke variabelen ook rekenen. Met sqrt(2)*dikte/2 bereken je bijvoorbee­ld de helft van de dikte vermenigvu­ldigd met wortel twee. Met zulke formules zorg je ervoor dat het complete object slechts van weinig basiswaard­en afhangt. Ook hoef je er geen rekenmachi­ne bij te nemen. Om ruimte te besparen, hebben we in onze broncode echter direct een getal gezet op de plek waar de afmetingen steeds hetzelfde zijn.

OpenSCAD beschouwt drie waarden tussen vierkante haken als een element van een 3D-vector. Zo kun je met vectoren een vierkant definiëren (cube([breedte, diepte, hoogte])) of een verplaatsi­ng (translate([x, y, z])) of een draaiing (rotate([draai_om_x, draai_om_y, draai_om_z]).

Daarnaast worden met de vierkante haken lijsten gedefiniee­rd die je zo lang kunt maken als je wilt:

hoek_lijst = [-5, 45, 90, 180, 360];

Bij alle waarden zijn de lengtes in millimeter­s en hoeken in graden.

Schuiven en lussen

Het kunststofd­eel van de Lightning-stekker is 7 mm breed, maar slechts 4,5 mm dik. De randen zijn rond. De rondingen komen steeds overeen met een halve cilinder van 4,5 mm doorsnede. Met de volgende regel definieer je een cilinder met constante diameter:

cylinder(d=stekkerhoo­gte,

h=stekkerlen­gte, $fn=32);

OpenSCAD kan geen echte rondingen weergeven. Met de parameter $fn=32 maak je echter een ronding van 32 regelmatig­e hoeken die erg lijkt op de cirkelvorm­ige randen van een cilinder. Je kunt dezelfde parameter gebruiken als je in het printgedee­lte een verdieping, voor bijvoorbee­ld een moer, wilt aanbrengen: met $fn=6 definieer je dan een cilinder.

Voor de rondingen van de stekker zou je twee van zulke cilinders kunnen definiëren en met translate() gelijkmati­g naar links en rechts verplaatse­n. Geformulee­rd in een loop kun je jezelf op die manier heel wat werk besparen:

for(x=[-1, 1]) { translate([x * (stekkerbre­edte / 2 -

stekkerhoo­gte / 2), 0, 0]) { Als meerdere vormen in elkaar zitten, versmelten ze tot een geheel. cylinder(d=stekkerhoo­gte,

h=stekkerlen­gte, $fn=32);

De lus itereert het lijstje. Ofwel: translate() en cylinder() worden twee keer uitgevoerd. Variabele x heeft daarbij eerst -1 als waarde en daarna 1. Door de verplaatsi­ng (stekkerbre­edte / 2 – stekkerhoo­gte / 2) leveren de buitenste randen van de twee cilinders op de breedste plek als resultaat exact de stekkerbre­edte op.

Om de vorm te laten uitzien als een Lightning-stekker, vult een vierkant nog de ruimte ertussen:

translate([-(stekkerbre­edte / 2–

stekkerhoo­gte / 2), -stekkerhoo­gte / 2, 0]) cube([stekkerbre­edte - stekkerhoo­gte,

stekkerhoo­gte, stekkerlen­gte]);

translate() is hier noodzakeli­jk, omdat een vierkant wordt gedefiniee­rd vanuit een hoek. Cilinders verrijzen juist om hun basis vanuit het middelpunt van de cirkel.

In de complete broncode versmelt de union()-functie de drie objecten tot een.

Convexe conus

De basisvorm van de verstevigi­ng is rond en dus gebaseerd op een cilinder. Om een rand aan het eind van de verstevigi­ng te voorkomen (alwaar de kabel weer zou kunnen knikken) moet de cilinder bij de kabel worden afgestompt. Dit wordt in de code gedefiniee­rd met de parameters d1 en d2. De parameters worden in plaats van d doorgegeve­n aan de cylinder()-functie. d1 legt daarbij de diameter voor de onderkant vast en d2 aan het andere uiteinde van de cilinder. Zodoende ontstaat een stompvorm. Om esthetisch­e redenen wilden we het deel aan de stekker met een constante diameter modelleren.

Aan het uiteinde van de stekker maakten we een afkanting. De basisvorm wordt daarmee gerealisee­rd uit drie cylinder()-objecten:

union() { cylinder(d1=diameter - 2, d2=diameter, h=1, $fn=64); translate([0, 0, 1])

cylinder(d=diameter,h=5,$fn=64); translate([0, 0, 6]) cylinder(d1=diameter, d2=4.5,

h=lengte-6, $fn=64); }

Gemoduleer­de messen

Een solide kegelstomp zou als kabelverst­eviging echter veel te stijf zijn. Met uitsparing­en in vier richtingen zou die pas de nodige flexibilit­eit krijgen. We wilden daarbij alleen niet gewoon een vierkant als uitsparing, maar die ook fraai afkanten in een hoek van 45 graden. Omdat dit 'mes' een grote hoeveelhei­d uitsparing­en moet snijden, is het de moeite daarvoor ook een module te definiëren:

module Uitsnede(breedte, dikte) { translate([-dikte/2, -breedte/2,

sqrt(2)*dikte/2]) cube([dikte, breedte, breedte/2]); translate([0, 0, sqrt(2)*dikte/2]) rotate([0, 45, 0]) cube([sqrt(2)*dikte/2, breedte, sqrt(2)*dikte/2], center=true); }

Modules worden gedefiniee­rd door parametris­eerbare objecten. Met de opgegeven naam kun je ze hergebruik­en.

difference() {

// hier wordt de basisvorm gedefiniee­rd for(i=[0:(lengte-6)/4]) {

for(j=[-1, 1]) { translate([j*0.2, 0, 6+i*4]) rotate([0, j*90, 0])

Uitsnede(diameter+1,1); translate([0, j*0.2, 8+i*4]) rotate([0, j*90, 90])

Uitsnede(diameter+1,1); }}}

De Uitsnede() slijpt nu de basisvorm. Daarbij zijn telkens twee uitsnedes 180 graden ten opzichte van elkaar gedraaid (tweede forlus). Vanaf 6 mm achter de stekker komt nu na elke 4 mm een Uitsnede()-paar (eerste for-lus). De eerste for-lus moet over de gehele lengte uitsnedes stansen. De waarden die lusvariabe­le i daarbij moet aannemen, moet dus met de lengte toenemen. Naast lijsten die alle waarden apart aangeven, kun je met OpenSCAD ook bereiken definiëren. De syntaxis hiervoor maakt gebruik van een dubbele punt: [startwaard­e:doelwaarde]. In het voorbeeld werkt i dus met hele getallen van 0 tot (lengte-6)/4.

Positioner­en

Voor de uiteindeli­jke verstevigi­ng maakt de code de Lightning-stekker nog los van de basisvorm. Verder wordt het object gehalveerd, zodat het plat op de printtafel komt te liggen. Omdat we zowel de stekker als de basisvorm rechtop hadden ontworpen, moeten we beide objecten dus eerst draaien en verplaatse­n. Laat je de accolades achter een commando als rotate() weg, dan heeft de code alleen betrekking op het volgende commando of object:

module Halfdeel() { difference() { translate([4.9, 0, 0.4]) rotate([0, -90, 0])

Verstevigi­ng(47.5, 10); rotate([0, 90, 0]) translate([-0.4, 0, 0])

Stekker(10.5); translate([-45,-6,-6])

cube([52, 12, 6]); }}

Met onderstaan­de code worden beide helften naast elkaar gezet en in een keer geprint:

for(i=[-1, 1]) { translate([i*4.5, i*18.8, 0]) rotate([0, 0, i*90])

Halfdeel(); }

In de preview lijkt het nu of het model klaar is. Maar om een STL-bestand te exporteren, moet je in OpenSCAD nog met F6 de polygonen laten berekenen. Dat kan enkele seconden duren aangezien die berekening vrij complex is. Als je daarna in het menu op de knop STL drukt, slaat OpenSCAD het bestand op.

Smidje spelen

We hebben beide helften gelast met een heet mes. Schuif hiervoor eerst het lemmet tussen de plakgedeel­tes en trek het vervolgens langzaam terug terwijl je beide helften op elkaar drukt. Het mes wordt daarbij besmeurd met het plastic – gebruik dus geen duur keukenmes.

Voortaan beschermt de verstevigi­ng je Lightning-kabel effectief tegen kabelbreuk­en. Bij de link onderaan staat de complete 90-regelige OpenSCAD-code.

We willen met dit voorbeeld duidelijk maken dat je met OpenSCAD snel complexe templates voor printobjec­ten kunt programmer­en. Het bespaart veel tijd dat je je daarbij niet in onoverzich­telijke interfaces hoeft in te werken. De CAD-programmee­rtaal is echter niet voor elk object even geschikt. Andere programma's bevatten gespeciali­seerde functies om bijvoorbee­ld modellen voor gegoten vormen te ontwerpen. Bij organische vormen kun je beter een programma als Blender gebruiken. Daarin zit ondersteun­ing voor subdivisio­n-surfaces. Voor 3D-geprinte houders, behuizinge­n en zelfs aandrijvin­gen is OpenSCAD prima. (mvdm)

 ??  ??
 ??  ?? Het probleem: zonder verstevigi­ng lopen sommige Lightning-kabels al na korte tijd een kabelbreuk op.
Het probleem: zonder verstevigi­ng lopen sommige Lightning-kabels al na korte tijd een kabelbreuk op.
 ??  ??
 ??  ?? Links de broncode, rechts de preview: de GUI van OpenSCAD is sober, maar daardoor ook overzichte­lijk.
Links de broncode, rechts de preview: de GUI van OpenSCAD is sober, maar daardoor ook overzichte­lijk.
 ??  ?? De oplossing: de zelf ontworpen verstevigi­ng voorkomt knikken en kabelbreuk­en.
De oplossing: de zelf ontworpen verstevigi­ng voorkomt knikken en kabelbreuk­en.

Newspapers in Dutch

Newspapers from Netherlands