--- /dev/null
+infty = 100;
+eps = 0.01;
+
+wall = 2;
+spring_y = 24;
+spring_x = 8;
+spring_z = 8.5;
+
+spring_low = 1; // mm lower than spring_x
+
+clip_add_z = 5;
+clip_w = 15;
+
+// bottom
+translate([0, -spring_y/2, 0]) cube([wall, spring_y, spring_z]);
+
+// sides
+for (i = [-1,1]) scale([1, i, 1])
+ translate([0, spring_y/2 - wall, 0])
+ cube([spring_x, wall, spring_z]);
+
+// clip
+translate([0, -clip_w/2, 0]) cube([wall, clip_w, spring_z + clip_add_z]);
+
+spring_top_r = 12;
+spring_y_off = spring_y/4 - 1.2;
+
+difference() {
+ union() {
+ // center beam
+ translate([spring_x - wall, -spring_y/2, 0])
+ cube([wall, spring_y, spring_z]);
+ // round bottom of the spring
+ for (i = [-1,1])
+ translate([spring_top_r+spring_x- wall- spring_low,
+ i*spring_y_off, 0])
+ cylinder(r = spring_top_r, h = spring_z,
+ $fn = 128);
+ }
+ // top of the spring
+ translate([spring_x, -infty/2, -infty/2]) cube(infty);
+
+ // sides
+ for (i = [-1, 1]) scale([1, i, 1])
+ translate([-infty/2, spring_y/2, -infty/2]) cube(infty);
+
+ // round top of the spring
+ for (i = [-1,1])
+ translate([spring_top_r+spring_x- wall- spring_low,
+ i*spring_y_off, -eps])
+ cylinder(r = spring_top_r - wall, h = spring_z + 2*eps,
+ $fn = 128);
+}