2. Computer-Aided Design (CAD)#

This week I learned how to create 2D images with Inkscape and how to make 3D models with OpensCAD and FreeCAD.

OpensCAD#

OpensCAD is a very useful tool that allows us to perform parametric modeling. This means that when you want to change the size of your object, you just have to change a variable.

It is very easy to learn how to use it and find a tutorial or explanation of some features.

Small tutorial#

// place a cube of a given size
cube(["X-axis size", "Y-axis size", "Z-axis size"], center = "true or false");
// place a cylinder of a given size
cylinder("height", d = "diameter");
// move the next piece with a defined distance
translate(["X-axis size", "Y-axis size", "Z-axis size"])
// rotate the next piece with a defined degree
rotate(["X-axis degree", "Y-axis degree", "Z-axis degree"])
// merge to piece together
union() {
    //piece1
    //piece2
}
// cut in the first piece with the shape of the second piece
difference() {
    //piece1
    //piece2
}

If you want to have more information on how to use OpensCAD, you can check the documentation or check the Cheat Sheet.

This Model is inspired by the FlexLinks: “Airplane” Beam by BYU_CMR. In order to get the correct size for the piece I checked a website to get the LEGO Brick Dimensions and Measurements by Christoph Bartneck.

Step 1 : Add a cube in the middle of the grid.

Step 2 : Add 2 cylinders to smooth the sides.

Step 3 : Use the difference with the cylinders to make a hole in the shape.

Step 4 : Use the difference with the cylinders to add details to the hole.

Step 5 : Repeat the shape twice on the sides.

Step 6 : Add a bar between the 2 new pieces.

Step 7 : Use the difference with the cubes on some parts of the bar.

Code and Render#

LEGO Bricks#

NOfPinX = 4;
NOfPinY = 2;



$fn = 100;

width = 7.8;
height = 9.6;
gap = 0.2;

pinHeight = 1.8;
pinWidth = 4.8;

insideUpWidth = 1;

insideOutWidth1xN = 1.5;
insideInWidth1xN = 3.2;

insideOutWidth = 1.2;
insideInWidth = 6.5;
insideSideWidth = 0.6;
insideSideLength = 0.2;


function WidthSize(nPin) = nPin * width + (nPin - 1) * gap;


module LegoCube1x1(){
    union(){
        difference(){
            cube([width, width, height]);
            translate([insideOutWidth1xN, insideOutWidth1xN, -insideUpWidth])
            cube([width - insideOutWidth1xN * 2, width - insideOutWidth1xN * 2, height]);
        }  // Add pin on the bloc
        translate([width/2, width/2, height])
        cylinder(pinHeight, d = pinWidth);
    }
}


module LegoCube1xN(nOfPin){
    union(){
        difference(){
            cube([width, WidthSize(nOfPin), height]);
            translate([insideOutWidth1xN, insideOutWidth1xN, -insideUpWidth])
            cube([width - insideOutWidth1xN * 2, WidthSize(nOfPin) - insideOutWidth1xN * 2, height]);
        }
        union(){ // Add pin on the bloc
            for(i = [1:nOfPin]){
                translate([width/2, WidthSize(i) - width/2, height])
                cylinder(pinHeight, d = pinWidth);
            }
        }
        union() {
            for(i = [1:nOfPin - 1]){
                translate([width/2, WidthSize(i) + gap/2, 0])
                cylinder(height, d = insideInWidth1xN);
            }
        }
    }
}


module LegoCubeNxM(nOfPinX, nOfPinY){
    union(){
        difference(){
            cube([WidthSize(nOfPinX), WidthSize(nOfPinY), height]);
            translate([insideOutWidth, insideOutWidth, -insideUpWidth])
            cube([WidthSize(nOfPinX) - insideOutWidth * 2, WidthSize(nOfPinY) - insideOutWidth * 2, height]);
        }
        union(){ // Add pin on the bloc
            for(i = [1:nOfPinX]){
                for(j = [1:nOfPinY]){
                    translate([WidthSize(i) - width/2, WidthSize(j) - width/2, height])
                    cylinder(pinHeight, d = pinWidth);
                }
            }
        }
        union(){
            for(i = [1:nOfPinX - 1]){
                for(j = [1:nOfPinY - 1]){
                    translate([WidthSize(i) + gap/2, WidthSize(j) + gap/2, 0])
                    difference(){
                        cylinder(height, d = insideInWidth);
                        translate([0, 0, -insideUpWidth])
                        cylinder(height, d = pinWidth);
                    }
                }
            }
        }
        union(){
            for(i = [1:nOfPinX]){
                translate([WidthSize(i) - width/2 - insideSideWidth/2, 0, 0])
                union(){
                    translate([0, insideOutWidth, 0])
                    cube([insideSideWidth, insideSideLength, height]);
                    translate([0, WidthSize(nOfPinY) - insideOutWidth - insideSideLength, 0])
                    cube([insideSideWidth, insideSideLength, height]);
                }
            }
            for(i = [1:nOfPinY]){
                translate([0, WidthSize(i) - width/2 - insideSideWidth/2, 0])
                union(){
                    translate([insideOutWidth, 0, 0])
                    cube([insideSideLength, insideSideWidth, height]);
                    translate([WidthSize(nOfPinX) - insideOutWidth - insideSideLength, 0, 0])
                    cube([insideSideLength, insideSideWidth, height]);
                }
            }
        }
    }
}


module LegoCube(nOfPinX, nOfPinY){
    translate([-WidthSize(nOfPinX/2), -WidthSize(nOfPinY/2), 0])
    if (nOfPinX == 1) {
        if (nOfPinY == 1) {
            LegoCube1x1();
        }
        else {
            LegoCube1xN(nOfPinY);
        }
    } 
    else if (nOfPinY == 1) {
        translate([0, width, 0])
        rotate([0, 0, -90])
        LegoCube1xN(nOfPinX);
    }
    else {
        LegoCubeNxM(nOfPinX, nOfPinY);
    }
}

LegoCube(NOfPinX, NOfPinY);

nOfPinMiddle = 3;
nOfPinSide = 2;
nOfPinBetweenX = 4;
nOfPinBetweenY = 3;



$fn = 100;

width = 7.8;
height = 7.8;
gap = 0.2;

pinWidth = 4.8;

insideOutWidthBeams = 6.2;
insideSideLengthBeams = 0.8;

linkWidth = 1;

function WidthSizeWithGap(nPin) = nPin * (width + gap);
function Hypotenuse(nPinX, nPinY) = sqrt(WidthSizeWithGap(nPinX) * WidthSizeWithGap(nPinX) + WidthSizeWithGap(nPinY) * WidthSizeWithGap(nPinY));

module LegoBeams(nOfPin){
    difference(){
        union(){
            cube([WidthSizeWithGap(nOfPin-1), width, height], center = true);
            translate([WidthSizeWithGap(nOfPin-1)/2, 0, -height/2])
            cylinder(h = height, d = width);
            translate([-WidthSizeWithGap(nOfPin-1)/2, 0, -height/2])
            cylinder(h = height, d = width);
        }
        union(){
            translate([-WidthSizeWithGap(nOfPin-1)/2, 0, 0])
            for (i = [1:nOfPin]){
                translate([WidthSizeWithGap(i-1), 0, 0])
                union(){
                    translate([0, 0, -height])
                    cylinder(h = height*2, d = pinWidth);
                    translate([0, 0, (height/2) - insideSideLengthBeams])
                    cylinder(h = insideSideLengthBeams*2, d = insideOutWidthBeams);
                    translate([0, 0, -(height/2) - insideSideLengthBeams])
                    cylinder(h = insideSideLengthBeams*2, d = insideOutWidthBeams);
                }
            }
        }
    }
}

module Flexlink(nOfPinMiddle, nOfPinSide, nOfPinBetweenX, nOfPinBetweenY){
    union(){
        union(){
            translate([Hypotenuse(nOfPinBetweenX, nOfPinBetweenY) - WidthSizeWithGap(nOfPinSide/2 - 1), 0, 0])
            LegoBeams(nOfPinSide);
            translate([-Hypotenuse(nOfPinBetweenX, nOfPinBetweenY) + WidthSizeWithGap(nOfPinSide/2 - 1), 0, 0])
            LegoBeams(nOfPinSide);

            rotate([0, 0, 90])
            LegoBeams(nOfPinMiddle);
        }
        union(){
            difference(){
                cube([Hypotenuse(nOfPinBetweenX, nOfPinBetweenY)*2, linkWidth, height], center = true);
                union(){
                    cube([insideOutWidthBeams, linkWidth * 2, height * 2], center = true);
                    translate([Hypotenuse(nOfPinBetweenX, nOfPinBetweenY) - WidthSizeWithGap(nOfPinSide/2 - 1), 0, 0])
                    cube([WidthSizeWithGap(nOfPinSide-1) + insideOutWidthBeams, linkWidth * 2, height * 2], center = true);
                    translate([-Hypotenuse(nOfPinBetweenX, nOfPinBetweenY) + WidthSizeWithGap(nOfPinSide/2 - 1), 0, 0])
                    cube([WidthSizeWithGap(nOfPinSide-1) + insideOutWidthBeams, linkWidth * 2, height * 2], center = true);
                }
            }
        }
    }
}

Flexlink(nOfPinMiddle, nOfPinSide, nOfPinBetweenX, nOfPinBetweenY);

License#

I Choose to license this work under Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0). This allows others to freely share or adapt this work if they credit me.

To find out which license to choose for your work, visit this website.