Merge branch 'master' into pcb_microswitch2

This commit is contained in:
Chris 2020-02-23 15:10:13 +00:00 committed by GitHub
commit 9a08fe9b5c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
101 changed files with 1055 additions and 235 deletions

16
.gitattributes vendored Normal file
View File

@ -0,0 +1,16 @@
# Set the default behavior, in case people don't have core.autocrlf set.
* text=auto eol=lf
# Declare text files that are normalized and converted on checkout.
*.scad text
*.py text
*.md text
# Handle Windows batch and command files
*.{bat,[bB][aA][tT]} text eol=crlf
*.{cmd,[cC][mM][dD]} text eol=crlf
# Denote files that are binary and should not be modified.
*.png binary
*.jpg binary

1
.gitignore vendored
View File

@ -7,6 +7,7 @@ tests/bom/
*.log
*.html
bounds.json
options.json
times.txt
*_diff.png
*.echo

BIN
docs/metric_threads.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -26,7 +26,7 @@ OpenSCAD has to be setup to find libraries by setting the ```OPENSCADPATH``` env
in the directory it points to. This can be done with ```git clone https://github.com/nophead/NopSCADlib.git``` while in that directory or, if you don't want to use GIT,
by downloading https://github.com/nophead/NopSCADlib/archive/master.zip and unzipping it to a directory called NopSCADlib.
The ```NopSCADlib/scripts``` directory needs to be added to the executable search path.
The ```NopSCADlib/scripts``` directory needs to be added to the executable search path, ```PATH``` on Windows and ```path``` on Linux and Mac.
The installation can be tested by opening ```NopSCADlib/libtest.scad``` in the OpenSCAD GUI. It should render all the objects in the library in about 1 minute.

View File

@ -39,6 +39,7 @@ pp2_colour = is_undef($pp2_colour) ? "red" : $pp2_colour; // pri
pp3_colour = is_undef($pp3_colour) ? "blue" : $pp3_colour; // printed part colour 3
pp4_colour = is_undef($pp4_colour) ? "darkorange" : $pp4_colour;// printed part colour 4
show_rays = is_undef($show_rays) ? false : $show_rays; // show camera sight lines and light direction
show_threads = is_undef($show_threads) ? false : $show_threads; // show screw threads
// Minimum wall is about two filaments wide but we extrude it closer to get better bonding
squeezed_wall = $preview ? 2 * extrusion_width - layer_height * (1 - PI / 4)
@ -59,7 +60,8 @@ grey60 = [0.6, 0.6, 0.6];
grey70 = [0.7, 0.7, 0.7];
grey80 = [0.8, 0.8, 0.8];
grey90 = [0.9, 0.9, 0.9];
brass = "gold";
brass = [255/255, 215/255, 0/255];
silver = [0.75, 0.75, 0.75];
/*
* Enums

View File

@ -91,3 +91,4 @@ use <utils/layout.scad>
use <utils/round.scad>
use <utils/offset.scad>
use <utils/sector.scad>
use <utils/thread.scad>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 760 KiB

After

Width:  |  Height:  |  Size: 766 KiB

View File

@ -136,13 +136,13 @@ translate([x5, cable_grommets_y + 250])
translate([900, 600])
box_test();
translate([850, 1220])
translate([850, 1260])
bbox_test();
x0 = 0;
inserts_y = 0;
nuts_y = inserts_y + 20;
washers_y = nuts_y + 60;
washers_y = nuts_y + 100;
screws_y = washers_y + 120;
o_rings_y = screws_y + 130;
springs_y = o_rings_y + 20;
@ -254,7 +254,7 @@ buttons_y = spades_y + 40;
jacks_y = buttons_y + 40;
microswitches_y = jacks_y + 40;
rockers_y = microswitches_y + 40;
toggles_y = rockers_y + 40;
toggles_y = rockers_y + 60;
components_y = toggles_y + 40;
translate([x2, leds_y])

View File

@ -34,7 +34,7 @@ knob_waves = 5;
knob_height = knob_stem_h + knob_thickness;
function knob_height() = knob_height;
module screw_knob(screw) { //! Generate the STL foe a knob to fit the specified hex screw
module screw_knob(screw) { //! Generate the STL for a knob to fit the specified hex screw
stl(str("screw_knob_M", screw_radius(screw) * 20));
knob_stem_r = nut_trap_radius(screw_nut(screw)) + knob_wall;

135
readme.md
View File

@ -32,8 +32,8 @@ See [usage](docs/usage.md) for requirements, installation instructions and a usa
<tr><td> <a href = "#Fans">Fans</a> </td><td> <a href = "#Rod">Rod</a> </td><td> <a href = "#Handle">Handle</a> </td><td> <a href = "#Rounded_polygon">Rounded_polygon</a> </td><td></td></tr>
<tr><td> <a href = "#Fuseholder">Fuseholder</a> </td><td> <a href = "#Screws">Screws</a> </td><td> <a href = "#Pcb_mount">Pcb_mount</a> </td><td> <a href = "#Sector">Sector</a> </td><td></td></tr>
<tr><td> <a href = "#Geared_steppers">Geared_steppers</a> </td><td> <a href = "#Sealing_strip">Sealing_strip</a> </td><td> <a href = "#Psu_shroud">Psu_shroud</a> </td><td> <a href = "#Sweep">Sweep</a> </td><td></td></tr>
<tr><td> <a href = "#Green_terminals">Green_terminals</a> </td><td> <a href = "#Sheets">Sheets</a> </td><td> <a href = "#Ribbon_clamp">Ribbon_clamp</a> </td><td> <a href = "#Tube">Tube</a> </td><td></td></tr>
<tr><td> <a href = "#Hot_ends">Hot_ends</a> </td><td> <a href = "#Spades">Spades</a> </td><td> <a href = "#Screw_knob">Screw_knob</a> </td><td></td><td></td></tr>
<tr><td> <a href = "#Green_terminals">Green_terminals</a> </td><td> <a href = "#Sheets">Sheets</a> </td><td> <a href = "#Ribbon_clamp">Ribbon_clamp</a> </td><td> <a href = "#Thread">Thread</a> </td><td></td></tr>
<tr><td> <a href = "#Hot_ends">Hot_ends</a> </td><td> <a href = "#Spades">Spades</a> </td><td> <a href = "#Screw_knob">Screw_knob</a> </td><td> <a href = "#Tube">Tube</a> </td><td></td></tr>
<tr><td> <a href = "#Hygrometer">Hygrometer</a> </td><td> <a href = "#Spools">Spools</a> </td><td> <a href = "#Socket_box">Socket_box</a> </td><td></td><td></td></tr>
<tr><td> <a href = "#Iecs">Iecs</a> </td><td> <a href = "#Springs">Springs</a> </td><td> <a href = "#Ssr_shroud">Ssr_shroud</a> </td><td></td><td></td></tr>
<tr><td> <a href = "#Inserts">Inserts</a> </td><td> <a href = "#Ssrs">Ssrs</a> </td><td> <a href = "#Strap_handle">Strap_handle</a> </td><td></td><td></td></tr>
@ -196,7 +196,7 @@ Individual teeth are not drawn, instead they are represented by a lighter colour
### Modules
| Module | Description |
|:--- |:--- |
| ```belt(type, points, gap = 0, gap_pt = undef)``` | Draw a belt path given a set of points and pitch radii where the pulleys are. Closed loop unless a gap is specified |
| ```belt(type, points, gap = 0, gap_pt = undef, belt_colour = grey20, tooth_colour = grey50)``` | Draw a belt path given a set of points and pitch radii where the pulleys are. Closed loop unless a gap is specified |
![belts](tests/png/belts.png)
@ -992,10 +992,11 @@ IEC mains inlets and outlet.
| 1 | ```iec(IEC_inlet)``` | IEC inlet |
| 1 | ```iec(IEC_inlet_atx)``` | IEC inlet for ATX |
| 1 | ```iec(IEC_outlet)``` | IEC outlet RS 811-7193 |
| 10 | ```nut(M3_nut, nyloc = true)``` | Nut M3 x 2.4mm nyloc |
| 1 | ```iec(IEC_switched_fused_inlet)``` | IEC320 C14 switched fused inlet module |
| 12 | ```nut(M3_nut, nyloc = true)``` | Nut M3 x 2.4mm nyloc |
| 4 | ```screw(M3_cs_cap_screw, 10)``` | Screw M3 cs cap x 10mm |
| 6 | ```screw(M3_cs_cap_screw, 12)``` | Screw M3 cs cap x 12mm |
| 10 | ```washer(M3_washer)``` | Washer M3 x 7mm x 0.5mm |
| 8 | ```screw(M3_cs_cap_screw, 12)``` | Screw M3 cs cap x 12mm |
| 12 | ```washer(M3_washer)``` | Washer M3 x 7mm x 0.5mm |
<a href="#top">Top</a>
@ -1152,7 +1153,9 @@ Nuts for leadscrews.
| ```leadnut_hole_dia(type)``` | The diameter of the screw holes |
| ```leadnut_hole_pitch(type)``` | The radia pitch of the screw holes |
| ```leadnut_holes(type)``` | The number of screw holes |
| ```leadnut_lead(type)``` | Screw lead |
| ```leadnut_od(type)``` | Outer diameter of the shank |
| ```leadnut_pitch(type)``` | Screw pitch |
| ```leadnut_screw(type)``` | The type of the fixing screws |
### Functions
@ -1620,11 +1623,16 @@ If a nut is given a child then it gets placed on its top surface.
| 1 | ```nut(M2p5_nut)``` | Nut M2.5 x 2.2mm |
| 1 | ```nut(M2p5_nut, nyloc = true)``` | Nut M2.5 x 2.2mm nyloc |
| 1 | ```nut(M2p5_nut, nylon = true)``` | Nut M2.5 x 2.2mm nylon |
| 1 | ```hammer_nut(M3_hammer_nut)``` | Nut M3 hammer |
| 1 | ```sliding_t_nut(M3_sliding_t_nut)``` | Nut M3 sliding T |
| 1 | ```nut(M3_nut)``` | Nut M3 x 2.4mm |
| 1 | ```nut(M3_nut, brass = true)``` | Nut M3 x 2.4mm brass |
| 1 | ```nut(M3_nut, nyloc = true)``` | Nut M3 x 2.4mm nyloc |
| 1 | ```hammer_nut(M4_hammer_nut)``` | Nut M4 hammer |
| 1 | ```sliding_t_nut(M4_sliding_t_nut)``` | Nut M4 sliding T |
| 1 | ```nut(M4_nut)``` | Nut M4 x 3.2mm |
| 1 | ```nut(M4_nut, nyloc = true)``` | Nut M4 x 3.2mm nyloc |
| 1 | ```sliding_t_nut(M5_sliding_t_nut)``` | Nut M5 sliding T |
| 1 | ```nut(M5_nut)``` | Nut M5 x 4mm |
| 1 | ```nut(M5_nut, nyloc = true)``` | Nut M5 x 4mm nyloc |
| 1 | ```nut(M6_half_nut)``` | Nut M6 x 3mm |
@ -1752,6 +1760,7 @@ PCBs and perfboard with optional components. The shape can be a rectangle with o
| Module | Description |
|:--- |:--- |
| ```barrel_jack(cutout = false)``` | Draw barrel power jack |
| ```buzzer(height, diameter, colour)``` | Draw PCB buzzer with specified height, diameter and color |
| ```chip(length, width, thickness, colour, cutout = false)``` | Draw a coloured cube to represent a chip, or other rectangular component |
| ```flat_flex(cutout = false)``` | Draw flat flexistrip connector as used on RPI0 |
| ```flex(cutout = false)``` | Draw flexistrip connector |
@ -1795,7 +1804,7 @@ PCBs and perfboard with optional components. The shape can be a rectangle with o
| 1 | ```molex_254(2)``` | Molex KK header 2 way |
| 1 | ```molex_254(3)``` | Molex KK header 3 way |
| 16 | ```nut(M2_nut, nyloc = true)``` | Nut M2 x 1.6mm nyloc |
| 28 | ```nut(M2p5_nut, nyloc = true)``` | Nut M2.5 x 2.2mm nyloc |
| 32 | ```nut(M2p5_nut, nyloc = true)``` | Nut M2.5 x 2.2mm nyloc |
| 12 | ```nut(M3_nut, nyloc = true)``` | Nut M3 x 2.4mm nyloc |
| 12 | ```nut(M4_nut, nyloc = true)``` | Nut M4 x 3.2mm nyloc |
| 1 | ```pcb(PI_IO)``` | PI_IO V2 |
@ -1806,11 +1815,13 @@ PCBs and perfboard with optional components. The shape can be a rectangle with o
| 1 | ```pcb(PERF74x51)``` | Perfboard 74 x 51mm |
| 1 | ```pcb(PERF80x20)``` | Perfboard 80 x 20mm |
| 1 | ```pin_socket(2p54header, 13, 2, right_angle = true)``` | Pin socket 13 x 2 right_angle |
| 1 | ```pcb(RAMPSEndstop)``` | RAMPS Endstop Switch |
| 1 | ```pcb(RPI3)``` | Raspberry Pi 3 |
| 1 | ```pcb(RPI0)``` | Raspberry Pi Zero |
| 16 | ```screw(M2_cap_screw, 25)``` | Screw M2 cap x 25mm |
| 4 | ```screw(M2p5_cap_screw, 16)``` | Screw M2.5 cap x 16mm |
| 8 | ```screw(M2p5_cap_screw, 20)``` | Screw M2.5 cap x 20mm |
| 4 | ```screw(M2p5_cap_screw, 35)``` | Screw M2.5 cap x 35mm |
| 8 | ```screw(M2p5_pan_screw, 20)``` | Screw M2.5 pan x 20mm |
| 4 | ```screw(M2p5_pan_screw, 25)``` | Screw M2.5 pan x 25mm |
| 4 | ```screw(M2p5_pan_screw, 35)``` | Screw M2.5 pan x 35mm |
@ -1822,7 +1833,7 @@ PCBs and perfboard with optional components. The shape can be a rectangle with o
| 2 | ```green_terminal(gt_2p54, 4)``` | Terminal block 4 way 0.1" |
| 1 | | USB A to Mini B lead |
| 16 | ```washer(M2_washer)``` | Washer M2 x 5mm x 0.3mm |
| 28 | ```washer(M2p5_washer)``` | Washer M2.5 x 5.9mm x 0.5mm |
| 32 | ```washer(M2p5_washer)``` | Washer M2.5 x 5.9mm x 0.5mm |
| 12 | ```washer(M3_washer)``` | Washer M3 x 7mm x 0.5mm |
| 12 | ```washer(M4_washer)``` | Washer M4 x 9mm x 0.8mm |
| 1 | ```pcb(ZC_A0591)``` | ZC-A0591 ULN2003 driver PCB |
@ -1838,6 +1849,7 @@ PCBs and perfboard with optional components. The shape can be a rectangle with o
| 4 | pcb_spacer25110_2.stl |
| 4 | pcb_spacer25120_2.stl |
| 4 | pcb_spacer25230.stl |
| 4 | pcb_spacer25240.stl |
| 4 | pcb_spacer2570.stl |
| 4 | pcb_spacer2580.stl |
| 4 | pcb_spacer2590.stl |
@ -1927,6 +1939,7 @@ Pin headers and sockets, etc.
|:--- |:--- |
| ```box_header(type, cols = 1, rows = 1, smt = false, cutout = false)``` | Draw box header |
| ```idc_transition(type, cols = 5, skip = [], cutout = false)``` | Draw IDC transition header |
| ```jst_xh_header(type, pin_count, right_angle=false, colour, pin_colour)``` | Draw JST XH connector |
| ```pin(type, length = undef)``` | Draw a header pin |
| ```pin_header(type, cols = 1, rows = 1, smt = false, right_angle = false, cutout = false)``` | Draw pin header |
| ```pin_socket(type, cols = 1, rows = 1, right_angle = false, height = 0, smt = false, cutout = false)``` | Draw pin socket |
@ -2135,10 +2148,10 @@ Linear rails with carriages.
### Modules
| Module | Description |
|:--- |:--- |
| ```carriage(type, rail)``` | Draw the specified carriage |
| ```carriage(type, rail, end_color = grey20, wiper_color = grey20)``` | Draw the specified carriage |
| ```carriage_hole_positions(type)``` | Position children over screw holes |
| ```rail(type, length)``` | Draw the specified rail |
| ```rail_assembly(type, length, pos)``` | Rail and carriage assembly |
| ```rail_assembly(type, length, pos, carriage_end_color = grey20, carriage_wiper_color = grey20)``` | Rail and carriage assembly |
| ```rail_hole_positions(type, length, first = 0, screws = 100, both_ends = true)``` | Position children over screw holes |
| ```rail_screws(type, length, thickness, screws = 100)``` | Place screws in the rail |
@ -2246,7 +2259,7 @@ Rocker switch. Also used for neon indicator in the same form factor.
| ```rocker_height(type)``` | Body height |
| ```rocker_part(type)``` | Part description |
| ```rocker_pivot(type)``` | Pivot distance from the back of the flange |
| ```rocker_slot_h(type)``` | Panel slow height |
| ```rocker_slot_h(type)``` | Panel slot height |
| ```rocker_slot_w(type)``` | Panel slot width |
| ```rocker_spades(type)``` | Spade types and positions |
| ```rocker_width(type)``` | Body width |
@ -2254,7 +2267,7 @@ Rocker switch. Also used for neon indicator in the same form factor.
### Modules
| Module | Description |
|:--- |:--- |
| ```rocker(type)``` | Draw the specified rocker switch |
| ```rocker(type, colour)``` | Draw the specified rocker switch |
| ```rocker_hole(type, h = 0)``` | Make a hole to accept a rocker switch, by default 2D, set h for 3D |
![rockers](tests/png/rockers.png)
@ -2262,8 +2275,8 @@ Rocker switch. Also used for neon indicator in the same form factor.
### Vitamins
| Qty | Module call | BOM entry |
| ---:|:--- |:---|
| 1 | ```rocker(neon_indicator)``` | Neon Indicator H8630FBNAL |
| 1 | ```rocker(small_rocker)``` | Rocker Switch PRASA1-16F-BB0BW |
| 2 | ```rocker(neon_indicator)``` | Neon Indicator H8630FBNAL |
| 2 | ```rocker(small_rocker)``` | Rocker Switch PRASA1-16F-BB0BW |
<a href="#top">Top</a>
@ -2281,14 +2294,20 @@ Steel rods and studding with chamfered ends.
### Modules
| Module | Description |
|:--- |:--- |
| ```rod(d , l)``` | Draw a smooth rod with specified length and diameter |
| ```studding(d , l)``` | Draw a threaded rod with specified length and diameter |
| ```leadscrew(d , l, lead, starts, center = true)``` | Draw a leadscrew with specified diameter, length, lead and number of starts |
| ```rod(d , l, center = true)``` | Draw a smooth rod with specified diameter and length |
| ```studding(d , l, center = true)``` | Draw a threaded rod with specified diameter and length |
![rod](tests/png/rod.png)
### Vitamins
| Qty | Module call | BOM entry |
| ---:|:--- |:---|
| 1 | ```leadscrew(10, 80, 8, 4)``` | Leadscrew 10 x 80mm, 8mm lead, 4 starts |
| 1 | ```leadscrew(12, 80, 12, 4)``` | Leadscrew 12 x 80mm, 12mm lead, 4 starts |
| 1 | ```leadscrew(16, 80, 16, 4)``` | Leadscrew 16 x 80mm, 16mm lead, 4 starts |
| 1 | ```leadscrew(6, 80, 2, 1)``` | Leadscrew 6 x 80mm, 2mm lead, 1 starts |
| 1 | ```leadscrew(8, 80, 8, 4)``` | Leadscrew 8 x 80mm, 8mm lead, 4 starts |
| 1 | ```rod(10, 80)``` | Smooth rod 10mm x 80mm |
| 1 | ```rod(12, 80)``` | Smooth rod 12mm x 80mm |
| 1 | ```rod(16, 80)``` | Smooth rod 16mm x 80mm |
@ -2358,17 +2377,17 @@ Machine screws and wood screws with various head styles.
| Qty | Module call | BOM entry |
| ---:|:--- |:---|
| 1 | ```screw(No632_pan_screw, 30)``` | Screw 6-32 pan x 30mm |
| 1 | ```screw(M2_cap_screw, 25)``` | Screw M2 cap x 25mm |
| 1 | ```screw(M2_cs_cap_screw, 25)``` | Screw M2 cs cap x 25mm |
| 1 | ```screw(M2p5_cap_screw, 25)``` | Screw M2.5 cap x 25mm |
| 1 | ```screw(M2p5_pan_screw, 30)``` | Screw M2.5 pan x 30mm |
| 1 | ```screw(M3_cap_screw, 25)``` | Screw M3 cap x 25mm |
| 1 | ```screw(M3_cs_cap_screw, 25)``` | Screw M3 cs cap x 25mm |
| 1 | ```screw(M3_dome_screw, 25)``` | Screw M3 dome x 25mm |
| 1 | ```screw(M2_cap_screw, 10)``` | Screw M2 cap x 10mm |
| 1 | ```screw(M2_cs_cap_screw, 10)``` | Screw M2 cs cap x 10mm |
| 1 | ```screw(M2p5_cap_screw, 10)``` | Screw M2.5 cap x 10mm |
| 1 | ```screw(M2p5_pan_screw, 10)``` | Screw M2.5 pan x 10mm |
| 1 | ```screw(M3_cap_screw, 10)``` | Screw M3 cap x 10mm |
| 1 | ```screw(M3_cs_cap_screw, 10)``` | Screw M3 cs cap x 10mm |
| 1 | ```screw(M3_dome_screw, 10)``` | Screw M3 dome x 10mm |
| 1 | ```screw(M3_grub_screw, 6)``` | Screw M3 grub x 6mm |
| 1 | ```screw(M3_hex_screw, 30)``` | Screw M3 hex x 30mm |
| 1 | ```screw(M3_low_cap_screw, 25)``` | Screw M3 low cap x 25mm |
| 1 | ```screw(M3_pan_screw, 30)``` | Screw M3 pan x 30mm |
| 1 | ```screw(M3_hex_screw, 10)``` | Screw M3 hex x 10mm |
| 1 | ```screw(M3_low_cap_screw, 10)``` | Screw M3 low cap x 10mm |
| 1 | ```screw(M3_pan_screw, 10)``` | Screw M3 pan x 10mm |
| 1 | ```screw(M4_cap_screw, 25)``` | Screw M4 cap x 25mm |
| 1 | ```screw(M4_cs_cap_screw, 25)``` | Screw M4 cs cap x 25mm |
| 1 | ```screw(M4_dome_screw, 25)``` | Screw M4 dome x 25mm |
@ -2383,8 +2402,8 @@ Machine screws and wood screws with various head styles.
| 1 | ```screw(M6_pan_screw, 30)``` | Screw M6 pan x 30mm |
| 1 | ```screw(M8_cap_screw, 35)``` | Screw M8 cap x 35mm |
| 1 | ```screw(M8_hex_screw, 30)``` | Screw M8 hex x 30mm |
| 1 | ```screw(No2_screw, 30)``` | Screw No2 pan wood x 30mm |
| 1 | ```screw(No4_screw, 30)``` | Screw No4 pan wood x 30mm |
| 1 | ```screw(No2_screw, 10)``` | Screw No2 pan wood x 10mm |
| 1 | ```screw(No4_screw, 10)``` | Screw No4 pan wood x 10mm |
| 1 | ```screw(No6_cs_screw, 30)``` | Screw No6 cs wood x 30mm |
| 1 | ```screw(No6_screw, 30)``` | Screw No6 pan wood x 30mm |
@ -2544,7 +2563,7 @@ Filament spool models
### Modules
| Module | Description |
|:--- |:--- |
| ```spool(type)``` | Draw specified spool |
| ```spool(type, filament_depth = 0, filament_colour = "white", filament_d = 3)``` | Draw specified spool with optional filament |
![spools](tests/png/spools.png)
@ -2672,7 +2691,7 @@ NEMA stepper motor model.
| ```NEMA_length(type)``` | Body length |
| ```NEMA_radius(type)``` | End cap radius |
| ```NEMA_shaft_dia(type)``` | Shaft diameter |
| ```NEMA_shaft_length(type)``` | Shaft length above the face |
| ```NEMA_shaft_length(type)``` | Shaft length above the face, if a list then a leadscrew: length, lead, starts |
| ```NEMA_width(type)``` | Width of the square face |
### Functions
@ -2684,7 +2703,7 @@ NEMA stepper motor model.
### Modules
| Module | Description |
|:--- |:--- |
| ```NEMA(type)``` | Draw specified NEMA stepper motor |
| ```NEMA(type, shaft_angle = 0)``` | Draw specified NEMA stepper motor |
| ```NEMA_outline(type)``` | 2D outline |
| ```NEMA_screw_positions(type, n = 4)``` | Positions children at the screw holes |
| ```NEMA_screws(type, screw, n = 4, screw_length = 8, earth = undef)``` | Place screws and optional earth tag |
@ -4093,7 +4112,7 @@ Knob with embedded hex head screw.
### Modules
| Module | Description |
|:--- |:--- |
| ```screw_knob(screw)``` | Generate the STL foe a knob to fit the specified hex screw |
| ```screw_knob(screw)``` | Generate the STL for a knob to fit the specified hex screw |
| ```screw_knob_assembly(screw, length)``` | Assembly with the screw in place |
![screw_knob](tests/png/screw_knob.png)
@ -4431,6 +4450,8 @@ Maths utilities for manipulating vectors and matrices.
### Functions
| Function | Description |
|:--- |:--- |
| ```angle_between(v1, v2)``` | Return the angle between two vectors |
| ```euler(R)``` | Convert a rotation matrix to a Euler rotation vector. |
| ```identity(n, x = 1)``` | Construct an arbitrary size identity matrix |
| ```reverse(v)``` | Reverse a vector |
| ```rotate(a, v)``` | Generate a 4x4 rotation matrix, ```a``` can be a vector of three angles or a single angle around ```z```, or around axis ```v``` |
@ -4441,6 +4462,7 @@ Maths utilities for manipulating vectors and matrices.
| ```transpose(m)``` | Transpose an arbitrary size matrix |
| ```unit(v)``` | Convert ```v``` to a unit vector |
| ```vec3(v)``` | Return a 3 vector with the first three elements of ```v``` |
| ```vec4(v)``` | Return a 4 vector with the first three elements of ```v``` |
![maths](tests/png/maths.png)
@ -4607,9 +4629,12 @@ An additional twist around the path can be specified. If the path is closed this
| ```after(path1, path2)``` | Translate ```path2``` so its start meets the end of ```path1``` and then concatenate |
| ```arc_points(r, a = [90, 0, 180], al = 90)``` | Generate the points of a circular arc |
| ```before(path1, path2)``` | Translate ```path1``` so its end meets the start of ```path2``` and then concatenate |
| ```circle_points(r = 1, z = 0)``` | Generate the points of a circle, setting z makes a single turn spiral |
| ```cap(facets, segment = 0, end)``` | Create the mesh for an end cap |
| ```circle_points(r = 1, z = 0, dir = -1)``` | Generate the points of a circle, setting z makes a single turn spiral |
| ```helical_twist_per_segment(r, pitch, sides)``` | Calculate the twist around Z that rotate_from_to() introduces |
| ```path_length(path, i = 0, length = 0)``` | Calculated the length along a path |
| ```rectangle_points(w, h)``` | Generate the points of a rectangle |
| ```skin_faces(points, npoints, facets, loop, offset = 0)``` | Create the mesh for the swept volume without end caps |
| ```sweep(path, profile, loop = false, twist = 0)``` | Generate the point list and face list of the swept volume |
### Modules
@ -4620,6 +4645,50 @@ An additional twist around the path can be specified. If the path is closed this
![sweep](tests/png/sweep.png)
<a href="#top">Top</a>
---
<a name="Thread"></a>
## Thread
Utilities for making threads with sweep. They can be used to model screws, nuts, studding, leadscrews, etc, and also to make printed threads.
The ends can be tapered, flat or chamfered by setting the ```top``` and ```bot``` parameters to -1 for tapered, 0 for a flat cut and positive to
specify a chamfer angle.
Threads are by default solid, so the male version is wrapped around a cylinder and the female inside a tube. This can be suppressed to just get the helix, for
example to make a printed pot with a screw top lid.
Threads with a typical 60 degree angle appear too bright with OpenSCAD's primitive lighting model as they face towards the lights more than the top and sides of
a cylinder. To get around this a colour can be passed to thread that is used to colour the cylinder and then toned down to colour the helix.
Making the ends requires a CGAL intersection, which make threads relatively slow. For this reason they are generally disabled when using the GUI but can
be enabled by setting ```$show_threads``` to ```true```. When the tests are run, by default, threads are enabled only for things that feature them like screws.
This behaviour can be changed by setting a ```SHOW_THREADS``` environment variable to ```false``` to disable all threads and ```true``` to enable all threads.
The same variable also affects the generation of assembly diagrams.
Threads obey the $fn, $fa, $fs variables.
[utils/thread.scad](utils/thread.scad) Implementation.
[tests/thread.scad](tests/thread.scad) Code for this example.
### Functions
| Function | Description |
|:--- |:--- |
| ```metric_coarse_pitch(d)``` | Convert metric diameter to pitch |
| ```thread_profile(h, crest, angle, overlap = 0.1)``` | Create thread profile path |
### Modules
| Module | Description |
|:--- |:--- |
| ```female_metric_thread(d, pitch, length, center = true, top = -1, bot = -1, colour = undef)``` | Create female thread with metric profile |
| ```male_metric_thread(d, pitch, length, center = true, top = -1, bot = -1, solid = true, colour = undef)``` | Create male thread with metric profile |
| ```thread(dia, pitch, length, profile, center = true, top = -1, bot = -1, starts = 1, solid = true, female = false, colour = undef)``` | Create male or femail thread, ends can be tapered, chamfered or square |
![thread](tests/png/thread.png)
<a href="#top">Top</a>
---

View File

@ -24,7 +24,7 @@ from __future__ import print_function
import subprocess, sys
def _run(args, silent):
def run_list(args, silent = False):
cmd = ["openscad"] + args
if not silent:
for arg in cmd:
@ -39,7 +39,7 @@ def _run(args, silent):
sys.exit(rc)
def run(*args):
_run(list(args), False)
run_list(list(args), False)
def run_silent(*args):
_run(list(args), True);
run_list(list(args), True);

49
scripts/options.py Normal file
View File

@ -0,0 +1,49 @@
#
# NopSCADlib Copyright Chris Palmer 2020
# 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/>.
#
# Set command line options from enviroment variables and check if they have changed
import json, os, deps
def check_options(dir = '.'):
global options, options_mtime
options = { "show_threads": str(os.getenv("SHOW_THREADS")) }
options_fname = dir + '/options.json'
try:
with open(options_fname) as json_file:
last_options = json.load(json_file)
except:
last_options = {}
if last_options != options:
with open(options_fname, 'w') as outfile:
json.dump(options, outfile, indent = 4)
options_mtime = deps.mtime(options_fname)
def have_changed(changed, target):
if not changed and deps.mtime(target) < options_mtime:
return "command line options changed"
return changed
def list():
result = []
for name in options.keys():
value = options[name]
if value != 'None':
result.append('-D$' + name + '=' + value)
return result

View File

@ -27,6 +27,7 @@ import openscad
import subprocess
import bom
import times
import options
import time
import json
import shutil
@ -96,6 +97,7 @@ def tests(tests):
index = {}
bodies = {}
times.read_times()
options.check_options(deps_dir)
#
# Make cover pic if does not exist as very slow. Delete it to force an update.
#
@ -190,11 +192,12 @@ def tests(tests):
oldest = png_name if mtime(png_name) < mtime(bom_name) else bom_name
changed = check_deps(oldest, dname)
changed = times.check_have_time(changed, scad_name)
changed = options.have_changed(changed, oldest)
if changed:
print(changed)
t = time.time()
tmp_name = 'tmp.png'
openscad.run("-D", "$bom=2", colour_scheme, "--projection=p", "--imgsize=%d,%d" % (w, h), "--camera=0,0,0,70,0,315,500", "--autocenter", "--viewall", "-d", dname, "-o", tmp_name, scad_name);
openscad.run_list(options.list() + ["-D$bom=2", colour_scheme, "--projection=p", "--imgsize=%d,%d" % (w, h), "--camera=0,0,0,70,0,315,500", "--autocenter", "--viewall", "-d", dname, "-o", tmp_name, scad_name]);
times.add_time(scad_name, t)
do_cmd(["magick", tmp_name, "-trim", "-resize", "1000x600", "-bordercolor", background, "-border", "10", tmp_name])
update_image(tmp_name, png_name)

View File

@ -28,6 +28,7 @@ import openscad
from tests import do_cmd, update_image, colour_scheme, background
import time
import times
import options
from deps import *
import os
import json
@ -102,6 +103,7 @@ def views(target, do_assemblies = None):
os.makedirs(deps_dir)
times.read_times(target_dir)
options.check_options(deps_dir)
bounds_fname = top_dir + 'stls/bounds.json'
with open(bounds_fname) as json_file:
bounds_map = json.load(json_file)
@ -154,7 +156,7 @@ def views(target, do_assemblies = None):
f.write("use <%s/%s>\n" % (dir, filename))
f.write("%s();\n" % module);
#
# Run openscad on th created file
# Run openscad on the created file
#
dname = deps_name(deps_dir, filename)
for explode in [0, 1]:
@ -163,11 +165,12 @@ def views(target, do_assemblies = None):
png_name = png_name.replace('_assembly', '_assembled')
changed = check_deps(png_name, dname)
changed = times.check_have_time(changed, png_name)
changed = options.have_changed(changed, png_name)
tmp_name = 'tmp.png'
if changed:
print(changed)
t = time.time()
openscad.run("-D$pose=1", "-D$explode=%d" % explode, colour_scheme, "--projection=p", "--imgsize=4096,4096", "--autocenter", "--viewall", "-d", dname, "-o", tmp_name, png_maker_name);
openscad.run_list(options.list() + ["-D$pose=1", "-D$explode=%d" % explode, colour_scheme, "--projection=p", "--imgsize=4096,4096", "--autocenter", "--viewall", "-d", dname, "-o", tmp_name, png_maker_name]);
times.add_time(png_name, t)
do_cmd(["magick", tmp_name, "-trim", "-resize", "1004x1004", "-bordercolor", background, "-border", "10", tmp_name])
update_image(tmp_name, png_name)

View File

@ -67,7 +67,7 @@ module belt_test() {
translate([-25, 0])
layout([for(b = belts) belt_width(b)], 10)
rotate([0, 90, 0])
belt(belts[$i], [[0, 0, 20], [0, 1, 20]]);
belt(belts[$i], [[0, 0, 20], [0, 1, 20]], belt_colour = $i%2==0 ? grey90 : grey20, tooth_colour = $i%2==0 ? grey70 : grey50);
}
if($preview)

View File

@ -35,4 +35,5 @@ module d_connectors()
}
if($preview)
d_connectors();
let($show_threads = true)
d_connectors();

View File

@ -37,4 +37,5 @@ module inserts() {
}
if($preview)
inserts();
let($show_threads = true)
inserts();

View File

@ -27,4 +27,5 @@ module leadnuts()
leadnut(leadnuts[$i]);
if($preview)
leadnuts();
let($show_threads = true)
leadnuts();

View File

@ -56,7 +56,7 @@ module maths() {
//
z = [0, 0, 1];
v = cross(u, z);
a = acos(u * z);
a = angle_between(u, z);
l = 20;
@ -64,6 +64,11 @@ module maths() {
translate_z(l)
vflip()
arrow(l);
//
// Test Euler
//
assert(euler(rotate(r)) == r, "euler() failed");
}
rotate(45)

View File

@ -22,13 +22,12 @@ use <../utils/layout.scad>
include <../vitamins/screws.scad>
module nuts() {
for(nyloc = [false, true])
translate([0, nyloc ? 20 : 0])
layout([for(n = nuts) 2 * nut_radius(n)], 5)
nut(nuts[$i], nyloc);
layout([for(n = nuts) 2 * nut_radius(n)], 5) let(n = nuts[$i]) {
for(nyloc = [false, true])
translate([0, nyloc ? 20 : 0])
nut(n, nyloc);
translate([0, 40])
layout([for(n = nuts) 2 * nut_radius(n)], 5) let(n = nuts[$i]) {
translate([0, 40]) {
if(n == M3_nut)
nut(n, brass = true);
@ -45,7 +44,28 @@ module nuts() {
if(n == M8_nut)
#nut_trap(M8_cap_screw, n, h = 30);
}
translate([0, 60]) {
if(n == M3_nut)
sliding_t_nut(M3_sliding_t_nut);
if(n == M4_nut)
sliding_t_nut(M4_sliding_t_nut);
if(n == M5_nut)
sliding_t_nut(M5_sliding_t_nut);
}
translate([0, 80]) {
if(n == M3_nut)
hammer_nut(M3_hammer_nut);
if(n == M4_nut)
hammer_nut(M4_hammer_nut);
}
}
}
if($preview)
nuts();
let($show_threads = true)
nuts();

View File

@ -29,4 +29,5 @@ module opengrab_test() {
}
if($preview)
opengrab_test();
let($show_threads = true)
opengrab_test();

View File

@ -16,7 +16,7 @@
// You should have received a copy of the GNU General Public License along with NopSCADlib.
// If not, see <https://www.gnu.org/licenses/>.
//
include <../lib.scad>
include <../core.scad>
use <../printed/pcb_mount.scad>
PI_IO = ["PI_IO", "PI_IO V2", 35.56, 25.4, 1.6, 0, 0, 0, "green", true, [],

View File

@ -26,4 +26,5 @@ module pillars()
pillar(pillars[$i]);
if($preview)
pillars();
let($show_threads = true)
pillars();

Binary file not shown.

Before

Width:  |  Height:  |  Size: 102 KiB

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 114 KiB

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 KiB

After

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 115 KiB

After

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 114 KiB

After

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 116 KiB

After

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 114 KiB

After

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 147 KiB

After

Width:  |  Height:  |  Size: 149 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 81 KiB

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 KiB

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 98 KiB

After

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 109 KiB

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 147 KiB

After

Width:  |  Height:  |  Size: 145 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 149 KiB

After

Width:  |  Height:  |  Size: 188 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 162 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 98 KiB

After

Width:  |  Height:  |  Size: 92 KiB

BIN
tests/png/thread.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 215 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 106 KiB

After

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 143 KiB

After

Width:  |  Height:  |  Size: 152 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 92 KiB

After

Width:  |  Height:  |  Size: 93 KiB

View File

@ -34,7 +34,7 @@ module rails()
nut = screw_nut(screw);
washer = screw_washer(screw);
rail_assembly(rail, length, rail_travel(rail, length) / 2);
rail_assembly(rail, length, rail_travel(rail, length) / 2, $i<2 ? grey20 : "green", $i<2 ? grey20 : "red");
rail_screws(rail, length, sheet + nut_thickness(nut, true) + washer_thickness(washer));

View File

@ -21,9 +21,13 @@ use <../utils/layout.scad>
include <../vitamins/rockers.scad>
module rockers()
layout([for(r = rockers) rocker_flange_w(r)], 5)
module rockers() {
layout([for(r = rockers) rocker_flange_w(r)], 5) {
rocker(rockers[$i]);
translate([0, 25])
rocker(rockers[$i], $i==0 ? "red" : "green");
}
}
if($preview)
rockers();

View File

@ -24,13 +24,23 @@ include <../vitamins/linear_bearings.scad>
use <../vitamins/rod.scad>
module rods()
layout([for(b = linear_bearings) 2 * bearing_radius(b)]) {
layout([for(b = linear_bearings) 2 * bearing_radius(b)]) let(d = bearing_rod_dia(linear_bearings[$i])){
rod(bearing_rod_dia(linear_bearings[$i]), 80);
rod(d, 80);
translate([0, 30])
studding(bearing_rod_dia(linear_bearings[$i]), 80);
studding(d, 80);
if(d >= 6)
translate([0, 60]) {
starts = d > 6 ? 4 : 1;
pitch = d > 14 ? 4
: d > 10 ? 3 : 2;
let($show_threads = true)
leadscrew(d, 80, starts * pitch, starts);
}
}
if($preview)
rods();
let($show_threads = true)
rods();

View File

@ -25,13 +25,15 @@ for(y = [0 : len(screw_lists) -1])
for(x = [0 : len(screw_lists[y]) -1]) {
screw = screw_lists[y][x];
if(screw) {
length = screw_max_thread(screw)
? screw_longer_than(screw_max_thread(screw) + 5)
: screw_head_type(screw) == hs_grub ? 6 : 30;
length = screw_head_type(screw) == hs_grub ? 6
: screw_radius(screw) <= 1.5 ? 10
: screw_max_thread(screw) ? screw_longer_than(screw_max_thread(screw) + 5)
: 30;
translate([x * 20, y * 20])
screw(screw, length);
}
}
if($preview)
screws();
let($show_threads = true)
screws();

View File

@ -23,9 +23,9 @@ use <../utils/layout.scad>
include <../vitamins/spools.scad>
module spools()
layout([for(s = spools) spool_height(s)], 100)
layout([for(s = spools) spool_height(s)], 100) let(s = spools[$i])
rotate([90, 0, 90])
spool(spools[$i]);
spool(s, filament_depth = spool_depth(s) / 2, filament_colour = [pp1_colour, pp2_colour, pp3_colour, pp4_colour][$i % 4], filament_d = $i ? 3 : 1.75);
if($preview)
spools();

View File

@ -44,7 +44,7 @@ knot = [ for(i=[0:.2:359])
(19*cos(3*i) + 40)*sin(2*i),
19*sin(3*i) ] ];
sweep(knot, L_points, loop = true, twist = 0);
sweep(knot, L_points, loop = true);
p = transform_points([[0,0,0], [20,0,5], [10,30,4], [0,0,0], [0,0,20]], scale(10));
n = 100;

52
tests/thread.scad Normal file
View File

@ -0,0 +1,52 @@
//
// NopSCADlib Copyright Chris Palmer 2020
// 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/>.
//
include <../core.scad>
use <../utils/thread.scad>
pitch = 2;
starts = 4;
profile = thread_profile(pitch / 2, pitch * 0.366, 30);
module threads()
for(female = [false, true]) translate([0, female ? -20 : 0]) {
length = female ? 8 : 40;
dia = female ? 8 : 8 - pitch;
colour = female ? brass : silver;
thread(dia, starts * pitch, length, profile, starts = starts, top = 45, bot = 45, female = female, colour = colour);
color(colour)
translate([20, 0])
thread(dia, starts * pitch, length, profile, starts = starts, top = 0, bot = 0, female = female);
translate([40, 0])
thread(dia, starts * pitch, length, profile, starts = starts, top = -1, bot = -1, female = female, colour = colour);
color(colour)
translate([60, 0])
thread(dia, 2 * pitch, length, profile, starts = 2, top = -1, bot = -1, female = female);
color(colour)
translate([80, 0])
thread(dia, pitch, length, profile, starts = 1, top = -1, bot = -1, female = female);
}
let($show_threads = true)
threads();

View File

@ -27,4 +27,5 @@ module toggles()
toggle(toggles[$i], 3);
if($preview)
toggles();
let($show_threads = true)
toggles();

View File

@ -43,7 +43,7 @@ module ellipse(xr, yr) scale([1, yr / xr]) circle4n(xr);
module extrude_if(h, center = true) //! Extrudes 2D object to 3D when ```h``` is nonzero, otherwise leaves it 2D
if(h)
linear_extrude(height = h, center = center) // 3D
linear_extrude(height = h, center = center, convexity = 2) // 3D
children();
else
children(); // 2D

View File

@ -39,9 +39,9 @@ function rotate(a, v) = //! Generate a 4x4 rotation matrix, ```a``` can be a vec
sy = sin(av[1]),
sz = sin(av[2]))
[
[ cy * cz, cz * sx * sy - cx * sz, cx * cz * sy + sx * sz, 0],
[ cy * sz, cx * cz + sx * sy * sz,-cz * sx + cx * sy * sz, 0],
[-sy, cy * sx, cx * cy, 0],
[ cy * cz, sx * sy * cz - cx * sz, cx * sy * cz + sx * sz, 0],
[ cy * sz, sx * sy * sz + cx * cz, cx * sy * sz - sx * cz, 0],
[-sy, sx * cy, cx * cy, 0],
[ 0, 0, 0, 1]
]
: let(s = sin(a),
@ -65,6 +65,7 @@ function scale(v) = let(s = is_list(v) ? v : [v, v, v]) //! Generate a 4x4 matr
];
function vec3(v) = [v.x, v.y, v.z]; //! Return a 3 vector with the first three elements of ```v```
function vec4(v) = [v.x, v.y, v.z, 1]; //! Return a 4 vector with the first three elements of ```v```
function transform(v, m) = vec3(m * [v.x, v.y, v.z, 1]); //! Apply 4x4 transform to a 3 vector by extending it and cropping it again
function transform_points(path, m) = [for(p = path) transform(p, m)]; //! Apply transform to a path
function unit(v) = let(n = norm(v)) n ? v / n : v; //! Convert ```v``` to a unit vector
@ -74,3 +75,11 @@ function transpose(m) = [ for(j = [0 : len(m[0]) - 1]) [ for(i = [0 : len(m) - 1
function identity(n, x = 1) = [for(i = [0 : n - 1]) [for(j = [0 : n - 1]) i == j ? x : 0] ]; //! Construct an arbitrary size identity matrix
function reverse(v) = let(n = len(v) - 1) n < 0 ? [] : [for(i = [0 : n]) v[n - i]]; //! Reverse a vector
function angle_between(v1, v2) = acos(v1 * v2 / (norm(v1) * norm(v2))); //! Return the angle between two vectors
// https://www.gregslabaugh.net/publications/euler.pdf
function euler(R) = let(ay = asin(-R[2][0]), cy = cos(ay)) //! Convert a rotation matrix to a Euler rotation vector.
cy ? [ atan2(R[2][1] / cy, R[2][2] / cy), ay, atan2(R[1][0] / cy, R[0][0] / cy) ]
: R[2][0] < 0 ? [atan2( R[0][1], R[0][2]), 180, 0]
: [atan2(-R[0][1], -R[0][2]), -180, 0];

View File

@ -62,6 +62,7 @@ function rotate_from_to(a, b) =
function calculate_twist(A, B) = let(D = transpose3(B) * A) atan2(D[1][0], D[0][0]);
//
// Compute a 4x3 matrix to orientate a frame of the sweep given the position and a 3x3 rotation matrix.
// Note that the rotation matrix is transposed to allow post multiplication.
//
function orientate(p, r) =
let(x = r[0], y = r[1], z = r[2])
@ -79,12 +80,21 @@ function rot3_z(a) =
[ [ c, -s, 0],
[ s, c, 0],
[ 0, 0, 1] ];
//
// Calculate the unit tangent at a vertex given the indices before and after. One of these can be the same as i in the case
// of the start and end of a non closed path.
// of the start and end of a non closed path. Note that the edges are converted to unit vectors so that their relative lengths
// don't affect the direction of the tangent.
//
function tangent(path, before, i, after) = unit(unit(path[after] - path[i]) - unit(path[before] - path[i]));
function tangent(path, before, i, after) = unit(unit(path[i] - path[before]) + unit(path[after] - path[i]));
//
// Calculate the twist per segment caused by rotate_from_to() instead of a simple Euler rotation around Z.
//
function helical_twist_per_segment(r, pitch, sides) = //! Calculate the twist around Z that rotate_from_to() introduces
let(step_angle = 360 / sides,
lt = 2 * r * sin(step_angle), // length of tangent between two facets
slope = atan(2 * pitch / sides / lt) // slope of tangents
) step_angle * sin(slope); // angle tangent should rotate around z projected onto axis rotate_from_to() uses
//
// Generate all the surface points of the swept volume.
//
@ -111,24 +121,28 @@ function skin_points(profile, path, loop, twist = 0) =
each profile4 * orientate(path[i], rotations[i] * rot3_z(za))
];
function cap(facets, segment = 0) = [for(i = [0 : facets - 1]) segment ? facets * segment + i : facets - 1 - i];
function cap(facets, segment = 0, end) = //! Create the mesh for an end cap
let(reverse = is_undef(end) ? segment : end)
[for(i = [0 : facets - 1]) facets * segment + (reverse ? i : facets - 1 - i)];
function quad(p, a, b, c, d) = norm(p[a] - p[c]) > norm(p[b] - p[d]) ? [[b, c, d], [b, d, a]] : [[a, b, c], [a, c, d]];
function skin_faces(points, segs, facets, loop) = [for(i = [0 : facets - 1], s = [0 : segs - (loop ? 1 : 2)])
each quad(points,
s * facets + i,
s * facets + (i + 1) % facets,
((s + 1) % segs) * facets + (i + 1) % facets,
((s + 1) % segs) * facets + i)];
function skin_faces(points, npoints, facets, loop, offset = 0) = //! Create the mesh for the swept volume without end caps
[for(i = [0 : facets - 1], s = [0 : npoints - (loop ? 1 : 2)])
let(j = s + offset, k = loop ? (j + 1) % npoints : j + 1)
each quad(points,
j * facets + i,
j * facets + (i + 1) % facets,
k * facets + (i + 1) % facets,
k * facets + i)];
function sweep(path, profile, loop = false, twist = 0) = //! Generate the point list and face list of the swept volume
let(
segments = len(path),
npoints = len(path),
facets = len(profile),
points = skin_points(profile, path, loop, twist),
skin_faces = skin_faces(points, segments, facets, loop),
faces = loop ? skin_faces : concat([cap(facets)], skin_faces, [cap(facets, segments - 1)])
skin_faces = skin_faces(points, npoints, facets, loop),
faces = loop ? skin_faces : concat([cap(facets)], skin_faces, [cap(facets, npoints - 1)])
) [points, faces];
module sweep(path, profile, loop = false, twist = 0) { //! Draw a polyhedron that is the swept volume
@ -141,9 +155,9 @@ function path_length(path, i = 0, length = 0) = //! Calculated the length along
i >= len(path) - 1 ? length
: path_length(path, i + 1, length + norm(path[i + 1] - path[i]));
function circle_points(r = 1, z = 0) = //! Generate the points of a circle, setting z makes a single turn spiral
function circle_points(r = 1, z = 0, dir = -1) = //! Generate the points of a circle, setting z makes a single turn spiral
let(sides = r2sides(r))
[for(i = [0 : sides - 1]) let(a = i * 360 / sides) [r * sin(a), r * cos(a), z * a / 360]];
[for(i = [0 : sides - 1]) let(a = dir * i * 360 / sides) [r * cos(a), r * sin(a), z * i / sides]];
function rectangle_points(w, h) = [[-w/2, -h/2, 0], [-w/2, h/2, 0], [w/2, h/2, 0], [w/2, -h/2, 0]]; //! Generate the points of a rectangle

217
utils/thread.scad Normal file
View File

@ -0,0 +1,217 @@
//
// NopSCADlib Copyright Chris Palmer 2019
// 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/>.
//
//
//! Utilities for making threads with sweep. They can be used to model screws, nuts, studding, leadscrews, etc, and also to make printed threads.
//!
//! The ends can be tapered, flat or chamfered by setting the ```top``` and ```bot``` parameters to -1 for tapered, 0 for a flat cut and positive to
//! specify a chamfer angle.
//!
//! Threads are by default solid, so the male version is wrapped around a cylinder and the female inside a tube. This can be suppressed to just get the helix, for
//! example to make a printed pot with a screw top lid.
//!
//! Threads with a typical 60 degree angle appear too bright with OpenSCAD's primitive lighting model as they face towards the lights more than the top and sides of
//! a cylinder. To get around this a colour can be passed to thread that is used to colour the cylinder and then toned down to colour the helix.
//!
//! Making the ends requires a CGAL intersection, which make threads relatively slow. For this reason they are generally disabled when using the GUI but can
//! be enabled by setting ```$show_threads``` to ```true```. When the tests are run, by default, threads are enabled only for things that feature them like screws.
//! This behaviour can be changed by setting a ```SHOW_THREADS``` environment variable to ```false``` to disable all threads and ```true``` to enable all threads.
//! The same variable also affects the generation of assembly diagrams.
//!
//! Threads obey the $fn, $fa, $fs variables.
//
include <../core.scad>
use <sweep.scad>
use <maths.scad>
use <tube.scad>
thread_colour_factor = 0.8; // 60 degree threads appear too bright due to the angle facing the light sources
function thread_profile(h, crest, angle, overlap = 0.1) = //! Create thread profile path
let(base = crest + 2 * (h + overlap) * tan(angle / 2))
[[-base / 2, -overlap, 0], [-crest / 2, h, 0], [crest / 2, h, 0], [base / 2, -overlap, 0]];
module thread(dia, pitch, length, profile, center = true, top = -1, bot = -1, starts = 1, solid = true, female = false, colour = undef) { //! Create male or femail thread, ends can be tapered, chamfered or square
//
// Apply colour if defined
//
module colour(factor) if(is_undef(colour)) children(); else color(colour * factor) children();
//
// Compress the profile to compensate for it being tilted by the helix angle
//
scale = cos(atan(pitch / (PI * dia)));
sprofile = [for(p = profile) [p.x * scale, p.y, p.z]];
//
// Extract some properties from the profile, perhaps they should be stored in it.
//
h = max([for(p = sprofile) p.y]);
maxx = max([for(p = sprofile) p.x]);
minx = min([for(p = sprofile) p.x]);
crest_xmax = max([for(p = sprofile) if(p.x != maxx) p.x]);
crest_xmin = min([for(p = sprofile) if(p.x != minx) p.x]);
//
// If the ends don't taper we need an extra half turn past the ends to be cropped horizontally.
//
extra_top = top < 0 ? 0 : -minx / pitch;
extra_bot = bot < 0 ? 0 : maxx / pitch;
turns = length / pitch + extra_top + extra_bot;
//
// Generate the helix path, possibly with tapered ends
//
dir = female ? 1 : -1;
r = dia / 2;
sides = r2sides4n(r);
step_angle = 360 / sides;
segs = ceil(turns * sides);
leadin = ceil(sides / starts);
final = floor(turns * sides) - leadin;
path = [for(i = [0 : segs],
R = i < leadin && bot < 0 ? r + dir * (h - h * i / leadin)
: i > final && top < 0 ? r + dir * h * (i - final) / leadin : r,
a = i * step_angle - 360 * extra_bot)
[R * cos(a), R * sin(a), a * pitch / 360]];
//
// Generate the skin vertices
//
facets = len(profile);
twist = helical_twist_per_segment(r, pitch, sides);
//
// For female threads we need to invert the profile
//
iprofile = female ? reverse([for(p = sprofile) [p.x, -p.y, 0]]) : sprofile;
//
// If the bottom is tapered then the twist will be greater, so pre-twist the profile to get the straight bit at the correct angle
//
rprofile = bot < 0 ? transform_points(iprofile, rotate(-dir * (helical_twist_per_segment(r - h, pitch, sides) - twist) * sides / PI))
: iprofile;
points = skin_points(rprofile, path, false, twist * segs);
//
// To form the ends correctly we need to use intersection but it is very slow with the full thread so we just
// intersect the start and the end and sweep the rest outside of the intersection.
//
top_chamfer_h = (top > 0 ? h * tan(top) : 0);
bot_chamfer_h = (bot > 0 ? h * tan(bot) : 0);
top_overlap = max( maxx, top_chamfer_h - crest_xmin) / pitch;
bot_overlap = max(-minx, bot_chamfer_h + crest_xmax) / pitch;
start = ceil(sides * (bot_overlap + extra_bot));
end = segs - ceil(sides * (top_overlap + extra_top));
start_skin_faces = skin_faces(points, start + 1, facets, false);
middle_skin_faces = skin_faces(points, end - start + 1, facets, false, start);
end_skin_faces = skin_faces(points, segs - end + 1, facets, false, end);
start_faces = concat([cap(facets) ], start_skin_faces, [cap(facets, start)]);
middle_faces = concat([cap(facets, start, false)], middle_skin_faces, [cap(facets, end)]);
end_faces = concat([cap(facets, end, false)], end_skin_faces, [cap(facets, segs)]);
overlap = - profile[0].y;
translate_z((center ? -length / 2 : 0)) {
ends_faces = concat(start_faces, end_faces);
for(i = [0 : starts - 1])
colour(thread_colour_factor)
rotate(360 * i / starts + (female ? 180 / starts : 0)) {
render() intersection() {
polyhedron(points, ends_faces);
len = length - 2 * eps;
rotate_extrude()
if(female) {
difference() {
translate([0, eps])
square([r + h + overlap, len]);
if(top_chamfer_h)
polygon([[0, length], [r, length], [r - h, length - top_chamfer_h], [0, length - top_chamfer_h]]);
if(bot_chamfer_h)
polygon([[0, 0], [r, 0], [r - h, bot_chamfer_h], [0, bot_chamfer_h]]);
}
}
else
difference() {
hull() {
translate([0, eps])
square([r, len]);
translate([0, bot_chamfer_h])
square([r + h + overlap, len - top_chamfer_h - bot_chamfer_h]);
}
if(!solid)
square([r - overlap, length]);
}
}
polyhedron(points, middle_faces);
}
if(solid)
colour(1)
rotate(90)
if(female)
tube(or = r + (top < 0 || bot < 0 ? h : 0) + 2 * overlap, ir = r, h = length, center = false);
else
cylinder(d = dia, h = length);
}
}
module male_metric_thread(d, pitch, length, center = true, top = -1, bot = -1, solid = true, colour = undef) { //! Create male thread with metric profile
H = pitch * sqrt(3) / 2;
h = 5 * H / 8;
minor_d = d - 2 * h;
thread(minor_d, pitch, length, thread_profile(h, pitch / 8, 60), center, top, bot, solid = solid, colour = colour);
}
module female_metric_thread(d, pitch, length, center = true, top = -1, bot = -1, colour = undef) { //! Create female thread with metric profile
H = pitch * sqrt(3) / 2;
h = 5 * H / 8;
thread(d, pitch, length, thread_profile(h, pitch / 4, 60), center, top, bot, solid = false, female = true, colour = colour);
}
function metric_coarse_pitch(d) //! Convert metric diameter to pitch
= d == 1.6 ? 0.35 // M1.6
: [0.4, // M2
0.45,// M2.5
0.5, // M3
0.6, // M3.5
0.7, // M4
0,
0.8, // M5
0,
1.0, // M6
0,
0,
0,
1.25, // M8
0,
0,
0,
1.5, // M10
0,
0,
0,
1.75, // M12
0,
0,
0,
0, // M14
0,
0,
0,
2.0, // M16
][d * 2 - 4];

View File

@ -41,9 +41,7 @@ function no_point(str) = chr([for(c = str) if(c == ".") ord("p") else ord(c)]);
// We model the belt path at the pitch radius of the pulleys and the pitch line of the belt to get an accurate length.
// The belt is then drawn by offseting each side from the pitch line.
//
module belt(type, points, gap = 0, gap_pt = undef) { //! Draw a belt path given a set of points and pitch radii where the pulleys are. Closed loop unless a gap is specified
belt_colour = grey20;
tooth_colour = grey50;
module belt(type, points, gap = 0, gap_pt = undef, belt_colour = grey20, tooth_colour = grey50) { //! Draw a belt path given a set of points and pitch radii where the pulleys are. Closed loop unless a gap is specified
width = belt_width(type);
pitch = belt_pitch(type);
thickness = belt_thickness(type);

View File

@ -21,6 +21,7 @@
//! D-connectors. Can be any number of ways, male or female, solder buckets, PCB mount or IDC, with or without pillars.
//
include <../core.scad>
use <../utils/thread.scad>
d_pillar_color = grey90;
d_plug_shell_color = grey80;
@ -51,16 +52,24 @@ module d_pillar() { //! Draw a pillar for a D-connector
height = 4.5;
screw = 2.5;
screw_length = 8;
color(d_pillar_color) {
translate_z(-screw_length)
cylinder(d = screw, h = screw_length + 1);
pitch = metric_coarse_pitch(screw);
translate_z(-screw_length)
if(show_threads)
male_metric_thread(screw, pitch, screw_length, false, top = 0, colour = d_pillar_color);
else
color(d_pillar_color)
cylinder(d = screw, h = screw_length + 1);
color(d_pillar_color) {
linear_extrude(height = height)
difference() {
circle(r = rad, $fn = 6);
circle(d = screw);
}
}
}
if(show_threads)
female_metric_thread(screw, pitch, height, false, colour = d_pillar_color);
}
module d_plug(type, socket = false, pcb = false, idc = false) { //! Draw specified D plug, which can be IDC, PCB or plain solder bucket

View File

@ -29,6 +29,10 @@ fused_spades2 = [[spade6p4, 13, -7, 0, 0],
[spade4p8, 8.5, -7, -9, 90],
[spade4p8, 8.5, 7, -9, 90]];
iec320c14FusedSwitchedSpades = [[spade4p8, 8.5, 7, 10, 0],
[spade4p8, 8.5, 0, 20, 0],
[spade4p8, 8.5, 9, -2, 0]];
inlet_spades = [[spade6p4, 9, -7, -5.5, 0],
[spade6p4, 9, 7, -5.5, 0],
[spade6p4, 9, 0, 5.5, 0]];
@ -52,10 +56,11 @@ outlet_spades = [[spade4p8ll, 8, -7, -2, 90],
// w h r t
IEC_fused_inlet = ["IEC_fused_inlet", "IEC fused inlet JR-101-1F", M3_cs_cap_screw, 36, 27, 16, 31, 3, 28, 31, 2, 2.0, 30, 33, 4, 3.0, 44, 15, fused_spades, false ];
IEC_fused_inlet2= ["IEC_fused_inlet2","IEC fused inlet old", M3_cs_cap_screw, 36, 27, 14, 31, 3, 28, 31, 2, 2.5, 30, 33, 4, 2.5, 44, 18, fused_spades2, false ];
IEC_320_C14_switched_fused_inlet = ["IEC_switched_fused_inlet", "IEC320 C14 switched fused inlet module",
M3_cs_cap_screw, 40, 27, 16,46.8,3,28, 48, 2.4, 1.0, 33, 57, 4, 3.0, 48,16.5, iec320c14FusedSwitchedSpades, false ];
IEC_inlet = ["IEC_inlet", "IEC inlet", M3_cs_cap_screw, 40, 28, 18, 20, 3, 28, 20.5, 4, 2.5, 37, 23, 1, 2.5, 48, 14, inlet_spades, false ];
IEC_inlet_atx = ["IEC_inlet_atx", "IEC inlet for ATX", M3_cs_cap_screw, 40, 27, 18, 19, 3, 30.5, 22, 2, 2.0, 30.5, 22, 2, 4.0, 50, 15, atx_spades, false ];
IEC_outlet = ["IEC_outlet", "IEC outlet RS 811-7193", M3_cs_cap_screw, 40, 32, 18, 24, 3, 28, 20.5, 2, 0.0, 29, 29, 2, 2.8, 50, 23, outlet_spades, true ];
iecs = [IEC_inlet, IEC_inlet_atx, IEC_fused_inlet, IEC_fused_inlet2, IEC_outlet];
iecs = [IEC_inlet, IEC_inlet_atx, IEC_fused_inlet, IEC_fused_inlet2, IEC_320_C14_switched_fused_inlet, IEC_outlet];
use <iec.scad>

View File

@ -22,6 +22,7 @@
//
include <../core.scad>
use <../utils/quadrant.scad>
use <../utils/thread.scad>
function insert_length(type) = type[1]; //! Length
function insert_outer_d(type) = type[2]; //! Outer diameter at the top
@ -45,17 +46,18 @@ module insert(type) { //! Draw specified insert
vitamin(str("insert(", type[0], "): Heatfit insert M", insert_screw_diameter(type)));
$fn = 64;
explode(20, offset =[0, 0, -5]) color(brass) translate_z(eps) {
vflip(){
r1 = insert_screw_diameter(type) / 2;
r2 = insert_barrel_d(type) / 2;
r3 = insert_ring3_d(type) / 2;
r4 = insert_ring2_d(type) / 2;
r5 = insert_outer_d(type) / 2;
h1 = ring1_h;
h2 = ring1_h + gap;
h3 = ring1_h + gap + ring2_h;
h4 = ring1_h + gap + ring2_h + gap;
thread_d = insert_screw_diameter(type);
explode(20, offset =[0, 0, -5]) translate_z(eps) vflip() {
r1 = thread_d / 2;
r2 = insert_barrel_d(type) / 2;
r3 = insert_ring3_d(type) / 2;
r4 = insert_ring2_d(type) / 2;
r5 = insert_outer_d(type) / 2;
h1 = ring1_h;
h2 = ring1_h + gap;
h3 = ring1_h + gap + ring2_h;
h4 = ring1_h + gap + ring2_h + gap;
color(brass)
rotate_extrude()
polygon([
[r1, 0],
@ -72,7 +74,9 @@ module insert(type) { //! Draw specified insert
[r5, h1],
[r5, 0],
]);
}
if(show_threads)
female_metric_thread(thread_d, metric_coarse_pitch(thread_d), length, center = false, colour = brass);
}
}

View File

@ -21,7 +21,8 @@
//! Nuts for leadscrews.
//
include <../core.scad>
include <../utils/tube.scad>
use <../utils/tube.scad>
use <../utils/thread.scad>
function leadnut_bore(type) = type[2]; //! Thread size
function leadnut_od(type) = type[3]; //! Outer diameter of the shank
@ -33,6 +34,8 @@ function leadnut_holes(type) = type[8]; //! The number of screw hole
function leadnut_hole_dia(type) = type[9]; //! The diameter of the screw holes
function leadnut_hole_pitch(type) = type[10]; //! The radia pitch of the screw holes
function leadnut_screw(type) = type[11]; //! The type of the fixing screws
function leadnut_pitch(type) = type[12]; //! Screw pitch
function leadnut_lead(type) = type[13]; //! Screw lead
function leadnut_shank(type) = leadnut_height(type) - leadnut_flange_t(type) - leadnut_flange_offset(type); //! The length of the shank below the flange
@ -47,11 +50,18 @@ module leadnut_screw_positions(type) { //! Position children at the screw holes
module leadnut(type) { //! Draw specified leadnut
vitamin(str("leadnut(", type[0], "): ", type[1]));
bore_r = (leadnut_bore(type) + 0.5) / 2;
bore_d = leadnut_bore(type);
bore_r = bore_d / 2;
h = leadnut_height(type);
pitch = leadnut_pitch(type);
lead = leadnut_lead(type);
color("dimgrey") vflip()
translate_z(-leadnut_flange_offset(type) - leadnut_flange_t(type)) {
tube(or = leadnut_od(type) / 2, ir = bore_r, h = leadnut_height(type), center = false);
tube(or = leadnut_od(type) / 2, ir = bore_r, h = h, center = false);
if(show_threads)
thread(bore_d, lead, h, thread_profile(pitch / 2, pitch * 0.366, 30), false, starts = lead / pitch, female = true, solid = false);
translate_z(leadnut_flange_offset(type))
linear_extrude(height = leadnut_flange_t(type))

View File

@ -17,8 +17,8 @@
// If not, see <https://www.gnu.org/licenses/>.
//
LSN8x2 = ["LSN8x2", "Leadscrew nut 8 x 2", 8, 10.2, 15, 22, 3.5, 1.5, 4, 3.5, 8, M3_cap_screw];
LSN8x8 = ["LSN8x8", "Leadscrew nut 8 x 8 RobotDigg",8, 12.75,19, 25.4, 4.1, 0, 3, 3.5, 19.05/2, M3_cap_screw];
LSN8x2 = ["LSN8x2", "Leadscrew nut 8 x 2", 8, 10.2, 15, 22, 3.5, 1.5, 4, 3.5, 8, M3_cap_screw, 2, 2];
LSN8x8 = ["LSN8x8", "Leadscrew nut 8 x 8 RobotDigg",8, 12.75,19, 25.4, 4.1, 0, 3, 3.5, 19.05/2, M3_cap_screw, 2, 8];
leadnuts = [LSN8x2, LSN8x8];

View File

@ -25,7 +25,10 @@
include <../core.scad>
use <washer.scad>
use <screw.scad>
use <../utils/fillet.scad>
use <../utils/rounded_cylinder.scad>
use <../utils/thread.scad>
use <../utils/tube.scad>
brass_colour = brass;
function nut_size(type) = type[1]; //! Diameter of the corresponding screw
@ -37,7 +40,8 @@ function nut_trap_depth(type) = type[6]; //! Depth of nut trap
function nut_flat_radius(type) = nut_radius(type) * cos(30); //! Radius across the flats
module nut(type, nyloc = false, brass = false, nylon = false) { //! Draw specified nut
hole_rad = nut_size(type) / 2;
thread_d = nut_size(type);
hole_rad = thread_d / 2;
outer_rad = nut_radius(type);
thickness = nut_thickness(type);
nyloc_thickness = nut_thickness(type, true);
@ -45,18 +49,29 @@ module nut(type, nyloc = false, brass = false, nylon = false) { //! Draw specifi
vitamin(str("nut(", type[0], arg(nyloc, false, "nyloc"), arg(brass, false, "brass"), arg(nylon, false, "nylon"),
"): Nut M", nut_size(type), " x ", thickness, "mm ", desc));
explode(nyloc ? 10 : 0)
color(brass ? brass_colour : nylon ? grey30: grey70) {
colour = brass ? brass_colour : nylon ? grey30: grey70;
explode(nyloc ? 10 : 0) {
color(colour) {
linear_extrude(height = thickness)
difference() {
circle(outer_rad, $fn = 6);
circle(hole_rad);
}
if(nyloc)
translate_z(-eps)
rounded_cylinder(r = outer_rad * cos(30) , h = nyloc_thickness, r2 = (nyloc_thickness - thickness) / 2, ir = hole_rad);
}
if(show_threads)
female_metric_thread(thread_d, metric_coarse_pitch(thread_d), thickness, center = false, colour = colour);
if(nyloc)
translate_z(thickness)
color("royalblue")
tube(or = thread_d / 2 + eps, ir = (thread_d * 0.8) / 2, h = (nyloc_thickness - thickness) * 0.8, center = false);
}
if($children)
translate_z(nut_thickness(type, nyloc))
children();
@ -73,7 +88,8 @@ module nut_and_washer(type, nyloc) { //! Draw nut with corresponding washer
}
module wingnut(type) { //! Draw a wingnut
hole_rad = nut_size(type) / 2;
thread_d = nut_size(type);
hole_rad = thread_d / 2;
bottom_rad = nut_radius(type);
top_rad = type[4] / 2;
thickness = nut_thickness(type);
@ -87,27 +103,107 @@ module wingnut(type) { //! Draw a wingnut
vitamin(str("wingnut(", type[0], "): Wingnut M", nut_size(type)));
explode(10) color(grey70) {
rotate_extrude()
polygon([
[hole_rad, 0],
[bottom_rad, 0],
[top_rad,, thickness],
[hole_rad, thickness]
]);
for(rot = [0, 180])
rotate([90, 0, rot]) linear_extrude(height = wing_thickness, center = true)
hull() {
translate([wing_span / 2 - wing_width / 2, wing_height - wing_width / 2])
circle(wing_width / 2);
polygon([
[bottom_rad * cos(top_angle) - eps, 0],
[wing_span / 2 - wing_width / 2, wing_height - wing_width / 2],
[top_rad * cos(top_angle) - eps, thickness],
]);
}
colour = silver;
explode(10) {
color(colour) {
rotate_extrude()
polygon([
[hole_rad, 0],
[bottom_rad, 0],
[top_rad,, thickness],
[hole_rad, thickness]
]);
for(rot = [0, 180])
rotate([90, 0, rot]) linear_extrude(height = wing_thickness, center = true)
hull() {
translate([wing_span / 2 - wing_width / 2, wing_height - wing_width / 2])
circle(wing_width / 2);
polygon([
[bottom_rad * cos(top_angle) - eps, 0],
[wing_span / 2 - wing_width / 2, wing_height - wing_width / 2],
[top_rad * cos(top_angle) - eps, thickness],
]);
}
}
if(show_threads)
female_metric_thread(thread_d, metric_coarse_pitch(thread_d), thickness, center = false, colour = colour);
}
}
module sliding_t_nut(type) {
vitamin(str("sliding_t_nut(", type[0], "): Nut M", nut_size(type), " sliding T"));
size = [type[7], type[2], nut_thickness(type)];
tabSizeY1 = type[8];
tabSizeY2 = type[9];
tabSizeZ = type[10];
holeRadius = nut_size(type) / 2;
if($preview)
color(grey80)
extrusionSlidingNut(size, tabSizeY1, tabSizeY2, tabSizeZ, holeRadius);
}
module hammer_nut(type) {
vitamin(str("hammer_nut(", type[0], "): Nut M", nut_size(type), " hammer"));
size = [type[7], type[2], nut_thickness(type)];
tabSizeY1 = type[8];
tabSizeY2 = type[9];
tabSizeZ = type[10];
holeRadius = nut_size(type) / 2;
if($preview)
color(grey80)
extrusionSlidingNut(size, tabSizeY1, tabSizeY2, tabSizeZ, holeRadius, 0, hammerNut = true);
}
module extrusionSlidingNut(size, tabSizeY1, tabSizeY2, tabSizeZ, holeRadius, holeOffset = 0, hammerNut = false) {
// center section
linear_extrude(size[2] - tabSizeZ)
difference() {
square([size[0], size[1]], center = true);
if(hammerNut) {
translate([size[0] / 2, size[1] / 2])
rotate(180)
fillet(1);
translate([-size[0] / 2, -size[1] / 2])
fillet(1);
}
if(holeRadius)
translate([holeOffset, 0])
circle(holeRadius);
}
translate_z(size[2] - tabSizeZ)
linear_extrude(tabSizeZ)
difference() {
square([size[0], tabSizeY2], center = true);
if(holeRadius)
translate([holeOffset, 0])
circle(holeRadius);
}
thread_d = 2 * holeRadius;
if(show_threads)
translate([holeOffset, 0])
female_metric_thread(thread_d, metric_coarse_pitch(thread_d), size[2], center = false);
// add the side tabs
for(m = [0, 1])
mirror([0, m, 0])
translate([0, tabSizeY2 / 2, size[2] - tabSizeZ]) {
cubeZ = 1;
translate([-size[0] / 2, 0, 0])
cube([size[0], (tabSizeY1 - tabSizeY2) / 2, cubeZ]);
translate_z(cubeZ)
rotate([0, -90, 0])
right_triangle(tabSizeZ - cubeZ, (tabSizeY1 - tabSizeY2) / 2, size[0], center = true);
}
}
function nut_trap_radius(nut, horizontal = false) = nut_radius(nut) + (horizontal ? layer_height / 4 : 0); //! Radius across the corners of a nut trap
function nut_trap_flat_radius(nut, horizontal = false) = nut_trap_radius(nut, horizontal) * cos(30); //! Radius across the flats of a nut trap

View File

@ -51,6 +51,13 @@ toggle_nut = ["toggle_nut", 6.1, 9.2, 1.5, 1.5, M6_washer, 1.5];
M4_wingnut = ["M4_wingnut", 4, 10, 3.75,8, M4_washer, 0, 22, 10, 6, 3];
// sx ty1 ty2 tz
M3_sliding_t_nut = ["M3_sliding_t_nut", 3, 6, 4.0, 0, M3_washer, 0, 10, 10, 6, 3];
M4_sliding_t_nut = ["M4_sliding_t_nut", 4, 6, 4.5, 0, M4_washer, 0, 11, 10, 6, 3.25];
M5_sliding_t_nut = ["M5_sliding_t_nut", 5, 6, 4.5, 0, M5_washer, 0, 11, 10, 7, 3.25];
M3_hammer_nut = ["M3_hammer_nut", 3, 6, 4.0, 0, M3_washer, 0, 5.5, 10, 6, 2.75];
M4_hammer_nut = ["M4_hammer_nut", 4, 6, 4.5, 0, M4_washer, 0, 5.5, 10, 6, 3.25];
nuts = [M2_nut, M2p5_nut, M3_nut, M4_nut, M5_nut, M6_nut, M8_nut];
use <nut.scad>

View File

@ -23,6 +23,7 @@
//! A permanent magnet that can be magnatized and de-magnatized electronically.
//
include <../core.scad>
use <../utils/thread.scad>
pitch = 33.8;
width = 40;
@ -64,15 +65,20 @@ module opengrab() { //! Draw OpenGrab module
translate_z(depth - pillar - pcb / 2)
cube([width, width, pcb], center = true);
color(brass)
translate_z(1)
opengrab_hole_positions()
translate_z(1)
opengrab_hole_positions() {
color(brass)
linear_extrude(height = depth - 1)
difference() {
circle(d = 4.7 / cos(30), $fn = 6);
circle(r = 3/2);
}
if(show_threads)
female_metric_thread(3, metric_coarse_pitch(3), depth - 1, center = false, colour = brass);
}
}
module opengrab_target() { //! Draw OpenGrab target

View File

@ -201,6 +201,13 @@ module jack(cutout = false) { //! Draw 3.5mm jack
}
}
module buzzer(height, diameter, colour) { //! Draw PCB buzzer with specified height, diameter and color
color (colour)
tube(or = diameter / 2, ir = height > 5 ? 1 : 0.75, h = height);
color("white")
cylinder(d = 2, h = max(height - 3 , 0.5));
}
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
@ -711,6 +718,7 @@ module pcb_component(comp, cutouts = false, angle = undef) { //! Draw pcb compon
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, "buzzer")) buzzer(param(4, 9), param(5, 12), param(6, grey20));
if(show(comp, "jack")) jack(cutouts);
if(show(comp, "barrel_jack")) barrel_jack(cutouts);
if(show(comp, "hdmi")) hdmi(hdmi_full, cutouts);
@ -719,6 +727,7 @@ module pcb_component(comp, cutouts = false, angle = undef) { //! Draw pcb compon
if(show(comp, "flat_flex")) flat_flex(cutouts);
if(show(comp, "D_plug")) if(!cutouts) translate_z(d_pcb_offset(comp[4])) d_plug(comp[4], pcb = true);
if(show(comp, "molex_hdr")) if(!cutouts) molex_254(comp[4]);
if(show(comp, "jst_xh")) if(!cutouts) jst_xh_header(jst_xh_header, comp[4], param(5, false), param(6, "white"), param(7, undef));
if(show(comp, "term254")) if(!cutouts) green_terminal(gt_2p54,comp[4], comp[5]);
if(show(comp, "gterm35")) if(!cutouts) green_terminal(gt_3p5, comp[4], comp[5]);
if(show(comp, "gterm635")) if(!cutouts) green_terminal(gt_6p35, comp[4], comp[5]);

View File

@ -21,6 +21,7 @@
//! Threaded pillars. Each end can be male or female.
//
include <../core.scad>
use <../utils/thread.scad>
function pillar_name(type) = type[1]; //! Name of part
function pillar_thread(type) = type[2]; //! Thread diameter
@ -41,30 +42,53 @@ module pillar(type) { //! Draw specified pillar
sex = str(sex(pillar_bot_thread(type)),"/", sex(pillar_top_thread(type)));
height = pillar_height(type);
thread_d = pillar_thread(type);
bot_thread_l = pillar_bot_thread(type);
top_thread_l = pillar_top_thread(type);
thread_colour = pillar_i_colour(type);
pitch = metric_coarse_pitch(thread_d);
vitamin(str("pillar(", type[0], "): Pillar ", pillar_name(type), " ", sex, " M", thread_d, "x", height));
if(bot_thread_l > 0)
translate_z(-bot_thread_l + eps)
if(show_threads)
male_metric_thread(thread_d, pitch, bot_thread_l, false, top = 0, colour = thread_colour);
else
color(thread_colour)
cylinder(h = bot_thread_l, d = thread_d);
if(top_thread_l > 0)
translate_z(height - eps)
if(show_threads)
male_metric_thread(thread_d, pitch, top_thread_l, false, bot = 0, colour = thread_colour);
else
color(thread_colour)
cylinder(h = top_thread_l, d = thread_d);
color(pillar_i_colour(type)) {
if(pillar_bot_thread(type) > 0)
translate_z(-pillar_bot_thread(type))
cylinder(h = pillar_bot_thread(type) + eps, d = pillar_thread(type));
if(pillar_top_thread(type) > 0)
translate_z(height - eps)
cylinder(h = pillar_top_thread(type) + eps, d = pillar_thread(type));
linear_extrude(height = height)
difference() {
circle(d = pillar_id(type), $fn = fn(pillar_ifn(type)));
circle(d = pillar_thread(type));
circle(d = thread_d);
}
top = height + min(pillar_top_thread(type), 0);
bot = -min(pillar_bot_thread(type), 0);
top = height + min(top_thread_l, 0);
bot = -min(bot_thread_l, 0);
translate_z(bot)
cylinder(h = top - bot, d = pillar_thread(type) + eps);
cylinder(h = top - bot, d = thread_d + eps);
}
if(show_threads) {
if(top_thread_l < 0)
translate_z(height)
vflip()
female_metric_thread(thread_d, pitch, -top_thread_l, false, colour = thread_colour);
if(bot_thread_l < 0)
female_metric_thread(thread_d, pitch, -bot_thread_l, false, colour = thread_colour);
}
if(pillar_od(type) > pillar_id(type))
color(pillar_o_colour(type)) linear_extrude(height = height)
difference() {

View File

@ -30,8 +30,8 @@
// d r r d d
//
M2x16_brass_pillar = ["M2x16_brass_pillar", "nurled", 2, 16, 3.17, 3.17, 0, 0, brass, brass, 3,-3];
M3x13_hex_pillar = ["M3x13_hex_pillar", "hex", 3, 13, 5/cos(30), 5/cos(30), 6, 6, "silver", "silver", -6, 6];
M3x20_hex_pillar = ["M3x20_hex_pillar", "hex", 3, 20, 5/cos(30), 5/cos(30), 6, 6, "silver", "silver", -8, 8];
M3x13_hex_pillar = ["M3x13_hex_pillar", "hex", 3, 13, 5/cos(30), 5/cos(30), 6, 6, "silver", silver, -6, 6];
M3x20_hex_pillar = ["M3x20_hex_pillar", "hex", 3, 20, 5/cos(30), 5/cos(30), 6, 6, "silver", silver, -8, 8];
M3x20_nylon_pillar = ["M3x20_nylon_pillar", "nylon", 3, 20, 8, 5/cos(30), 0, 6, "white", brass, -6, 6];
M4x17_nylon_pillar = ["M4x17_nylon_pillar", "nylon", 4, 20, 8, 5/cos(30), 0, 6, "white", brass, -6, 6];
M3x20_nylon_hex_pillar = ["M3x20_nylon_hex_pillar", "hex nylon", 3, 20, 8/cos(30), 8/cos(30), 6, 6, grey20, grey20, -6, 6];

View File

@ -205,3 +205,71 @@ module pin_socket(type, cols = 1, rows = 1, right_angle = false, height = 0, smt
}
}
}
module jst_xh_header(type, pin_count, right_angle=false, colour, pin_colour) { //! Draw JST XH connector
colour = colour ? colour : hdr_base_colour(type);
pin_colour = pin_colour ? pin_colour : hdr_pin_colour(type);
sizeY = 5.75;
pitch = hdr_pitch(type);
module jst_xh_socket(type, pin_count) {
socketSizeZ = hdr_socket_depth(type);
pinOffsetX = 2.45;
sizeY = 5.75;
wallThickness = 0.8;
size = [pinOffsetX * 2 + (pin_count - 1) * pitch, sizeY, socketSizeZ];
translate([-size[0] / 2, -size[1] / 2, 0]) {
// the base
cube([size[0], size[1], wallThickness]);
// the three full sides
translate([0, size[1] - wallThickness, 0])
cube([size[0], wallThickness, size[2]]);
cube([wallThickness, size[1], size[2]]);
translate([size[0] - wallThickness, 0, 0])
cube([wallThickness, size[1], size[2]]);
// the sides with cutouts
cube([size[0], wallThickness, 2]);
cutoutWidth = 1;
cutoutOffset = pinOffsetX - cutoutWidth / 2;
cube([cutoutOffset, wallThickness, size[2]]);
translate([size[0] - cutoutOffset, 0, 0])
cube([cutoutOffset, wallThickness, size[2]]);
cube([cutoutOffset, wallThickness, size[2]]);
translate([size[0]-cutoutOffset, 0, 0])
cube([cutoutOffset, wallThickness, size[2]]);
translate([cutoutOffset + cutoutWidth, 0, 0])
cube([size[0] - 2 * (cutoutWidth + cutoutOffset), wallThickness, size[2]]);
}
} // end module
color(colour)
if(right_angle)
translate([0, -1, sizeY / 2])
rotate([-90, 0, 180])
jst_xh_socket(type, pin_count);
else
jst_xh_socket(type, pin_count);
color(pin_colour)
for(x = [0 : pin_count - 1]) {
pinWidth = hdr_pin_width(type);
verticalPinLength = right_angle ? hdr_pin_below(type) + sizeY / 2 : hdr_pin_length(type);
translate([pitch * (x - (pin_count - 1) / 2), 0, 0]) {
pin(type, verticalPinLength);
if(right_angle) {
translate([0, -pinWidth / 2, sizeY / 2 - pinWidth / 2])
rotate([0, -90, 0])
rotate_extrude(angle = 90, $fn = 32)
translate([0, -pinWidth / 2])
square(pinWidth);
translate([0, -sizeY / 2 - 3 * pinWidth / 4, sizeY / 2])
rotate([90,0,0])
pin(type, hdr_pin_length(type) - hdr_pin_below(type));
}
}
}
}

View File

@ -25,6 +25,7 @@
// c
//
2p54header = ["2p54header", 2.54, 11.6, 3.2, 0.66, "gold", grey20, 8.5];
jst_xh_header = ["JST XH header",2.5,10,3.4, 0.64, "gold", grey90, 7];
pin_headers = [ 2p54header ];

View File

@ -65,7 +65,7 @@ module carriage_hole_positions(type) { //! Position children over screw holes
children();
}
module carriage(type, rail) { //! Draw the specified carriage
module carriage(type, rail, end_color = grey20, wiper_color = grey20) { //! Draw the specified carriage
total_l = carriage_length(type);
block_l = carriage_block_length(type);
block_w = carriage_width(type);
@ -100,19 +100,30 @@ module carriage(type, rail) { //! Draw the specified carriage
carriage_hole_positions(type)
circle(screw_pilot_hole(screw));
}
}
color(grey20)
for(end = [-1, 1])
translate([end * (block_l / 2 + end_l / 2), 0])
rotate([90, 0, 90])
linear_extrude(height = end_l, center = true)
difference() {
translate([-end_w / 2, carriage_clearance(type)])
square([end_w, end_h]);
cutout();
}
module carriage_end(type, end_w, end_h, end_l) {
wiper_length = 0.5;
color(wiper_color) translate_z(-end_l/2) linear_extrude(wiper_length)
difference() {
translate([-end_w/2, carriage_clearance(type)])
square([end_w, end_h]);
cutout();
}
color(end_color) translate_z(wiper_length-end_l/2) linear_extrude(end_l-wiper_length)
difference() {
translate([-end_w/2, carriage_clearance(type)])
square([end_w, end_h]);
cutout();
}
}
translate([-(block_l+end_l)/2,0,0])
rotate([90, 0, 90])
carriage_end(type, end_w, end_h, end_l);
translate([(block_l+end_l)/2,0,0])
rotate([90, 0, -90])
carriage_end(type, end_w, end_h, end_l);
}
module rail(type, length) { //! Draw the specified rail
@ -139,11 +150,11 @@ module rail(type, length) { //! Draw the specified rail
}
}
module rail_assembly(type, length, pos) { //! Rail and carriage assembly
module rail_assembly(type, length, pos, carriage_end_color = grey20, carriage_wiper_color = grey20) { //! Rail and carriage assembly
rail(type, length);
translate([pos, 0])
carriage(rail_carriage(type), type);
carriage(rail_carriage(type), type, carriage_end_color, carriage_wiper_color);
}

View File

@ -25,7 +25,7 @@ use <spade.scad>
function rocker_part(type) = type[1]; //! Part description
function rocker_slot_w(type) = type[2]; //! Panel slot width
function rocker_slot_h(type) = type[3]; //! Panel slow height
function rocker_slot_h(type) = type[3]; //! Panel slot height
function rocker_flange_w(type) = type[4]; //! Flange width
function rocker_flange_h(type) = type[5]; //! Flange height
function rocker_flange_t(type) = type[6]; //! Flange thickness
@ -37,7 +37,7 @@ function rocker_pivot(type) = type[11]; //! Pivot distance from the back of
function rocker_button(type) = type[12]; //! How far the button extends from the bezel
function rocker_spades(type) = type[13]; //! Spade types and positions
module rocker(type) { //! Draw the specified rocker switch
module rocker(type, colour) { //! Draw the specified rocker switch
vitamin(str("rocker(", type[0], "): ", rocker_part(type)));
bezel = rocker_bezel(type);
@ -65,7 +65,7 @@ module rocker(type) { //! Draw the specified rocker switch
rounded_rectangle([rocker_width(type), rocker_height(type), rocker_depth(type) + eps], 0.5, center = false);
}
if(rocker_pivot(type))
color(grey30)
color(colour ? colour : grey30)
translate_z(rocker_pivot(type))
rotate([90, 0, 90])
linear_extrude(height = rocker_w, center = true)
@ -78,7 +78,7 @@ module rocker(type) { //! Draw the specified rocker switch
}
else
color("red") cube([rocker_w, rocker_h, 2 * (rocker_flange_t(type) + rocker_button(type))], center = true);
color(colour ? colour : "red") cube([rocker_w, rocker_h, 2 * (rocker_flange_t(type) + rocker_button(type))], center = true);
for(spade = rocker_spades(type))
translate([spade[2], spade[3], -rocker_depth(type)])

View File

@ -21,30 +21,57 @@
//! Steel rods and studding with chamfered ends.
//
include <../core.scad>
use <../utils/thread.scad>
rod_colour = grey80;
studding_colour = grey70;
leadscrew_colour = grey70;
module rod(d , l) { //! Draw a smooth rod with specified length and diameter
module rod(d , l, center = true) { //! Draw a smooth rod with specified diameter and length
vitamin(str("rod(", d, ", ", l, "): Smooth rod ", d, "mm x ", l, "mm"));
chamfer = d / 10;
color(rod_colour)
hull() {
cylinder(d = d, h = l - 2 * chamfer, center = true);
translate_z(center ? 0 : l / 2)
hull() {
cylinder(d = d, h = l - 2 * chamfer, center = true);
cylinder(d = d - 2 * chamfer, h = l, center = true);
}
cylinder(d = d - 2 * chamfer, h = l, center = true);
}
}
module studding(d , l) { //! Draw a threaded rod with specified length and diameter
module studding(d , l, center = true) { //! Draw a threaded rod with specified diameter and length
vitamin(str("studding(", d, ", ", l,"): Threaded rod M", d, " x ", l, "mm"));
chamfer = d / 20;
color(studding_colour)
hull() {
cylinder(d = d, h = l - 2 * chamfer, center = true);
pitch = metric_coarse_pitch(d);
cylinder(d = d - 2 * chamfer, h = l, center = true);
}
translate_z(center ? 0 : l / 2)
if(show_threads && pitch)
male_metric_thread(d, pitch, l, colour = rod_colour);
else
color(studding_colour)
hull() {
cylinder(d = d, h = l - 2 * chamfer, center = true);
cylinder(d = d - 2 * chamfer, h = l, center = true);
}
}
module leadscrew(d , l, lead, starts, center = true) { //! Draw a leadscrew with specified diameter, length, lead and number of starts
vitamin(str("leadscrew(", d, ", ", l, ", ", lead, ", ", starts, "): Leadscrew ", d, " x ", l, "mm, ", lead, "mm lead, ", starts, " starts"));
pitch = lead / starts;
chamfer = pitch / 2;
translate_z(center ? 0 : l / 2)
if(show_threads && pitch)
thread(d - pitch, lead, l, thread_profile(pitch / 2, pitch * 0.366, 30), top = 45, bot = 45, starts = starts, center = center, colour = rod_colour);
else
color(leadscrew_colour)
hull() {
cylinder(d = d, h = l - 2 * chamfer, center = true);
cylinder(d = d - 2 * chamfer, h = l, center = true);
}
}

View File

@ -24,6 +24,7 @@ include <../core.scad>
use <washer.scad>
use <../utils/rounded_cylinder.scad>
use <../utils/thread.scad>
function screw_head_type(type) = type[2]; //! Head style hs_cap, hs_pan, hs_cs, hs_hex, hs_grub, hs_cs_cap, hs_dome
function screw_radius(type) = type[3] / 2; //! Nominal radius
@ -69,28 +70,36 @@ module screw(type, length, hob_point = 0, nylon = false) { //! Draw specified sc
socket_depth= screw_socket_depth(type);
socket_rad = socket_af / cos(30) / 2;
max_thread = screw_max_thread(type);
thread = max_thread ? min(length, max_thread) : length;
shank = length - thread;
thread = max_thread ? length >= max_thread + 5 ? max_thread
: length
: length;
d = 2 * screw_radius(type);
pitch = metric_coarse_pitch(d);
colour = nylon || head_type == hs_grub ? grey40 : grey80;
module shaft(headless = 0) {
module shaft(socket = 0, headless = false) {
point = screw_nut(type) ? 0 : 3 * rad;
color(colour * 0.9 )
rotate_extrude() {
translate([0, -length + point])
square([rad, length - headless - point]);
shank = length - thread - socket;
if(point)
polygon([
[0, -length], [0, point - length], [rad - 0.1, point - length]
]);
}
if(shank >= 5)
if(show_threads && !point && pitch)
translate_z(-length)
male_metric_thread(d, pitch, thread - (shank > 0 || headless ? 0 : socket), false, top = headless ? -1 : 0, solid = !headless, colour = colour);
else
color(colour * 0.9)
rotate_extrude() {
translate([0, -length + point])
square([rad, length - socket - point]);
if(point)
polygon([
[0.4, -length], [0, point - length], [rad, point - length]
]);
}
if(shank > 0)
color(colour)
translate_z(-shank)
cylinder(r = rad + eps, h = shank - headless);
translate_z(-shank - socket)
cylinder(r = rad + eps, h = shank);
}
explode(length + 10) {
@ -102,6 +111,7 @@ module screw(type, length, hob_point = 0, nylon = false) { //! Draw specified sc
linear_extrude(height = socket_depth)
difference() {
circle(head_rad);
circle(socket_rad, $fn = 6);
}
@ -110,14 +120,20 @@ module screw(type, length, hob_point = 0, nylon = false) { //! Draw specified sc
}
if(head_type == hs_grub) {
color(colour) {
r = show_threads ? rad - pitch / 2 : rad;
translate_z(-socket_depth)
linear_extrude(height = socket_depth)
difference() {
circle(r = rad);
circle(r);
circle(socket_rad, $fn = 6);
}
shaft(socket_depth);
shaft(socket_depth, true);
if(show_threads)
translate_z(-length)
cylinder(r = r, h = length - socket_depth);
}
}
if(head_type == hs_hex) {

View File

@ -20,6 +20,7 @@
//! Filament spool models
include <../core.scad>
include <../utils/tube.scad>
function spool_diameter(type) = type[1]; //! Outside diameter
function spool_width(type) = type[2]; //! Internal width
@ -32,7 +33,7 @@ function spool_hub_taper(type) = type[8]; //! Diameter at which it tapers do
function spool_height(type) = spool_width(type) + 2 * spool_hub_thickness(type); //! Outside width
function spool_pitch(type) = spool_width(type) + spool_rim_thickness(type); //! Spacing of the rims
module spool(type) { //! Draw specified spool
module spool(type, filament_depth = 0, filament_colour = "white", filament_d = 3) { //! Draw specified spool with optional filament
vitamin(str("spool(", type[0], "): Filament spool ", spool_diameter(type), " x ", spool_width(type)));
h = spool_height(type);
@ -57,4 +58,25 @@ module spool(type) { //! Draw specified spool
[r3, h - spool_hub_thickness(type) + spool_rim_thickness(type)],
[r2, h],
]);
if(filament_depth) {
w = spool_width(type);
r = r5 + filament_depth;
color(filament_colour)
if(filament_d) {
n = round(w / filament_d) + 1;
fd = w / n;
rotate_extrude($fn = 180) {
for(i = [0 : n -1])
translate([r - fd / 2, i * fd - w / 2 + fd / 2])
circle(d = fd, $fn = 32);
translate([r5, -w / 2])
square([filament_depth - fd / 2, w]);
}
}
else
tube(r, r5, w, $fn = 180);
}
}

View File

@ -26,6 +26,7 @@ include <screws.scad>
use <washer.scad>
include <ring_terminals.scad>
use <../utils/tube.scad>
use <rod.scad>
function NEMA_width(type) = type[1]; //! Width of the square face
function NEMA_length(type) = type[2]; //! Body length
@ -34,7 +35,7 @@ function NEMA_body_radius(type) = type[4]; //! Body radius
function NEMA_boss_radius(type) = type[5]; //! Boss around the spindle radius
function NEMA_boss_height(type) = type[6]; //! Boss height
function NEMA_shaft_dia(type) = type[7]; //! Shaft diameter
function NEMA_shaft_length(type)= type[8]; //! Shaft length above the face
function NEMA_shaft_length(type)= type[8]; //! Shaft length above the face, if a list then a leadscrew: length, lead, starts
function NEMA_hole_pitch(type) = type[9]; //! Screw hole pitch
function NEMA_holes(type) = [-NEMA_hole_pitch(type) / 2, NEMA_hole_pitch(type) / 2]; //! Screw positions for for loop
function NEMA_big_hole(type) = NEMA_boss_radius(type) + 0.2; //! Clearance hole for the big boss
@ -50,7 +51,7 @@ module NEMA_outline(type) //! 2D outline
circle(NEMA_radius(type));
}
module NEMA(type) { //! Draw specified NEMA stepper motor
module NEMA(type, shaft_angle = 0) { //! Draw specified NEMA stepper motor
side = NEMA_width(type);
length = NEMA_length(type);
body_rad = NEMA_body_radius(type);
@ -88,9 +89,15 @@ module NEMA(type) { //! Draw specified NEMA stepper motor
}
}
color(NEMA_shaft_length(type) > 50 ? "silver" : stepper_cap_colour)
translate_z(-5)
cylinder(r = shaft_rad, h = NEMA_shaft_length(type) + 5); // shaft
shaft = NEMA_shaft_length(type);
translate_z(-5)
rotate(shaft_angle)
if(!is_list(shaft))
color(stepper_cap_colour)
cylinder(r = shaft_rad, h = shaft + 5); // shaft
else
not_on_bom()
leadscrew(shaft_rad * 2, shaft.x + 5, shaft.y, shaft.z, center = false)
translate([0, side / 2, -length + cap / 2])
rotate([90, 0, 0])

View File

@ -22,14 +22,14 @@
//
// corner body boss boss shaft
// side, length, radius, radius, radius, depth, shaft, length, holes
NEMA17 = ["NEMA17", 42.3, 47, 53.6/2, 25, 11, 2, 5, 24, 31 ];
NEMA17M = ["NEMA17M", 42.3, 40, 53.6/2, 25, 11, 2, 5, 20, 31 ];
NEMA17M8= ["NEMA17M8", 42.3, 40, 53.6/2, 25, 11, 2, 8, 280, 31 ];
NEMA17S = ["NEMA17S", 42.3, 34, 53.6/2, 25, 11, 2, 5, 24, 31 ];
NEMA16 = ["NEMA16", 39.5, 19.2, 50.6/2, 50.6/2, 11, 2, 5, 12, 31 ];
NEMA14 = ["NEMA14", 35.2, 36, 46.4/2, 21, 11, 2, 5, 21, 26 ];
NEMA23 = ["NEMA23", 56.4, 51.2, 75.7/2, 35, 38.1/2, 1.6, 6.35, 24, 47.1 ];
// side, length, radius, radius, radius, depth, shaft, length, holes
NEMA17 = ["NEMA17", 42.3, 47, 53.6/2, 25, 11, 2, 5, 24, 31 ];
NEMA17M = ["NEMA17M", 42.3, 40, 53.6/2, 25, 11, 2, 5, 20, 31 ];
NEMA17M8= ["NEMA17M8", 42.3, 40, 53.6/2, 25, 11, 2, 8, [280, 8, 4], 31 ];
NEMA17S = ["NEMA17S", 42.3, 34, 53.6/2, 25, 11, 2, 5, 24, 31 ];
NEMA16 = ["NEMA16", 39.5, 19.2, 50.6/2, 50.6/2, 11, 2, 5, 12, 31 ];
NEMA14 = ["NEMA14", 35.2, 36, 46.4/2, 21, 11, 2, 5, 21, 26 ];
NEMA23 = ["NEMA23", 56.4, 51.2, 75.7/2, 35, 38.1/2, 1.6, 6.35, 24, 47.1 ];
stepper_motors = [NEMA14, NEMA16, NEMA17S, NEMA17M, NEMA17, NEMA23];

View File

@ -23,6 +23,8 @@
include <../core.scad>
use <nut.scad>
use <washer.scad>
use <../utils/thread.scad>
use <../utils/tube.scad>
function toggle_part(type) = type[1]; //! Part description
function toggle_width(type) = type[2]; //! Body width
@ -80,7 +82,29 @@ module toggle(type, thickness) { //! Draw specified toggle switch with the nuts
translate_z(-h1 / 2 - t)
cube([toggle_width(type), toggle_height(type), h1], center = true);
color("silver") {
if(show_threads) {
d = toggle_od(type);
pitch = inch(1/40);
h = 5 * pitch * sqrt(3) / 16;
male_metric_thread(d, pitch, thread, center = false, solid = false, colour = silver);
color(silver)
tube(or = d / 2 - h, ir = toggle_id(type) / 2, h = thread, center = false);
}
else
color(silver)
rotate_extrude()
difference() {
hull() {
square([toggle_od(type) / 2, thread - chamfer]);
square([toggle_od(type) / 2 - chamfer, thread]);
}
square([toggle_id(type) / 2, thread + 1]);
}
color(silver) {
if(toggle_collar_t(type))
cylinder(d = toggle_collar_d(type), h = toggle_collar_t(type));
@ -90,15 +114,6 @@ module toggle(type, thickness) { //! Draw specified toggle switch with the nuts
translate_z(-h2 / 2)
cube([toggle_width(type) + 2 * eps, toggle_height(type) - 2 * inset, h2], center = true);
rotate_extrude()
difference() {
hull() {
square([toggle_od(type) / 2, thread - chamfer]);
square([toggle_od(type) / 2 - chamfer, thread]);
}
square([toggle_id(type) / 2, thread + 1]);
}
translate_z(toggle_pivot(type)) {
angle = toggle_angle(type);

Some files were not shown because too many files have changed in this diff Show More