Raspberry Pi 3 Model B Open Case

This is an open case for a Raspberry Pi 3 Model B.

It’s meant to be mounted on top of an SSD or 2.5" HDD.

All of these models were made with CascadeStudio.

top.glb (source code)
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
const Vector2 = THREE.Vector2;
const Vector3 = THREE.Vector3;

const BOARD_CORNER_RADIUS = 3;
const BOARD_FILLET_RADIUS = 2;
const BOARD_HOLE_DISTANCE = new Vector2(58, 49);
const BOARD_HOLE_MARGIN = 3.5;
const BOARD_HOLE_RADIUS = 1.35;
const BOARD_SIZE = new Vector3(85, 56, 1.6);
const BOARD_HOLE_OFFSET =
  (BOARD_SIZE.x - BOARD_HOLE_DISTANCE.x) / 2 - BOARD_HOLE_MARGIN;

const COLUMN_CHAMFER_DISTANCE = 2;
const COLUMN_DIAMETER = BOARD_HOLE_RADIUS * 2 + BOARD_HOLE_MARGIN;
const COLUMN_HOLE_RADIUS = BOARD_HOLE_RADIUS;
const COLUMN_SIZE = new Vector3(COLUMN_DIAMETER, COLUMN_DIAMETER, 13.5);

const FAN_FILLET_RADIUS = 2;
const FAN_HOLE_RADIUS = 19;
const FAN_SCREW_HOLE_RADIUS = 2;
const FAN_SCREW_HOLE_SPACING = 32;
const FAN_SIZE = new Vector3(40, 40, 10);

const PLATFORM_CHAMFER_DISTANCE = 2;
const PLATFORM_SIZE = new Vector3(
  BOARD_HOLE_DISTANCE.x + COLUMN_SIZE.x,
  BOARD_HOLE_DISTANCE.y + COLUMN_SIZE.y,
  3
);

const COLUMN_X = BOARD_HOLE_DISTANCE.x / 2;
const COLUMN_Y = BOARD_HOLE_DISTANCE.y / 2;
const COLUMN_Z = (PLATFORM_SIZE.z - COLUMN_SIZE.z) / 2;

function Combination(x, y, z, shape) {
  return [
    Translate([-x, +y, z], shape),
    Translate([+x, +y, z], shape),
    Translate([-x, -y, z], shape),
    Translate([+x, -y, z], shape),
  ];
}

function Board() {
  let shape = Box(BOARD_SIZE.x, BOARD_SIZE.y, BOARD_SIZE.z, true);
  {
    const edgeList = [0, 2, 4, 6];
    shape = FilletEdges(shape, BOARD_CORNER_RADIUS, edgeList);
  }
  {
    const x = BOARD_HOLE_DISTANCE.x / 2;
    const y = BOARD_HOLE_DISTANCE.y / 2;
    const offset =
      (BOARD_SIZE.x - BOARD_HOLE_DISTANCE.x) / 2 - BOARD_HOLE_MARGIN;
    const hole = Cylinder(BOARD_HOLE_RADIUS, BOARD_SIZE.z, true);
    const holes = [
      Translate([-x - offset, +y, 0], hole),
      Translate([+x - offset, +y, 0], hole),
      Translate([-x - offset, -y, 0], hole),
      Translate([+x - offset, -y, 0], hole),
    ];

    shape = Difference(shape, holes);
  }
  return shape;
}

function Fan() {
  let shape = Box(FAN_SIZE.x, FAN_SIZE.y, FAN_SIZE.z, true);
  {
    const edgeList = [0, 2, 4, 6];
    shape = FilletEdges(shape, FAN_FILLET_RADIUS, edgeList);
  }
  {
    const hole = Cylinder(FAN_HOLE_RADIUS, FAN_SIZE.z, true);
    shape = Difference(shape, [hole]);
  }
  {
    const halfHoleSpacing = FAN_SCREW_HOLE_SPACING / 2;
    const hole = Cylinder(FAN_SCREW_HOLE_RADIUS, FAN_SIZE.z, true);
    const holes = Combination(halfHoleSpacing, halfHoleSpacing, 0, hole);
    shape = Difference(shape, holes);
  }
  return shape;
}

function Column() {
  let shape = Box(COLUMN_SIZE.x, COLUMN_SIZE.y, COLUMN_SIZE.z, true);
  {
    const chamferEdges = [0, 2, 4, 6];
    shape = ChamferEdges(shape, COLUMN_CHAMFER_DISTANCE, chamferEdges);
  }
  {
    const hole = Cylinder(COLUMN_HOLE_RADIUS, COLUMN_SIZE.z, true);
    shape = Difference(shape, [hole]);
  }
  return shape;
}

function Platform() {
  let shape = Box(PLATFORM_SIZE.x, PLATFORM_SIZE.y, PLATFORM_SIZE.z, true);
  {
    const width = PLATFORM_SIZE.x - COLUMN_SIZE.x * 2;
    const height = (PLATFORM_SIZE.y - FAN_SIZE.y) / 2;
    const y = (height - PLATFORM_SIZE.y) / 2 - 1.5;
    let cut = Box(width, height, PLATFORM_SIZE.z, true);
    cut = Translate([0, -y, 0], cut);
    shape = Difference(shape, [cut]);
  }
  {
    const edgeList = [0, 2, 5, 14, 20, 21, 22, 23];
    shape = ChamferEdges(shape, PLATFORM_CHAMFER_DISTANCE, edgeList);
  }
  {
    const hole = Cylinder(FAN_HOLE_RADIUS, PLATFORM_SIZE.z, true);
    shape = Difference(shape, [hole]);
  }
  {
    const hole = Cylinder(FAN_SCREW_HOLE_RADIUS, PLATFORM_SIZE.z, true);
    const x = FAN_SCREW_HOLE_SPACING / 2;
    const y = FAN_SCREW_HOLE_SPACING / 2;
    const holes = Combination(x, y, 0, hole);
    shape = Difference(shape, holes);
  }
  {
    const hole = Cylinder(BOARD_HOLE_RADIUS, PLATFORM_SIZE.z, true);
    const holes = Combination(COLUMN_X, COLUMN_Y, 0, hole);
    shape = Difference(shape, holes);
  }
  return shape;
}

const board = Board();

const column = Column();
const columns = Combination(COLUMN_X, COLUMN_Y, COLUMN_Z, column);

let fan = Fan();
fan = Translate(
  [-BOARD_HOLE_OFFSET, 0, (BOARD_SIZE.z + FAN_SIZE.z) / 2 + COLUMN_SIZE.z],
  fan
);

let platform = Platform();

platform = Union([...columns, platform], false);
platform = Translate(
  [-BOARD_HOLE_OFFSET, 0, (BOARD_SIZE.z - PLATFORM_SIZE.z) / 2 + COLUMN_SIZE.z],
  platform
);
base.glb (source code)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
const Vector2 = THREE.Vector2
const Vector3 = THREE.Vector3

const HOLE_DISTANCE = new Vector2(38.3, 30.86);
const HOLE_DIAMETER = 3
const HOLE_MARGIN = 2.565

const BASE_SIZE = new Vector3(
    HOLE_DISTANCE.x * 2 + HOLE_DIAMETER + HOLE_MARGIN * 2,
    HOLE_DISTANCE.y * 2 + HOLE_DIAMETER + HOLE_MARGIN * 2,
    3
)
const BASE_CHAFER_DISTANCE = 3
const BASE_HOLE_SIZE = new Vector3(
    BASE_SIZE.x - HOLE_DIAMETER * 2 - HOLE_MARGIN * 4,
    BASE_SIZE.y - HOLE_DIAMETER * 2 - HOLE_MARGIN * 4,
    BASE_SIZE.z
)

const PLATFORM_HOLE_DISTANCE = new Vector2(29, 24.5);
const PLATFORM_HOLE_OFFSET = HOLE_DISTANCE.x - PLATFORM_HOLE_DISTANCE.x

const hole = Cylinder(HOLE_DIAMETER / 2, BASE_SIZE.z, true)
const holes = [
    Translate([-HOLE_DISTANCE.x, +HOLE_DISTANCE.y, 0], hole),
    Translate([+HOLE_DISTANCE.x, +HOLE_DISTANCE.y, 0], hole),
    Translate([-HOLE_DISTANCE.x, -HOLE_DISTANCE.y, 0], hole),
    Translate([+HOLE_DISTANCE.x, -HOLE_DISTANCE.y, 0], hole),
]

function Hexagon(width, depth) {
  const degreesToRadians = Math.PI / 180
  const height = width / Math.tan(degreesToRadians * 60);
  const box = Box(width, height, depth, true);
  const rotationAxis = [0, 0, 1];
  return Union(
    [box, Rotate(rotationAxis, 60, box), Rotate(rotationAxis, 120, box)],
    false
  );
}

function HexagonalSocket(width, depth, margin) {
    const hole = Hexagon(width, depth)
    const socket = Hexagon(width + margin, depth)
    return Difference(socket, [hole])
}

const HEX_HEIGHT = 2.4
const hex = HexagonalSocket(2.5, HEX_HEIGHT, HOLE_MARGIN)
let platform_holes = [
    Translate([-PLATFORM_HOLE_DISTANCE.x + PLATFORM_HOLE_OFFSET, +PLATFORM_HOLE_DISTANCE.y, BASE_SIZE.z - (BASE_SIZE.z - HEX_HEIGHT)], hex),
    Translate([+PLATFORM_HOLE_DISTANCE.x + PLATFORM_HOLE_OFFSET, +PLATFORM_HOLE_DISTANCE.y, BASE_SIZE.z - (BASE_SIZE.z - HEX_HEIGHT)], hex),
    Translate([-PLATFORM_HOLE_DISTANCE.x + PLATFORM_HOLE_OFFSET, -PLATFORM_HOLE_DISTANCE.y, BASE_SIZE.z - (BASE_SIZE.z - HEX_HEIGHT)], hex),
    Translate([+PLATFORM_HOLE_DISTANCE.x + PLATFORM_HOLE_OFFSET, -PLATFORM_HOLE_DISTANCE.y, BASE_SIZE.z - (BASE_SIZE.z - HEX_HEIGHT)], hex),
]

let base = Box(BASE_SIZE.x, BASE_SIZE.y, BASE_SIZE.z, true)
base = ChamferEdges(base, BASE_CHAFER_DISTANCE, [0, 2, 4, 6])
let base_hole = Box(BASE_HOLE_SIZE.x, BASE_HOLE_SIZE.y, BASE_HOLE_SIZE.z, true)
base = Difference(base, [base_hole])
base = ChamferEdges(base, BASE_CHAFER_DISTANCE, [32, 33, 34, 35])
let support = Box(HOLE_DIAMETER + HOLE_MARGIN * 2, BASE_SIZE.y, BASE_SIZE.z, true)
support = Translate([-PLATFORM_HOLE_DISTANCE.x + PLATFORM_HOLE_OFFSET, 0, 0], support)
base = Union([base, support])
base = ChamferEdges(base, BASE_CHAFER_DISTANCE, [23, 26, 25, 28])
base = Difference(base, holes)

platform_holes.push(base)

base = Union(platform_holes)
side.glb (source code)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
const Vector2 = THREE.Vector2
const Vector3 = THREE.Vector3

const HOLE_DIAMETER = 3.1
const HOLE_DEPTH = 3
const HOLE_MARGIN = 3

const HARD_DISK_GAP = 3
const FLOOR_GAP = 3

const HARD_DISK_SMALL_SIZE = new Vector3(100.2, 69.85, 6.8)
const HARD_DISK_BIG_SIZE = new Vector3(100.4, 69.85, 9.5)
const HARD_DISK_HOLE_SPACING = 76.6;

const HOLE_X = HARD_DISK_HOLE_SPACING / 2;
const HOLE_Y = (HARD_DISK_GAP + HARD_DISK_SMALL_SIZE.z) / 2;

const SIDE_EXTENSION = 3
const SIDE_SIZE = new Vector3(
    100.4,
    SIDE_EXTENSION + HARD_DISK_BIG_SIZE.z + FLOOR_GAP,
    3
)
const SIDE_HOLE_SIZE = new Vector3(
    SIDE_SIZE.x - HOLE_DIAMETER * 2 - HOLE_MARGIN * 2,
    SIDE_SIZE.y - HOLE_DIAMETER * 2 - HOLE_MARGIN * 2,
    SIDE_SIZE.z
)

const SIDE_COLUMN_SIZE = new Vector3(
    HOLE_DIAMETER + HOLE_MARGIN,
    SIDE_SIZE.y,
    SIDE_SIZE.z
)

function HardDisks() {
    let hard_disk_big = Box(HARD_DISK_BIG_SIZE.x, HARD_DISK_BIG_SIZE.y, HARD_DISK_BIG_SIZE.z)
    // let hard_disk_small = Box(HARD_DISK_SMALL_SIZE.x, HARD_DISK_SMALL_SIZE.y, HARD_DISK_SMALL_SIZE.z)
    {
        let hole = Cylinder(HOLE_DIAMETER / 2, 3, true)
        hole = Rotate([1, 0, 0], 90, hole)
        let holes = [
            Translate([14, HOLE_DEPTH / 2, HOLE_MARGIN], hole),
            Translate([90.6, HOLE_DEPTH / 2, HOLE_MARGIN], hole),
            Translate([14, HARD_DISK_BIG_SIZE.y - HOLE_DEPTH / 2, HOLE_MARGIN], hole),
            Translate([90.6, HARD_DISK_BIG_SIZE.y - HOLE_DEPTH / 2, HOLE_MARGIN], hole)
        ]
        hard_disk_big = Difference(hard_disk_big, holes)
        // hard_disk_small = Difference(hard_disk_small, holes)
    }

    hard_disk_big = Rotate([0, 1, 0], 180, hard_disk_big)
    // hard_disk_small = Rotate([0, 1, 0], 180, hard_disk_small)

    hard_disk_big = Translate([HARD_DISK_BIG_SIZE.x / 2, 0 - HARD_DISK_BIG_SIZE.y / 2, HARD_DISK_BIG_SIZE.z], hard_disk_big)
    // hard_disk_small = Translate([HARD_DISK_SMALL_SIZE.x / 2, 0 - HARD_DISK_SMALL_SIZE.y / 2, HARD_DISK_SMALL_SIZE.z], hard_disk_small)

    hard_disk_big = Translate([0, 0, FLOOR_GAP], hard_disk_big)
    // hard_disk_small = Translate([0, 0, FLOOR_GAP + HARD_DISK_BIG_SIZE.z + HARD_DISK_GAP], hard_disk_small)
}

// HardDisks()

let hole = Cylinder(HOLE_DIAMETER / 2, HOLE_DEPTH, true)
let holes = Union([
    Translate([-HOLE_X, +HOLE_Y, 0], hole),
    Translate([+HOLE_X, +HOLE_Y, 0], hole),
    // Translate([-HOLE_X, -HOLE_Y, 0], hole),
    // Translate([+HOLE_X, -HOLE_Y, 0], hole),
])
holes = Translate([0, SIDE_SIZE.y / 2 - SIDE_EXTENSION - HOLE_MARGIN - HOLE_Y, 0], holes)

let side = Box(SIDE_SIZE.x, SIDE_SIZE.y, SIDE_SIZE.z, true)

// let side = Box(SIDE_SIZE.x, SIDE_SIZE.y, SIDE_SIZE.z, true)
side = Difference(side, [holes])
// let side_hole = Box(SIDE_HOLE_SIZE.x, SIDE_HOLE_SIZE.y, SIDE_HOLE_SIZE.z, true)
// side = Difference(side, [side_hole])
// let side_column = Box(SIDE_COLUMN_SIZE.x, SIDE_COLUMN_SIZE.y, SIDE_COLUMN_SIZE.z, true)
// side = Union([side, side_column])
// side = ChamferEdges(side, 3, [0, 2, 6, 21, 36, 37, 38, 39, 42, 43, 44, 45])

side = ChamferEdges(side, 3, [0, 2, 5, 12])

side = Rotate([1, 0, 0], 90, side)
side = Translate([0, 0 - HARD_DISK_BIG_SIZE.y / 2 - HOLE_DEPTH / 2, SIDE_SIZE.y / 2], side)

// let side_bottom = Box(SIDE_WIDTH, SIDE_BOTTOM_HEIGHT, HOLE_DEPTH, true)
// side_bottom = Translate([0, 0 - SIDE_HEIGHT / 2 - SIDE_BOTTOM_HEIGHT / 2 + 3, 0], side_bottom)

// let side_hole = Box(SIDE_HOLE_SIZE.x, SIDE_HOLE_SIZE.y, SIDE_HOLE_SIZE.z, true)
// side_hole = Translate([0, 0, 0], side_hole)