Skip to content

Instantly share code, notes, and snippets.

@eclecticc eclecticc/M.2.scad
Last active Nov 19, 2019

Embed
What would you like to do?
Parametric M.2 mockup generator
// M.2 Mockup Generator
// by Nirav Patel <https://eclecti.cc>
//
// To the extent possible under law, Nirav Patel has waived all copyright
// and related or neighboring rights to M.2 Mockup Generator.
//
// An easy to use parametric M.2 mockup generator.
// See https://en.wikipedia.org/wiki/M.2 for more information about the
// M.2 (formerly NGFF) standard.
edge_width = 19.85;
edge_length = 4;
edge_r = 0.5;
hole_r = 1.75;
key_r = 0.6;
key_length = 3.5;
pcb_thick = 0.8;
bottom_edge_keepout = 5.2;
top_gnd_pad_r = 2.75;
bottom_gnd_pad_r = 3;
bottom_gnd_pad_offset = 1;
bevel = 0.3;
bevel_angle = 20;
$fn=50;
module key_cutout() {
union() {
translate([0, key_length - key_r]) circle(r = key_r);
translate([-key_r, -1]) square([key_r*2,key_length - key_r +1]);
}
}
function get_key(key_type="mm") =
key_table[search([key_type],key_table,1,0)[0]][1];
key_table = [["", 100], ["A", 6.625], ["B", 5.625], ["C", 4.625], ["D", 3.625], ["E", 2.625], ["F", 1.625], ["G", -1.125], ["H", -2.125], ["J", -3.125], ["K", -4.125], ["L", -5.125], ["M", -6.125]];
module m2_2d(width=22, length=30, key="M", key2="") {
// Start with a 2d version
difference() {
square([width, length]);
// Left cutout
translate([(width-edge_width)/2-width, -edge_r]) square([width, edge_length]);
translate([(width-edge_width)/2-width-edge_r, 0]) square([width, edge_length]);
translate([(width-edge_width)/2-edge_r, edge_length-edge_r]) circle(r=edge_r);
// Right cutout
translate([width-(width-edge_width)/2, -edge_r]) square([width, edge_length]);
translate([width-(width-edge_width)/2+edge_r, 0]) square([width, edge_length]);
translate([width-(width-edge_width)/2+edge_r, edge_length-edge_r]) circle(r=edge_r);
// Hole cutout
translate([width/2, length]) circle(r = hole_r);
// Key cutouts
translate([width/2 + get_key(key), 0])
key_cutout();
translate([width/2 + get_key(key2), 0])
key_cutout();
}
}
module m2_text(width=22, length=30, height="", key="", key2="") {
if (key2 != "") {
string = str(width, length, "-", height, "-", key, "-", key2);
linear_extrude(height = 1)
text(string, size = 2.5);
} else {
string = str(width, length, "-", height, "-", key);
linear_extrude(height = 1)
text(string, size = 2.5);
}
}
module m2(width=22, length=30, height="", key="", key2="") {
union() {
difference() {
linear_extrude(height = pcb_thick)
m2_2d(width, length, key, key2);
// The card edge bevel
translate([0, bevel, 0]) rotate([180-bevel_angle, 0, 0]) cube([width, 10, 10]);
translate([0, bevel, pcb_thick]) rotate([90+bevel_angle, 0, 0]) cube([width, 10, 10]);
}
difference() {
// The various component keepout zones and embossed text
if (height == "S1") {
difference() {
translate([0, edge_length, pcb_thick]) cube([width, length-edge_length, 1.2]);
translate([1, edge_length+1, pcb_thick+1.2-0.5]) m2_text(width, length, height, key, key2);
}
} else if (height == "S2") {
difference() {
translate([0, edge_length, pcb_thick]) cube([width, length-edge_length, 1.35]);
translate([1, edge_length+1, pcb_thick+1.35-0.5]) m2_text(width, length, height, key, key2);
}
} else if (height == "S3") {
difference() {
translate([0, edge_length, pcb_thick]) cube([width, length-edge_length, 1.5]);
translate([1, edge_length+1, pcb_thick+1.5-0.5]) m2_text(width, length, height, key, key2);
}
} else if (height == "D1") {
difference() {
translate([0, edge_length, pcb_thick]) cube([width, length-edge_length, 1.2]);
translate([1, edge_length+1, pcb_thick+1.2-0.5]) m2_text(width, length, height, key, key2);
}
translate([0, bottom_edge_keepout, -1.35]) cube([width, length-bottom_edge_keepout, 1.35]);
} else if (height == "D2") {
difference() {
translate([0, edge_length, pcb_thick]) cube([width, length-edge_length, 1.35]);
translate([1, edge_length+1, pcb_thick+1.35-0.5]) m2_text(width, length, height, key, key2);
}
translate([0, bottom_edge_keepout, -1.35]) cube([width, length-bottom_edge_keepout, 1.35]);
} else if (height == "D3") {
difference() {
translate([0, edge_length, pcb_thick]) cube([width, length-edge_length, 1.5]);
translate([1, edge_length+1, pcb_thick+1.5-0.5]) m2_text(width, length, height, key, key2);
}
translate([0, bottom_edge_keepout, -1.35]) cube([width, length-bottom_edge_keepout, 1.35]);
} else if (height == "D4") {
difference() {
translate([0, edge_length, pcb_thick]) cube([width, length-edge_length, 1.5]);
translate([1, edge_length+1, pcb_thick+1.5-0.5]) m2_text(width, length, height, key, key2);
}
translate([0, bottom_edge_keepout, -0.7]) cube([width, length-bottom_edge_keepout, 0.7]);
} else if (height == "D5") {
difference() {
translate([0, edge_length, pcb_thick]) cube([width, length-edge_length, 1.5]);
translate([1, edge_length+1, pcb_thick+1.5-0.5]) m2_text(width, length, height, key, key2);
}
translate([0, bottom_edge_keepout, -1.5]) cube([width, length-bottom_edge_keepout, 1.5]);
} else {
translate([1, edge_length+1, pcb_thick-0.5]) m2_text(width, length, height, key, key2);
}
// The ground pad keepouts
translate([width/2, length, pcb_thick]) cylinder(r = top_gnd_pad_r, h = 10);
translate([width/2, length-bottom_gnd_pad_offset, -10]) {
cylinder(r = bottom_gnd_pad_r, h = 10);
translate([-bottom_gnd_pad_r, 0, 0]) cube([bottom_gnd_pad_r*2, bottom_gnd_pad_offset, 10]);
}
}
}
}
m2(width=22, length=30, height="S3", key="A", key2="E");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.