2019-06-08 17:10:47 -04:00
//
// NopSCADlib Copyright Chris Palmer 2018
// nop.head@gmail.com
// hydraraptor.blogspot.com
//
// This file is part of NopSCADlib.
//
// NopSCADlib is free software: you can redistribute it and/or modify it under the terms of the
// GNU General Public License as published by the Free Software Foundation, either version 3 of
// the License, or (at your option) any later version.
//
// NopSCADlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along with NopSCADlib.
// If not, see <https://www.gnu.org/licenses/>.
//
//
//! PCBs and perfboard with optional components. The shape can be a rectangle with optionally rounded corners or a polygon for odd shapes like Arduino.
//
panel_clearance = 0.2 ;
include < ../core.scad >
include < buttons.scad >
2019-07-04 07:03:38 -04:00
include < green_terminals.scad >
include < pin_headers.scad >
2020-03-02 09:15:51 -05:00
use < microswitch.scad >
2019-07-04 07:03:38 -04:00
2019-06-08 17:10:47 -04:00
use < ../utils/rounded_cylinder.scad >
use < ../utils/dogbones.scad >
2020-02-25 15:39:37 -05:00
use < ../utils/thread.scad >
2019-06-08 17:10:47 -04:00
use < ../utils/tube.scad >
use < d_connector.scad >
2020-04-10 07:39:46 -04:00
use < led.scad >
2020-04-13 13:06:09 -04:00
use < dip.scad >
2020-04-14 13:09:58 -04:00
use < axial.scad >
2020-04-21 06:02:48 -04:00
use < smd.scad >
2019-06-08 17:10:47 -04:00
function pcb_name ( type ) = type [ 1 ] ; //! Description
function pcb_length ( type ) = type [ 2 ] ; //! Length
function pcb_width ( type ) = type [ 3 ] ; //! Width
function pcb_thickness ( type ) = type [ 4 ] ; //! Thickness
function pcb_radius ( type ) = type [ 5 ] ; //! Corner radius
function pcb_hole_d ( type ) = type [ 6 ] ; //! Mounting hole diameter
function pcb_land_d ( type ) = type [ 7 ] ; //! Pad around mounting hole
function pcb_colour ( type ) = type [ 8 ] ; //! Colour of the subtrate
function pcb_parts_on_bom ( type ) = type [ 9 ] ; //! True if the parts should be separate BOM items
function pcb_holes ( type ) = type [ 10 ] ; //! List of hole positions
function pcb_components ( type ) = type [ 11 ] ; //! List of components
function pcb_accessories ( type ) = type [ 12 ] ; //! List of accessories to go on the BOM, SD cards, USB cables, etc.
function pcb_grid ( type ) = type [ 13 ] ; //! Grid if a perfboard
function pcb_polygon ( type ) = type [ 14 ] ; //! Optional outline polygon for odd shaped boards
function pcb_screw ( type , cap = hs_cap ) = Len ( type [ 15 ] ) ? type [ 15 ] : find_screw ( cap , screw_smaller_than ( pcb_hole_d ( type ) ) ) ; //! Mounting screw type
2020-07-04 04:53:09 -04:00
function pcb_size ( type ) = [ pcb_length ( type ) , pcb_width ( type ) , pcb_thickness ( type ) ] ; //! Length, width and thickness in a vector
2019-06-08 17:10:47 -04:00
2019-11-15 08:30:27 -05:00
function pcb_grid_pos ( type , x , y , z = 0 ) = //! Returns a pcb grid position
[ - pcb_length ( type ) / 2 + pcb_grid ( type ) . x + 2.54 * x ,
- pcb_width ( type ) / 2 + pcb_grid ( type ) . y + 2.54 * y , pcb_thickness ( type ) + z ] ;
module pcb_grid ( type , x , y , z = 0 ) //! Positions children at specified grid position
translate ( pcb_grid_pos ( type , x , y , z ) )
2019-06-08 17:10:47 -04:00
children ( ) ;
// allows negative ordinates to represent offsets from the far edge
function pcb_coord ( type , p ) = let ( l = pcb_length ( type ) , w = pcb_width ( type ) ) //! Convert offsets from the edge to coordinates relative to the centre
2019-07-04 07:03:38 -04:00
[ ( p . x >= 0 ? p . x : l + p . x ) - l / 2 ,
( p . y >= 0 ? p . y : w + p . y ) - w / 2 ] ;
2019-06-08 17:10:47 -04:00
2020-03-07 17:11:09 -05:00
module pcb_hole_positions ( type , all = true ) { // Positition children at the hole positions, including holes not used for screws
2019-06-08 17:10:47 -04:00
holes = pcb_holes ( type ) ;
2020-03-07 17:11:09 -05:00
for ( $ i = [ 0 : 1 : len ( holes ) - 1 ] ) {
hole = holes [ $ i ] ;
if ( len ( hole ) = = 2 || all )
translate ( pcb_coord ( type , hole ) )
2019-06-08 17:10:47 -04:00
children ( ) ;
2020-03-07 17:11:09 -05:00
}
2019-06-08 17:10:47 -04:00
}
2020-03-07 17:11:09 -05:00
module pcb_screw_positions ( type ) //! Positions children at the mounting hole positions
pcb_hole_positions ( type , false ) children ( ) ;
2019-07-04 07:03:38 -04:00
module chip ( length , width , thickness , colour , cutout = false ) //! Draw a coloured cube to represent a chip, or other rectangular component
2019-06-08 17:10:47 -04:00
if ( ! cutout )
2019-07-04 07:03:38 -04:00
color ( colour )
2019-06-08 17:10:47 -04:00
translate_z ( thickness / 2 ) cube ( [ length , width , thickness ] , center = true ) ;
2020-04-20 12:51:02 -04:00
module usb_A_tongue ( ) {
l = 9 ;
w = 12 ;
h = 2 ;
color ( "white" )
translate ( [ - 1 , 0 , h / 2 ] )
rotate ( [ 90 , 0 , 90 ] )
hull ( ) {
linear_extrude ( l - 2 )
square ( [ w , h ] , center = true ) ;
linear_extrude ( l )
square ( [ w - 1 , h - 1 ] , center = true ) ;
}
}
2020-02-25 15:39:37 -05:00
module usb_Ax1 ( cutout = false ) { //! Draw USB type A single socket
usb_A ( h = 6.5 , v_flange_l = 4.5 , bar = 0 , cutout = cutout ) ;
}
2019-06-08 17:10:47 -04:00
module usb_Ax2 ( cutout = false ) { //! Draw USB type A dual socket
2020-02-25 15:39:37 -05:00
usb_A ( h = 15.6 , v_flange_l = 12.15 , bar = 3.4 , cutout = cutout ) ;
}
module usb_A ( h , v_flange_l , bar , cutout ) {
2019-06-08 17:10:47 -04:00
l = 17 ;
w = 13.25 ;
flange_t = 0.4 ;
h_flange_h = 0.8 ;
h_flange_l = 11 ;
v_flange_h = 1 ;
socket_h = ( h - 2 * flange_t - bar ) / 2 ;
translate_z ( h / 2 )
if ( cutout )
rotate ( [ 90 , 0 , 90 ] )
rounded_rectangle ( [ w + 2 * v_flange_h + 2 * panel_clearance ,
h + 2 * h_flange_h + 2 * panel_clearance , 100 ] , r = cnc_bit_r , center = false ) ;
2020-04-20 12:51:02 -04:00
else {
2019-06-08 17:10:47 -04:00
color ( "silver" ) rotate ( [ 0 , 90 , 0 ] ) {
2020-03-29 15:18:57 -04:00
linear_extrude ( l , center = true )
2019-06-08 17:10:47 -04:00
difference ( ) {
square ( [ h , w ] , center = true ) ;
for ( s = [ - 1 , 1 ] )
translate ( [ s * ( bar / 2 + socket_h / 2 ) , 0 ] )
square ( [ socket_h , w - 2 * flange_t ] , center = true ) ;
}
translate_z ( - l / 2 + 0.5 )
cube ( [ h , w , 1 ] , center = true ) ;
translate_z ( l / 2 - flange_t )
2020-03-29 15:18:57 -04:00
linear_extrude ( flange_t ) difference ( ) {
2019-06-08 17:10:47 -04:00
union ( ) {
square ( [ h + 2 * h_flange_h , h_flange_l ] , center = true ) ;
square ( [ v_flange_l , w + 2 * v_flange_h ] , center = true ) ;
}
square ( [ h - eps , w - eps ] , center = true ) ;
}
2020-04-20 12:51:02 -04:00
}
for ( z = bar ? [ - 1 , 1 ] : [ 0 ] )
translate_z ( z * ( bar / 2 + socket_h / 2 ) )
usb_A_tongue ( ) ;
}
}
2020-04-20 12:52:37 -04:00
module molex_usb_Ax2 ( cutout ) { //! Draw Molex USB connector suitable for perf board
w = 15.9 ;
h = 16.6 ;
l = 17 ;
pin_l = 2.8 ;
clearance = 0.2 ;
2020-04-20 13:51:26 -04:00
tag_l = 4.4 ;
2020-04-20 12:52:37 -04:00
tag_r = 0.5 ;
tag_w = 1.5 ;
tag_t = 0.3 ;
tag_p = 5.65 ;
if ( cutout )
translate ( [ 0 , - w / 2 - clearance , - clearance ] )
cube ( [ 100 , w + 2 * clearance , h + 2 * clearance ] ) ;
else {
color ( silver )
translate ( [ - l / 2 , 0 ] )
rotate ( [ 90 , 0 , 90 ] )
translate ( [ - w / 2 , 0 ] ) {
cube ( [ w , h , l - 9 ] ) ;
linear_extrude ( l )
difference ( ) {
square ( [ w , h ] ) ;
for ( z = [ - 1 , 1 ] )
translate ( [ w / 2 , h / 2 + z * 8.5 / 2 ] )
square ( [ 12.6 , 5.08 ] , center = true ) ;
}
}
for ( z = [ - 1 , 1 ] )
translate_z ( h / 2 + z * 8.5 / 2 )
usb_A_tongue ( ) ;
color ( silver )
rotate ( - 90 ) {
for ( x = [ - 1.5 : 1 : 1.5 ] , y = [ 0.5 : 1 : 1.5 ] )
translate ( [ inch ( x / 10 ) , - l / 2 + inch ( y / 10 ) ] )
hull ( ) {
cube ( [ 0.6 , 0.3 , 2 * pin_l - 2 ] , center = true ) ;
cube ( [ 0.4 , 0.3 , 2 * pin_l ] , center = true ) ;
}
for ( side = [ - 1 , 1 ] , end = [ 0 , 1 ] )
translate ( [ side * w / 2 , - l / 2 + tag_w / 2 + end * tag_p ] )
rotate ( - side * 90 )
hull ( ) {
translate ( [ 0 , tag_l - tag_r ] )
cylinder ( r = tag_r , h = tag_t ) ;
translate ( [ - tag_w / 2 , 0 ] )
cube ( [ tag_w , eps , tag_t ] ) ;
}
}
}
2019-06-08 17:10:47 -04:00
}
module rj45 ( cutout = false ) { //! Draw RJ45 Ethernet connector
l = 21 ;
w = 16 ;
h = 13.5 ;
plug_h = 6.8 ;
plug_w = 12 ;
plug_z = 4 ;
tab_z = 0.8 ;
tab_w = 4 ;
translate_z ( h / 2 )
if ( cutout )
rotate ( [ 90 , 0 , 90 ] )
dogbone_rectangle ( [ w + 2 * panel_clearance , h + 2 * panel_clearance , 100 ] , center = false ) ;
else {
rotate ( [ 0 , 90 , 0 ] ) {
mouth = plug_z + plug_h - tab_z ;
color ( "silver" ) {
2020-03-29 15:18:57 -04:00
linear_extrude ( l , center = true )
2019-06-08 17:10:47 -04:00
difference ( ) {
square ( [ h , w ] , center = true ) ;
translate ( [ h / 2 - tab_z - mouth / 2 , 0 ] )
square ( [ mouth + 0.1 , plug_w + 0.1 ] , center = true ) ;
}
translate_z ( - l / 2 )
cube ( [ h , w , eps ] , center = true ) ;
}
2020-06-20 05:17:29 -04:00
color ( grey ( 30 ) ) {
2020-03-29 15:18:57 -04:00
linear_extrude ( l - 0.2 , center = true )
2019-06-08 17:10:47 -04:00
difference ( ) {
square ( [ h - 0.1 , w - 0.1 ] , center = true ) ;
translate ( [ h / 2 - plug_z - plug_h / 2 , 0 ] )
square ( [ plug_h , plug_w - 0.1 ] , center = true ) ;
translate ( [ h / 2 - tab_z - plug_h / 2 , 0 ] )
square ( [ plug_h , tab_w ] , center = true ) ;
}
translate_z ( - l / 2 + 1 )
cube ( [ h - 0.1 , w - 0.1 , 0.1 ] , center = true ) ;
}
}
}
}
module jack ( cutout = false ) { //! Draw 3.5mm jack
l = 12 ;
w = 7 ;
h = 6 ;
d = 6 ;
ch = 2.5 ;
translate_z ( h / 2 )
if ( cutout )
rotate ( [ 0 , 90 , 0 ] )
cylinder ( d = d + 2 * panel_clearance , h = 100 ) ;
else
2020-06-20 05:17:29 -04:00
color ( grey ( 20 ) )
2019-06-08 17:10:47 -04:00
rotate ( [ 0 , 90 , 0 ] ) {
2020-03-29 15:18:57 -04:00
linear_extrude ( l / 2 )
2019-06-08 17:10:47 -04:00
difference ( ) {
square ( [ h , w ] , center = true ) ;
circle ( d = 3.5 ) ;
}
tube ( or = d / 2 , ir = 3.5 / 2 , h = l / 2 + ch , center = false ) ;
translate_z ( - l / 4 )
cube ( [ h , w , l / 2 ] , center = true ) ;
}
}
2020-03-29 16:36:11 -04:00
module buzzer ( height , diameter , colour ) { //! Draw PCB buzzer with specified height, diameter and colour
2020-01-15 10:50:18 -05:00
color ( colour )
2020-02-25 15:39:37 -05:00
tube ( or = diameter / 2 , ir = height > 5 ? 1 : 0.75 , h = height , center = false ) ;
2020-01-15 10:50:18 -05:00
color ( "white" )
cylinder ( d = 2 , h = max ( height - 3 , 0.5 ) ) ;
}
2020-02-25 15:39:37 -05:00
module potentiometer ( h1 , h2 ) {
color ( "silver" ) {
baseSize = [ 12 , 11 , 6 ] ;
translate_z ( baseSize . z / 2 )
cube ( baseSize , center = true ) ;
translate_z ( baseSize . z ) {
cylinder ( d = 5 , h = h1 - 0.5 ) ;
if ( show_threads )
male_metric_thread ( 6 , metric_coarse_pitch ( 5 ) , length = h1 - 0.5 , center = false ) ;
}
translate_z ( baseSize . z + h1 - 0.5 )
cylinder ( d = 3 , h = 0.5 ) ;
translate_z ( baseSize . z + h1 )
linear_extrude ( h2 )
difference ( ) {
circle ( d = 5 ) ;
square ( [ 0.75 , 5 ] , center = true ) ;
}
}
}
2019-09-14 18:26:26 -04:00
function hdmi_depth ( type ) = type [ 2 ] ; //! Front to back depth
function hdmi_width1 ( type ) = type [ 3 ] ; //! Inside width at the top
function hdmi_width2 ( type ) = type [ 4 ] ; //! Inside width at the bottom
function hdmi_height1 ( type ) = type [ 5 ] ; //! Inside height at the sides
function hdmi_height2 ( type ) = type [ 6 ] ; //! Inside height in the middle
function hdmi_height ( type ) = type [ 7 ] ; //! Outside height above the PCB
function hdmi_thickness ( type ) = type [ 8 ] ; //! Wall thickness of the metal
hdmi_full = [ "hdmi_full" , "HDMI socket" , 12 , 14 , 10 , 3 , 4.5 , 6.5 , 0.5 ] ;
hdmi_mini = [ "hdmi_mini" , "Mini HDMI socket" , 7.5 , 10.5 , 8.3 , 1.28 , 2.5 , 3.2 , 0.35 ] ;
module hdmi ( type , cutout = false ) { //! Draw HDMI socket
vitamin ( str ( "hdmi(" , type [ 0 ] , "): " , type [ 1 ] ) ) ;
l = hdmi_depth ( type ) ;
iw1 = hdmi_width1 ( type ) ;
iw2 = hdmi_width2 ( type ) ;
ih1 = hdmi_height1 ( type ) ;
ih2 = hdmi_height2 ( type ) ;
h = hdmi_height ( type ) ;
t = hdmi_thickness ( type ) ;
2019-06-08 17:10:47 -04:00
module D ( ) {
hull ( ) {
translate ( [ - iw1 / 2 , h - t - ih1 ] )
square ( [ iw1 , ih1 ] ) ;
translate ( [ - iw2 / 2 , h - t - ih2 ] )
square ( [ iw2 , ih2 ] ) ;
}
}
if ( cutout )
rotate ( [ 90 , 0 , 90 ] )
2020-03-29 15:18:57 -04:00
linear_extrude ( 100 )
2019-06-08 17:10:47 -04:00
offset ( t + panel_clearance )
D ( ) ;
else
color ( "silver" )
rotate ( [ 90 , 0 , 90 ] ) {
2020-03-29 15:18:57 -04:00
linear_extrude ( l , center = true )
2019-06-08 17:10:47 -04:00
difference ( ) {
offset ( t )
D ( ) ;
D ( ) ;
}
translate_z ( - l / 2 )
2020-03-29 15:18:57 -04:00
linear_extrude ( 1 )
2019-06-08 17:10:47 -04:00
offset ( t )
D ( ) ;
}
}
module usb_uA ( cutout = false ) { //! Draw USB micro A connector
l = 6 ;
iw1 = 7 ;
iw2 = 5.7 ;
ih1 = 1 ;
ih2 = 1.85 ;
h = 2.65 ;
t = 0.4 ;
flange_h = 3 ;
flange_w = 8 ;
module D ( ) {
hull ( ) {
translate ( [ - iw1 / 2 , h - t - ih1 ] )
square ( [ iw1 , ih1 ] ) ;
translate ( [ - iw2 / 2 , h - t - ih2 ] )
square ( [ iw2 , ih2 ] ) ;
}
}
if ( cutout )
rotate ( [ 90 , 0 , 90 ] )
2020-03-29 15:18:57 -04:00
linear_extrude ( 100 )
2019-06-08 17:10:47 -04:00
offset ( ( flange_h - ih2 ) / 2 + 2 * panel_clearance )
D ( ) ;
else
color ( "silver" ) rotate ( [ 90 , 0 , 90 ] ) {
2020-03-29 15:18:57 -04:00
linear_extrude ( l , center = true )
2019-06-08 17:10:47 -04:00
difference ( ) {
offset ( t )
D ( ) ;
D ( ) ;
}
translate_z ( - l / 2 )
2020-03-29 15:18:57 -04:00
linear_extrude ( 1 )
2019-06-08 17:10:47 -04:00
offset ( t )
D ( ) ;
translate_z ( l / 2 - t )
2020-03-29 15:18:57 -04:00
linear_extrude ( t ) difference ( ) {
2019-06-08 17:10:47 -04:00
union ( ) {
translate ( [ 0 , h - t - ih1 / 2 ] )
square ( [ flange_w , ih1 ] , center = true ) ;
translate ( [ 0 , h / 2 + flange_h / 4 ] )
square ( [ iw1 , flange_h / 2 ] , center = true ) ;
translate ( [ 0 , h / 2 - flange_h / 4 ] )
square ( [ iw2 , flange_h / 2 ] , center = true ) ;
}
D ( ) ;
}
}
}
module usb_B ( cutout = false ) { //! Draw USB B connector
l = 16.4 ;
w = 12.2 ;
h = 11 ;
tab_w = 5.6 ;
tab_h = 3.2 ;
d_h = 7.78 ;
d_w = 8.45 ;
d_w2 = 5 ;
d_h2 = d_h - ( d_w - d_w2 ) / 2 ;
module D ( )
hull ( ) {
translate ( [ - d_w / 2 , 0 ] )
square ( [ d_w , d_h2 ] ) ;
translate ( [ - d_w2 / 2 , 0 ] )
square ( [ d_w2 , d_h ] ) ;
}
if ( cutout )
translate ( [ 50 , 0 , h / 2 - panel_clearance ] )
cube ( [ 100 , w + 2 * panel_clearance , h + 2 * panel_clearance ] , center = true ) ;
else
translate_z ( h / 2 ) rotate ( [ 90 , 0 , 90 ] ) {
color ( "silver" ) {
2020-03-29 15:18:57 -04:00
linear_extrude ( l , center = true )
2019-06-08 17:10:47 -04:00
difference ( ) {
square ( [ w , h ] , center = true ) ;
translate ( [ 0 , - d_h / 2 ] )
offset ( delta = 0.2 )
D ( ) ;
}
translate_z ( - l / 2 + 0.1 )
cube ( [ w , h , 0.2 ] , center = true ) ;
}
color ( "white" ) {
2020-03-29 15:18:57 -04:00
linear_extrude ( l - 0.4 , center = true )
2019-06-08 17:10:47 -04:00
difference ( ) {
square ( [ w - 0.2 , h - 0.2 ] , center = true ) ;
translate ( [ 0 , - d_h / 2 ] )
difference ( ) {
D ( ) ;
translate ( [ 0 , d_h / 2 ] )
square ( [ tab_w , tab_h ] , center = true ) ;
}
}
translate_z ( - ( l - 0.4 ) / 2 + 1 )
cube ( [ w - 0.2 , h - 0.2 , 2 ] , center = true ) ;
}
}
}
module barrel_jack ( cutout = false ) { //! Draw barrel power jack
l = 13.2 ;
w = 8.89 ;
h = 11 ;
bore_d = 6.3 ;
bore_h = 6.5 ;
bore_l = 11.8 ;
pin_d = 2 ;
front = 3.3 ;
r = 0.5 ;
contact_d = 2 ;
contact_w = 4 ;
inset = 1 ;
if ( cutout )
;
else {
2020-06-20 05:17:29 -04:00
color ( grey ( 20 ) ) rotate ( [ 0 , 90 , 0 ] ) {
2020-03-29 15:18:57 -04:00
linear_extrude ( l , center = true ) {
2019-06-08 17:10:47 -04:00
difference ( ) {
translate ( [ - h / 2 , 0 ] )
rounded_square ( [ h , w ] , r ) ;
translate ( [ - bore_h , 0 ] )
circle ( d = bore_d ) ;
translate ( [ - h / 2 - bore_h , 0 ] )
square ( [ h , w ] , center = true ) ;
}
}
translate_z ( l / 2 - front )
2020-03-29 15:18:57 -04:00
linear_extrude ( front ) {
2019-06-08 17:10:47 -04:00
difference ( ) {
translate ( [ - h / 2 , 0 ] )
rounded_square ( [ h , w ] , r ) ;
translate ( [ - bore_h , 0 ] )
circle ( d = bore_d ) ;
}
}
translate ( [ - bore_h , 0 ] )
tube ( or = w / 2 - 0.5 , ir = bore_d / 2 , h = l ) ;
translate ( [ - bore_h , 0 , - l / 2 ] )
cylinder ( d = w - 1 , h = l - bore_l ) ;
}
color ( "silver" ) {
translate ( [ l / 2 - inset - pin_d / 2 , 0 , bore_h ] )
hull ( ) {
sphere ( pin_d / 2 ) ;
rotate ( [ 0 , - 90 , 0 ] )
cylinder ( d = pin_d , h = bore_l - inset ) ;
}
hull ( ) {
translate ( [ l / 2 - inset - contact_d / 2 , 0 , bore_h - bore_d / 2 ] )
rotate ( [ 90 , 0 , 0 ] )
cylinder ( d = contact_d , h = contact_w , center = true ) ;
translate ( [ l / 2 - bore_l , 0 , bore_h - bore_d / 2 + contact_d / 4 ] )
cube ( [ eps , contact_w , eps ] , center = true ) ;
}
}
}
}
2019-07-04 07:03:38 -04:00
module uSD ( size , cutout = false ) { //! Draw uSD socket
min_w = 12 ;
w = size . x - min_w ;
t = 0.15 ;
if ( cutout )
;
else
translate_z ( size . z / 2 ) {
color ( "silver" )
rotate ( [ 90 , 0 , 90 ] ) {
2020-03-29 15:18:57 -04:00
linear_extrude ( size . y , center = true )
2019-07-04 07:03:38 -04:00
difference ( ) {
square ( [ size . x , size . z ] , center = true ) ;
square ( [ size . x - 2 * t , size . z - 2 * t ] , center = true ) ;
}
translate_z ( - size . y / 2 + t / 2 )
cube ( [ size . x , size . z , t ] , center = true ) ;
}
if ( w > 0 )
2020-06-20 05:17:29 -04:00
color ( grey ( 20 ) )
2019-07-04 07:03:38 -04:00
rotate ( [ 90 , 0 , 90 ] )
translate_z ( t )
2020-03-29 15:18:57 -04:00
linear_extrude ( size . y - t , center = true )
2019-07-04 07:03:38 -04:00
difference ( ) {
square ( [ size . x - 2 * t , size . z - 2 * t ] , center = true ) ;
translate ( [ - size . x / 2 + min_w / 2 + 0.7 , size . z / 2 - t ] )
square ( [ min_w , 2.2 ] , center = true ) ;
}
}
}
2019-06-08 17:10:47 -04:00
module flex ( cutout = false ) { //! Draw flexistrip connector
l = 20.6 ;
w = 3 ;
h = 5.6 ;
top_l = 22.4 ;
top_t = 1.1 ;
tab_l = 13 ;
tab_w = 1 ;
slot_l = 16.4 ;
slot_w = 0.7 ;
slot_offset = 0.6 ;
if ( cutout )
;
else {
2020-06-20 05:17:29 -04:00
color ( grey ( 30 ) ) {
2019-06-08 17:10:47 -04:00
translate_z ( 0.5 )
cube ( [ l , w , 1 ] , center = true ) ;
2020-03-29 15:18:57 -04:00
linear_extrude ( h )
2019-06-08 17:10:47 -04:00
difference ( ) {
square ( [ l , w ] , center = true ) ;
translate ( [ 0 , - w / 2 + slot_offset + slot_w / 2 ] )
square ( [ slot_l , slot_w ] , center = true ) ;
}
translate_z ( h - top_t )
2020-03-29 15:18:57 -04:00
linear_extrude ( top_t )
2019-06-08 17:10:47 -04:00
difference ( ) {
union ( ) {
square ( [ top_l , w ] , center = true ) ;
hull ( ) {
translate ( [ 0 , - w / 2 + ( w + tab_w ) / 2 ] )
square ( [ tab_l - 1 , w + tab_w ] , center = true ) ;
square ( [ tab_l , w ] , center = true ) ;
}
}
translate ( [ 0 , - w / 2 + slot_offset + slot_w / 2 ] )
square ( [ slot_l , slot_w ] , center = true ) ;
}
}
}
}
2020-06-29 18:01:34 -04:00
small_ff = [ [ 11.8 , 0.9 ] , [ 17 , 1.4 , 1.2 ] , [ 12 , 1.6 , 1.2 ] , [ 16 , 1.1 , 1.2 ] ] ;
2020-07-04 09:14:25 -04:00
large_ff = [ [ 16 , 1.25 ] , [ 22 , 1.5 , 2.5 ] , [ 16 , 4.0 , 2.5 ] , [ 21 , 0 , 2.5 ] ] ;
2019-09-14 18:26:26 -04:00
2020-06-29 18:01:34 -04:00
function ff_slot ( type ) = type [ 0 ] ; //! Flat flex slot size
function ff_latch ( type ) = type [ 1 ] ; //! Flat flex latch size
function ff_mid ( type ) = type [ 2 ] ; //! Flat flex middle section size
function ff_back ( type ) = type [ 3 ] ; //! Flat flex back section size
2019-09-14 18:26:26 -04:00
2020-06-29 18:01:34 -04:00
module flat_flex ( type , cutout = false ) { //! Draw flat flexistrip connector as used on RPI0
slot = ff_slot ( type ) ;
latch = ff_latch ( type ) ;
mid = ff_mid ( type ) ;
back = ff_back ( type ) ;
2019-09-14 18:26:26 -04:00
2020-06-29 18:01:34 -04:00
w = latch . y + mid . y + back . y ;
2019-09-14 18:26:26 -04:00
if ( cutout )
;
else {
2020-06-29 18:01:34 -04:00
color ( grey ( 30 ) )
translate ( [ 0 , w / 2 - latch . y ] )
rotate ( [ 90 , 0 , 180 ] )
linear_extrude ( latch . y )
2019-09-14 18:26:26 -04:00
difference ( ) {
2020-06-29 18:01:34 -04:00
translate ( [ - latch . x / 2 , 0 ] )
square ( [ latch . x , latch . z ] ) ;
2019-09-14 18:26:26 -04:00
2020-06-29 18:01:34 -04:00
square ( [ slot . x , slot . y * 2 ] , center = true ) ;
2019-09-14 18:26:26 -04:00
}
2020-06-29 18:01:34 -04:00
color ( "ivory" ) {
translate ( [ - back . x / 2 , - w / 2 ] )
if ( back . y )
cube ( back ) ;
2019-09-14 18:26:26 -04:00
2020-06-29 18:01:34 -04:00
translate ( [ - mid . x / 2 , - w / 2 + back . y ] )
cube ( mid ) ;
2019-09-14 18:26:26 -04:00
}
2020-06-29 18:01:34 -04:00
color ( grey ( 80 ) )
2020-07-04 09:14:25 -04:00
translate ( [ - back . x / 2 , - w / 2 + back . y + eps ] )
cube ( [ back . x , mid . y - 2 * eps , mid . z - eps ] ) ;
2019-09-14 18:26:26 -04:00
}
}
2020-02-26 02:19:55 -05:00
module terminal_35 ( ways , colour = "blue" ) { //! Draw 3.5mm terminal block
2019-06-08 17:10:47 -04:00
vitamin ( str ( "terminal_35(" , ways , "): Terminal block " , ways , " way 3.5mm" ) ) ;
pitch = 3.5 ;
width = ways * pitch ;
depth = 7 ;
height = 8.3 ;
chamfer_h = 3 ;
chamfer_d = 1 ;
box_z = 0.5 ;
box_w = 2.88 ;
box_h = 4.1 ;
wire_z = 2 ;
wire_d = 2 ;
pin_l = 4.2 ;
pin_d = 0.9 ;
module single ( ) {
screw_r = 1 ;
2020-02-26 02:19:55 -05:00
color ( colour ) {
2019-06-08 17:10:47 -04:00
rotate ( [ 90 , 0 , 0 ] )
2020-03-29 15:18:57 -04:00
linear_extrude ( pitch , center = true )
2019-06-08 17:10:47 -04:00
polygon ( points = [
[ depth / 2 , 0 ] ,
[ depth / 2 , box_z ] ,
[ - depth / 2 + 1 , box_z ] ,
[ - depth / 2 + 1 , box_z + box_h ] ,
[ depth / 2 , box_z + box_h ] ,
[ depth / 2 , height - chamfer_h ] ,
[ depth / 2 - chamfer_d , height ] ,
[ - screw_r - eps , height ] ,
[ - screw_r - eps , box_z + box_h ] ,
[ screw_r + eps , box_z + box_h ] ,
[ screw_r + eps , height ] ,
[ - depth / 2 , height ] ,
[ - depth / 2 , 0 ] ,
] ) ;
2020-03-29 15:18:57 -04:00
linear_extrude ( box_z + box_h )
2019-06-08 17:10:47 -04:00
difference ( ) {
square ( [ depth , pitch ] , center = true ) ;
translate ( [ 1 , 0 ] )
square ( [ depth , box_w ] , center = true ) ;
}
translate_z ( box_z + box_h )
2020-03-29 15:18:57 -04:00
linear_extrude ( height - box_z - box_h )
2019-06-08 17:10:47 -04:00
difference ( ) {
square ( [ 2 * screw_r + 0.1 , pitch ] , center = true ) ;
circle ( screw_r ) ;
}
}
color ( "silver" ) {
screw_z = box_z + box_h ;
translate_z ( screw_z ) {
cylinder ( r = screw_r , h = height - screw_z - 1 ) ; // screw
2020-03-29 15:18:57 -04:00
linear_extrude ( height - screw_z - 0.5 )
2019-06-08 17:10:47 -04:00
difference ( ) {
circle ( 1 ) ;
square ( [ 4 , 0.5 ] , center = true ) ; // screw slot
square ( [ 0.5 , 1.7 ] , center = true ) ; // second screw slot
}
}
translate_z ( box_z - pin_l )
cylinder ( d = pin_d , h = pin_l + box_z , $fn = 16 ) ; // pin
translate_z ( box_z + box_h / 2 ) // terminal
rotate ( [ 0 , - 90 , 0 ] ) {
2020-03-29 15:18:57 -04:00
linear_extrude ( depth - 2 , center = true )
2019-06-08 17:10:47 -04:00
difference ( ) {
square ( [ box_h , box_w ] , center = true ) ;
translate ( [ wire_z - box_z - box_h / 2 , 0 ] )
circle ( d = wire_d ) ;
}
translate_z ( depth / 2 - 1.5 )
cube ( [ box_h , box_w , 1 ] , center = true ) ;
}
}
}
for ( i = [ 0 : ways - 1 ] )
translate ( [ 0 , i * pitch - width / 2 + pitch / 2 ] )
single ( ) ;
}
module molex_254 ( ways ) { //! Draw molex header
vitamin ( str ( "molex_254(" , ways , "): Molex KK header " , ways , " way" ) ) ;
pitch = 2.54 ;
width = ways * pitch - 0.1 ;
depth = 6.35 ;
height = 8.15 ;
base = 3.18 ;
back = 1 ;
below = 2.3 ;
above = 9 ;
color ( "white" )
union ( ) {
translate ( [ - depth / 2 , - width / 2 , ] )
cube ( [ depth , width , base ] ) ;
w = width - pitch ;
translate ( [ - depth / 2 , - w / 2 ] )
cube ( [ back , w , height ] ) ;
}
color ( "silver" )
for ( i = [ 0 : ways - 1 ] )
translate ( [ 0 , i * pitch - width / 2 + pitch / 2 , ( above + below ) / 2 - below ] )
cube ( [ 0.44 , 0.75 , above + below ] , center = true ) ;
}
2020-03-27 13:28:20 -04:00
module standoff ( h , d , h2 , d2 ) { //! Draw a standoff
2019-07-04 07:03:38 -04:00
color ( "white" ) {
cylinder ( d = d , h = h ) ;
hull ( ) {
translate_z ( - ( h2 - h ) / 2 + d2 / 2 )
sphere ( d = d2 ) ;
translate_z ( h + ( h2 - h ) / 2 - d2 / 2 )
sphere ( d = d2 ) ;
}
}
}
2020-03-28 06:51:43 -04:00
module trimpot10 ( vertical , cutout = false ) { //! Draw a ten turn trimpot
2020-03-27 13:28:20 -04:00
l = 10 ;
w = 9.5 ;
h = 4.8 ;
foot_w = 1 ;
foot_h = 0.5 ;
screw_h = 1.5 ;
screw_d = 2.25 ;
slot_w = 0.6 ;
slot_h = 0.8 ;
2020-03-28 06:51:43 -04:00
module screw_pos ( )
translate ( [ - w / 2 + screw_d / 2 , - l / 2 , h - screw_d / 2 ] )
rotate ( [ 90 , 0 , 0 ] )
children ( ) ;
2020-03-27 13:28:20 -04:00
translate ( vertical ? [ 0 , - h / 2 , l / 2 ] : [ 0 , 0 ] )
rotate ( [ vertical ? - 90 : 0 , 0 , 0 ] ) {
2020-03-28 06:51:43 -04:00
if ( cutout )
screw_pos ( )
2020-04-23 18:13:10 -04:00
poly_drill ( r = ( screw_d + 1 ) / 2 , h = 100 , center = false ) ;
2020-03-28 06:51:43 -04:00
else
color ( "#2CA1FD" ) {
translate ( [ 0 , - foot_h / 2 , foot_h / 2 + h / 2 ] )
cube ( [ w , l - foot_h , h - foot_h ] , center = true ) ;
for ( x = [ - 1 , 1 ] , y = [ - 1 , 1 ] )
translate ( [ x * ( w - foot_w ) / 2 , y * ( l - foot_w ) / 2 , h / 2 ] )
cube ( [ foot_w , foot_w , h ] , center = true ) ;
2020-03-27 13:28:20 -04:00
2020-03-28 06:51:43 -04:00
}
2020-03-27 13:28:20 -04:00
2020-03-28 06:51:43 -04:00
color ( brass )
screw_pos ( ) {
2020-03-27 13:28:20 -04:00
cylinder ( d = screw_d , h = screw_h - slot_h ) ;
2020-03-29 15:18:57 -04:00
linear_extrude ( screw_h )
2020-03-27 13:28:20 -04:00
difference ( ) {
circle ( d = screw_d ) ;
square ( [ slot_w , screw_d + 1 ] , center = true ) ;
}
}
2020-03-28 06:51:43 -04:00
}
2020-03-27 13:28:20 -04:00
}
2020-04-30 08:31:20 -04:00
module block ( size , colour , makes_cutout , cutouts ) //! Draw a coloured cube to represent a random PCB component
if ( cutouts ) {
if ( makes_cutout )
translate ( [ - 50 , 0 , size . z / 2 - panel_clearance ] )
cube ( [ 100 , size . y + 2 * panel_clearance , size . z + 2 * panel_clearance ] , center = true ) ;
}
else
color ( colour )
translate_z ( size . z / 2 )
cube ( size , center = true ) ;
2019-06-08 17:10:47 -04:00
module pcb_component ( comp , cutouts = false , angle = undef ) { //! Draw pcb component from description
function show ( comp , part ) = ( comp [ 3 ] = = part || comp [ 3 ] = = str ( "-" , part ) ) && ( ! cutouts || angle = = undef || angle = = comp . z ) ;
2019-10-22 11:17:22 -04:00
function param ( n , default = 0 ) = len ( comp ) > n ? comp [ n ] : default ;
2019-06-08 17:10:47 -04:00
rotate ( comp . z ) {
2020-04-30 08:31:20 -04:00
// Components that have a cutout parameter go in this section
2020-05-18 10:27:22 -04:00
if ( show ( comp , "2p54header" ) ) pin_header ( 2 p54header , comp [ 4 ] , comp [ 5 ] , param ( 6 , false ) , false , cutouts , colour = param ( 7 , undef ) ) ;
if ( show ( comp , "2p54boxhdr" ) ) box_header ( 2 p54header , comp [ 4 ] , comp [ 5 ] , param ( 6 , false ) , cutouts ) ;
if ( show ( comp , "2p54socket" ) ) pin_socket ( 2 p54header , comp [ 4 ] , comp [ 5 ] , param ( 6 , false ) , param ( 7 , 0 ) , param ( 8 , false ) , cutouts , param ( 9 , undef ) ) ;
2020-06-20 05:17:29 -04:00
if ( show ( comp , "chip" ) ) chip ( comp [ 4 ] , comp [ 5 ] , comp [ 6 ] , param ( 7 , grey ( 30 ) ) , cutouts ) ;
2020-04-30 08:31:20 -04:00
if ( show ( comp , "rj45" ) ) rj45 ( cutouts ) ;
if ( show ( comp , "usb_A" ) ) usb_Ax1 ( cutouts ) ;
if ( show ( comp , "usb_Ax2" ) ) usb_Ax2 ( cutouts ) ;
if ( show ( comp , "usb_uA" ) ) usb_uA ( cutouts ) ;
if ( show ( comp , "usb_B" ) ) usb_B ( cutouts ) ;
if ( show ( comp , "jack" ) ) jack ( cutouts ) ;
if ( show ( comp , "barrel_jack" ) ) barrel_jack ( cutouts ) ;
if ( show ( comp , "hdmi" ) ) hdmi ( hdmi_full , cutouts ) ;
if ( show ( comp , "mini_hdmi" ) ) hdmi ( hdmi_mini , cutouts ) ;
if ( show ( comp , "flex" ) ) flex ( cutouts ) ;
2020-06-29 18:01:34 -04:00
if ( show ( comp , "flat_flex" ) ) flat_flex ( param ( 4 , false ) ? large_ff : small_ff , cutouts ) ;
2020-04-30 08:31:20 -04:00
if ( show ( comp , "uSD" ) ) uSD ( comp [ 4 ] , cutouts ) ;
if ( show ( comp , "trimpot10" ) ) trimpot10 ( param ( 4 , false ) , cutouts ) ;
2020-04-20 12:52:37 -04:00
if ( show ( comp , "molex_usb_Ax2" ) ) molex_usb_Ax2 ( cutouts ) ;
2020-04-30 08:31:20 -04:00
if ( show ( comp , "smd_led" ) ) smd_led ( comp [ 4 ] , comp [ 5 ] , cutouts ) ;
if ( show ( comp , "block" ) ) block ( size = [ comp [ 4 ] , comp [ 5 ] , comp [ 6 ] ] , colour = comp [ 7 ] , makes_cutout = param ( 8 ) ) ;
if ( ! cutouts ) {
// Components that don't have a cutout parameter go in this section
if ( show ( comp , "button_6mm" ) ) square_button ( button_6mm ) ;
if ( show ( comp , "microswitch" ) ) translate_z ( microswitch_thickness ( comp [ 4 ] ) / 2 ) microswitch ( comp [ 4 ] ) ;
if ( show ( comp , "pcb" ) ) translate_z ( comp [ 4 ] ) pcb ( comp [ 5 ] ) ;
if ( show ( comp , "standoff" ) ) standoff ( comp [ 4 ] , comp [ 5 ] , comp [ 6 ] , comp [ 7 ] ) ;
if ( show ( comp , "term254" ) ) green_terminal ( gt_2p54 , comp [ 4 ] , comp [ 5 ] , param ( 6 , "lime" ) ) ;
if ( show ( comp , "gterm" ) ) green_terminal ( comp [ 4 ] , comp [ 5 ] , comp [ 6 ] , param ( 7 , "lime" ) ) ;
if ( show ( comp , "gterm35" ) ) green_terminal ( gt_3p5 , comp [ 4 ] , comp [ 5 ] , param ( 6 , "lime" ) ) ;
if ( show ( comp , "gterm508" ) ) green_terminal ( gt_5p08 , comp [ 4 ] , comp [ 5 ] , param ( 6 , "lime" ) ) ;
if ( show ( comp , "gterm635" ) ) green_terminal ( gt_6p35 , comp [ 4 ] , comp [ 5 ] , param ( 6 , "lime" ) ) ;
if ( show ( comp , "term35" ) ) terminal_35 ( comp [ 4 ] , param ( 5 , "blue" ) ) ;
if ( show ( comp , "transition" ) ) idc_transition ( 2 p54header , comp [ 4 ] , comp [ 5 ] ) ;
if ( show ( comp , "led" ) ) led ( comp [ 4 ] , comp [ 5 ] , 2.6 ) ;
if ( show ( comp , "pdip" ) ) pdip ( comp [ 4 ] , comp [ 5 ] , param ( 6 , false ) , param ( 7 , inch ( 0.3 ) ) ) ;
if ( show ( comp , "ax_res" ) ) ax_res ( comp [ 4 ] , comp [ 5 ] , param ( 6 , 5 ) , param ( 7 , 0 ) ) ;
if ( show ( comp , "D_plug" ) ) translate_z ( d_pcb_offset ( comp [ 4 ] ) ) d_plug ( comp [ 4 ] , pcb = true ) ;
if ( show ( comp , "molex_hdr" ) ) molex_254 ( comp [ 4 ] ) ;
if ( show ( comp , "jst_xh" ) ) jst_xh_header ( jst_xh_header , comp [ 4 ] , param ( 5 , false ) , param ( 6 , "white" ) , param ( 7 , undef ) ) ;
if ( show ( comp , "potentiometer" ) ) potentiometer ( param ( 4 , 5 ) , param ( 5 , 9 ) ) ;
2020-06-20 05:17:29 -04:00
if ( show ( comp , "buzzer" ) ) buzzer ( param ( 4 , 9 ) , param ( 5 , 12 ) , param ( 6 , grey ( 20 ) ) ) ;
2020-06-27 14:59:49 -04:00
if ( show ( comp , "smd_res" ) ) smd_resistor ( comp [ 4 ] , comp [ 5 ] ) ;
2020-04-30 08:31:20 -04:00
}
2019-06-08 17:10:47 -04:00
}
}
2019-11-15 08:30:27 -05:00
function pcb_component_position ( type , name , index = 0 ) = //! Return x y position of specified component
[ for ( comp = pcb_components ( type ) , p = [ pcb_coord ( type , [ comp . x , comp . y ] ) ] ) if ( comp [ 3 ] = = name ) [ p . x , p . y ] ] [ index ] ;
2019-10-22 11:17:22 -04:00
2019-08-18 07:19:48 -04:00
module pcb_component_position ( type , name ) { //! Position child at the specified component position
for ( comp = pcb_components ( type ) ) {
p = pcb_coord ( type , [ comp . x , comp . y ] ) ;
if ( comp [ 3 ] [ 0 ] = = "-" ) {
if ( comp [ 3 ] = = str ( "-" , name ) )
translate ( [ p . x , p . y ] )
vflip ( )
children ( ) ;
}
else
if ( comp [ 3 ] = = name )
translate ( [ p . x , p . y , pcb_thickness ( type ) ] )
children ( ) ;
}
}
2019-06-08 17:10:47 -04:00
module pcb_components ( type , cutouts = false , angle = undef ) { //! Draw list of PCB components on the PCB
not_on_bom ( pcb_parts_on_bom ( type ) )
for ( comp = pcb_components ( type ) ) {
p = pcb_coord ( type , [ comp . x , comp . y ] ) ;
if ( comp [ 3 ] [ 0 ] = = "-" )
translate ( [ p . x , p . y ] )
vflip ( )
pcb_component ( comp , cutouts , angle ) ;
else
translate ( [ p . x , p . y , pcb_thickness ( type ) ] )
pcb_component ( comp , cutouts , angle ) ;
}
}
module pcb_cutouts ( type , angle = undef ) pcb_components ( type , true , angle ) ; //! Make cut outs to clear components on a PCB
module pcb_grid_positions ( type ) {
2019-09-14 18:26:26 -04:00
grid = pcb_grid ( type ) ;
x0 = grid . x ;
y0 = grid . y ;
2019-06-08 17:10:47 -04:00
2019-09-14 18:26:26 -04:00
cols = is_undef ( grid [ 2 ] ) ? round ( ( pcb_length ( type ) - 2 * x0 ) / inch ( 0.1 ) ) : grid [ 2 ] - 1 ;
rows = is_undef ( grid [ 3 ] ) ? round ( ( pcb_width ( type ) - 2 * y0 ) / inch ( 0.1 ) ) : grid [ 3 ] - 1 ;
2019-06-08 17:10:47 -04:00
for ( x = [ 0 : cols ] , y = [ 0 : rows ] )
pcb_grid ( type , x , y )
children ( ) ;
}
module pcb ( type ) { //! Draw specified PCB
grid = pcb_grid ( type ) ;
t = pcb_thickness ( type ) ;
if ( pcb_name ( type ) )
vitamin ( str ( "pcb(" , type [ 0 ] , "): " , pcb_name ( type ) ) ) ;
for ( part = pcb_accessories ( type ) )
vitamin ( part ) ;
pcb_components ( type ) ;
2020-03-29 15:18:57 -04:00
color ( pcb_colour ( type ) ) linear_extrude ( t ) difference ( ) {
2019-06-08 17:10:47 -04:00
if ( Len ( pcb_polygon ( type ) ) )
polygon ( pcb_polygon ( type ) ) ;
else
rounded_square ( [ pcb_length ( type ) , pcb_width ( type ) ] , r = pcb_radius ( type ) ) ;
2020-03-07 17:11:09 -05:00
pcb_hole_positions ( type )
2019-06-08 17:10:47 -04:00
circle ( d = pcb_hole_d ( type ) + eps ) ;
if ( Len ( grid ) )
pcb_grid_positions ( type )
circle ( d = 1 + eps ) ;
}
2020-03-27 13:29:50 -04:00
land = pcb_land_d ( type ) ;
hole = pcb_hole_d ( type ) ;
2019-06-08 17:10:47 -04:00
color ( "silver" )
translate_z ( t / 2 )
2020-03-07 17:11:09 -05:00
pcb_hole_positions ( type )
2020-03-27 13:29:50 -04:00
if ( is_list ( land ) )
2020-03-29 15:18:57 -04:00
linear_extrude ( t + 2 * eps , center = true )
2020-03-27 13:29:50 -04:00
difference ( ) {
square ( land , center = true ) ;
circle ( d = hole ) ;
}
else
tube ( or = max ( land , 1 ) / 2 , ir = hole / 2 , h = t + 2 * eps ) ;
2019-06-08 17:10:47 -04:00
2019-11-15 08:30:27 -05:00
fr4 = pcb_colour ( type ) ! = "sienna" ;
2019-06-08 17:10:47 -04:00
plating = 0.15 ;
2019-11-15 08:30:27 -05:00
color ( pcb_colour ( type ) = = "green" ? "silver" : "gold" )
2019-06-08 17:10:47 -04:00
translate_z ( - plating )
2020-03-29 15:18:57 -04:00
linear_extrude ( fr4 ? t + 2 * plating : plating )
2019-06-08 17:10:47 -04:00
if ( Len ( grid ) ) {
pcb_grid_positions ( type )
difference ( ) {
circle ( d = 2 ) ;
circle ( d = 1 ) ;
}
2019-09-14 18:26:26 -04:00
if ( fr4 && len ( grid ) < 3 ) { // oval lands at the ends
2019-06-08 17:10:47 -04:00
screw_x = pcb_coord ( type , pcb_holes ( type ) [ 0 ] ) . x ;
y0 = pcb_grid ( type ) . y ;
rows = round ( ( pcb_width ( type ) - 2 * y0 ) / inch ( 0.1 ) ) ;
for ( end = [ - 1 , 1 ] , y = [ 1 : rows - 1 ] )
translate ( [ end * screw_x , y0 + y * inch ( 0.1 ) - pcb_width ( type ) / 2 ] )
hull ( )
for ( x = [ - 1 , 1 ] )
translate ( [ x * 1.6 / 2 , 0 ] )
circle ( d = 2 ) ;
}
}
}
2019-07-25 16:20:41 -04:00
module pcb_spacer ( screw , height , wall = 1.8 , taper = 0 ) { //! Generate STL for PCB spacer
stl ( str ( "pcb_spacer" , round ( screw_radius ( screw ) * 20 ) , round ( height * 10 ) , taper ? str ( "_" , taper ) : "" ) ) ;
2019-06-08 17:10:47 -04:00
ir = screw_clearance_radius ( screw ) ;
or = corrected_radius ( ir ) + wall ;
2019-07-25 16:20:41 -04:00
if ( height > taper )
2020-03-29 15:18:57 -04:00
linear_extrude ( height - taper )
2019-07-25 16:20:41 -04:00
poly_ring ( or , ir ) ;
if ( taper )
2020-03-29 15:18:57 -04:00
linear_extrude ( height )
2019-07-25 16:20:41 -04:00
poly_ring ( ir + 2 * extrusion_width , ir ) ;
2019-06-08 17:10:47 -04:00
}
module pcb_base ( type , height , thickness , wall = 2 ) { //! Generate STL for a base with PCB spacers
screw = pcb_screw ( type ) ;
ir = screw_clearance_radius ( screw ) ;
or = corrected_radius ( ir ) + wall ;
union ( ) {
2020-03-29 15:18:57 -04:00
linear_extrude ( thickness )
2019-06-08 17:10:47 -04:00
difference ( ) {
hull ( )
pcb_screw_positions ( type )
poly_ring ( or , ir ) ;
pcb_screw_positions ( type )
poly_circle ( ir ) ;
}
2020-03-29 15:18:57 -04:00
linear_extrude ( height )
2019-06-08 17:10:47 -04:00
pcb_screw_positions ( type )
poly_ring ( or , ir ) ;
}
}
module pcb_assembly ( type , height , thickness ) { //! Draw PCB assembly with spaces and fasteners in place
translate_z ( height )
pcb ( type ) ;
screw = pcb_screw ( type ) ;
if ( ! is_undef ( screw ) ) {
washer = screw_washer ( screw ) ;
nut = screw_nut ( screw ) ;
screw_length = screw_longer_than ( height + thickness + pcb_thickness ( type ) + washer_thickness ( washer ) + nut_thickness ( nut , true ) ) ;
taper = screw_smaller_than ( pcb_hole_d ( type ) ) > 2 * screw_radius ( screw ) ; // Arduino?
pcb_screw_positions ( type ) {
translate_z ( height + pcb_thickness ( type ) )
screw ( screw , screw_length ) ;
2020-04-06 10:02:50 -04:00
stl_colour ( pp1_colour )
2019-07-25 16:20:41 -04:00
if ( taper )
pcb_spacer ( screw , height , taper = 2 ) ;
2019-06-08 17:10:47 -04:00
else
pcb_spacer ( screw , height ) ;
translate_z ( - thickness )
vflip ( )
nut_and_washer ( nut , true ) ;
}
}
}