1
0
mirror of https://github.com/nophead/NopSCADlib.git synced 2025-09-03 12:22:46 +02:00

Compare commits

...

141 Commits

Author SHA1 Message Date
Chris Palmer
7c2df8d36d The pose module can now specify the camera distance supressing viewall and
autocentre.
2021-02-20 19:28:52 +00:00
Chris Palmer
8474718884 Added printed pocket_handle(). 2021-02-17 13:20:39 +00:00
Chris Palmer
fe0f32ddc5 Merge branch 'martinbudden-polyholes' 2021-02-11 09:41:27 +00:00
Chris Palmer
f191b9b0f4 Updated readme 2021-02-11 09:40:18 +00:00
Chris Palmer
2b3908b6fd Merge branch 'polyholes' of https://github.com/martinbudden/NopSCADlib into martinbudden-polyholes 2021-02-11 09:11:42 +00:00
Chris Palmer
0a84bf0927 plateup.py now saves the used files to speed up processing when a part hasn't changed.
Added times to plateup.py.
2021-02-11 09:10:15 +00:00
Chris Palmer
da825b17ab Added colorama.init() to plateup.py to handle new coloured changed messages. 2021-02-10 10:22:38 +00:00
Chris Palmer
ca153c971d Fixed platters and panels not working in the GUI, a regression.
set_config() now puts $cwd in target.scad.
use_stl() and use_dxf() included again instead of used.
2021-02-10 10:17:03 +00:00
Martin Budden
0199587907 Allow poly_shapes to collapse to non-poly form. 2021-02-10 08:29:15 +00:00
Chris Palmer
60350eb228 Updated gallery.py for new page break format. 2021-02-09 23:44:03 +00:00
Chris Palmer
4f9729cf86 Now shows what changed to trigger an openscad invocation in cyan. 2021-02-09 23:32:53 +00:00
Chris Palmer
26f1338ca2 Fixed removal of old deps 2021-02-09 14:34:27 +00:00
Chris Palmer
fc44b43638 Temporary files used during make_all and tests now in tmp dir. 2021-02-09 09:52:26 +00:00
Chris Palmer
182f39876a Moved deps directories to separate stl deps from views deps. 2021-02-09 09:18:30 +00:00
Chris Palmer
055e90cbb3 /stls/ and /dxfs/ excluded from deps to prevent circular dependencies. 2021-02-08 22:44:21 +00:00
Chris Palmer
832380f893 Fixed set_config always writing to target.scad. 2021-02-08 20:31:10 +00:00
Chris Palmer
929d082b25 openscad.py now quits if there are errors or warnings in the log.
This is because the exit status is not always set correctly.
2021-02-08 16:03:59 +00:00
Chris Palmer
57212b5701 set_config.py now defines $target. 2021-02-08 15:00:44 +00:00
Chris Palmer
1c3f136657 Fixed $cwd and $target not defined during silent run. 2021-02-08 15:00:01 +00:00
Chris Palmer
cfd2fd32a1 Now checks openscad.echo for warnings when used instead of openscad.log. 2021-02-08 14:58:50 +00:00
Chris Palmer
f573a91a09 Removed redundant rounded_rectangle center = false. 2021-02-08 09:41:07 +00:00
Chris Palmer
d75aff2ccd rounded_retangle() centre now defaults to false. 2021-02-08 09:24:00 +00:00
Chris Palmer
491d85156c Merge branch 'martinbudden-rounded_cubes' 2021-02-08 08:29:50 +00:00
Chris Palmer
c89ce6843f Updated images and readme. 2021-02-08 08:29:08 +00:00
Chris Palmer
1915dae034 Merge branch 'rounded_cubes' of https://github.com/martinbudden/NopSCADlib into martinbudden-rounded_cubes 2021-02-07 22:17:22 +00:00
Chris Palmer
05e8055ce2 Merge branch 'martinbudden-btt_skr_e3_turbo' 2021-02-07 22:01:41 +00:00
Chris Palmer
21822b9abb Updated pictures and readme. 2021-02-07 22:01:26 +00:00
Chris Palmer
d83d4b89bf Merge branch 'btt_skr_e3_turbo' of https://github.com/martinbudden/NopSCADlib into martinbudden-btt_skr_e3_turbo 2021-02-07 21:48:16 +00:00
Chris Palmer
613152f589 Merge branch 'martinbudden-bl30x10' 2021-02-07 21:46:28 +00:00
Chris Palmer
d90c00d140 Updated images and readme. 2021-02-07 21:46:15 +00:00
Chris Palmer
b52ca9589a Merge branch 'bl30x10' of https://github.com/martinbudden/NopSCADlib into martinbudden-bl30x10 2021-02-07 21:25:53 +00:00
Martin Budden
0d024060fc Added BTT_SKR_E3_TURBO. 2021-02-07 07:51:10 +00:00
Martin Budden
c4fe1d1098 Added assertion to check r value. Used extrud_if. 2021-02-07 07:29:02 +00:00
Chris Palmer
a3ced6de45 Merge branch 'martinbudden-mgn9_correction' 2021-02-06 15:29:51 +00:00
Chris Palmer
1cdfe3267c Merge branch 'mgn9_correction' of https://github.com/martinbudden/NopSCADlib into martinbudden-mgn9_correction 2021-02-06 15:28:49 +00:00
Chris Palmer
b67cf4ce97 Library printed parts now make use of stl() child. 2021-02-06 15:24:19 +00:00
Chris Palmer
5bac2bf46d stl() and dxf() can now have the code to make the STL or DXF as a child.
This allows them to be replaced by the STL or DXF when making assembly views.

use_dxf() and use_stl() make use of $cwd and $target, so can be in bom.scad
and be documented.

Corrected the spelling of widget in BOM test.
2021-02-06 15:23:10 +00:00
Chris Palmer
079168142b Views.py and plateup.py now define $cwd and $target. 2021-02-06 15:12:21 +00:00
Chris Palmer
cb30f0c63d Times for parts that no longer exist pruned from build times.
Now shows changes to the total time.
2021-02-06 10:39:39 +00:00
Martin Budden
812fbc106c Updated screw hole position. 2021-02-04 19:59:28 +00:00
Martin Budden
dd38fa6e5d Added 30x10 square radial fan. 2021-02-04 18:26:44 +00:00
Martin Budden
5cdcd4ad37 Corrected MGN9 rail end value. 2021-02-03 11:24:44 +00:00
Chris Palmer
4cb324ed37 Merge branch 'martinbudden-rails_rename' 2021-02-03 07:10:27 +00:00
Chris Palmer
eb997aa18c Updated readme for rails. Note interface change. 2021-02-03 07:10:07 +00:00
Chris Palmer
f09343a285 Merge branch 'rails_rename' of https://github.com/martinbudden/NopSCADlib into martinbudden-rails_rename 2021-02-03 06:38:07 +00:00
Chris Palmer
54aab027bd Merge branch 'martinbudden-skr_mini_e3_update' 2021-02-03 06:35:54 +00:00
Chris Palmer
cc61a11602 Updated PCB images. 2021-02-03 06:35:42 +00:00
Chris Palmer
9cf2e9d7c3 Merge branch 'skr_mini_e3_update' of https://github.com/martinbudden/NopSCADlib into martinbudden-skr_mini_e3_update 2021-02-03 06:26:36 +00:00
Chris Palmer
9da8a3cb26 Set ngb for most library assemblies. 2021-02-03 06:21:44 +00:00
Chris Palmer
36521cf0b9 Set ngb parameter of assembly() to remove it from the global BOM and merge
its parts into it parent's global BOM column.
2021-02-03 06:21:17 +00:00
Martin Budden
22b7aa956c Renamed rounded_rectangle_* to rounded_cube_*. 2021-02-02 17:32:44 +00:00
Martin Budden
f760aaa20a Changed carriage to specify its rail type. 2021-02-02 12:23:03 +00:00
Martin Budden
1c445385b4 Made C version of linear rails and carriages explicit. 2021-02-01 19:21:50 +00:00
Martin Budden
45f3fc275f BTT_SKR_MINI_E3_V2_0 tidy and correction. 2021-02-01 19:19:20 +00:00
Chris Palmer
f7fbbd5fe4 No longer runs markdown twice to make printme.html.
Instead uses empty spans to mark page breaks and then replaces them.
2021-02-01 00:10:54 +00:00
Chris Palmer
a769a38dff Generation of the html files included in the build times. 2021-01-31 10:52:26 +00:00
Chris Palmer
0485eeeb34 Removed page break at the end for printme.html 2021-01-31 10:50:20 +00:00
Chris Palmer
0a7208ff5a Fixed codespell path for multi-target builds. 2021-01-31 10:47:54 +00:00
Chris Palmer
f32182d6df Merge branch 'martinbudden-pulley_colour' 2021-01-26 17:35:02 +00:00
Chris Palmer
84fbd05f9b Updated readme for pulley colour. 2021-01-26 17:34:43 +00:00
Chris Palmer
2a1fa3fe6b Merge branch 'pulley_colour' of https://github.com/martinbudden/NopSCADlib into martinbudden-pulley_colour 2021-01-26 17:10:58 +00:00
Chris Palmer
176dc3231c Merge branch 'martinbudden-screw_m5_dome' 2021-01-26 17:03:32 +00:00
Chris Palmer
e7ac18e3c0 Updated images and readme. 2021-01-26 17:03:16 +00:00
Martin Budden
74b8dcb6d8 Added colour parameter to pulley. 2021-01-26 15:20:20 +00:00
Martin Budden
6269575fd4 Added M5_dome_screw. 2021-01-26 15:12:52 +00:00
Chris Palmer
2923e35725 Added microswitch_op_tol() and microswitch_fp_max() functions. 2021-01-24 21:44:57 +00:00
Chris Palmer
5a1b06fbb9 Merge branch 'martinbudden-BTT_SKR_MINI_E3_V2_0' 2021-01-24 11:20:37 +00:00
Chris Palmer
fd174bbfb4 Updated readme and images. 2021-01-24 11:20:01 +00:00
Chris Palmer
186f31bb09 Merge branch 'BTT_SKR_MINI_E3_V2_0' of https://github.com/martinbudden/NopSCADlib into martinbudden-BTT_SKR_MINI_E3_V2_0 2021-01-24 10:59:03 +00:00
Martin Budden
80f0490d58 Added BTT_SKR_MINI_E3_V2_0 pcb. 2021-01-24 10:55:49 +00:00
Chris Palmer
c9e9942070 Fixed some paths that used NopSCADlib instead of .. 2021-01-23 21:15:00 +00:00
Chris Palmer
e41366e20c Added explicit error message when tmp.png is not generated as expected.
Prints a newline after test runs rather than before.
2021-01-21 12:49:48 +00:00
Chris Palmer
0595fb5a92 Merge branch 'martinbudden-btt_skr_1_4' 2021-01-18 15:57:04 +00:00
Chris Palmer
abb676b75c Updated readme and cover picture for BTT_SKR_V1_4_TURBO PCB.
Added list of hidden pcbs to hide the boring ones.
Smaller PCBs closer together to make space.
2021-01-18 15:56:09 +00:00
Chris Palmer
19bae20e24 Merge branch 'btt_skr_1_4' of https://github.com/martinbudden/NopSCADlib into martinbudden-btt_skr_1_4 2021-01-18 12:54:03 +00:00
Chris Palmer
a7d181ffc4 Merge branch 'martinbudden-rectangular_tube' 2021-01-18 12:52:53 +00:00
Chris Palmer
6b2f8d282b Updated readme and images. 2021-01-18 12:52:41 +00:00
Chris Palmer
5bb95b2406 Merge branch 'rectangular_tube' of https://github.com/martinbudden/NopSCADlib into martinbudden-rectangular_tube 2021-01-18 10:34:51 +00:00
Chris Palmer
dc3905b284 Removed redundant longer = true with nyloc = true. 2021-01-18 10:33:17 +00:00
Martin Budden
bd2ea3f284 Added a rectangular tube. 2021-01-17 16:34:09 +00:00
Martin Budden
62183bcadc Added BTT SKR V1.4 Turbo pcb. 2021-01-17 16:29:42 +00:00
Chris Palmer
7f9122ae66 Added --hardwarnings to openscad.py 2021-01-15 18:13:20 +00:00
Chris Palmer
93b260b7b9 Added screw_length() to calculuate screw lengths includin washers, inserts and nuts. 2021-01-15 18:12:37 +00:00
Chris Palmer
c33876530e Merge branch 'martinbudden-green_terminals' 2021-01-13 21:31:25 +00:00
Chris Palmer
8fea8f437b Updated images and readme for green terminals. 2021-01-13 21:31:14 +00:00
Chris Palmer
bc3ef607af Merge branch 'green_terminals' of https://github.com/martinbudden/NopSCADlib into martinbudden-green_terminals 2021-01-13 21:17:08 +00:00
Chris Palmer
6bcdc24cd3 Updated readme an images for ESP-01. 2021-01-13 21:12:29 +00:00
Chris Palmer
b8b4232882 Merge branch 'ESP8266' of https://github.com/martinbudden/NopSCADlib 2021-01-13 20:21:43 +00:00
Chris Palmer
0394d9981f Merge branch 'martinbudden-tft35' 2021-01-13 20:20:24 +00:00
Chris Palmer
e4e7096e3c Merge branch 'martinbudden-ESP8266' 2021-01-13 20:18:13 +00:00
Chris Palmer
d71bb4bdfa Remove commented out code. 2021-01-13 20:17:43 +00:00
Chris Palmer
89c3767f21 Update image. 2021-01-13 20:09:16 +00:00
Martin Budden
c837de721d Renamed ESP8266 to ESP_01 and rotated. 2021-01-13 18:52:14 +00:00
Martin Budden
f8c87bd8e3 Added ESP8266. 2021-01-13 17:22:46 +00:00
Martin Budden
ef58fe5818 Minor corrections to positions on BigTreeTech_TFT35v3_0_PCB. 2021-01-13 15:57:27 +00:00
Martin Budden
9c0c0c0acf Added green terminals gt_5x11 and gt_5x17. 2021-01-13 15:51:41 +00:00
Chris Palmer
ac6e8e040a Fix for image magick returning non-integer pixels. 2021-01-12 14:51:55 +00:00
Chris Palmer
accf4f7bc1 Added printed pulleys to the big picture. 2021-01-10 22:31:14 +00:00
Chris Palmer
6bd4638e7d Fixed screw hole position of inverted printed_pulley.
Unexploded assembly view shows round screw holes to represent the tapped state.
2021-01-10 21:28:31 +00:00
Chris Palmer
4cca9d5285 Merge branch 'martinbudden-printed_pulleys' 2021-01-10 12:11:29 +00:00
Chris Palmer
c3fc352288 Fixed orientation of inverted pulley.
Added stl and assembly calls.
Same render handling as pulleys.
Updated pics and readme.
2021-01-10 12:11:03 +00:00
Chris Palmer
a8b634de39 Better pose for pulley test so screws can be seen. 2021-01-10 11:49:32 +00:00
Chris Palmer
1a55a08c59 Merge branch 'printed_pulleys' of https://github.com/martinbudden/NopSCADlib into martinbudden-printed_pulleys 2021-01-09 23:38:48 +00:00
Chris Palmer
8ca4bb5adc Merge branch 'martinbudden-linear_rails' 2021-01-09 23:37:26 +00:00
Chris Palmer
53e3378efe Updated images and readme 2021-01-09 23:37:06 +00:00
Chris Palmer
888199f698 Merge branch 'linear_rails' of https://github.com/martinbudden/NopSCADlib into martinbudden-linear_rails 2021-01-09 20:54:28 +00:00
Chris Palmer
f51e93969d Merge branch 'martinbudden-teardrop_chamfer' 2021-01-09 19:55:45 +00:00
Chris Palmer
757b808f07 Updated readme for teardrops chamfer one side. 2021-01-09 19:55:31 +00:00
Chris Palmer
eca8f2eccc Merge branch 'teardrop_chamfer' of https://github.com/martinbudden/NopSCADlib into martinbudden-teardrop_chamfer 2021-01-09 19:26:36 +00:00
Chris Palmer
450224ec39 Merge branch 'martinbudden-fan_rename' 2021-01-09 19:24:53 +00:00
Chris Palmer
dcd2624a12 Updated readme for blower(BL40x10). 2021-01-09 19:24:06 +00:00
Chris Palmer
83e8502ecb Merge branch 'fan_rename' of https://github.com/martinbudden/NopSCADlib into martinbudden-fan_rename 2021-01-09 19:22:51 +00:00
Chris Palmer
a722df0b2b J-head heater components now hidden when taped. 2021-01-09 19:21:49 +00:00
Chris Palmer
6d223c8d1f Added render to countersink. 2021-01-09 19:11:20 +00:00
Chris Palmer
6d59ea2bc8 Added render option to drag_chain_assembly(). 2021-01-09 18:43:43 +00:00
Martin Budden
b74cbee151 Rendering changes to match pulleys. 2021-01-09 18:15:19 +00:00
Martin Budden
9f7efd50fb Replaced poly_circle bores with circular bores. 2021-01-09 17:52:24 +00:00
Martin Budden
0b14d3fbc4 Added printable pulleys. 2021-01-09 17:52:24 +00:00
Martin Budden
8243b244af Clarified name of BL40x10 blower. 2021-01-09 13:02:57 +00:00
Martin Budden
1a2e04367d Added option to chamfer only one end of a teardrop. 2021-01-09 12:59:01 +00:00
Martin Budden
abc38f2744 Changed linear rails to use a v-slot rather than a square slot. 2021-01-09 12:08:45 +00:00
Chris Palmer
f97070099e Merge branch 'martinbudden-pulley_drawing_efficiency' 2021-01-09 11:15:08 +00:00
Chris Palmer
729891b675 Improved pulley.scad speed. 2021-01-09 11:13:14 +00:00
Chris Palmer
4b533cffd2 Merge branch 'pulley_drawing_efficiency' of https://github.com/martinbudden/NopSCADlib into martinbudden-pulley_drawing_efficiency 2021-01-08 22:06:31 +00:00
Chris Palmer
a40a2190dc Merge branch 'martinbudden-vero_size' 2021-01-08 21:26:32 +00:00
Chris Palmer
6556d14a11 Updated readme for veroboard_size(). 2021-01-08 21:26:18 +00:00
Chris Palmer
c7d12b20c9 Merge branch 'vero_size' of https://github.com/martinbudden/NopSCADlib into martinbudden-vero_size 2021-01-08 21:24:58 +00:00
Chris Palmer
545329b875 Bug fix hygrometer_hole() when h > 0. 2021-01-08 21:24:06 +00:00
Martin Budden
760e3a890d Added vero_size function. 2021-01-08 11:47:34 +00:00
Martin Budden
bd4f7b155b Conditionally rendered pulleys to speed up drawing. 2021-01-08 11:33:17 +00:00
Chris Palmer
16c1eeef27 Documented circle_tangent() and simplified it. 2021-01-06 10:54:21 +00:00
Chris Palmer
800bb89921 Added microswitch_size(). 2021-01-06 09:36:13 +00:00
Chris Palmer
41a0723362 Can now control the number of index_screws in rail_screws() 2021-01-04 15:26:29 +00:00
Chris Palmer
6b8ea9685e Fixed rail_hole_positions() bug. 2021-01-04 14:46:54 +00:00
Chris Palmer
0cf8cb7d28 Added missing vitamin() call in magnet.scad. 2021-01-04 01:04:04 +00:00
Chris Palmer
7c439a687f Fixed openscad.py on Linux. 2021-01-03 09:51:20 +00:00
Chris Palmer
4a95ce528e Merge branch 'martinbudden-pancake_stepper' 2021-01-02 11:02:27 +00:00
Chris Palmer
138f45730b Updated images and readme. 2021-01-02 11:02:06 +00:00
Chris Palmer
8d1ff3584c Merge branch 'pancake_stepper' of https://github.com/martinbudden/NopSCADlib into martinbudden-pancake_stepper 2021-01-02 10:38:27 +00:00
Martin Budden
3e4eedc25f Added JST connector to NEMA17P in tests. 2020-12-31 12:30:06 +00:00
Martin Budden
7449857ab7 Added NEMA17P pancake stepper motor. 2020-12-31 12:20:11 +00:00
107 changed files with 2755 additions and 1504 deletions

View File

@@ -172,7 +172,7 @@ This is achieved by having a pair of modules: -
//! Place inserts in the bottom of the posts and push them home with a soldering iron with a conical bit heated to 200°C.
//
module handle_assembly() pose([225, 0, 150], [0, 0, 14]) //! Printed part with inserts in place
assembly("handle") {
assembly("handle", ngb = true) {
translate_z(handle_height())
stl_colour(pp1_colour) vflip() handle_stl();
@@ -182,7 +182,7 @@ This is achieved by having a pair of modules: -
}
module handle_fastened_assembly(thickness) { //! Assembly with fasteners in place
screw_length = screw_longer_than(thickness + insert_length(insert) + 2 * washer_thickness(screw_washer(screw)));
screw_length = screw_length(screw, thickness, 2, true, longer = true);
handle_assembly();
@@ -201,6 +201,9 @@ When the parent assembly is shown exploded the handle's screws will be exploded
Note also the `pose([225, 0, 150], [0, 0, 14])` call before the `assembly()` call. This allows the sub-assembly to be posed differently in its build step but doesn't
affect its orientation in the parent assembly. The pose parameters are the rotation and the translation taken from the GUI.
Setting `ngb = true` in the `assembly()` prevents the handle assembly appearing as a columun in the top level BOM in the build instructions.
Instead its parts are merged into the parent BOM so the correct quantites are listed.
### Exploded diagrams
A lot of vitamins explode themselves when `$explode=1`. This is done with module `explode()` that can be passed a Z offset, or a 3D vector that gives the displacement

View File

@@ -2,6 +2,7 @@
{
"name": "base_assembly",
"big": null,
"ngb": false,
"count": 1,
"assemblies": {},
"vitamins": {
@@ -20,6 +21,7 @@
{
"name": "feet_assembly",
"big": null,
"ngb": false,
"count": 1,
"assemblies": {
"base_assembly": 1
@@ -46,6 +48,7 @@
{
"name": "mains_in_assembly",
"big": null,
"ngb": false,
"count": 1,
"assemblies": {
"feet_assembly": 1
@@ -82,6 +85,7 @@
{
"name": "main_assembly",
"big": null,
"ngb": false,
"count": 1,
"assemblies": {
"mains_in_assembly": 1

View File

@@ -15,6 +15,7 @@ Earth leakage can be measured Canadian CSA style by disconnected the neutral lin
![Main Assembly](assemblies/main_assembled.png)
<span></span>
---
## Table of Contents
@@ -24,6 +25,7 @@ Earth leakage can be measured Canadian CSA style by disconnected the neutral lin
1. [Mains In Assembly](#mains_in_assembly)
1. [Main Assembly](#main_assembly)
<span></span>
[Top](#TOP)
---
@@ -54,6 +56,7 @@ Earth leakage can be measured Canadian CSA style by disconnected the neutral lin
| &nbsp;&nbsp;1&nbsp; | &nbsp;&nbsp;.&nbsp; | &nbsp;&nbsp;.&nbsp; | &nbsp;&nbsp;.&nbsp; | &nbsp;&nbsp;1&nbsp; | &nbsp;&nbsp;socket_box.stl |
| &nbsp;&nbsp;1&nbsp; | &nbsp;&nbsp;4&nbsp; | &nbsp;&nbsp;.&nbsp; | &nbsp;&nbsp;.&nbsp; | &nbsp;&nbsp;5&nbsp; | &nbsp;&nbsp;Total 3D printed parts count |
<span></span>
[Top](#TOP)
---
@@ -81,6 +84,7 @@ Earth leakage can be measured Canadian CSA style by disconnected the neutral lin
![base_assembled](assemblies/base_assembled.png)
<span></span>
[Top](#TOP)
---
@@ -117,6 +121,7 @@ Earth leakage can be measured Canadian CSA style by disconnected the neutral lin
![feet_assembled](assemblies/feet_assembled.png)
<span></span>
[Top](#TOP)
---
@@ -156,6 +161,7 @@ Earth leakage can be measured Canadian CSA style by disconnected the neutral lin
![mains_in_assembled](assemblies/mains_in_assembled.png)
<span></span>
[Top](#TOP)
---
@@ -199,4 +205,5 @@ Earth leakage can be measured Canadian CSA style by disconnected the neutral lin
![main_assembled](assemblies/main_assembled.png)
<span></span>
[Top](#TOP)

View File

@@ -1,40 +1,30 @@
# A gallery of projects made with NopSCADlib
<a name="TOP"></a>
## ArduinoThermostat
Arduino thermostat to control a beer fridge to use it as an environmental chamber.
![](ArduinoThermostat.png)
<a name="TOP"></a>
## EnviroPlus
Environmental monitor using Enviro+ sensor board and a Raspberry Pi Zero.
![](EnviroPlus.png)
<a name="TOP"></a>
## FilamentDryBox
A small fan oven with a spool holder to keep the filament warm and dry.
![](FilamentDryBox.png)
<a name="TOP"></a>
## HydraBot
Current state of HydraRaptor after being modified for laser engraving.
![](HydraBot.png)
<a name="TOP"></a>
## IOT 50V PSU
WiFi controllable PSU
![](IOT_50V_PSU.png)
<a name="TOP"></a>
## Lab ATX PSU
Bench power supply built around an ATX PSU.
@@ -47,15 +37,11 @@ Bench power supply built around an ATX PSU.
<a name="TOP"></a>
## Laser Load
15kV dummy load for testing CO2 laser PSUs
![](Laser_load.png)
<a name="TOP"></a>
## MainsBreakOutBox
13A socket break out box with 4mm jacks to measure voltage and / or load current and earth leakage current.
@@ -72,8 +58,6 @@ Earth leakage can be measured Canadian CSA style by disconnected the neutral lin
![](MainsBreakOutBox.png)
<a name="TOP"></a>
## Mains Box
Mains isolated and variable supply with metering.
@@ -81,15 +65,11 @@ Mains isolated and variable supply with metering.
<a name="TOP"></a>
## SunBot
A solar tracker to keep a solar panel pointing at the sun.
![](SunBot.png)
<a name="TOP"></a>
## Turntable
WiFi enabled remote control turntable for photography
@@ -97,8 +77,6 @@ WiFi enabled remote control turntable for photography
Was actually made from DiBond but shown made with carbon fibre here.
<a name="TOP"></a>
## Variac
Motorised variac with WiFi control, see [hydraraptor.blogspot.com/2018/04/esp8266-spi-spy](https://hydraraptor.blogspot.com/2018/04/esp8266-spi-spy.html)
@@ -106,4 +84,3 @@ Motorised variac with WiFi control, see [hydraraptor.blogspot.com/2018/04/esp826

View File

@@ -35,7 +35,6 @@ include <vitamins/displays.scad>
include <vitamins/extrusions.scad>
include <vitamins/extrusion_brackets.scad>
include <vitamins/geared_steppers.scad>
include <vitamins/green_terminals.scad>
include <vitamins/hot_ends.scad>
include <vitamins/inserts.scad>
include <vitamins/kp_pillow_blocks.scad>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 860 KiB

After

Width:  |  Height:  |  Size: 886 KiB

View File

@@ -117,7 +117,9 @@ use <tests/flat_hinge.scad>
use <tests/foot.scad>
use <tests/handle.scad>
use <tests/PCB_mount.scad>
use <tests/pocket_handle.scad>
use <tests/printed_box.scad>
use <tests/printed_pulleys.scad>
use <tests/ribbon_clamp.scad>
use <tests/screw_knob.scad>
use <tests/socket_box.scad>
@@ -170,13 +172,19 @@ translate([x5, cable_grommets_y + 370])
translate([x5 + 60, cable_grommets_y + 200])
strap_handles();
translate([640, cable_grommets_y + 200])
printed_pulley_test();
translate([x5, cable_grommets_y + 250])
handle();
translate([950, 600])
box_test();
translate([890, 750])
translate([830, 770])
pocket_handles();
translate([950, 750])
printed_boxes();
translate([850, 1330])
@@ -351,7 +359,7 @@ modules_y = iecs_y + 60;
ssrs_y = modules_y + 80;
blowers_y = ssrs_y + 60;
batteries_y = blowers_y + 100;
steppers_y = batteries_y + 70;
steppers_y = batteries_y + 55;
panel_meters_y = steppers_y + 70;
extrusions_y = panel_meters_y + 80;

View File

@@ -75,9 +75,9 @@ function box_corner_overlap(type) = box_wall(type);
function box_corner_rad(type) = box_sheet_slot(type) - sheet_slot_clearance / 2 + box_corner_gap(type) + box_corner_overlap(type);
function box_sheet_r(type) = box_corner_rad(type) - box_sheet_slot(type) - box_corner_overlap(type);
function box_screw_length(type, top) = screw_longer_than(2 * washer_thickness(box_washer(type))
+ sheet_thickness(top ? box_top_sheet(type) : box_base_sheet(type))
+ box_corner_gap(type) + box_profile_overlap(type) + box_insert_l(type) - 1);
function box_screw_length(type, top) =
let(s = top ? box_top_sheet(type) : box_base_sheet(type))
screw_length(box_screw(type), sheet_thickness(s) + box_corner_gap(type) + box_profile_overlap(type) - 1, washers = 2, insert = true, longer = true);
function box_wall_clearance(type) = box_sheet_slot(type) / 2 - sheet_thickness(box_sheets(type)) / 2;
function box_margin(type) = box_profile_overlap(type) + box_corner_gap(type); //! How much the bezel intrudes on the specified height
@@ -139,17 +139,17 @@ module box_corner_profile_2D(type) { //! The 2D shape of the corner profile.
}
module box_corner_profile(type) { //! Generates the corner profile STL for 3D printing.
stl("box_corner_profile");
length = box_height(type) - 2 * box_margin(type);
difference() {
linear_extrude(length, center = true, convexity = 5)
box_corner_profile_2D(type);
for(z = [-1, 1])
translate([box_hole_inset(type), box_hole_inset(type), z * length / 2])
insert_hole(box_insert(type), 5);
}
stl("box_corner_profile")
difference() {
linear_extrude(length, center = true, convexity = 5)
box_corner_profile_2D(type);
for(z = [-1, 1])
translate([box_hole_inset(type), box_hole_inset(type), z * length / 2])
insert_hole(box_insert(type), 5);
}
}
module box_corner_profile_section(type, section, sections) { //! Generates interlocking sections of the corner profile to allow it to be taller than the printer
@@ -209,7 +209,6 @@ module box_corner_quadrants(type, width, depth)
}
module box_bezel(type, bottom) { //! Generates top and bottom bezel STLs
stl(bottom ? "bottom_bezel" : "top_bezel");
feet = bottom && box_feet(type);
t = box_sheet_slot(type);
outset = box_outset(type);
@@ -221,66 +220,67 @@ module box_bezel(type, bottom) { //! Generates top and bottom bezel STLs
height = box_bezel_height(type, bottom);
foot_extension = foot_height - height;
difference() {
w = box_width(type);
d = box_depth(type);
translate_z(-box_profile_overlap(type)) difference() {
tw = w + 2 * outset;
td = d + 2 * outset;
rounded_rectangle([tw, td, feet ? foot_height : height], box_corner_rad(type), false);
//
// Remove edges between the feet
//
if(feet)
hull() {
translate_z(height + 0.5)
cube([w - 2 * foot_length, td + 1, 1], center = true);
stl(bottom ? "bottom_bezel" : "top_bezel")
difference() {
w = box_width(type);
d = box_depth(type);
translate_z(-box_profile_overlap(type)) difference() {
tw = w + 2 * outset;
td = d + 2 * outset;
rounded_rectangle([tw, td, feet ? foot_height : height], box_corner_rad(type));
//
// Remove edges between the feet
//
if(feet)
hull() {
translate_z(height + 0.5)
cube([w - 2 * foot_length, td + 1, 1], center = true);
translate_z(foot_height + 1)
cube([w - 2 * (foot_length - foot_extension), td + 1, 1], center = true);
}
if(feet)
hull() {
translate_z(height + 0.5)
cube([tw + 1, d - 2 * foot_length, 1], center = true);
translate_z(foot_height + 1)
cube([tw + 1, d - 2 * (foot_length - foot_extension), 1], center = true);
}
}
//
// slots for side panels
//
translate_z(-box_profile_overlap(type))
linear_extrude(2 * box_profile_overlap(type), center = true)
for(i = [-1, 1]) {
translate([i * (w + t - sheet_slot_clearance) / 2, 0])
square([t, d - 2 * cgap], center = true);
translate([0, i * (d + t - sheet_slot_clearance) / 2])
square([w - 2 * cgap, t], center = true);
}
//
// recess for top / bottom panel
//
translate_z(cgap)
rounded_rectangle([w + bezel_clearance, d + bezel_clearance, height], inner_r + bezel_clearance / 2, false);
//
// leave plastic over the corner profiles
//
translate_z(-box_profile_overlap(type) - 1)
linear_extrude(box_profile_overlap(type) + cgap + 2)
union() {
difference() {
square([w - 2 * inset,
d - 2 * inset], center = true);
box_corner_quadrants(type, w, d);
translate_z(foot_height + 1)
cube([w - 2 * (foot_length - foot_extension), td + 1, 1], center = true);
}
box_screw_hole_positions(type)
poly_circle(screw_clearance_radius(box_screw(type)));
}
}
if(feet)
hull() {
translate_z(height + 0.5)
cube([tw + 1, d - 2 * foot_length, 1], center = true);
translate_z(foot_height + 1)
cube([tw + 1, d - 2 * (foot_length - foot_extension), 1], center = true);
}
}
//
// slots for side panels
//
translate_z(-box_profile_overlap(type))
linear_extrude(2 * box_profile_overlap(type), center = true)
for(i = [-1, 1]) {
translate([i * (w + t - sheet_slot_clearance) / 2, 0])
square([t, d - 2 * cgap], center = true);
translate([0, i * (d + t - sheet_slot_clearance) / 2])
square([w - 2 * cgap, t], center = true);
}
//
// recess for top / bottom panel
//
translate_z(cgap)
rounded_rectangle([w + bezel_clearance, d + bezel_clearance, height], inner_r + bezel_clearance / 2);
//
// leave plastic over the corner profiles
//
translate_z(-box_profile_overlap(type) - 1)
linear_extrude(box_profile_overlap(type) + cgap + 2)
union() {
difference() {
square([w - 2 * inset,
d - 2 * inset], center = true);
box_corner_quadrants(type, w, d);
}
box_screw_hole_positions(type)
poly_circle(screw_clearance_radius(box_screw(type)));
}
}
}
dowel_length = 20;
@@ -485,7 +485,6 @@ module box_shelf_screw_positions(type, screw_positions, thickness = 0, wall = un
}
module box_shelf_bracket(type, screw_positions, wall = undef) { //! Generates a shelf bracket, the first optional child is a 2D cutout and the second 3D cutouts
stl("shelf_bracket");
w = is_undef(wall) ? box_wall(type) : wall;
insert = box_shelf_insert(type);
lip = 2 * insert_boss_radius(insert, w);
@@ -513,44 +512,45 @@ module box_shelf_bracket(type, screw_positions, wall = undef) { //! Generates a
square([lip, eps]);
}
difference() {
union() {
linear_extrude(w)
difference() {
shape()
if($children)
children(0);
round(2) offset(-width)
stl("shelf_bracket")
difference() {
union() {
linear_extrude(w)
difference() {
shape()
if($children)
children(0);
}
linear_extrude(lip)
difference() {
shape()
if($children)
children(0);
round(2) offset(-width)
shape()
if($children)
children(0);
}
offset(-w)
linear_extrude(lip)
difference() {
shape()
if($children)
children(0);
}
offset(-w)
shape()
if($children)
children(0);
}
hflip()
box_shelf_screw_positions(type, screw_positions, 0, w)
boss();
}
if($children > 1)
hflip()
children(1);
hflip()
box_shelf_screw_positions(type, screw_positions, 0, w)
boss();
insert_hole(insert, counterbore = 1, horizontal = true);
}
if($children > 1)
hflip()
children(1);
hflip()
box_shelf_screw_positions(type, screw_positions, 0, w)
insert_hole(insert, counterbore = 1, horizontal = true);
}
}
module box_shelf_bracket_section(type, rows, cols, x, y) { //! Generates sections of the shelf bracket to allow it to be bigger than the printer

View File

@@ -49,84 +49,84 @@ module ribbon_grommet_hole(ways, h = 50, expand = true) { //! Generate a hole fo
}
module ribbon_grommet(ways, thickness) { //! Generate the STL for a printed ribbon grommet
stl(str("ribbon_grommet_", ways, "_", thickness));
width = 2 * (wall + clearance) + thickness;
slot_length = ribbon_clamp_slot(ways);
length = slot_length + 2 * wall + 2 * overlap;
rotate([90, 0, 0])
union() {
for(side = [-1, 1])
translate_z(side * (width - wall) / 2)
linear_extrude(wall, center = true, convexity = 5)
difference() {
hull() {
translate([-length / 2, 0])
square([length, base]);
stl(str("ribbon_grommet_", ways, "_", thickness))
rotate([90, 0, 0])
union() {
for(side = [-1, 1])
translate_z(side * (width - wall) / 2)
linear_extrude(wall, center = true, convexity = 5)
difference() {
hull() {
translate([-length / 2, 0])
square([length, base]);
for(end = [-1, 1])
translate([end * (length / 2 - rad), height - rad])
semi_circle(rad);
for(end = [-1, 1])
translate([end * (length / 2 - rad), height - rad])
semi_circle(rad);
}
translate([-slot_length / 2, base])
square([slot_length, slot_height]);
}
translate([-slot_length / 2, base])
square([slot_length, slot_height]);
}
linear_extrude(width -1, center = true)
difference() {
ribbon_grommet_hole(ways, expand = false, h = 0);
linear_extrude(width -1, center = true)
difference() {
ribbon_grommet_hole(ways, expand = false, h = 0);
translate([-slot_length / 2, base])
square([slot_length, slot_height]);
}
}
translate([-slot_length / 2, base])
square([slot_length, slot_height]);
}
}
}
module round_grommet_top(diameter, thickness, od = undef) { //! Generate the STL for a round grommet top half
stl(str("round_grommet_top_", round(diameter * 10), "_", thickness));
chamfer = layer_height;
h = wall + thickness + wall;
r1 = diameter / 2;
r2 = od == undef ? corrected_radius(r1) + wall : od / 2;
r3 = r2 + overlap;
r0 = r1 + 1;
union() {
rotate_extrude()
polygon([
[r0, 0],
[r3 - chamfer, 0],
[r3, chamfer],
[r3, wall],
[r2, wall],
[r2, h - chamfer],
[r2 - chamfer, h],
[r0, h],
]);
stl(str("round_grommet_top_", round(diameter * 10), "_", thickness))
union() {
rotate_extrude()
polygon([
[r0, 0],
[r3 - chamfer, 0],
[r3, chamfer],
[r3, wall],
[r2, wall],
[r2, h - chamfer],
[r2 - chamfer, h],
[r0, h],
]);
render() difference() {
cylinder(r = r0 + eps, h = h);
render() difference() {
cylinder(r = r0 + eps, h = h);
poly_cylinder(r = r1, h = 100, center = true);
poly_cylinder(r = r1, h = 100, center = true);
}
}
}
}
module round_grommet_bottom(diameter, od = undef) { //! Generate the STL for a round grommet bottom half
stl(str("round_grommet_bottom_", round(diameter * 10)));
chamfer = layer_height;
r1 = diameter / 2;
r2 = od == undef ? corrected_radius(r1) + wall : od / 2;
r3 = r2 + max(overlap, wall + chamfer);
rotate_extrude()
polygon([
[r2, chamfer],
[r2 + chamfer, 0],
[r3, 0],
[r3, wall - chamfer],
[r3 - chamfer, wall],
[r2, wall],
]);
stl(str("round_grommet_bottom_", round(diameter * 10)))
rotate_extrude()
polygon([
[r2, chamfer],
[r2 + chamfer, 0],
[r3, 0],
[r3, wall - chamfer],
[r3 - chamfer, wall],
[r2, wall],
]);
}
module round_grommet_hole(diameter, h = 100) //! Make a hole for a round grommet
@@ -161,30 +161,30 @@ module mouse_grommet_hole(r, h = 50, z = undef, expand = wall + clearance) //! M
function mouse_grommet_offset(r) = r + wall;
module mouse_grommet(r, thickness) { //! Make the STL for a mouse grommet
stl(str("mouse_grommet_", r * 10, "_", thickness));
width = 2 * (wall + clearance) + thickness;
length = 2 * r + 2 * wall + 2 * overlap;
rotate([90, 0, 0])
union() {
for(side = [-1, 1])
translate_z(side * (width - wall) / 2)
linear_extrude(wall, center = true)
difference() {
mouse_grommet_hole(r, z = r + wall, h = 0, expand = wall + overlap);
stl(str("mouse_grommet_", r * 10, "_", thickness))
rotate([90, 0, 0])
union() {
for(side = [-1, 1])
translate_z(side * (width - wall) / 2)
linear_extrude(wall, center = true)
difference() {
mouse_grommet_hole(r, z = r + wall, h = 0, expand = wall + overlap);
translate([0, wall])
mouse_grommet_hole(r, h = 0, expand = 0);
}
linear_extrude(width - 1, center = true)
difference() {
mouse_grommet_hole(r, h = 0, z = r + wall, expand = wall);
translate([0, wall])
mouse_grommet_hole(r, h = 0, expand = 0);
}
linear_extrude(width - 1, center = true)
difference() {
mouse_grommet_hole(r, h = 0, z = r + wall, expand = wall);
translate([0, wall])
mouse_grommet_hole(r, h = 0, expand = 0);
}
}
}
}
module mouse_grommet_assembly(r, thickness)

View File

@@ -68,7 +68,7 @@ function cam_screw_length(cam) = let(
front = cam_front_size(cam),
screw = pcb_screw(camera_pcb(cam)),
nut = screw_nut(screw)
) screw_longer_than(front.z + washer_thickness(screw_washer(screw)) - nut_trap_depth(nut) + nut_thickness(nut, true));
) screw_length(screw, front.z - nut_trap_depth(nut), 1, nyloc = true);
function hinge_z(cam) = cam_screw_length(cam) - hinge_r;
@@ -82,7 +82,6 @@ module cam_holes(cam) {
}
module rpi_camera_focus_ring_stl() { //! Focus ring the glue onto RPI lens
stl("rpi_camera_focus_ring");
rad = 15 / 2;
hole_r1 = 2.5 / 2;
@@ -93,58 +92,58 @@ module rpi_camera_focus_ring_stl() { //! Focus ring the glue onto RPI lens
x = rad / (sin(angle / 2) + cos(angle / 2));
r = x * sin(angle / 2);
difference() {
linear_extrude(height = thickness, convexity = 5)
difference() {
union() {
circle(x);
stl("rpi_camera_focus_ring")
difference() {
linear_extrude(height = thickness, convexity = 5)
difference() {
union() {
circle(x);
for(i = [0 : flutes - 1])
rotate([0, 0, 2 * angle * i])
translate([x, 0])
circle(r);
}
for(i = [0 : flutes - 1])
rotate([0, 0, 2 * angle * i])
rotate([0, 0, 2 * angle * i + angle])
translate([x, 0])
circle(r);
}
for(i = [0 : flutes - 1])
rotate([0, 0, 2 * angle * i + angle])
translate([x, 0])
circle(r);
}
hull() {
poly_cylinder(r = hole_r1, h = 0.1, center = true);
hull() {
poly_cylinder(r = hole_r1, h = 0.1, center = true);
translate([0, 0, thickness])
poly_cylinder(r = hole_r2, h = 0.1, center = true);
translate([0, 0, thickness])
poly_cylinder(r = hole_r2, h = 0.1, center = true);
}
}
}
}
module camera_back(cam) { //! Make the STL for a camera case back
stl(str("camera_back_", cam[0]));
pcb = camera_pcb(cam);
back = cam_back_size(cam);
screw = pcb_screw(pcb);
nut = screw_nut(screw);
translate_z(back.z)
hflip()
difference() {
translate_z(back.z / 2)
cube(back, center = true);
stl(str("camera_back_", cam[0]))
translate_z(back.z)
hflip()
difference() {
translate_z(back.z / 2)
cube(back, center = true);
translate([0, -cam_back_overlap])
cube([pcb_length(pcb) - 2 * cam_back_overlap, pcb_width(pcb), 2 * cam_back_clearance], center = true);
translate([0, -cam_back_overlap])
cube([pcb_length(pcb) - 2 * cam_back_overlap, pcb_width(pcb), 2 * cam_back_clearance], center = true);
translate([0, -pcb_width(pcb) / 2])
cube([connector_size.x + 2 * clearance, 2 * connector_size.y + 1, 2 * round_to_layer(connector_size.z + clearance)], center = true);
translate([0, -pcb_width(pcb) / 2])
cube([connector_size.x + 2 * clearance, 2 * connector_size.y + 1, 2 * round_to_layer(connector_size.z + clearance)], center = true);
translate_z(back.z)
cam_holes(cam)
hflip()
nut_trap(screw, nut, supported = true);
}
translate_z(back.z)
cam_holes(cam)
hflip()
nut_trap(screw, nut, supported = true);
}
}
module camera_front(cam, hinge = 0) { //! Make the STL for a camera case front
stl(str("camera_front_", cam[0]));
front = cam_front_size(cam);
back = cam_back_size(cam);
pcb = camera_pcb(cam);
@@ -170,70 +169,71 @@ module camera_front(cam, hinge = 0) { //! Make the STL for a camera case front
translate([0, (hinge ? front.x * hinge : front.y) / 2 + hinge_offset, hinge_r])
children();
difference() {
union() {
hull()
for(x = [-1, 1], y = [-1, 1])
translate([x * (front.x / 2 - rad), y * (front.y / 2 - rad)])
hull() { // 3D truncated teardrop gives radiused edges without exceeding 45 degree overhang
translate_z(front.z - 1)
cylinder(r = rad, h = 1);
stl(str("camera_front_", cam[0]))
difference() {
union() {
hull()
for(x = [-1, 1], y = [-1, 1])
translate([x * (front.x / 2 - rad), y * (front.y / 2 - rad)])
hull() { // 3D truncated teardrop gives radiused edges without exceeding 45 degree overhang
translate_z(front.z - 1)
cylinder(r = rad, h = 1);
translate_z(rad)
sphere(rad);
translate_z(rad)
sphere(rad);
cylinder(r = rad * (sqrt(2) - 1), h = eps);
}
cylinder(r = rad * (sqrt(2) - 1), h = eps);
}
hinge_pos()
hull() {
rotate([-90, 0, -90])
teardrop(r = hinge_r, h = hinge_h, center = false);
hinge_pos()
hull() {
rotate([-90, 0, -90])
teardrop(r = hinge_r, h = hinge_h, center = false);
translate([0, -10, -hinge_r])
cube([hinge_h, eps, 2 * hinge_r]);
}
}
hinge_pos()
rotate([90, 0, 90])
teardrop_plus(r = screw_clearance_radius(hinge_screw), h = 100, center = true);
translate_z(front.z / 2 + shelf - layer_height) // recess for the back
cube([back.x + 2 * clearance, back.y + 2 * clearance, front.z], center = true);
translate_z(front.z / 2 + shelf - pcb_size.z) // recess for PCB
cube([pcb_size.x + 2 * clearance, pcb_size.y + 2 * clearance, front.z], center = true);
translate_z(shelf)
hflip() {
pcb_component_position(pcb, "smd_led") // clearance for LED
cube(led_clearance, center = true);
pcb_component_position(pcb, "smd_res") // clearance for resistor
cube(res_clearance, center = true);
translate([0, -10, -hinge_r])
cube([hinge_h, eps, 2 * hinge_r]);
}
}
translate([conn_pos.x, lens_offset.y + sensor_length / 2, shelf - pcb_size.z]) // clearance for sensor connector
cube([conn.x + 2 * clearance, sensor_length, 2 * cam_front_clearance(cam)], center = true);
hinge_pos()
rotate([90, 0, 90])
teardrop_plus(r = screw_clearance_radius(hinge_screw), h = 100, center = true);
translate([0, -front.y / 2, shelf + front.z / 2]) // slot for connector
cube([connector_slot.x, connector_slot.y, front.z], center = true);
translate_z(front.z / 2 + shelf - layer_height) // recess for the back
cube([back.x + 2 * clearance, back.y + 2 * clearance, front.z], center = true);
translate_z(cam_back_clearance + layer_height)
cam_holes(cam)
rotate(90)
poly_cylinder(r = screw_clearance_radius(screw), h = 100, center = true);
translate_z(front.z / 2 + shelf - pcb_size.z) // recess for PCB
cube([pcb_size.x + 2 * clearance, pcb_size.y + 2 * clearance, front.z], center = true);
translate_z(shelf)
hflip() {
pcb_component_position(pcb, "smd_led") // clearance for LED
cube(led_clearance, center = true);
pcb_component_position(pcb, "smd_res") // clearance for resistor
cube(res_clearance, center = true);
}
translate([conn_pos.x, lens_offset.y + sensor_length / 2, shelf - pcb_size.z]) // clearance for sensor connector
cube([conn.x + 2 * clearance, sensor_length, 2 * cam_front_clearance(cam)], center = true);
translate([0, -front.y / 2, shelf + front.z / 2]) // slot for connector
cube([connector_slot.x, connector_slot.y, front.z], center = true);
translate_z(cam_back_clearance + layer_height)
cam_holes(cam)
rotate(90)
poly_cylinder(r = screw_clearance_radius(screw), h = 100, center = true);
translate_z(shelf - pcb_size.z)
hflip()
camera_lens(cam, clearance);
translate_z(shelf - pcb_size.z)
hflip()
camera_lens(cam, clearance);
hflip()
pcb_component_position(pcb, "smd_led")
rotate(45)
poly_cylinder(r = led_hole_r, h = 100, center = true); // hole for led
}
pcb_component_position(pcb, "smd_led")
rotate(45)
poly_cylinder(r = led_hole_r, h = 100, center = true); // hole for led
}
}
function bracket_thickness(cam) = max(wall, min(3.5, hinge_z(cam) - hinge_r - 1));
@@ -253,38 +253,39 @@ module camera_bracket_position(cam) //! Position children at the bracket positio
children();
module camera_bracket(cam) { //! Make the STL for the camera bracket
stl(str("camera_bracket_", cam[0]));
t = bracket_thickness(cam);
z = hinge_z(cam);
translate([hinge_h / 2, 0])
difference() {
hull() {
translate_z(eps / 2)
cube([hinge_h, 2 * hinge_r, eps], center = true);
translate_z(z)
rotate([0, 90, 0])
cylinder(r = hinge_r, h = hinge_h, center = true);
stl(str("camera_bracket_", cam[0])) union() {
translate([hinge_h / 2, 0])
difference() {
hull() {
translate_z(eps / 2)
cube([hinge_h, 2 * hinge_r, eps], center = true);
translate_z(z)
rotate([0, 90, 0])
cylinder(r = hinge_r, h = hinge_h, center = true);
}
translate([hinge_h / 2, 0, z])
rotate([90, 0, 90])
nut_trap(hinge_screw, screw_nut(hinge_screw), horizontal = true);
}
translate([hinge_h / 2, 0, z])
rotate([90, 0, 90])
nut_trap(hinge_screw, screw_nut(hinge_screw), horizontal = true);
}
linear_extrude(t)
difference() {
hull()
linear_extrude(t)
difference() {
hull()
camera_bracket_screw_positions(cam)
circle(washer_radius(screw_washer(bracket_screw)) + 0.5);
camera_bracket_screw_positions(cam)
circle(washer_radius(screw_washer(bracket_screw)) + 0.5);
camera_bracket_screw_positions(cam)
poly_circle(screw_clearance_radius(bracket_screw));
}
poly_circle(screw_clearance_radius(bracket_screw));
}
}
}
module camera_assembly(cam, angle = 0) //! Camera case assembly
assembly(str("camera_", cam[0])) {
assembly(str("camera_", cam[0]), ngb = true) {
front = cam_front_size(cam);
screw = pcb_screw(camera_pcb(cam));
nut = screw_nut(screw);
@@ -344,9 +345,8 @@ module camera_fastened_assembly(cam, thickness, angle = 0) {
camera_bracket_position(cam)
camera_bracket_screw_positions(cam) {
nut = screw_nut(bracket_screw);
washer = screw_washer(bracket_screw);
t = bracket_thickness(cam);
screw_length = screw_longer_than(thickness + t + nut_thickness(nut, true) + 2 * washer_thickness(washer));
screw_length = screw_length(bracket_screw, thickness + t, 2, nyloc = true);
vflip()
translate_z(thickness)
screw_and_washer(bracket_screw, screw_length);

View File

@@ -27,7 +27,6 @@ include <../utils/core/core.scad>
function carrier_height() = 3; //! Height of PCB carrier
module ESP12F_carrier_stl() { //! Generate the STL for an ESP12 carrier
stl("ESP12F_carrier");
pins = 8;
pitch1 = 2;
pitch2 = 2.54;
@@ -43,29 +42,29 @@ module ESP12F_carrier_stl() { //! Generate the STL for an ESP12 carrier
width1 = wpitch1 + hole + squeezed_wall * 2;
width2 = wpitch2 + hole2 + squeezed_wall * 2;
difference() {
hull() {
translate_z(height - eps / 2)
cube([width1, length1, eps], center = true);
stl("ESP12F_carrier")
difference() {
hull() {
translate_z(height - eps / 2)
cube([width1, length1, eps], center = true);
translate_z(eps / 2)
cube([width2, length2, eps], center = true);
translate_z(eps / 2)
cube([width2, length2, eps], center = true);
}
for(side = [-1, 1])
for(i = [0 : pins - 1])
hull() {
translate([side * wpitch1 / 2, i * pitch1 - (pins - 1) * pitch1 / 2, height])
cube([hole, hole, eps], center = true);
translate([side * wpitch2 / 2, i * pitch2 - (pins - 1) * pitch2 / 2])
cube([hole2, hole2, eps], center = true);
}
}
for(side = [-1, 1])
for(i = [0 : pins - 1])
hull() {
translate([side * wpitch1 / 2, i * pitch1 - (pins - 1) * pitch1 / 2, height])
cube([hole, hole, eps], center = true);
translate([side * wpitch2 / 2, i * pitch2 - (pins - 1) * pitch2 / 2])
cube([hole2, hole2, eps], center = true);
}
}
}
module TP4056_carrier_stl() { //! Generate the STL for an TP4056 carrier, two required
stl("TP4056_carrier");
pitch = 2.54;
outer_pitch = 13.9;
inner_pitch = 7.54;
@@ -78,30 +77,30 @@ module TP4056_carrier_stl() { //! Generate the STL for an TP4056 carrier, two re
width = hole + squeezed_wall * 2;
spacing = inch(0.9);
difference() {
hull() {
translate_z(height - eps / 2)
cube([width, length1, eps], center = true);
stl("TP4056_carrier")
difference() {
hull() {
translate_z(height - eps / 2)
cube([width, length1, eps], center = true);
translate_z(eps / 2)
cube([width, length2, eps], center = true);
translate_z(eps / 2)
cube([width, length2, eps], center = true);
}
for(i = [0 : pins - 1])
let(x = [-outer_pitch / 2, - inner_pitch / 2, 0, 0, inner_pitch / 2, outer_pitch / 2][i])
if(x)
hull() {
translate([0, x, height])
cube([hole, hole, eps], center = true);
translate([0, i * pitch - (pins - 1) * pitch / 2])
cube([hole, hole, eps], center = true);
}
}
for(i = [0 : pins - 1])
let(x = [-outer_pitch / 2, - inner_pitch / 2, 0, 0, inner_pitch / 2, outer_pitch / 2][i])
if(x)
hull() {
translate([0, x, height])
cube([hole, hole, eps], center = true);
translate([0, i * pitch - (pins - 1) * pitch / 2])
cube([hole, hole, eps], center = true);
}
}
}
module MT3608_carrier_stl() { //! Generate the STL for an MT3608 carrier, two required
stl("MT3608_carrier");
pcb_width = 17;
w_pitch_top = 6.81;
w_pitch_bot = inch(0.3);
@@ -113,21 +112,22 @@ module MT3608_carrier_stl() { //! Generate the STL for an MT3608 carrier, two re
width = hole + 2 * wall;
offset = (l_pitch_top - l_pitch_bot) / 2;
difference() {
hull() {
translate([offset, 0, height - eps / 2])
rounded_rectangle([width, pcb_width - 2, eps], 1);
translate_z(eps / 2)
rounded_rectangle([width, pcb_width - 2, eps], 1);
}
for(side = [-1, 1])
stl("MT3608_carrier")
difference() {
hull() {
translate([offset, side * w_pitch_top / 2, height])
cube([hole, hole, eps], center = true);
translate([offset, 0, height - eps / 2])
rounded_rectangle([width, pcb_width - 2, eps], 1, true);
translate([0, side * w_pitch_bot / 2])
cube([hole, hole, eps], center = true);
translate_z(eps / 2)
rounded_rectangle([width, pcb_width - 2, eps], 1, true);
}
}
for(side = [-1, 1])
hull() {
translate([offset, side * w_pitch_top / 2, height])
cube([hole, hole, eps], center = true);
translate([0, side * w_pitch_bot / 2])
cube([hole, hole, eps], center = true);
}
}
}

View File

@@ -72,8 +72,6 @@ module corner_block_holes(screw = def_screw) //! Place children at all the holes
children();
module corner_block(screw = def_screw, name = false) { //! Generate the STL for a printed corner block
stl(name ? name : str("corner_block", "_M", screw_radius(screw) * 20));
r = 1;
cb_width = corner_block_width(screw);
cb_height = cb_width;
@@ -81,43 +79,45 @@ module corner_block(screw = def_screw, name = false) { //! Generate the STL for
insert = screw_insert(screw);
corner_rad = insert_outer_d(insert) / 2 + wall;
offset = corner_block_hole_offset(screw);
difference() {
hull() {
translate([r, r])
rounded_cylinder(r = r, h = cb_height, r2 = r);
translate([r, cb_depth - r])
cylinder(r = r, h = cb_height - corner_rad);
stl(name ? name : str("corner_block", "_M", screw_radius(screw) * 20))
difference() {
hull() {
translate([r, r])
rounded_cylinder(r = r, h = cb_height, r2 = r);
translate([cb_width - r, r])
cylinder(r = r, h = cb_height - corner_rad);
translate([r, cb_depth - r])
cylinder(r = r, h = cb_height - corner_rad);
translate([offset, offset, offset])
sphere(corner_rad);
translate([cb_width - r, r])
cylinder(r = r, h = cb_height - corner_rad);
translate([offset, offset])
cylinder(r = corner_rad, h = offset);
translate([offset, offset, offset])
sphere(corner_rad);
translate([offset, r, offset])
rotate([-90, 0, 180])
rounded_cylinder(r = corner_rad, h = r, r2 = r);
translate([offset, offset])
cylinder(r = corner_rad, h = offset);
translate([r, offset, offset])
rotate([0, 90, 180])
rounded_cylinder(r = corner_rad, h = r, r2 = r);
translate([offset, r, offset])
rotate([-90, 0, 180])
rounded_cylinder(r = corner_rad, h = r, r2 = r);
translate([r, offset, offset])
rotate([0, 90, 180])
rounded_cylinder(r = corner_rad, h = r, r2 = r);
}
corner_block_v_hole(screw)
insert_hole(insert, overshoot);
corner_block_h_holes(screw)
insert_hole(insert, overshoot, true);
children();
}
corner_block_v_hole(screw)
insert_hole(insert, overshoot);
corner_block_h_holes(screw)
insert_hole(insert, overshoot, true);
children();
}
}
module corner_block_assembly(screw = def_screw, name = false) //! The printed block with inserts
assembly(str("corner_block_M", 20 * screw_radius(screw))) {
assembly(str("corner_block_M", 20 * screw_radius(screw)), ngb = true) {
insert = screw_insert(screw);
stl_colour(name ? pp2_colour : pp1_colour)
@@ -133,12 +133,10 @@ assembly(str("corner_block_M", 20 * screw_radius(screw))) {
module fastened_corner_block_assembly(thickness, screw = def_screw, thickness_below = undef, thickness_side2 = undef, name = false, show_block = true, star_washers = true) { //! Printed block with all fasteners
thickness2 = !is_undef(thickness_below) ? thickness_below : thickness;
thickness3 = !is_undef(thickness_side2) ? thickness_side2 : thickness;
washer = screw_washer(screw);
insert = screw_insert(screw);
function screw_length(t) = screw_shorter_than((star_washers ? 2 : 1) * washer_thickness(washer) + t + insert_length(insert) + overshoot);
screw_length = screw_length(thickness);
screw_length2 = screw_length(thickness2);
screw_length3 = screw_length(thickness3);
function screw_len(t) = screw_length(screw, t + overshoot, star_washers ? 2 : 1, true);
screw_length = screw_len(thickness);
screw_length2 = screw_len(thickness2);
screw_length3 = screw_len(thickness3);
if(show_block)
corner_block_assembly(screw, name) children();

View File

@@ -54,44 +54,44 @@ module door_hinge_hole_positions(dir = 0) { //! Position chidren
}
module door_hinge(door_thickness) { //! Generates STL for the moving part of the hinge
stl(str("door_hinge_", door_thickness));
hole_pitch = width - 10;
union() {
rotate([90, 0, 0])
linear_extrude(width, center = true)
stl(str("door_hinge_", door_thickness))
union() {
rotate([90, 0, 0])
linear_extrude(width, center = true)
difference() {
hull() {
translate([dia / 2, thickness + door_thickness / 2])
intersection() {
rotate(180)
teardrop(r = dia / 2, h = 0, truncate = false);
square([dia + 1, 2 * thickness + door_thickness], center = true);
}
square([1, thickness + door_thickness]);
}
translate([dia / 2, thickness + door_thickness / 2])
teardrop_plus(r = screw_clearance_radius(pin_screw), h = 0);
}
linear_extrude(thickness)
difference() {
hull() {
translate([dia / 2, thickness + door_thickness / 2])
intersection() {
rotate(180)
teardrop(r = dia / 2, h = 0, truncate = false);
translate([0, -width / 2])
square([1, width]);
square([dia + 1, 2 * thickness + door_thickness], center = true);
}
square([1, thickness + door_thickness]);
for(side = [-1, 1])
translate([-width + rad, side * (width / 2 - rad)])
circle4n(rad);
}
translate([dia / 2, thickness + door_thickness / 2])
teardrop_plus(r = screw_clearance_radius(pin_screw), h = 0);
rotate(180)
vflip()
door_hinge_hole_positions()
poly_circle(screw_clearance_radius(screw));
}
linear_extrude(thickness)
difference() {
hull() {
translate([0, -width / 2])
square([1, width]);
for(side = [-1, 1])
translate([-width + rad, side * (width / 2 - rad)])
circle4n(rad);
}
rotate(180)
vflip()
door_hinge_hole_positions()
poly_circle(screw_clearance_radius(screw));
}
}
}
}
module door_hinge_6_stl() door_hinge(6);
@@ -136,8 +136,7 @@ module door_hinge_assembly(top, door_thickness = 6) { //! The moving assembly th
dir = top ? -1 : 1;
pin_x = door_hinge_pin_x();
pin_y = door_hinge_pin_y();
washer = screw_washer(screw);
screw_length = screw_shorter_than(thickness + door_thickness + washer_thickness(washer));
screw_length = screw_length(screw, thickness + door_thickness, 1);
translate([0, pin_y - (thickness + door_thickness / 2), dir * width / 2]) {
rotate([90, 0, 180])
@@ -148,20 +147,20 @@ module door_hinge_assembly(top, door_thickness = 6) { //! The moving assembly th
screw_and_washer(screw, screw_length);
}
translate([pin_x, pin_y, top ? 0 : -washer_thickness(screw_washer(pin_screw))])
washer(screw_washer(pin_screw));
washer = screw_washer(pin_screw);
wt = washer_thickness(washer);
translate([pin_x, pin_y, top ? 0 : -wt])
washer(washer);
translate([pin_x, pin_y, top ? washer_thickness(screw_washer(pin_screw)) + stat_width : width])
screw_and_washer(pin_screw, screw_longer_than(2 * washer_thickness(screw_washer(pin_screw)) + width + stat_width));
translate([pin_x, pin_y, top ? wt + stat_width : width])
screw_and_washer(pin_screw, screw_length(pin_screw, width + stat_width, 2, longer = true));
}
module door_hinge_static_assembly(top, sheet_thickness = 3) { //! The stationary assembly
dir = top ? -1 : 1;
pin_x = door_hinge_pin_x();
stat_washer = screw_washer(stat_screw);
stat_nut = screw_nut(stat_screw);
stat_screw_length = screw_longer_than(thickness + sheet_thickness + 2 * washer_thickness(stat_washer) + nut_thickness(stat_nut, true));
stat_screw_length = screw_length(stat_screw, thickness + sheet_thickness, 2, nyloc = true);
translate([pin_x, 0, -dir * (stat_width / 2 + washer_thickness(screw_washer(pin_screw)))])
rotate([90, 0, 0]) {
@@ -169,9 +168,10 @@ module door_hinge_static_assembly(top, sheet_thickness = 3) { //! The stationary
door_hinge_stat_hole_positions() {
screw_and_washer(stat_screw, stat_screw_length);
translate_z(-thickness - sheet_thickness)
vflip()
nut_and_washer(stat_nut, true);
nut_and_washer(screw_nut(stat_screw), true);
}
}
}

View File

@@ -38,30 +38,30 @@ function door_latch_offset() = width / 2 + 1; //! Offset of the axle from the do
nut_trap_depth = round_to_layer(screw_head_height(screw)) + 4 * layer_height;
module door_latch_stl() { //! Generates the STL for the printed part
stl("door_latch");
ridge = 4;
difference() {
union() {
hull() {
rounded_rectangle([length, width, thickness - tan(30) * (width - ridge) / 2], rad, center = false);
translate_z(thickness / 2)
cube([length, ridge, thickness], center = true);
stl("door_latch")
difference() {
union() {
hull() {
rounded_rectangle([length, width, thickness - tan(30) * (width - ridge) / 2], rad);
translate_z(thickness / 2)
cube([length, ridge, thickness], center = true);
}
cylinder(d = width, h = height);
}
cylinder(d = width, h = height);
hanging_hole(nut_trap_depth, screw_clearance_radius(screw))
circle(r = nut_trap_radius(screw_nut(screw)), $fn = 6);
}
hanging_hole(nut_trap_depth, screw_clearance_radius(screw))
circle(r = nut_trap_radius(screw_nut(screw)), $fn = 6);
}
}
module door_latch_assembly(sheet_thickness = 3) { //! The assembly for a specified sheet thickess
washer = screw_washer(screw);
nut = screw_nut(screw);
screw_length = screw_longer_than(height - nut_trap_depth + sheet_thickness + 2 * washer_thickness(washer) + nut_thickness(nut, true));
screw_length = screw_length(screw, height - nut_trap_depth + sheet_thickness, 2, nyloc = true);
translate([0, -height - washer_thickness(washer)])
rotate([-90, 0, 0]) {

View File

@@ -251,7 +251,7 @@ module drag_chain_link(type, start = false, end = false, check_kids = true) { //
}
// Need to use a wrapper because can't define nested modules in an assembly
module _drag_chain_assembly(type, pos = 0) {
module _drag_chain_assembly(type, pos = 0, render = false) {
s = drag_chain_size(type);
x = (1 + exploded()) * s.x;
r = drag_chain_radius(type) * x / s.x;
@@ -278,8 +278,11 @@ module _drag_chain_assembly(type, pos = 0) {
module link(n) // Position and colour link with origin at the hinge hole
translate([-z / 2, 0, -z / 2]) {
stl_colour(n < 0 || n == npoints - 1 ? pp3_colour : n % 2 ? pp1_colour : pp2_colour)
drag_chain_link(type, start = n == -1, end = n == npoints - 1, check_kids = false)
let($fasteners = 0) children();
render_if(render)
drag_chain_link(type, start = n == -1, end = n == npoints - 1, check_kids = false)
let($fasteners = 0)
children();
let($fasteners = 1) children();
}
@@ -307,15 +310,15 @@ module _drag_chain_assembly(type, pos = 0) {
//! 1. Remove the support material from the links with side cutters.
//! 1. Clip the links together with the special ones at the ends.
module drag_chain_assembly(type, pos = 0) //! Drag chain assembly
assembly(str(drag_chain_name(type), "_drag_chain"), big = true)
module drag_chain_assembly(type, pos = 0, render = false) //! Drag chain assembly
assembly(str(drag_chain_name(type), "_drag_chain"), big = true, ngb = true)
if($children == 2)
_drag_chain_assembly(type, pos) {
_drag_chain_assembly(type, pos, render) {
children(0);
children(1);
}
else if($children == 1)
_drag_chain_assembly(type, pos)
_drag_chain_assembly(type, pos, render)
children(0);
else
_drag_chain_assembly(type, pos);
_drag_chain_assembly(type, pos, render);

View File

@@ -71,42 +71,42 @@ module fixing_block_h_hole_2D(screw = def_screw) //! Position 2D child on the ho
children();
module fixing_block(screw = def_screw) { //! Generate the STL
stl(str("fixing_block_M", screw_radius(screw) * 20));
r = 1;
r = 1;
insert = screw_insert(screw);
corner_rad = insert_outer_d(insert) / 2 + wall;
fb_width = fixing_block_width(screw);
fb_height = fixing_block_height(screw);
fb_depth = fixing_block_depth(screw);
difference() {
union() {
linear_extrude(fb_height, convexity = 5)
difference() {
hull() {
for(side = [-1, 1]) {
translate([side * (fb_width / 2 - corner_rad), fb_depth - corner_rad])
circle4n(corner_rad);
stl(str("fixing_block_M", screw_radius(screw) * 20))
difference() {
union() {
linear_extrude(fb_height, convexity = 5)
difference() {
hull() {
for(side = [-1, 1]) {
translate([side * (fb_width / 2 - corner_rad), fb_depth - corner_rad])
circle4n(corner_rad);
translate([side * (fb_width / 2 - r), r])
circle4n(r);
translate([side * (fb_width / 2 - r), r])
circle4n(r);
}
}
fixing_block_v_holes(screw)
poly_circle(screw_clearance_radius(screw));
}
fixing_block_v_holes(screw)
poly_circle(screw_clearance_radius(screw));
}
}
translate_z(fb_height)
fixing_block_v_holes(screw)
insert_hole(insert);
}
translate_z(fb_height)
fixing_block_v_holes(screw)
insert_hole(insert);
fixing_block_h_hole(screw)
insert_hole(insert, 10, true);
}
fixing_block_h_hole(screw)
insert_hole(insert, 10, true);
}
}
module fixing_block_assembly(screw = def_screw) pose([55, 180, 25], [0, 4.8, 4.8]) //! Printed part with the inserts inserted
assembly(str("fixing_block_M", 20 * screw_radius(screw))) {
assembly(str("fixing_block_M", 20 * screw_radius(screw)), ngb = true) {
translate_z(fixing_block_height(screw))
rotate([0, 180, 0])
stl_colour(pp1_colour) render() fixing_block(screw);
@@ -122,9 +122,7 @@ assembly(str("fixing_block_M", 20 * screw_radius(screw))) {
module fastened_fixing_block_assembly(thickness, screw = def_screw, screw2 = undef, thickness2 = undef, show_block = true, star_washers = true) { //! Assembly with fasteners in place
module fb_screw(screw, thickness) {
washer = screw_washer(screw);
insert = screw_insert(screw);
screw_length = screw_longer_than((star_washers ? 2 : 1) * washer_thickness(washer) + thickness + insert_length(insert));
screw_length = screw_length(screw, thickness, star_washers ? 2 : 1, true, longer = true);
if(thickness)
translate_z(thickness)

View File

@@ -65,8 +65,6 @@ module hinge_screw_positions(type) { //! Place children at the screw positions
}
module hinge_male(type, female = false) { //! The half with the stationary pin
stl(str("hinge_", female ? "fe": "", "male_", type[0]));
r = hinge_radius(type);
w = hinge_width(type);
t = hinge_thickness(type);
@@ -85,37 +83,40 @@ module hinge_male(type, female = false) { //! The half with the stationary
teardrop_r = kr / cos(22.5); // The corner on the teardrop
inset = sqrt(sqr(teardrop_r + gap) - sqr(kr - t)) - kr;
linear_extrude(t)
difference() {
hull() {
for(side = [-1, 1])
translate([side * (w / 2 - r), hinge_depth(type) - r])
circle4n(r);
stl(str("hinge_", female ? "fe": "", "male_", type[0]))
union() {
linear_extrude(t)
difference() {
hull() {
for(side = [-1, 1])
translate([side * (w / 2 - r), hinge_depth(type) - r])
circle4n(r);
translate([-w / 2, inset])
square([w, eps]);
}
hinge_screw_positions(type)
poly_circle(screw_clearance_radius(hinge_screw(type)));
translate([-w / 2, inset])
square([w, eps]);
}
hinge_screw_positions(type)
poly_circle(screw_clearance_radius(hinge_screw(type)));
}
pitch = mw + gap + fw + gap;
dir = female ? -1 : 1;
translate([0, -kr, kr])
rotate([90, 0, -90])
for(z = [0 : (female ? fn : mn) - 1])
translate_z(-dir * w / 2 + z * dir * pitch + (female ? -fw - mw - gap : 0))
linear_extrude(female ? fw : mw)
difference() {
hull() {
rotate(180)
teardrop(r = kr, h = 0);
translate([-kr - 1, -kr])
square(1);
}
teardrop_plus(r = pr + (female ? gap : 0), h = 0);
}
}
pitch = mw + gap + fw + gap;
dir = female ? -1 : 1;
translate([0, -kr, kr])
rotate([90, 0, -90])
for(z = [0 : (female ? fn : mn) - 1])
translate_z(-dir * w / 2 + z * dir * pitch + (female ? -fw - mw - gap : 0))
linear_extrude(female ? fw : mw)
difference() {
hull() {
rotate(180)
teardrop(r = kr, h = 0);
translate([-kr - 1, -kr])
square(1);
}
teardrop_plus(r = pr + (female ? gap : 0), h = 0);
}
}
module hinge_female(type) hinge_male(type, true);
@@ -129,7 +130,7 @@ module hinge_both(type) { //! Both parts together for printing
}
module hinge_assembly(type, angle = 0)
assembly(str("hinge_", type[0])) { //! Assembled hinge
assembly(str("hinge_", type[0]), ngb = true) { //! Assembled hinge
kr = hinge_knuckle_dia(type) / 2;
hr = hinge_pin_dia(type) / 2;
w = hinge_width(type);
@@ -155,9 +156,7 @@ module hinge_fastened_assembly(type, thickness1, thickness2, angle, show_hinge =
hinge_assembly(type, angle);
screw = hinge_screw(type);
washer_t = 2 * washer_thickness(screw_washer(screw));
nut = screw_nut(screw);
nut_t = nut_thickness(nut, true);
t = hinge_thickness(type);
kr = hinge_knuckle_dia(type) / 2;
@@ -165,7 +164,7 @@ module hinge_fastened_assembly(type, thickness1, thickness2, angle, show_hinge =
if(thickness)
hinge_screw_positions(type) {
translate_z(t)
screw_and_washer(screw, screw_longer_than(t + thickness + washer_t + nut_t));
screw_and_washer(screw, screw_length(screw, t + thickness, 2, nyloc = true));
translate_z(-thickness)
vflip()

View File

@@ -39,7 +39,6 @@ function foot_screw(type = foot) = type[4]; //! Screw type
function foot_slant(type = foot) = type[5]; //! Taper angle
module foot(type = foot) { //! Generate STL
stl("foot");
h = foot_height(type);
t = foot_thickness(type);
r1 = washer_radius(screw_washer(foot_screw(type)));
@@ -47,32 +46,32 @@ module foot(type = foot) { //! Generate STL
r2 = r3 - h * tan(foot_slant(type));
r = foot_rad(type);
union() {
rotate_extrude(convexity = 3) {
hull() {
translate([r1, 0])
square([r3 - r1, eps]);
stl("foot")
union() {
rotate_extrude(convexity = 3) {
hull() {
translate([r1, 0])
square([r3 - r1, eps]);
for(x = [r1 + r, r2 - r])
translate([x, h - r])
circle4n(r);
for(x = [r1 + r, r2 - r])
translate([x, h - r])
circle4n(r);
}
}
linear_extrude(t)
difference() {
circle(r1 + eps);
poly_circle( screw_clearance_radius(foot_screw(type)));
}
}
linear_extrude(t)
difference() {
circle(r1 + eps);
poly_circle( screw_clearance_radius(foot_screw(type)));
}
}
}
module foot_assembly(t = 0, type = foot, flip = false) { //! Assembly with fasteners in place for specified sheet thickness
screw = foot_screw(type);
washer = screw_washer(screw);
nut = screw_nut(screw);
squeeze = 0.5;
screw_length = screw_longer_than(foot_thickness(type) + t + 2 * washer_thickness(washer) + nut_thickness(nut, true) - squeeze);
screw_length = screw_length(screw, foot_thickness(type) + t - squeeze, 2, nyloc = true);
vflip() explode(15, true) {
stl_colour(pp4_colour) foot(type);
@@ -94,7 +93,6 @@ module foot_assembly(t = 0, type = foot, flip = false) { //! Assembly with faste
}
module insert_foot(type = insert_foot) { //! Generate STL for foot with insert
stl("insert_foot");
h = foot_height(type);
r3 = foot_diameter(type) / 2;
r2 = r3 - h * tan(foot_slant(type));
@@ -104,36 +102,37 @@ module insert_foot(type = insert_foot) { //! Generate STL for foot with insert
h2 = insert_hole_length(insert);
r4 = insert_hole_radius(insert);
r5 = r4 + 1;
union() {
rotate_extrude() {
union() {
hull() {
translate([r5, 0]) {
square([r3 - r5, eps]);
square([eps, h]);
}
stl("insert_foot")
union() {
rotate_extrude() {
union() {
hull() {
translate([r5, 0]) {
square([r3 - r5, eps]);
square([eps, h]);
}
translate([r2 - r, h - r])
circle4n(r);
translate([r2 - r, h - r])
circle4n(r);
}
}
}
linear_extrude(h2 + eps)
difference() {
circle(r5 + eps);
poly_circle(r4);
}
translate_z(h2)
cylinder(r = r5 + eps, h = h - h2);
}
linear_extrude(h2 + eps)
difference() {
circle(r5 + eps);
poly_circle(r4);
}
translate_z(h2)
cylinder(r = r5 + eps, h = h - h2);
}
}
//
//! Place the insert in the bottom of the foot and push home with a soldering iron with a conical bit heated to 200&deg;C.
//
module insert_foot_assembly(type = insert_foot) //! Printed part with insert in place
assembly("insert_foot") {
assembly("insert_foot", ngb = true) {
screw = foot_screw(type);
insert = screw_insert(screw);
@@ -146,9 +145,7 @@ assembly("insert_foot") {
module fastened_insert_foot_assembly(t = 3, type = insert_foot) { //! Assembly with fasteners in place for specified sheet thickness
screw = foot_screw(type);
washer = screw_washer(screw);
insert = screw_insert(screw);
screw_length = screw_shorter_than(insert_length(insert) + t + 2 * washer_thickness(washer));
screw_length = screw_length(screw, t, 2, insert = true);
explode(-10) insert_foot_assembly(type);

View File

@@ -46,8 +46,6 @@ module handle_holes(h = 100) //! Drills holes for the screws
drill(screw_clearance_radius(screw), h);
module handle_stl() { //! generate the STL
stl("handle");
module end(end)
translate([end * pitch / 2, 0])
rotate_extrude()
@@ -59,29 +57,30 @@ module handle_stl() { //! generate the STL
square([dia / 2 + 1, dia + 1]);
}
translate_z(dia / 2)
union() {
hull() {
end(-1);
stl("handle")
translate_z(dia / 2)
union() {
hull() {
end(-1);
end(1);
}
handle_screw_positions()
render() difference() {
h = height + dia / 2;
cylinder(d = dia, h = h);
translate_z(h)
insert_hole(insert, 6);
end(1);
}
}
handle_screw_positions()
render() difference() {
h = height + dia / 2;
cylinder(d = dia, h = h);
translate_z(h)
insert_hole(insert, 6);
}
}
}
//
//! Place inserts in the bottom of the posts and push them home with a soldering iron with a conical bit heated to 200&deg;C.
//
module handle_assembly() pose([225, 0, 150], [0, 0, 14]) //! Printed part with inserts in place
assembly("handle") {
assembly("handle", ngb = true) {
translate_z(handle_height())
stl_colour(pp1_colour) vflip() handle_stl();
@@ -91,7 +90,7 @@ assembly("handle") {
}
module handle_fastened_assembly(thickness) { //! Assembly with fasteners in place
screw_length = screw_longer_than(thickness + insert_length(insert) + 2 * washer_thickness(screw_washer(screw)));
screw_length = screw_length(screw, thickness, 2, true, longer = true);
handle_assembly();

View File

@@ -66,35 +66,35 @@ module pcb_mount_washer_stl() //! A plastic washer to clamp a PCB
pcb_mount_ring();
module pcb_mount(pcb, height = 5, washers = true) { //! Make the STL of a pcb mount for the specified PCB.
stl(str("pcb_mount_", pcb[0], "_", height));
y_pitch = pcb_width(pcb) > 4 * pillar_r + 4 ? pillar_r + 1
: pcb_width(pcb) / 2 + frame_w + 1 + pillar_r;
if(washers)
for(x = [-1, 1], y = [-1, 1])
translate([x * (pillar_r + 1), y * y_pitch, 0])
pcb_mount_washer_stl();
stl(str("pcb_mount_", pcb[0], "_", height)) union() {
if(washers)
for(x = [-1, 1], y = [-1, 1])
translate([x * (pillar_r + 1), y * y_pitch, 0])
pcb_mount_washer_stl();
for(x = [-1, 1])
translate([x * pillar_x_pitch(pcb) / 2, 0, frame_t / 2])
cube([frame_w, pillar_y_pitch(pcb) - 2 * wall, frame_t], center = true);
for(x = [-1, 1])
translate([x * pillar_x_pitch(pcb) / 2, 0, frame_t / 2])
cube([frame_w, pillar_y_pitch(pcb) - 2 * wall, frame_t], center = true);
for(y = [-1, 1])
translate([0, y * pillar_y_pitch(pcb) / 2, frame_t / 2])
cube([pillar_x_pitch(pcb) - 2 * wall, frame_w, frame_t], center = true);
for(y = [-1, 1])
translate([0, y * pillar_y_pitch(pcb) / 2, frame_t / 2])
cube([pillar_x_pitch(pcb) - 2 * wall, frame_w, frame_t], center = true);
pcb_mount_screw_positions(pcb)
linear_extrude(height)
pcb_mount_ring();
linear_extrude(height + pcb_thickness(pcb) - layer_height)
difference() {
pcb_mount_screw_positions(pcb)
pcb_mount_screw_positions(pcb)
linear_extrude(height)
pcb_mount_ring();
square([pcb_length(pcb) + 2 * clearance, pcb_width(pcb) + 2 * clearance], center = true);
}
linear_extrude(height + pcb_thickness(pcb) - layer_height)
difference() {
pcb_mount_screw_positions(pcb)
pcb_mount_ring();
square([pcb_length(pcb) + 2 * clearance, pcb_width(pcb) + 2 * clearance], center = true);
}
}
}
module pcb_mount_assembly(pcb, thickness, height = 5) { //! A PCB mount assembly with fasteners
@@ -103,10 +103,9 @@ module pcb_mount_assembly(pcb, thickness, height = 5) { //! A PCB mount assembly
stl_colour(pp1_colour) pcb_mount(pcb, washers = false);
washer = screw_washer(screw);
nut = screw_nut(screw);
t = pcb_thickness(pcb);
screw_length = screw_longer_than(height + t + washer_thickness + thickness + washer_thickness(washer) + nut_thickness(nut, true));
screw_length = screw_length(screw, height + t + washer_thickness + thickness, 1, nyloc = true);
pcb_mount_screw_positions(pcb) {
translate_z(height + t) {

154
printed/pocket_handle.scad Normal file
View File

@@ -0,0 +1,154 @@
//
// NopSCADlib Copyright Chris Palmer 2021
// 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/>.
//
//
//! Customisable pocket handle
//
include <../core.scad>
function pocket_handle(hand_size = [90, 40, 40], slant = 35, screw = M3_cs_cap_screw, panel_t = 3, wall = 4, rad = 4) = //! Construct a pocket_handle property list
[hand_size, slant, screw, panel_t, wall, rad];
function pocket_handle_hand_size(type) = type[0]; //! Size of the hole for the fingers
function pocket_handle_slant(type) = type[1]; //! Upward slant of the hand hole
function pocket_handle_screw(type) = type[2]; //! Screw type, can be countersunk or not
function pocket_handle_panel_t(type) = type[3]; //! Thickness of the panel it is mounted in
function pocket_handle_wall(type) = type[4]; //! Wall thickness
function pocket_handle_rad(type) = type[5]; //! Min corner rad
function pocket_handle_flange(type) = //! Size of the flange
let(w = pocket_handle_wall(type),
f = washer_diameter(screw_washer(pocket_handle_screw(type))) + 2 + w,
s = pocket_handle_hand_size(type))
[s.x + 2 * f, s.y + 2 * f, w];
module pocket_handle_hole_positions(type) { //! Place children at screw hole positions
f = pocket_handle_flange(type);
h = pocket_handle_hand_size(type);
x_pitch = (f.x + h.x) / 4;
y_pitch = (f.y + h.y) / 4;
for(x = [-1, 1], y = [-1, 1])
translate([x * x_pitch, y * y_pitch])
children();
}
module pocket_handle_holes(type, h = 0) { //! Panel cutout and screw holes
hand = pocket_handle_hand_size(type);
w = pocket_handle_wall(type);
slot = [hand.x + 2 * w, hand.y + 2 * w];
t = pocket_handle_panel_t(type);
clearance = norm([slot.y, t]) - slot.y + 0.2; // has to be enough clearance for the diagonal to swing it in
extrude_if(h) {
pocket_handle_hole_positions(type)
drill(screw_clearance_radius(pocket_handle_screw(type)), 0);
rounded_square([slot.x + clearance, slot.y + clearance], pocket_handle_rad(type) + w + clearance / 2);
}
}
module pocket_handle(type) { //! Generate STL for pocket_handle
f = pocket_handle_flange(type);
r = pocket_handle_rad(type);
s = pocket_handle_slant(type);
o = f.z * tan(s);
h = pocket_handle_hand_size(type);
t = pocket_handle_panel_t(type);
w = pocket_handle_wall(type);
screw = pocket_handle_screw(type) ;
stl("pocket_handle")
union() {
difference() {
hull() {
rounded_rectangle(f, r);
translate_z(f.z - eps)
rounded_rectangle([f.x + 2 * o, f.y + 2 * o, eps], r + o);
}
hull() {
rounded_rectangle([h.x, h.y, f.z + eps], r);
translate_z(-eps)
rounded_rectangle([h.x + 2 * o, h.y + 2 * o, eps], r + o);
}
pocket_handle_hole_positions(type) {
if(screw_head_height(screw))
translate_z(-eps)
poly_cylinder(r = screw_clearance_radius(screw), h = f.z + 2 * eps, center = false);
else
screw_polysink(screw, h = 2 * f.z + eps, alt = true);
}
}
translate_z(f.z)
linear_extrude(t)
difference() {
rounded_square([h.x + 2 * w, h.y + 2 * w], r + w);
rounded_square([h.x, h.y], r);
}
translate_z(f.z + t)
difference() {
height = h.z - f.z - t;
hull() {
rounded_rectangle([h.x + 2 * w, h.y + 2 * w, eps], r + w);
translate((height + w) * [0, sin(s), cos(s)])
rounded_rectangle([h.x + 2 * w, h.y + 2 * w, eps], r + w);
}
hull() {
translate_z(-eps)
rounded_rectangle([h.x, h.y, eps], r);
translate(height * [0, sin(s), cos(s)])
rounded_rectangle([h.x, h.y, eps], r);
}
}
}
}
module pocket_handle_assembly(type) { //! Assembly with fasteners in place
f = pocket_handle_flange(type);
screw = pocket_handle_screw(type);
nut = screw_nut(screw);
t = pocket_handle_panel_t(type);
washers = screw_head_height(screw) ? 2 : 1;
screw_length = screw_length(screw, f.z + t, washers, nyloc = true);
translate_z(f.z + t / 2) hflip() {
stl_colour(pp1_colour)
pocket_handle(type);
pocket_handle_hole_positions(type) {
translate_z(f.z + t)
explode(15, true)
nut_and_washer(nut, true);
vflip()
if(washers == 2)
screw_and_washer(screw, screw_length);
else
screw(screw, screw_length);
}
}
}

View File

@@ -65,10 +65,8 @@ function pbox_insert(type) = screw_insert(pbox_screw(type)); //! The insert for
function pbox_washer(type) = screw_washer(pbox_screw(type)); //! The washer for the base screws
function pbox_screw_length(type, panel_thickness = 0) = //! Length of the base screw
let(foot = pbox_foot(type))
screw_shorter_than(pbox_base(type) + washer_thickness(pbox_washer(type))
+ insert_length(pbox_insert(type))
+ (foot ? foot_thickness(foot) : panel_thickness));
let(foot = pbox_foot(type), screw = pbox_screw(type))
screw_length(screw, pbox_base(type) + (foot ? foot_thickness(foot) : panel_thickness), 1, true);
function pbox_mid_offset(type) = pbox_ridges(type).y + pbox_wall(type) / 2; // Offset to wall midpoint
@@ -131,28 +129,27 @@ module pbox_outer_shape(type) //! 2D outer shape of the box
offset(pbox_wall(type) / 2) pbox_mid_shape(type);
module pbox_base(type) { //! Generate the STL for the base
stl(str(pbox_name(type),"_base"));
t = pbox_base(type);
difference() {
union() {
linear_extrude(t)
offset(base_outset - 0.2)
pbox_inner_shape(type);
if($children > 0)
children(0);
stl(str(pbox_name(type),"_base"))
difference() {
union() {
linear_extrude(t)
offset(base_outset - 0.2)
pbox_inner_shape(type);
if($children > 0)
children(0);
}
pbox_screw_positions(type)
poly_cylinder(r = screw_clearance_radius(pbox_screw(type)), h = 2 * t + eps, center = true);
if($children > 1)
children(1);
}
pbox_screw_positions(type)
poly_cylinder(r = screw_clearance_radius(pbox_screw(type)), h = 2 * t + eps, center = true);
if($children > 1)
children(1);
}
}
module pbox(type) { //! Generate the STL for the main case
stl(pbox_name(type));
height = pbox_height(type);
total_height = pbox_total_height(type);
top_thickness = pbox_top(type);
@@ -161,60 +158,61 @@ module pbox(type) { //! Generate the STL for the main case
ledge_inset = base_outset - base_overlap;
ledge_h = pbox_base(type) ? (ledge_outset - ledge_inset) * 2 : 0;
difference() {
union() {
linear_extrude(total_height)
pbox_outer_shape(type);
if($children > 2)
children(2);
}
stl(pbox_name(type))
difference() {
translate_z(top_thickness)
union() {
linear_extrude(height + eps)
offset(-wall / 2) pbox_mid_shape(type);
union() {
linear_extrude(total_height)
pbox_outer_shape(type);
translate_z(height) // Recess for the base
linear_extrude(total_height - height)
offset(base_outset)
pbox_inner_shape(type);
}
// Ledge to support the lid
if(ledge_h)
translate_z(top_thickness + height - ledge_h)
difference() {
rounded_rectangle([pbox_width(type) + 2 * outset, pbox_depth(type) + 2 * outset, ledge_h], 1, center = false);
if($children > 2)
children(2);
}
difference() {
translate_z(top_thickness)
union() {
linear_extrude(height + eps)
offset(-wall / 2) pbox_mid_shape(type);
hull() {
linear_extrude(ledge_h + eps)
offset(ledge_inset)
translate_z(height) // Recess for the base
linear_extrude(total_height - height)
offset(base_outset)
pbox_inner_shape(type);
linear_extrude(eps)
offset(ledge_outset)
pbox_inner_shape(type);
}
pbox_screw_positions(type)
insert_hole(pbox_insert(type));
}
// Ledge to support the lid
if(ledge_h)
translate_z(top_thickness + height - ledge_h)
difference() {
rounded_rectangle([pbox_width(type) + 2 * outset, pbox_depth(type) + 2 * outset, ledge_h], 1);
// Corner lugs for inserts
outset = wall + pbox_ridges(type).y;
or = pbox_radius(type) + outset;
inset = pbox_screw_inset(type) + outset;
br = insert_boss_radius(pbox_insert(type), wall);
ext = sqrt(2) * inset - or * (sqrt(2) - 1) - br;
translate_z(height + top_thickness)
pbox_screw_positions(type)
insert_lug(pbox_insert(type), wall, counter_bore = 0, extension = ext, corner_r = or);
hull() {
linear_extrude(ledge_h + eps)
offset(ledge_inset)
pbox_inner_shape(type);
if($children > 0)
children(0);
linear_extrude(eps)
offset(ledge_outset)
pbox_inner_shape(type);
}
pbox_screw_positions(type)
insert_hole(pbox_insert(type));
}
// Corner lugs for inserts
outset = wall + pbox_ridges(type).y;
or = pbox_radius(type) + outset;
inset = pbox_screw_inset(type) + outset;
br = insert_boss_radius(pbox_insert(type), wall);
ext = sqrt(2) * inset - or * (sqrt(2) - 1) - br;
translate_z(height + top_thickness)
pbox_screw_positions(type)
insert_lug(pbox_insert(type), wall, counter_bore = 0, extension = ext, corner_r = or);
if($children > 0)
children(0);
}
if($children > 1)
children(1);
}
if($children > 1)
children(1);
}
}
module pbox_inserts(type) //! Place the inserts for the base screws

View File

@@ -0,0 +1,200 @@
//
// 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/>.
//
//! Printed pulleys are a remix of droftarts's (see <https://www.thingiverse.com/droftarts/designs>) Parametric Pulleys
//! on Thingiverse (see <https://www.thingiverse.com/thing:16627>) and are licensed under the
//! Creative Commons - Attribution - Share Alike license (see <https://creativecommons.org/licenses/by-sa/3.0/>)
//
include <../core.scad>
include <../vitamins/pulleys.scad>
printed_pulley_GT2_profile = [[0.747183,-0.5],[0.747183,0],[0.647876,0.037218],[0.598311,0.130528],[0.578556,0.238423],[0.547158,0.343077],[0.504649,0.443762],[0.451556,0.53975],[0.358229,0.636924],[0.2484,0.707276],[0.127259,0.750044],[0,0.76447],[-0.127259,0.750044],[-0.2484,0.707276],[-0.358229,0.636924],[-0.451556,0.53975],[-0.504797,0.443762],[-0.547291,0.343077],[-0.578605,0.238423],[-0.598311,0.130528],[-0.648009,0.037218],[-0.747183,0],[-0.747183,-0.5]];
function printed_pulley_inverted(type) = pulley_hub_dia(type) < pulley_flange_dia(type); //! Need to print upside down to prevent overhang
function printed_pulley_od(tooth_count, tooth_pitch, pitch_line_offset)
= tooth_count * tooth_pitch / PI - 2 * pitch_line_offset;
module printed_pulley_teeth_from_profile(tooth_count, tooth_depth, tooth_width, tooth_profile) {
pulley_od = printed_pulley_od(tooth_count, 2, 0.254);
difference() {
rotate (90 / tooth_count)
circle(r = pulley_od / 2, $fn = tooth_count * 4);
tooth_distance_from_centre = sqrt(pulley_od * pulley_od - (tooth_width + 0.2) * (tooth_width + 0.2)) / 2;
for(i = [1 : tooth_count])
rotate(i * 360 / tooth_count)
translate([0, -tooth_distance_from_centre])
scale([(tooth_width + 0.2) / tooth_width, 1])
polygon(tooth_profile);
}
}
module printed_pulley_GT2_teeth(type) {
tooth_count = pulley_teeth(type);
if (tooth_count == 0)
circle(r = pulley_od(type) / 2);
else
printed_pulley_teeth_from_profile(tooth_count, 0.764, 1.494, printed_pulley_GT2_profile);
}
module printed_pulley_teeth(type) { //! Draw the pulley's teeth
tooth_count = pulley_teeth(type);
tw = pulley_od(type) * PI / (tooth_count * 2);
ir = pulley_ir(type);
or = pulley_od(type) / 2;
T_angle = 40;
GT_r = 0.555;
for (i = [0 : 1 : tooth_count - 1])
rotate(i * 360 / tooth_count)
if (pulley_type(type)[0] == "G")
translate([0, ir + GT_r])
hull() {
circle(GT_r);
translate([0, GT_r])
square(2 * GT_r, center = true);
}
else
translate([0, (ir + or) / 2])
hull() {
for(side = [-1, 1])
translate([side * tw / 2, 0])
rotate(-side * T_angle / 2)
square([eps, (or - ir)], center = true);
translate([0, 1])
square([tw, eps], center = true);
}
}
module printed_pulley(type) { //! Draw a printable pulley
ft = pulley_flange_thickness(type);
hl = pulley_hub_length(type);
w = pulley_width(type);
r1 = pulley_bore(type) / 2;
or = pulley_od(type) / 2;
screw_z = pulley_screw_z(type);
module core() {
translate_z(pulley_hub_length(type) + ft)
linear_extrude(w + 1) let($fa = 1, $fs = 0.1)
if ("GT2" == str(pulley_type(type)[0], pulley_type(type)[1], pulley_type(type)[2]))
difference() {
printed_pulley_GT2_teeth(type);
circle(d = pulley_bore(type));
}
else
difference() {
circle(or);
printed_pulley_teeth(type);
circle(d = pulley_bore(type));
}
}
module screw_holes() {
if(pulley_screws(type))
translate_z(screw_z)
for(i = [0 : pulley_screws(type) - 1])
rotate([-90, 180, i * -90])
if(show_supports())
teardrop(r = screw_pilot_hole(pulley_screw(type)), h = pulley_flange_dia(type) / 2 + 1, center = false);
else
cylinder(r = screw_radius(pulley_screw(type)), h = pulley_flange_dia(type) / 2 + 1);
}
module hub()
linear_extrude(hl)
difference() {
circle(d= pulley_hub_dia(type));
circle(d = pulley_bore(type));
}
stl(str("printed_pulley_", type[0]))
translate_z(printed_pulley_inverted(type) ? - hl : 0) {
// hub
if(hl)
translate_z(printed_pulley_inverted(type) ? hl + w + 2 * ft : 0)
if(screw_z && screw_z < hl)
render()
difference() {
hub();
screw_holes();
}
else
hub();
// bottom flange
translate_z(hl)
linear_extrude(ft)
difference() {
circle(d = pulley_flange_dia(type));
circle(d = pulley_bore(type));
}
// top flange
translate_z(hl + ft + w) {
// inner part, supported by core
linear_extrude(ft)
difference() {
circle(r = or);
circle(d = pulley_bore(type));
}
// outer part at 45 degrees for printing
rotate_extrude()
translate([or - eps, ft])
vflip()
right_triangle(ft, ft);
}
if(screw_z && screw_z > hl)
render()
difference() { // T5 pulleys have screws through the teeth
core();
translate_z(printed_pulley_inverted(type) ? pulley_height(type) + hl - 2 * screw_z : 0)
screw_holes();
}
else
core();
}
}
module printed_pulley_assembly(type, colour = pp1_colour) //! Draw a printed pulley with its grub screws in place
assembly(str("printed_pulley_", type[0]), ngb = true) {
translate_z(pulley_offset(type)) {
stl_colour(colour)
if(printed_pulley_inverted(type))
translate_z(pulley_height(type))
hflip()
printed_pulley(type);
else
printed_pulley(type);
if(pulley_screws(type))
translate_z(pulley_screw_z(type))
for(i = [0 : pulley_screws(type) - 1])
rotate([-90, 0, i * -90])
translate_z(pulley_bore(type) / 2 + pulley_screw_length(type))
screw(pulley_screw(type), pulley_screw_length(type));
}
}

View File

@@ -79,8 +79,6 @@ module psu_shroud_holes(type, cable_d, cables = 1) {
}
module psu_shroud(type, cable_d, name, cables = 1) { //! Generate the STL file for a specified ssr and cable
stl(str("psu_shroud_", name));
extent = psu_shroud_extent(type);
depth = psu_shroud_depth(type);
width = psu_shroud_width(type);
@@ -109,41 +107,43 @@ module psu_shroud(type, cable_d, name, cables = 1) { //! Generate the STL file f
}
}
// base and sides
translate([centre_x, -centre_y]) {
rounded_rectangle([depth - eps, width - eps, top], rad, center = false);
stl(str("psu_shroud_", name)) {
// base and sides
translate([centre_x, -centre_y]) {
rounded_rectangle([depth - eps, width - eps, top], rad);
linear_extrude(height)
difference() {
linear_extrude(height)
difference() {
shape();
translate([depth / 2, width / 2 - 5])
square([2 * (depth - extent + terminal_clearance), 10], center = true);
}
linear_extrude(height - terminal_block_height(tb) - psu_terminal_block_z(type) - terminal_clearance)
shape();
translate([depth / 2, width / 2 - 5])
square([2 * (depth - extent + terminal_clearance), 10], center = true);
}
linear_extrude(height - terminal_block_height(tb) - psu_terminal_block_z(type) - terminal_clearance)
shape();
}
// cable slots
for(i = [0 : 1 : cables - 1])
translate([centre_x - depth / 2 + wall / 2, -centre_y + (i - cables / 2 + 0.5) * psu_shroud_cable_pitch(cable_d), height / 2])
rotate([90, 0, 90])
linear_extrude(wall, center = true)
difference() {
square([cable_d + eps, height], center = true);
// cable slots
for(i = [0 : 1 : cables - 1])
translate([centre_x - depth / 2 + wall / 2, -centre_y + (i - cables / 2 + 0.5) * psu_shroud_cable_pitch(cable_d), height / 2])
rotate([90, 0, 90])
linear_extrude(wall, center = true)
difference() {
square([cable_d + eps, height], center = true);
translate([0, height / 2])
vertical_tearslot(h = 0, r = cable_d / 2, l = cable_d);
}
// insert lugs
mirror([0, 1, 0])
psu_shroud_hole_positions(type)
translate_z(height)
rotate($side * 90)
insert_lug(insert, wall, counter_bore);
}
translate([0, height / 2])
vertical_tearslot(h = 0, r = cable_d / 2, l = cable_d);
}
// insert lugs
mirror([0, 1, 0])
psu_shroud_hole_positions(type)
translate_z(height)
rotate($side * 90)
insert_lug(insert, wall, counter_bore);
}
}
module psu_shroud_assembly(type, cable_d, name, cables = 1) //! The printed parts with inserts fitted
assembly(str("PSU_shroud_", name)) {
assembly(str("PSU_shroud_", name), ngb = true) {
translate_z(psu_shroud_height(type))
vflip()
@@ -156,8 +156,7 @@ assembly(str("PSU_shroud_", name)) {
module psu_shroud_fastened_assembly(type, cable_d, thickness, name, cables = 1) //! Assembly with screws in place
{
washer = screw_washer(screw);
screw_length = screw_shorter_than(2 * washer_thickness(washer) + thickness + insert_length(insert) + counter_bore);
screw_length = screw_length(screw,thickness + counter_bore, 2, true);
psu_shroud_assembly(type, cable_d, name, cables);

View File

@@ -47,7 +47,6 @@ module ribbon_clamp_holes(ways, h = 20, screw = screw) //! Drill screw holes
module ribbon_clamp(ways, screw = screw) { //! Generate STL for given number of ways
screw_d = screw_radius(screw) * 2;
stl(str("ribbon_clamp_", ways, screw_d != 3 ? str("_", screw_d) : ""));
pitch = ribbon_clamp_hole_pitch(ways, screw);
d = ribbon_clamp_width(screw);
@@ -55,34 +54,35 @@ module ribbon_clamp(ways, screw = screw) { //! Generate STL for given number of
t = round_to_layer(ribbon_clamp_slot_depth() + wall);
insert = screw_insert(screw);
difference() {
union() {
hull() {
translate_z(h - t / 2)
cube([ribbon_clamp_hole_pitch(ways, screw), d, t], center = true);
stl(str("ribbon_clamp_", ways, screw_d != 3 ? str("_", screw_d) : ""))
difference() {
union() {
hull() {
translate_z(h - t / 2)
cube([ribbon_clamp_hole_pitch(ways, screw), d, t], center = true);
translate_z(1)
cube([pitch, max(wall, d - 2 * (h - t)), 2], center = true);
translate_z(1)
cube([pitch, max(wall, d - 2 * (h - t)), 2], center = true);
}
ribbon_clamp_hole_positions(ways, screw, -1)
cylinder(d = d, h = h);
ribbon_clamp_hole_positions(ways, screw, 1)
cylinder(d = d, h = h);
}
ribbon_clamp_hole_positions(ways, screw, -1)
cylinder(d = d, h = h);
ribbon_clamp_hole_positions(ways, screw, 1)
cylinder(d = d, h = h);
}
translate_z(h)
cube([ribbon_clamp_slot(ways), d + 1, ribbon_clamp_slot_depth() * 2], center = true);
ribbon_clamp_hole_positions(ways, screw)
translate_z(h)
rotate(22.5)
insert_hole(insert, ribbon_clamp_screw_depth(screw) - insert_length(insert));
}
cube([ribbon_clamp_slot(ways), d + 1, ribbon_clamp_slot_depth() * 2], center = true);
ribbon_clamp_hole_positions(ways, screw)
translate_z(h)
rotate(22.5)
insert_hole(insert, ribbon_clamp_screw_depth(screw) - insert_length(insert));
}
}
module ribbon_clamp_assembly(ways, screw = screw) pose([55, 180, 25]) //! Printed part with inserts in place
assembly(let(screw_d = screw_radius(screw) * 2)str("ribbon_clamp_", ways, screw_d != 3 ? str("_", screw_d) : "")) {
assembly(let(screw_d = screw_radius(screw) * 2)str("ribbon_clamp_", ways, screw_d != 3 ? str("_", screw_d) : ""), ngb = true) {
h = ribbon_clamp_height(screw);
insert = screw_insert(screw);
@@ -101,8 +101,7 @@ module ribbon_clamp_fastened_assembly(ways, thickness, screw = screw) { //! Clam
vitamin(str(": Tape self amalgamating silicone ",tape_l," x 25mm"));
washer = screw_washer(screw);
screw_length = screw_shorter_than(2 * washer_thickness(washer) + thickness + ribbon_clamp_screw_depth(screw));
screw_length = screw_length(screw, thickness + ribbon_clamp_screw_depth(screw), 2);
ribbon_clamp_assembly(ways, screw);

View File

@@ -34,32 +34,31 @@ knob_height = knob_stem_h + knob_thickness;
function knob_height() = knob_height;
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;
function wave(a) = knob_r + sin(a * knob_waves) * knob_wave;
union() {
render() difference() {
cylinder(r = knob_stem_r, h = knob_thickness + knob_stem_h);
stl(str("screw_knob_M", screw_radius(screw) * 20))
union() {
render() difference() {
cylinder(r = knob_stem_r, h = knob_thickness + knob_stem_h);
hanging_hole(knob_nut_trap_depth(screw), screw_clearance_radius(screw))
rotate(45)
circle(r = nut_trap_radius(screw_nut(screw)), $fn = 6);
}
linear_extrude(knob_thickness, convexity = 3)
difference() {
polygon(points = [for(a = [0 : 359]) [wave(a) * sin(a), wave(a) * cos(a)]]);
circle(knob_stem_r - eps);
hanging_hole(knob_nut_trap_depth(screw), screw_clearance_radius(screw))
rotate(45)
circle(r = nut_trap_radius(screw_nut(screw)), $fn = 6);
}
}
linear_extrude(knob_thickness, convexity = 3)
difference() {
polygon(points = [for(a = [0 : 359]) [wave(a) * sin(a), wave(a) * cos(a)]]);
circle(knob_stem_r - eps);
}
}
}
//! Place the screw through the printed part
module screw_knob_assembly(screw, length) //! Assembly with the screw in place
assembly(str("screw_knob_M", 20 * screw_radius(screw), "_", length)) {
assembly(str("screw_knob_M", 20 * screw_radius(screw), "_", length), ngb = true) {
translate_z(knob_height)
vflip()
stl_colour(pp1_colour) screw_knob(screw);

View File

@@ -41,7 +41,6 @@ height = base_thickness + box_height;
function socket_box_depth() = height; //! Outside depth of the backbox
module socket_box(type) { //! Generate STL of the backbox for the specified socket
stl(str("socket_box_",type[0]));
screw = mains_socket_screw(type);
screw_clearance_radius = screw_clearance_radius(screw);
@@ -51,37 +50,38 @@ module socket_box(type) { //! Generate STL of the backbox for the specified sock
insert_boss = mains_socket_insert_boss(type);
insert_hole_radius = insert_hole_radius(insert);
difference() {
linear_extrude(height, convexity = 5)
face_plate(type);
stl(str("socket_box_",type[0]))
difference() {
translate_z(base_thickness)
linear_extrude(height, convexity = 5)
offset(-wall) offset(1) face_plate(type);
linear_extrude(height, convexity = 5)
face_plate(type);
for(side = [-1, 1])
hull()
for(x = [1, 2])
translate([side * mains_socket_pitch(type) / x, 0])
cylinder(d = insert_boss, h = 100);
}
//
// Socket holes
//
translate_z(height)
mains_socket_hole_positions(type) {
poly_cylinder(r = screw_clearance_radius, h = 2 * box_height, center = true);
difference() {
translate_z(base_thickness)
linear_extrude(height, convexity = 5)
offset(-wall) offset(1) face_plate(type);
poly_cylinder(r = insert_hole_radius, h = 2 * insert_length, center = true);
for(side = [-1, 1])
hull()
for(x = [1, 2])
translate([side * mains_socket_pitch(type) / x, 0])
cylinder(d = insert_boss, h = 100);
}
//
// Cable hole
//
translate([cable_x, cable_y(type), cable_z])
rotate([90, 0, 0])
teardrop_plus(r = cable_d / 2, h = 30);
}
//
// Socket holes
//
translate_z(height)
mains_socket_hole_positions(type) {
poly_cylinder(r = screw_clearance_radius, h = 2 * box_height, center = true);
poly_cylinder(r = insert_hole_radius, h = 2 * insert_length, center = true);
}
//
// Cable hole
//
translate([cable_x, cable_y(type), cable_z])
rotate([90, 0, 0])
teardrop_plus(r = cable_d / 2, h = 30);
}
}
module socket_box_MKLOGIC_stl() socket_box(MKLOGIC);
@@ -105,8 +105,7 @@ module socket_box_MKLOGIC_assembly() socket_box_assembly(MKLOGIC);
module socket_box_fastened_assembly(type, thickness) { //! The socket and backbox on each side of the specified panel thickness
screw = mains_socket_screw(type);
insert = screw_insert(screw);
screw_length = screw_longer_than(mains_socket_height(type) + thickness + insert_length(insert));
screw_length = screw_length(screw, mains_socket_height(type) + thickness, 0, true, longer = true);
explode(-50)
translate_z(-height - thickness)

View File

@@ -61,53 +61,54 @@ module ssr_shroud_holes(type, cable_d) { //! Drill the screw and ziptie holes
}
module ssr_shroud(type, cable_d, name) { //! Generate the STL file for a specified ssr and cable
stl(str("ssr_shroud_", name));
width = ssr_shroud_width(type);
depth = ssr_length(type) / 3 + ssr_shroud_extent(type, cable_d);
height = ssr_shroud_height(type);
cable_x = ssr_shroud_cable_x(type, cable_d);
center_x = -ssr_length(type) / 6 - depth / 2;
// base and sides
translate([center_x, 0]) {
rounded_rectangle([depth - eps, width - eps, top], rad, center = false);
linear_extrude(height) difference() {
round(or = wall / 2 - eps, ir = 0) difference() {
rounded_square([depth, width], rad);
stl(str("ssr_shroud_", name)) {
// base and sides
translate([center_x, 0]) {
rounded_rectangle([depth - eps, width - eps, top], rad);
rounded_square([depth - 2 * wall, width - 2 * wall], rad - wall);
linear_extrude(height) difference() {
round(or = wall / 2 - eps, ir = 0) difference() {
rounded_square([depth, width], rad);
translate([depth / 2, 0])
square([2 * rad, width], center = true);
rounded_square([depth - 2 * wall, width - 2 * wall], rad - wall);
translate([depth / 2, 0])
square([2 * rad, width], center = true);
}
translate([cable_x - center_x, 0])
square([cable_d, width + 1], center = true);
}
translate([cable_x - center_x, 0])
square([cable_d, width + 1], center = true);
}
}
// cable slots
for(side = [-1, 1])
translate([cable_x, side * (width / 2 - wall / 2), height / 2])
rotate([90, 0, 0])
linear_extrude(wall, center = true)
difference() {
square([cable_d + eps, height], center = true);
// cable slots
for(side = [-1, 1])
translate([cable_x, side * (width / 2 - wall / 2), height / 2])
rotate([90, 0, 0])
linear_extrude(wall, center = true)
difference() {
square([cable_d + eps, height], center = true);
translate([0, height / 2])
vertical_tearslot(h = 0, r = cable_d / 2, l = cable_d);
}
// insert boss
ssr_shroud_hole_positions(type)
vflip()
translate_z(height)
rotate($side * 90)
insert_lug(insert, wall, counter_bore);
translate([0, height / 2])
vertical_tearslot(h = 0, r = cable_d / 2, l = cable_d);
}
// insert boss
ssr_shroud_hole_positions(type)
vflip()
translate_z(height)
rotate($side * 90)
insert_lug(insert, wall, counter_bore);
}
}
module ssr_shroud_assembly(type, cable_d, name) //! The printed parts with inserts fitted
assembly(str("SSR_shroud_", name)) {
assembly(str("SSR_shroud_", name), ngb = true) {
translate_z(ssr_shroud_height(type))
vflip()
@@ -119,8 +120,7 @@ assembly(str("SSR_shroud_", name)) {
module ssr_shroud_fastened_assembly(type, cable_d, thickness, name) //! Assembly with screws in place
{
washer = screw_washer(screw);
screw_length = screw_shorter_than(2 * washer_thickness(washer) + thickness + insert_length(insert) + counter_bore);
screw_length = screw_length(screw, thickness + counter_bore, 2, true);
ssr_shroud_assembly(type, cable_d, name);

View File

@@ -75,32 +75,29 @@ module strap_holes(length, type = strap, h = 100) //! The panel cut outs
strap_boss_shape(type);
module strap(length, type = strap) { //! Generate the STL for the rubber strap
stl("strap");
len = length - 2 * (wall + clearance);
w = strap_width(type);
linear_extrude(strap_thickness(type), convexity = 3)
difference() {
rounded_square([len, w], w / 2 - eps);
stl("strap")
linear_extrude(strap_thickness(type), convexity = 3)
difference() {
rounded_square([len, w], w / 2 - eps);
for(end = [-1, 1])
translate([end * (len / 2 - strap_min_width(type) - strap_boss_r(type) - clearance), 0])
rotate(end * 90 + 90)
hull() {
offset(clearance)
strap_boss_shape(type);
translate([strap_extension(type) / 2, 0])
for(end = [-1, 1])
translate([end * (len / 2 - strap_min_width(type) - strap_boss_r(type) - clearance), 0])
rotate(end * 90 + 90)
hull() {
offset(clearance)
strap_boss_shape(type);
}
}
translate([strap_extension(type) / 2, 0])
offset(clearance)
strap_boss_shape(type);
}
}
}
module strap_end(type = strap) { //! Generate the STL for end piece
stl("strap_end");
z1 = strap_height(type) - strap_thickness(type) - clearance;
z2 = strap_height(type) + strap_key(type);
r1 = strap_boss_r(type) - 1;
@@ -121,48 +118,49 @@ module strap_end(type = strap) { //! Generate the STL for end piece
circle(r1);
}
union() {
linear_extrude(z1)
with_hole()
outer();
translate_z(z1)
linear_extrude(strap_height(type) - z1)
difference() {
stl("strap_end")
union() {
linear_extrude(z1)
with_hole()
outer();
hull() {
translate([0, -strap_width(type) / 2 - clearance])
square([strap_boss_r(type) + overlap, strap_width(type) + 2 * clearance]);
translate_z(z1)
linear_extrude(strap_height(type) - z1)
difference() {
outer();
translate([-strap_extension(type) / 2, 0])
circle(d = strap_width(type) + 2 * clearance);
hull() {
translate([0, -strap_width(type) / 2 - clearance])
square([strap_boss_r(type) + overlap, strap_width(type) + 2 * clearance]);
translate([-strap_extension(type) / 2, 0])
circle(d = strap_width(type) + 2 * clearance);
}
}
}
linear_extrude(strap_height(type) - layer_height)
with_hole()
strap_boss_shape(type);
linear_extrude(strap_height(type) - layer_height)
with_hole()
strap_boss_shape(type);
linear_extrude(z2)
with_hole()
offset(cnc_bit_r)
offset(-step - cnc_bit_r)
strap_boss_shape(type);
linear_extrude(z2)
with_hole()
offset(cnc_bit_r)
offset(-step - cnc_bit_r)
strap_boss_shape(type);
render() difference() {
cylinder(r = r1 + eps, h = z2);
render() difference() {
cylinder(r = r1 + eps, h = z2);
translate_z(z2)
insert_hole(strap_insert(type), counterbore);
translate_z(z2)
insert_hole(strap_insert(type), counterbore);
}
}
}
}
//
//! * Place the insert into the hole and push home with a soldering iron with a tapered bit heated to 200&deg;C.
//
module strap_end_assembly(type = strap)
assembly("strap_end") {
assembly("strap_end", ngb = true) {
stl_colour(pp1_colour)
strap_end(type);
@@ -172,11 +170,9 @@ assembly("strap_end") {
module strap_assembly(length, type = strap) { //! Assembly with screws in place
screw = strap_screw(type);
washer = screw_washer(screw);
penny = penny_washer(washer);
insert = strap_insert(type);
penny = penny_washer(screw_washer(screw));
screw_length = screw_shorter_than(washer_thickness(washer) + washer_thickness(penny) + insert_length(insert) + panel_clearance + counterbore);
screw_length = screw_length(screw, washer_thickness(penny) + panel_clearance + counterbore, 1, true);
stl_colour(pp4_colour) strap(length, type);

325
readme.md
View File

@@ -35,15 +35,15 @@ See [usage](docs/usage.md) for requirements, installation instructions and a usa
<tr><td> <a href = "#Displays">Displays</a> </td><td> <a href = "#Nuts">Nuts</a> </td><td> <a href = "#Spools">Spools</a> </td><td> <a href = "#Handle">Handle</a> </td><td> <a href = "#Rounded_cylinder">Rounded_cylinder</a> </td><td></td></tr>
<tr><td> <a href = "#Extrusion_brackets">Extrusion_brackets</a> </td><td> <a href = "#O_ring">O_ring</a> </td><td> <a href = "#Springs">Springs</a> </td><td> <a href = "#PCB_mount">PCB_mount</a> </td><td> <a href = "#Rounded_polygon">Rounded_polygon</a> </td><td></td></tr>
<tr><td> <a href = "#Extrusions">Extrusions</a> </td><td> <a href = "#Opengrab">Opengrab</a> </td><td> <a href = "#Stepper_motors">Stepper_motors</a> </td><td> <a href = "#PSU_shroud">PSU_shroud</a> </td><td> <a href = "#Rounded_right_triangle">Rounded_right_triangle</a> </td><td></td></tr>
<tr><td> <a href = "#Fans">Fans</a> </td><td> <a href = "#PCB">PCB</a> </td><td> <a href = "#Swiss_clips">Swiss_clips</a> </td><td> <a href = "#Press_fit">Press_fit</a> </td><td> <a href = "#Sector">Sector</a> </td><td></td></tr>
<tr><td> <a href = "#Fuseholder">Fuseholder</a> </td><td> <a href = "#PCBs">PCBs</a> </td><td> <a href = "#Toggles">Toggles</a> </td><td> <a href = "#Printed_box">Printed_box</a> </td><td> <a href = "#Sweep">Sweep</a> </td><td></td></tr>
<tr><td> <a href = "#Geared_steppers">Geared_steppers</a> </td><td> <a href = "#PSUs">PSUs</a> </td><td> <a href = "#Transformers">Transformers</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 = "#Green_terminals">Green_terminals</a> </td><td> <a href = "#Panel_meters">Panel_meters</a> </td><td> <a href = "#Tubings">Tubings</a> </td><td> <a href = "#SSR_shroud">SSR_shroud</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 = "#Pillars">Pillars</a> </td><td> <a href = "#Variacs">Variacs</a> </td><td> <a href = "#Screw_knob">Screw_knob</a> </td><td></td><td></td></tr>
<tr><td> <a href = "#Hygrometer">Hygrometer</a> </td><td> <a href = "#Pin_headers">Pin_headers</a> </td><td> <a href = "#Veroboard">Veroboard</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 = "#Pulleys">Pulleys</a> </td><td> <a href = "#Washers">Washers</a> </td><td> <a href = "#Strap_handle">Strap_handle</a> </td><td></td><td></td></tr>
<tr><td> <a href = "#Inserts">Inserts</a> </td><td></td><td> <a href = "#Wire">Wire</a> </td><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td> <a href = "#Zipties">Zipties</a> </td><td></td><td></td><td></td></tr>
<tr><td> <a href = "#Fans">Fans</a> </td><td> <a href = "#PCB">PCB</a> </td><td> <a href = "#Swiss_clips">Swiss_clips</a> </td><td> <a href = "#Pocket_handle">Pocket_handle</a> </td><td> <a href = "#Sector">Sector</a> </td><td></td></tr>
<tr><td> <a href = "#Fuseholder">Fuseholder</a> </td><td> <a href = "#PCBs">PCBs</a> </td><td> <a href = "#Toggles">Toggles</a> </td><td> <a href = "#Press_fit">Press_fit</a> </td><td> <a href = "#Sweep">Sweep</a> </td><td></td></tr>
<tr><td> <a href = "#Geared_steppers">Geared_steppers</a> </td><td> <a href = "#PSUs">PSUs</a> </td><td> <a href = "#Transformers">Transformers</a> </td><td> <a href = "#Printed_box">Printed_box</a> </td><td> <a href = "#Thread">Thread</a> </td><td></td></tr>
<tr><td> <a href = "#Green_terminals">Green_terminals</a> </td><td> <a href = "#Panel_meters">Panel_meters</a> </td><td> <a href = "#Tubings">Tubings</a> </td><td> <a href = "#Printed_pulleys">Printed_pulleys</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 = "#Pillars">Pillars</a> </td><td> <a href = "#Variacs">Variacs</a> </td><td> <a href = "#Ribbon_clamp">Ribbon_clamp</a> </td><td></td><td></td></tr>
<tr><td> <a href = "#Hygrometer">Hygrometer</a> </td><td> <a href = "#Pin_headers">Pin_headers</a> </td><td> <a href = "#Veroboard">Veroboard</a> </td><td> <a href = "#SSR_shroud">SSR_shroud</a> </td><td></td><td></td></tr>
<tr><td> <a href = "#IECs">IECs</a> </td><td> <a href = "#Pulleys">Pulleys</a> </td><td> <a href = "#Washers">Washers</a> </td><td> <a href = "#Screw_knob">Screw_knob</a> </td><td></td><td></td></tr>
<tr><td> <a href = "#Inserts">Inserts</a> </td><td></td><td> <a href = "#Wire">Wire</a> </td><td> <a href = "#Socket_box">Socket_box</a> </td><td></td><td></td></tr>
<tr><td></td><td></td><td> <a href = "#Zipties">Zipties</a> </td><td> <a href = "#Strap_handle">Strap_handle</a> </td><td></td><td></td></tr>
</table>
---
@@ -288,6 +288,8 @@ Models of radial blowers.
| `blower_screw_holes(type)` | List of XY coordinates of the screw holes |
| `blower_top(type)` | Thickness of the top |
| `blower_wall(type)` | Side wall thickness |
| `blower_wall_left(type)` | Left side wall thickness |
| `blower_wall_right(type)` | Right wall thickness (for square fans) |
| `blower_width(type)` | Width of enclosing rectangle |
### Functions
@@ -311,10 +313,12 @@ Models of radial blowers.
| 1 | `blower(PE4020)` | Blower Pengda Technology 4020 |
| 1 | `blower(RB5015)` | Blower Runda RB5015 |
| 4 | `screw(M2_cap_screw, 8)` | Screw M2 cap x 8mm |
| 2 | `screw(M2_cap_screw, 10)` | Screw M2 cap x 10mm |
| 3 | `screw(M3_cap_screw, 20)` | Screw M3 cap x 20mm |
| 2 | `screw(M4_cap_screw, 25)` | Screw M4 cap x 25mm |
| 1 | `blower(BL40x10)` | Square radial 4010 |
| 4 | `washer(M2_washer)` | Washer M2 x 5mm x 0.3mm |
| 1 | `blower(BL30x10)` | Square radial fan 3010 |
| 1 | `blower(BL40x10)` | Square radial fan 4010 |
| 6 | `washer(M2_washer)` | Washer M2 x 5mm x 0.3mm |
| 3 | `washer(M3_washer)` | Washer M3 x 7mm x 0.5mm |
| 2 | `washer(M4_washer)` | Washer M4 x 9mm x 0.8mm |
@@ -1048,10 +1052,12 @@ Parametric green terminal blocks
### Vitamins
| Qty | Module call | BOM entry |
| ---:|:--- |:---|
| 1 | `green_terminal(gt_6p35, 2)` | Terminal block 2 way 0.25" |
| 1 | `green_terminal(gt_5p08, 3)` | Terminal block 3 way 0.2" |
| 1 | `green_terminal(gt_3p5, 4)` | Terminal block 4 way 3.5mm |
| 1 | `green_terminal(gt_2p54, 5)` | Terminal block 5 way 0.1" |
| 1 | `green_terminal(gt_5x17, 2)` | Terminal block 2 way 5mm |
| 1 | `green_terminal(gt_5x11, 3)` | Terminal block 3 way 5mm |
| 1 | `green_terminal(gt_6p35, 4)` | Terminal block 4 way 0.25" |
| 1 | `green_terminal(gt_5p08, 5)` | Terminal block 5 way 0.2" |
| 1 | `green_terminal(gt_3p5, 6)` | Terminal block 6 way 3.5mm |
| 1 | `green_terminal(gt_2p54, 7)` | Terminal block 7 way 0.1" |
<a href="#top">Top</a>
@@ -1102,17 +1108,17 @@ Needs updating as mostly obsolete versions.
### Vitamins
| Qty | Module call | BOM entry |
| ---:|:--- |:---|
| 2 | `tubing(HSHRNK16)` | Heatshrink sleeving ID 1.6mm x 15mm |
| 2 | `tubing(HSHRNK16)` | Heatshrink sleeving ID 1.6mm x 15mm - not shown |
| 4 | `tubing(HSHRNK64, 60)` | Heatshrink sleeving ID 6.4mm x 60mm |
| 1 | `e3d_hot_end(E3Dv5, 3)` | Hot end E3D V5 direct 3mm |
| 1 | `e3d_hot_end(E3Dv6, 3)` | Hot end E3D V6 direct 3mm |
| 1 | `e3d_hot_end(E3D_clone, 3)` | Hot end E3D clone aliexpress 3mm |
| 1 | `jhead_hot_end(JHeadMk5, 3)` | Hot end JHead MK5 3mm |
| 2 | `tubing(PTFE07, 62)` | PTFE sleeving OD 1.2mm ID 0.71mm x 62mm |
| 2 | `tubing(PTFE20, 45)` | PTFE sleeving OD 2.6mm ID 2mm x 45mm |
| 1 | `resistor(RIE1212UB5C5R6)` | Resistor UB5C 5R6F 5R6 3W vitreous enamel |
| 2 | `tubing(PTFE07, 62)` | PTFE sleeving OD 1.2mm ID 0.71mm x 62mm - not shown |
| 2 | `tubing(PTFE20, 45)` | PTFE sleeving OD 2.6mm ID 2mm x 45mm - not shown |
| 1 | `resistor(RIE1212UB5C5R6)` | Resistor UB5C 5R6F 5R6 3W vitreous enamel - not shown |
| 1 | | Tape self amalgamating silicone 110mm x 25mm |
| 1 | `resistor(Epcos)` | Thermistor Epcos B57560G104F 100K 1% |
| 1 | `resistor(Epcos)` | Thermistor Epcos B57560G104F 100K 1% - not shown |
| 2 | | Wire Red PTFE 16/0.2mm strands, length 170mm |
| 4 | `ziptie(small_ziptie, 8)` | Ziptie 2.5mm x 100mm min length |
@@ -1687,6 +1693,13 @@ Cylindrical and ring magnets.
![magnets](tests/png/magnets.png)
### Vitamins
| Qty | Module call | BOM entry |
| ---:|:--- |:---|
| 1 | `magnet(MAG484)` | Magnet 6.35mm diameter, 6.35mm high, 3.175mm bore |
| 1 | `magnet(MAG8x4x4p2)` | Magnet 8mm diameter, 4mm high, 4.2mm bore |
| 1 | `magnet(MAG5x8)` | Magnet 8mm diameter, 5mm high |
<a href="#top">Top</a>
@@ -1741,7 +1754,11 @@ UK 13A sockets at the moment.
---
<a name="Microswitches"></a>
## Microswitches
Used for limit switches.
Used for limit switches. Currently only the button type is supported as the lever and roller types are less accurate.
The switch is drawn with the button at the nominal operation point. This can be plus or minus `microswitch_op_tol(type)`.
When the button is released it comes out by a maximum of `microswitch_fp_max(type)` from the nominal operating point.
[vitamins/microswitches.scad](vitamins/microswitches.scad) Object definitions.
@@ -1754,14 +1771,16 @@ Used for limit switches.
|:--- |:--- |
| `microswitch_body_clr(type)` | Body colour |
| `microswitch_button_clr(type)` | Button colour |
| `microswitch_button_pos(type)` | Button position |
| `microswitch_button_pos(type)` | Button position at operating point |
| `microswitch_button_t(type)` | Button thickness |
| `microswitch_button_w(type)` | Button width |
| `microswitch_fp_max(type)` | Free position maximum |
| `microswitch_hole_d(type)` | Screw hole diameter |
| `microswitch_holes(type)` | Hole positions |
| `microswitch_leg(type)` | Leg types |
| `microswitch_legs(type)` | Leg positions |
| `microswitch_length(type)` | Body length |
| `microswitch_op_tol(type)` | Operating position +/- tolerance |
| `microswitch_radius(type)` | Body corner radius |
| `microswitch_thickness(type)` | Body thickness |
| `microswitch_width(type)` | Body width |
@@ -1771,6 +1790,7 @@ Used for limit switches.
|:--- |:--- |
| `microswitch_lower_extent(type)` | How far legs extend downwards |
| `microswitch_right_extent(type)` | How far legs extend right |
| `microswitch_size(type)` | Body size |
### Modules
| Module | Description |
@@ -2295,25 +2315,31 @@ PCBs and perfboard with optional components. The shape can be a rectangle with o
| ---:|:--- |:---|
| 1 | `pcb(ArduinoLeonardo)` | Arduino Leonardo |
| 1 | `pcb(ArduinoUno3)` | Arduino Uno R3 |
| 1 | `pcb(BTT_SKR_E3_TURBO)` | BigTreeTech SKR E3 Turbo |
| 1 | `pcb(BTT_SKR_MINI_E3_V2_0)` | BigTreeTech SKR Mini E3 v2.0 |
| 1 | `pcb(BTT_SKR_V1_4_TURBO)` | BigTreeTech SKR v1.4 Turbo |
| 1 | | Cat 5 patch cable 300mm |
| 1 | `d_plug(DCONN15, pcb = true)` | D-type 15 way PCB mount plug |
| 1 | `pcb(DuetE)` | Duet 2 Ethernet electronics |
| 1 | `pcb(Duex2)` | Duex2 expansion board |
| 1 | `pcb(Duex2)` | Duex2 expansion board - not shown |
| 1 | `pcb(Duex5)` | Duex5 expansion board |
| 1 | `pcb(ESP-01)` | ESP-01 |
| 1 | `pcb(EnviroPlus)` | Enviro+ |
| 1 | `pcb(ExtruderPCB)` | Extruder connection PCB |
| 1 | `pcb(Keyes5p1)` | Keyes5.1 Arduino Uno expansion board |
| 1 | `pcb(Keyes5p1)` | Keyes5.1 Arduino Uno expansion board - not shown |
| 1 | `pcb(MP1584EN)` | MP1584EN 3A buck converter |
| 1 | `pcb(MT3608)` | MT3608 boost converter module |
| 1 | `pcb(Melzi)` | Melzi electronics - not shown |
| 4 | | Micro SD card |
| 1 | | Micro SD card - not shown |
| 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 |
| 34 | `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 |
| 30 | `nut(M2p5_nut, nyloc = true)` | Nut M2.5 x 2.2mm nyloc |
| 22 | `nut(M3_nut, nyloc = true)` | Nut M3 x 2.4mm nyloc |
| 8 | `nut(M4_nut, nyloc = true)` | Nut M4 x 3.2mm nyloc |
| 1 | `pcb(PI_IO)` | PI_IO V2 |
| 1 | `pcb(PSU12V1A)` | PSU 12V 1A |
| 1 | `pcb(PSU12V1A)` | PSU 12V 1A - not shown |
| 1 | `pcb(PERF60x40)` | Perfboard 60 x 40mm |
| 1 | `pcb(PERF70x30)` | Perfboard 70 x 30mm |
| 1 | `pcb(PERF70x50)` | Perfboard 70 x 50mm |
@@ -2329,19 +2355,20 @@ PCBs and perfboard with optional components. The shape can be a rectangle with o
| 2 | `screw(M2p5_cap_screw, 20)` | Screw M2.5 cap x 20mm |
| 8 | `screw(M2p5_cap_screw, 25)` | Screw M2.5 cap x 25mm |
| 8 | `screw(M2p5_cap_screw, 30)` | Screw M2.5 cap x 30mm |
| 4 | `screw(M2p5_pan_screw, 20)` | Screw M2.5 pan x 20mm |
| 12 | `screw(M2p5_pan_screw, 25)` | Screw M2.5 pan x 25mm |
| 4 | `screw(M3_cap_screw, 16)` | Screw M3 cap x 16mm |
| 8 | `screw(M3_cap_screw, 30)` | Screw M3 cap x 30mm |
| 12 | `screw(M4_cap_screw, 35)` | Screw M4 cap x 35mm |
| 9 | `screw(M3_cap_screw, 30)` | Screw M3 cap x 30mm |
| 9 | `screw(M3_cap_screw, 35)` | Screw M3 cap x 35mm |
| 8 | `screw(M4_cap_screw, 35)` | Screw M4 cap x 35mm |
| 1 | `pcb(TP4056)` | TP4056 Li-lon Battery charger module |
| 3 | `terminal_35(2)` | Terminal block 2 way 3.5mm |
| 2 | `green_terminal(gt_2p54, 4)` | Terminal block 4 way 0.1" |
| 1 | | USB A to Mini B lead - not shown |
| 1 | `pcb(WD2002SJ)` | WD2002SJ Buck Boost DC-DC converter |
| 16 | `washer(M2_washer)` | Washer M2 x 5mm x 0.3mm |
| 34 | `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 |
| 30 | `washer(M2p5_washer)` | Washer M2.5 x 5.9mm x 0.5mm |
| 22 | `washer(M3_washer)` | Washer M3 x 7mm x 0.5mm |
| 8 | `washer(M4_washer)` | Washer M4 x 9mm x 0.8mm |
| 1 | `pcb(ZC_A0591)` | ZC-A0591 ULN2003 driver PCB |
### Printed
@@ -2351,21 +2378,21 @@ PCBs and perfboard with optional components. The shape can be a rectangle with o
| 4 | pcb_spacer2070.stl |
| 4 | pcb_spacer2080.stl |
| 4 | pcb_spacer2090.stl |
| 4 | pcb_spacer25110.stl |
| 4 | pcb_spacer25120.stl |
| 4 | pcb_spacer25130.stl |
| 4 | pcb_spacer25140_2.stl |
| 4 | pcb_spacer25140.stl |
| 4 | pcb_spacer25150_2.stl |
| 4 | pcb_spacer25160_2.stl |
| 4 | pcb_spacer25180.stl |
| 4 | pcb_spacer25190.stl |
| 4 | pcb_spacer25200.stl |
| 2 | pcb_spacer2580.stl |
| 4 | pcb_spacer30170.stl |
| 4 | pcb_spacer30180.stl |
| 5 | pcb_spacer30200.stl |
| 5 | pcb_spacer30210.stl |
| 4 | pcb_spacer30220.stl |
| 4 | pcb_spacer3050.stl |
| 4 | pcb_spacer40210.stl |
| 4 | pcb_spacer40220.stl |
| 4 | pcb_spacer40230.stl |
| 4 | pcb_spacer40240.stl |
<a href="#top">Top</a>
@@ -2595,8 +2622,8 @@ Timing belt pulleys, both toothed and plain with internal bearings for idlers.
### Modules
| Module | Description |
|:--- |:--- |
| `pulley(type)` | Draw a pulley |
| `pulley_assembly(type)` | Draw a pulley with its grub screws in place |
| `pulley(type, colour = silver)` | Draw a pulley |
| `pulley_assembly(type, colour = silver)` | Draw a pulley with its grub screws in place |
![pulleys](tests/png/pulleys.png)
@@ -2643,13 +2670,15 @@ Linear rails with carriages.
| `carriage_length(type)` | Overall length |
| `carriage_pitch_x(type)` | Screw hole x pitch |
| `carriage_pitch_y(type)` | Screw hole y pitch |
| `carriage_rail(type)` | Rail type |
| `carriage_screw(type)` | Carriage screw type |
| `carriage_width(type)` | Width of carriage |
| `rail_bore(type)` | Counter bore diameter for screw head |
| `rail_bore_depth(type)` | Counter bore depth |
| `rail_carriage(type)` | Carriage type |
| `rail_end(type)` | Minimum distance screw can be from the end |
| `rail_end_screw(type)` | Screw used for ends only (Countersink used for better location) |
| `rail_groove_offset(type)` | Offset of centre of groove from top of rail |
| `rail_groove_width(type)` | Groove width |
| `rail_height(type)` | Height of rail section |
| `rail_hole(type)` | Screw hole diameter |
| `rail_pitch(type)` | Distance between screws |
@@ -2661,27 +2690,26 @@ Linear rails with carriages.
|:--- |:--- |
| `carriage_screw_depth(type)` | Carriage thread depth |
| `carriage_size(type)` | Size of carriage |
| `carriage_travel(type, rail_length)` | How far the carriage can travel on a given length rail |
| `rail_holes(type, length)` | Number of holes in a rail given its `length` |
| `rail_screw_height(type, screw)` | Position screw taking into account countersink into counterbored hole |
| `rail_travel(type, length)` | How far the carriage can travel |
### Modules
| Module | Description |
|:--- |:--- |
| `carriage(type, rail, end_colour = grey(20)` | Draw the specified carriage |
| `carriage(type, end_colour = grey(20)` | 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, carriage_end_colour = grey(20)` | Rail and carriage assembly |
| `rail(type, length, colour = grey(90)` | Draw the specified rail |
| `rail_assembly(carriage, length, pos, carriage_end_colour = grey(20)` | 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 |
| `rail_screws(type, length, thickness, screws = 100, index_screws = undef)` | Place screws in the rail |
![rails](tests/png/rails.png)
### Vitamins
| Qty | Module call | BOM entry |
| ---:|:--- |:---|
| 1 | `rail(MGN12, 200)` | Linear rail MGN12 x 200mm |
| 1 | `rail(MGN12H, 200)` | Linear rail MGN12H x 200mm |
| 2 | `rail(MGN12, 200)` | Linear rail MGN12 x 200mm |
| 1 | `rail(MGN15, 200)` | Linear rail MGN15 x 200mm |
| 1 | `rail(MGN5, 200)` | Linear rail MGN5 x 200mm |
| 1 | `rail(MGN7, 200)` | Linear rail MGN7 x 200mm |
@@ -2889,10 +2917,11 @@ For an explanation of `screw_polysink()` see <https://hydraraptor.blogspot.com/2
|:--- |:--- |
| `screw_boss_diameter(type)` | Boss big enough for nut trap and washer |
| `screw_head_depth(type, d = 0)` | How far a counter sink head will go into a straight hole diameter d |
| `screw_longer_than(x)` | Returns shortest screw length longer or equal to x |
| `screw_length(screw, thickness, washers, insert = false, nyloc = false, nut = false, longer = false)` | Returns the length of the longest or shortest screw that will got through `thickness` and `washers` and possibly an `insert`, `nut` or `nyloc` |
| `screw_longer_than(x)` | Returns the length of the shortest screw length longer or equal to x |
| `screw_nut_radius(type)` | Radius of matching nut |
| `screw_polysink_r(type, z)` | Countersink hole profile corrected for rounded staircase extrusions. |
| `screw_shorter_than(x)` | Returns longest screw length shorter than or equal to x |
| `screw_shorter_than(x)` | Returns the length of the longest screw shorter than or equal to x |
### Modules
| Module | Description |
@@ -2928,6 +2957,7 @@ For an explanation of `screw_polysink()` see <https://hydraraptor.blogspot.com/2
| 1 | `screw(M4_pan_screw, 30)` | Screw M4 pan x 30mm |
| 1 | `screw(M5_cap_screw, 30)` | Screw M5 cap x 30mm |
| 1 | `screw(M5_cs_cap_screw, 30)` | Screw M5 cs cap x 30mm |
| 1 | `screw(M5_dome_screw, 30)` | Screw M5 dome x 30mm |
| 1 | `screw(M5_hex_screw, 30)` | Screw M5 hex x 30mm |
| 1 | `screw(M5_pan_screw, 30)` | Screw M5 pan x 30mm |
| 1 | `screw(M6_cap_screw, 30)` | Screw M6 cap x 30mm |
@@ -3461,15 +3491,16 @@ NEMA stepper motor model.
| Qty | Module call | BOM entry |
| ---:|:--- |:---|
| 4 | `ring_terminal(M3_ringterm)` | Ring terminal 3mm |
| 15 | `screw(M3_pan_screw, 8)` | Screw M3 pan x 8mm |
| 20 | `screw(M3_pan_screw, 8)` | Screw M3 pan x 8mm |
| 1 | `NEMA(NEMA14)` | Stepper motor NEMA14 x 36mm |
| 1 | `NEMA(NEMA16)` | Stepper motor NEMA16 x 19.2mm |
| 1 | `NEMA(NEMA17P)` | Stepper motor NEMA17 x 26.5mm |
| 1 | `NEMA(NEMA17S)` | Stepper motor NEMA17 x 34mm |
| 1 | `NEMA(NEMA17M)` | Stepper motor NEMA17 x 40mm |
| 1 | `NEMA(NEMA17)` | Stepper motor NEMA17 x 47mm |
| 1 | `NEMA(NEMA23)` | Stepper motor NEMA22 x 51.2mm |
| 11 | `washer(M3_washer)` | Washer M3 x 7mm x 0.5mm |
| 15 | `star_washer(M3_washer)` | Washer star M3 x 0.5mm |
| 16 | `washer(M3_washer)` | Washer M3 x 7mm x 0.5mm |
| 20 | `star_washer(M3_washer)` | Washer star M3 x 0.5mm |
<a href="#top">Top</a>
@@ -3767,6 +3798,7 @@ Veroboard with mounting holes, track breaks, removed tracks, solder points and c
| Function | Description |
|:--- |:--- |
| `vero_length(type)` | Length of the board |
| `vero_size(type)` | Board size |
| `vero_thickness(type)` | Thickness of the substrate |
| `vero_track_thickness(type)` | Thickness of the tracks |
| `vero_track_width(type)` | The width of the tracks |
@@ -3780,7 +3812,7 @@ Veroboard with mounting holes, track breaks, removed tracks, solder points and c
| `vero_mounting_hole_positions(type)` | Positions children at the mounting holes |
| `vero_mounting_holes(type, h = 100)` | Drill mounting holes in a panel |
| `veroboard(type)` | Draw specified veroboard with missing tracks and track breaks |
| `veroboard_assembly(type, height, thickness, flip = false)` | Draw the assembly with components and fasteners in place |
| `veroboard_assembly(type, height, thickness, flip = false, ngb = false)` | Draw the assembly with components and fasteners in place |
![veroboard](tests/png/veroboard.png)
@@ -4549,7 +4581,7 @@ to the assembly, for example to add inserts.
### Modules
| Module | Description |
|:--- |:--- |
| `drag_chain_assembly(type, pos = 0)` | Drag chain assembly |
| `drag_chain_assembly(type, pos = 0, render = false)` | Drag chain assembly |
| `drag_chain_link(type, start = false, end = false, check_kids = true)` | One link of the chain, special case for start and end |
| `drag_chain_screw_positions(type, end)` | Place children at the screw positions, end = 0 for the start, 1 for the end |
| `screw_lug(screw, h = 0)` | Create a D shaped lug for a screw |
@@ -4924,6 +4956,56 @@ The stl must be given a parameterless wrapper in the project that uses it.
| 1 | pcb_mount_PI_IO_5.stl |
<a href="#top">Top</a>
---
<a name="Pocket_handle"></a>
## Pocket_handle
Customisable pocket handle
[printed/pocket_handle.scad](printed/pocket_handle.scad) Implementation.
[tests/pocket_handle.scad](tests/pocket_handle.scad) Code for this example.
### Properties
| Function | Description |
|:--- |:--- |
| `pocket_handle_hand_size(type)` | Size of the hole for the fingers |
| `pocket_handle_panel_t(type)` | Thickness of the panel it is mounted in |
| `pocket_handle_rad(type)` | Min corner rad |
| `pocket_handle_screw(type)` | Screw type, can be countersunk or not |
| `pocket_handle_slant(type)` | Upward slant of the hand hole |
| `pocket_handle_wall(type)` | Wall thickness |
### Functions
| Function | Description |
|:--- |:--- |
| `pocket_handle(hand_size = [90, 40, 40], slant = 35, screw = M3_cs_cap_screw, panel_t = 3, wall = 4, rad = 4)` | Construct a pocket_handle property list |
| `pocket_handle_flange(type)` | Size of the flange |
### Modules
| Module | Description |
|:--- |:--- |
| `pocket_handle(type)` | Generate STL for pocket_handle |
| `pocket_handle_assembly(type)` | Assembly with fasteners in place |
| `pocket_handle_hole_positions(type)` | Place children at screw hole positions |
| `pocket_handle_holes(type, h = 0)` | Panel cutout and screw holes |
![pocket_handle](tests/png/pocket_handle.png)
### Vitamins
| Qty | Module call | BOM entry |
| ---:|:--- |:---|
| 4 | `nut(M3_nut, nyloc = true)` | Nut M3 x 2.4mm nyloc |
| 4 | `screw(M3_cs_cap_screw, 12)` | Screw M3 cs cap x 12mm |
| 4 | `washer(M3_washer)` | Washer M3 x 7mm x 0.5mm |
### Printed
| Qty | Filename |
| ---:|:--- |
| 1 | pocket_handle.stl |
<a href="#top">Top</a>
---
@@ -5029,6 +5111,73 @@ It can also have printed feet on the base with the screws doubling up to hold th
| 1 | box2_assembly |
<a href="#top">Top</a>
---
<a name="Printed_pulleys"></a>
## Printed_pulleys
Printed pulleys are a remix of droftarts's (see <https://www.thingiverse.com/droftarts/designs>) Parametric Pulleys
on Thingiverse (see <https://www.thingiverse.com/thing:16627>) and are licensed under the
Creative Commons - Attribution - Share Alike license (see <https://creativecommons.org/licenses/by-sa/3.0/>)
[printed/printed_pulleys.scad](printed/printed_pulleys.scad) Implementation.
[tests/printed_pulleys.scad](tests/printed_pulleys.scad) Code for this example.
### Functions
| Function | Description |
|:--- |:--- |
| `printed_pulley_inverted(type)` | Need to print upside down to prevent overhang |
### Modules
| Module | Description |
|:--- |:--- |
| `printed_pulley(type)` | Draw a printable pulley |
| `printed_pulley_assembly(type, colour = pp1_colour)` | Draw a printed pulley with its grub screws in place |
| `printed_pulley_teeth(type)` | Draw the pulley's teeth |
![printed_pulleys](tests/png/printed_pulleys.png)
### Vitamins
| Qty | Module call | BOM entry |
| ---:|:--- |:---|
| 1 | `screw(M3_grub_screw, 3)` | Screw M3 grub x 3mm |
| 2 | `screw(M3_grub_screw, 4.5)` | Screw M3 grub x 4.5mm |
| 2 | `screw(M3_grub_screw, 4)` | Screw M3 grub x 4mm |
| 4 | `screw(M3_grub_screw, 6)` | Screw M3 grub x 6mm |
| 1 | `screw(M4_grub_screw, 6)` | Screw M4 grub x 6mm |
### Printed
| Qty | Filename |
| ---:|:--- |
| 1 | printed_pulley_GT2x12_pulley.stl |
| 1 | printed_pulley_GT2x16_plain_idler.stl |
| 1 | printed_pulley_GT2x16_pulley.stl |
| 1 | printed_pulley_GT2x16_toothed_idler.stl |
| 1 | printed_pulley_GT2x16x7_plain_idler.stl |
| 1 | printed_pulley_GT2x20_plain_idler.stl |
| 1 | printed_pulley_GT2x20_toothed_idler.stl |
| 1 | printed_pulley_GT2x20ob_pulley.stl |
| 1 | printed_pulley_GT2x20um_pulley.stl |
| 1 | printed_pulley_T2p5x16_pulley.stl |
| 1 | printed_pulley_T5x10_pulley.stl |
### Assemblies
| Qty | Name |
| ---:|:--- |
| 1 | printed_pulley_GT2x12_pulley_assembly |
| 1 | printed_pulley_GT2x16_plain_idler_assembly |
| 1 | printed_pulley_GT2x16_pulley_assembly |
| 1 | printed_pulley_GT2x16_toothed_idler_assembly |
| 1 | printed_pulley_GT2x16x7_plain_idler_assembly |
| 1 | printed_pulley_GT2x20_plain_idler_assembly |
| 1 | printed_pulley_GT2x20_toothed_idler_assembly |
| 1 | printed_pulley_GT2x20ob_pulley_assembly |
| 1 | printed_pulley_GT2x20um_pulley_assembly |
| 1 | printed_pulley_T2p5x16_pulley_assembly |
| 1 | printed_pulley_T5x10_pulley_assembly |
<a href="#top">Top</a>
---
@@ -5727,7 +5876,8 @@ Cylinder with a rounded end.
---
<a name="Rounded_polygon"></a>
## Rounded_polygon
Draw a polygon with rounded corners. Each element of the vector is the XY coordinate and a radius. Radius can be negative for a concave corner.
Draw a polygon with rounded corners. Each element of the vector is the XY coordinate and a radius in clockwise order.
Radius can be negative for a concave corner.
Because the tangents need to be calculated to find the length these can be calculated separately and re-used when drawing to save calculating them twice.
@@ -5738,6 +5888,7 @@ Because the tangents need to be calculated to find the length these can be calcu
### Functions
| Function | Description |
|:--- |:--- |
| `circle_tangent(p1, p2)` | Compute the clockwise tangent between two circles represented as [x,y,r] |
| `rounded_polygon_length(points, tangents)` | Calculate the length given the point list and the list of tangents computed by ` rounded_polygon_tangents` |
| `rounded_polygon_tangents(points)` | Compute the straight sections needed to draw and to compute the lengths |
@@ -5885,6 +6036,7 @@ Simple tube or ring
### Modules
| Module | Description |
|:--- |:--- |
| `rectangular_tube(size, center = true, thickness = 1, fillet = 0.5)` | Create a retangular tube with filleted corners |
| `ring(or, ir)` | Create a ring with specified external and internal radii |
| `tube(or, ir, h, center = true)` | Create a tube with specified external and internal radii and height `h` |
| `woven_tube(or, ir, h, center= true, colour = grey(30)` | Create a woven tube with specified external and internal radii, height `h`, colours, warp and weft |
@@ -5904,9 +6056,23 @@ Assembly views shown in the instructions can be large or small and this is deduc
parts are used.
This heuristic isn't always correct, so the default can be overridden by setting the `big` parameter of `assembly` to `true` or `false`.
Setting the `ngb` parameter of `assembly` to `true` removes its column from the global BOM and merges it parts into its parent assembly column of the global BOM.
This is to prevent the global BOM page becoming too wide in large projects by having it include just the major assemblies.
The example below shows how to define a vitamin and incorporate it into an assembly with sub-assemblies and make an exploded view.
The resulting flat BOM is shown but heirachical BOMs are also generated for real projects.
If the code to make an STL or DXF is made a child of the `stl()` or `dxf()` module then the STL or DXF will be used in the assembly views generated by `views.py` instead of generating
it with code.
This can speed up the generation of the build instructions greatly but isn't compatible with STLs that include support structures.
The `pose()` module allows assembly views in the readme to be posed differently to the default view in the GUI:
* Setting the `exploded` parameter to `true` allows just the exploded version to be posed and setting to `false` allows just the assembled view to be posed, the default is both.
* If the `d` parameter is set to specify the camera distance then the normal `viewall` and `autocenter` options are supressed allowing a small section to be zoomed in to fill the view.
* To get the parameter values make the GUI window square, pose the view with the mouse and then copy the viewport parameters from the Edit menu and paste them into the pose invocation.
* Two `pose()` modules can be chained to allow different poses for exploded and assembled views.
[utils/core/bom.scad](utils/core/bom.scad) Implementation.
[tests/BOM.scad](tests/BOM.scad) Code for this example.
@@ -5923,19 +6089,21 @@ The resulting flat BOM is shown but heirachical BOMs are also generated for real
### Modules
| Module | Description |
|:--- |:--- |
| `assembly(name, big = undef)` | Name an assembly that will appear on the BOM, there needs to a module named `<name>_assembly` to make it. `big` can force big or small assembly diagrams. |
| `assembly(name, big = undef, ngb = false)` | Name an assembly that will appear on the BOM, there needs to a module named `<name>_assembly` to make it. `big` can force big or small assembly diagrams. |
| `dxf(name)` | Name a dxf that will appear on the BOM, there needs to a module named `<name>_dxf` to make it |
| `explode(d, explode_children = false, offset = [0,0,0])` | Explode children by specified Z distance or vector `d`, option to explode grand children |
| `hidden()` | Make item invisible, except on the BOM |
| `no_explode()` | Prevent children being exploded |
| `no_pose()` | Force children not to be posed even if parent is |
| `not_on_bom(on = false)` | Specify the following child parts are not on the BOM, for example when they are on a PCB that comes assembled |
| `pose(a = [55, 0, 25], t = [0, 0, 0], exploded = undef)` | Pose an STL or assembly for rendering to png by specifying rotation `a` and translation `t`, `exploded = true for` just the exploded view or `false` for unexploded only. |
| `pose(a = [55, 0, 25], t = [0, 0, 0], exploded = undef, d = undef)` | Pose an STL or assembly for rendering to png by specifying rotation `a`, translation `t` and optionally `d`, `exploded = true for` just the exploded view or `false` for unexploded only. |
| `pose_hflip(exploded = undef)` | Pose an STL or assembly for rendering to png by flipping around the Y axis, `exploded = true for` just the exploded view or `false` for unexploded only. |
| `pose_vflip(exploded = undef)` | Pose an STL or assembly for rendering to png by flipping around the X axis, `exploded = true for` just the exploded view or `false` for unexploded only. |
| `stl(name)` | Name an stl that will appear on the BOM, there needs to a module named `<name>_stl` to make it |
| `stl_colour(colour = pp1_colour, alpha = 1)` | Colour an stl where it is placed in an assembly. `alpha` can be used to make it appear transparent. |
| `vitamin(description)` | Describe a vitamin for the BOM entry and precede it with a module call that creates it, eg. "wigit(42): Type 42 widget" |
| `use_dxf(name)` | Import a DXF to make a build panel |
| `use_stl(name)` | Import an STL to make a build platter |
| `vitamin(description)` | Describe a vitamin for the BOM entry and precede it with a module call that creates it, eg. "widget(42): Widget size 42" |
![bom](tests/png/bom.png)
@@ -5962,9 +6130,9 @@ The resulting flat BOM is shown but heirachical BOMs are also generated for real
### Assemblies
| Qty | Name |
| ---:|:--- |
| 1 | widget_assembly |
| 1 | widget_base_assembly |
| 1 | widget_top_assembly |
| 1 | widgit_base_assembly |
| 1 | wigdit_assembly |
<a href="#top">Top</a>
@@ -6062,18 +6230,18 @@ leaving a scar on either surface.
### Functions
| Function | Description |
|:--- |:--- |
| `corrected_diameter(d, n = 0)` | Adjusted diameter to make flats lie on the circle |
| `corrected_radius(r, n = 0)` | Adjusted radius to make flats lie on the circle |
| `sides(r)` | Optimium number of sides for specified radius |
| `corrected_diameter(d, n = undef)` | Adjusted diameter to make flats lie on the circle |
| `corrected_radius(r, n = undef)` | Adjusted radius to make flats lie on the circle |
| `sides(r, n = undef)` | Optimium number of sides for specified radius |
### Modules
| Module | Description |
|:--- |:--- |
| `drill(r, h = 100, center = true)` | Make a cylinder for drilling holes suitable for CNC routing, set h = 0 for circle |
| `poly_circle(r, sides = 0)` | Make a circle adjusted to print the correct size |
| `poly_cylinder(r, h, center = false, sides = 0, chamfer = false, twist = 0)` | Make a cylinder adjusted to print the correct size |
| `poly_circle(r, sides = undef)` | Make a circle adjusted to print the correct size |
| `poly_cylinder(r, h, center = false, sides = undef, chamfer = false, twist = 0)` | Make a cylinder adjusted to print the correct size |
| `poly_drill(r, h = 100, center = true)` | Make a cylinder for drilling holes suitable for CNC routing if cnc_bit_r is non zero, otherwise a poly_cylinder. |
| `poly_ring(or, ir, sides = 0)` | Make a 2D ring adjusted to have the correct internal radius |
| `poly_ring(or, ir, sides = undef)` | Make a 2D ring adjusted to have the correct internal radius |
| `poly_tube(or, ir, h, center = false)` | Make a tube adjusted to have the correct internal radius |
| `slot(r, l, h = 100)` | Make a horizontal slot suitable for CNC routing, set h = 0 for 2D version |
@@ -6125,9 +6293,10 @@ Rectangle with rounded corners.
### Modules
| Module | Description |
|:--- |:--- |
| `rounded_rectangle(size, r, center = true, xy_center = true)` | Like `cube()` but corners rounded in XY plane and separate centre options for xy and z. |
| `rounded_rectangle_xz(size, r, center = true, xy_center = true)` | Like `cube()` but corners rounded in XZ plane and separate centre options for xy and z. |
| `rounded_rectangle_yz(size, r, center = true, xy_center = true)` | Like `cube()` but corners rounded in YX plane and separate centre options for xy and z. |
| `rounded_cube_xy(size, r = 0, xy_center = false, z_center = false)` | Like `cube()` but corners rounded in XY plane and separate centre options for xy and z. |
| `rounded_cube_xz(size, r = 0, xy_center = false, z_center = false)` | Like `cube()` but corners rounded in XZ plane and separate centre options for xy and z. |
| `rounded_cube_yz(size, r = 0, xy_center = false, z_center = false)` | Like `cube()` but corners rounded in YX plane and separate centre options for xy and z. |
| `rounded_rectangle(size, r, center = false, xy_center = true)` | Like `cube()` but corners rounded in XY plane and separate centre options for xy and z. |
| `rounded_square(size, r, center = true)` | Like `square()` but with with rounded corners |
![rounded_rectangle](tests/png/rounded_rectangle.png)
@@ -6171,12 +6340,12 @@ do not intrude into the circle. See <https://hydraraptor.blogspot.com/2020/07/ho
### Modules
| Module | Description |
|:--- |:--- |
| `semi_teardrop(h, r, d = undef, center = true, chamfer = 0, plus = false)` | A semi teardrop in the positive Y domain |
| `teardrop(h, r, center = true, truncate = true, chamfer = 0, plus = false)` | For making horizontal holes that don't need support material, set `truncate = false` to make traditional RepRap teardrops that don't even need bridging |
| `teardrop_chamfer(h, center, chamfer)` | Helper module for adding chamfer to a teardrop |
| `teardrop_plus(h, r, center = true, truncate = true, chamfer = 0)` | Slightly elongated teardrop to allow for the 3D printing staircase effect |
| `tearslot(h, r, w, center = true, chamfer = 0, plus = false)` | A horizontal slot that doesn't need support material |
| `vertical_tearslot(h, r, l, center = true, chamfer = 0, plus = false)` | A vertical slot that doesn't need support material |
| `semi_teardrop(h, r, d = undef, center = true, chamfer = 0, chamfer_both_ends = true, plus = false)` | A semi teardrop in the positive Y domain |
| `teardrop(h, r, center = true, truncate = true, chamfer = 0, chamfer_both_ends = true, plus = false)` | For making horizontal holes that don't need support material, set `truncate = false` to make traditional RepRap teardrops that don't even need bridging |
| `teardrop_chamfer(h, center, chamfer, chamfer_both_ends)` | Helper module for adding chamfer to a teardrop |
| `teardrop_plus(h, r, center = true, truncate = true, chamfer = 0, chamfer_both_ends = true)` | Slightly elongated teardrop to allow for the 3D printing staircase effect |
| `tearslot(h, r, w, center = true, chamfer = 0, chamfer_both_ends = true, plus = false)` | A horizontal slot that doesn't need support material |
| `vertical_tearslot(h, r, l, center = true, chamfer = 0, chamfer_both_ends = true, plus = false)` | A vertical slot that doesn't need support material |
![teardrops](tests/png/teardrops.png)

View File

@@ -60,6 +60,8 @@ class BOM:
def __init__(self, name):
self.name = name
self.big = None
self.ngb = False
self.zoomed = 0
self.count = 1
self.vitamins = {}
self.printed = {}
@@ -73,6 +75,8 @@ class BOM:
return {
"name" : self.name,
"big" : self.big,
"ngb" : self.ngb,
"zoomed" : self.zoomed,
"count" : self.count,
"assemblies" : assemblies,
"vitamins" : {v : self.vitamins[v].data() for v in self.vitamins},
@@ -249,7 +253,7 @@ def boms(target = None, assembly = None):
#
# Run openscad
#
openscad.run("-D", "$bom=2", "-D", "$preview=true", "--hardwarnings", "-o", "openscad.echo", "-d", bom_dir + "/bom.deps", bom_maker_name)
openscad.run("-D", "$bom=2", "-D", "$preview=true", "-o", "openscad.echo", "-d", bom_dir + "/bom.deps", bom_maker_name)
os.remove(bom_maker_name)
print("Generating bom ...", end=" ")

View File

@@ -18,6 +18,7 @@
#
import os
from set_config import source_dir
from colorama import Fore
def mtime(file):
if os.path.isfile(file):
@@ -41,13 +42,13 @@ def read_deps(dname):
def check_deps(target, dname):
target_mtime = mtime(target)
if not target_mtime:
return target + " missing"
return Fore.CYAN + target + " missing" + Fore.WHITE
if not os.path.isfile(dname):
return "no deps"
return Fore.CYAN + "no deps" + Fore.WHITE
deps = read_deps(dname)
for dep in deps:
if mtime(dep) > target_mtime:
return dep + ' changed'
return Fore.CYAN + dep + ' changed' + Fore.WHITE
return None
def source_dirs(bom_dir):

View File

@@ -28,7 +28,10 @@ from set_config import *
import time
import times
from deps import *
from tmpdir import *
import json
import shutil
from colorama import Fore, init
def bom_to_parts(bom_dir, part_type, assembly = None):
#
@@ -43,7 +46,7 @@ def bom_to_parts(bom_dir, part_type, assembly = None):
if words:
last_word = words[-1]
if last_word.endswith(suffix):
part_files.append(last_word[:-4] + '.' + part_type)
part_files.append(last_word[:-4] + '.' + part_type)
return part_files
def usage(t):
@@ -62,20 +65,29 @@ def make_parts(target, part_type, parts = None):
#
top_dir = set_config(target, lambda: usage(part_type))
target_dir = top_dir + part_type + 's'
deps_dir = top_dir + "deps"
deps_dir = target_dir + "/deps"
bom_dir = top_dir + "bom"
tmp_dir = mktmpdir(top_dir)
if not os.path.isdir(target_dir):
os.makedirs(target_dir)
if not os.path.isdir(deps_dir):
os.makedirs(deps_dir)
old_deps = top_dir + 'deps' #old location
if os.path.isdir(old_deps):
shutil.rmtree(old_deps)
times.read_times(target_dir)
#
# Decide which files to make
#
all_parts = bom_to_parts(bom_dir, part_type)
if parts:
targets = list(parts) #copy the list so we dont modify the list passed in
else:
targets = bom_to_parts(bom_dir, part_type)
targets = list(all_parts)
for file in os.listdir(target_dir):
if file.endswith('.' + part_type):
if not file in targets:
@@ -119,15 +131,15 @@ def make_parts(target, part_type, parts = None):
changed = check_deps(part_file, dname)
changed = times.check_have_time(changed, part)
if part_type == 'stl' and not changed and not part in bounds_map:
changed = "No bounds"
changed = Fore.CYAN + "No bounds" + Fore.WHITE
if changed:
print(changed)
#
# make a file to use the module
#
part_maker_name = part_type + ".scad"
part_maker_name = tmp_dir + '/' + part_type + ".scad"
with open(part_maker_name, "w") as f:
f.write("use <%s/%s>\n" % (dir, filename))
f.write("use <%s/%s>\n" % (reltmp(dir, target), filename))
f.write("%s();\n" % module);
t = time.time()
openscad.run("-D$bom=1", "-d", dname, "-o", part_file, part_maker_name)
@@ -144,10 +156,14 @@ def make_parts(target, part_type, parts = None):
with open(bounds_fname, 'w') as outfile:
json.dump(bounds_map, outfile, indent = 4)
#
# Remove tmp dir
#
rmtmpdir(tmp_dir)
#
# List the ones we didn't find
#
if targets:
for part in targets:
print("Could not find a module called", part[:-4] + module_suffix, "to make", part)
usage(part_type)
times.print_times()
times.print_times(all_parts)

View File

@@ -68,9 +68,10 @@ def gallery(force):
match = re.match(r"^(#+).*$", line)
if match:
line = '#' + line
if line == '---\n':
break;
print(line[:-1], file = output_file)
if line == '---\n' or line == '<span></span>\n':
break
if line != '<a name="TOP"></a>\n':
print(line[:-1], file = output_file)
else:
print(Fore.MAGENTA + "Can't find", document, Fore.WHITE);
with open(target_dir + "/readme.html", "wt") as html_file:

View File

@@ -25,19 +25,25 @@ from __future__ import print_function
import subprocess, sys
def run_list(args, silent = False, verbose = False):
cmd = ["openscad.exe"] + args
cmd = ["openscad", "--hardwarnings"] + args
if not silent:
for arg in cmd:
print(arg, end=" ")
print()
with open("openscad.log", "w") as log:
rc = subprocess.call(cmd, stdout = log, stderr = log)
for line in open("openscad.log", "rt"):
log_file = "openscad.echo" if "openscad.echo" in cmd else "openscad.log"
bad = False
for line in open(log_file, "rt"):
if verbose or 'ERROR:' in line or 'WARNING:' in line:
bad = True
print(line[:-1])
if rc:
sys.exit(rc)
if bad:
sys.exit(1)
def run(*args):
run_list(list(args), False)

View File

@@ -20,6 +20,7 @@
# Set command line options from enviroment variables and check if they have changed
import json, os, deps
from colorama import Fore, init
def check_options(dir = '.'):
global options, options_mtime
@@ -37,7 +38,7 @@ def check_options(dir = '.'):
def have_changed(changed, target):
if not changed and deps.mtime(target) < options_mtime:
return "command line options changed"
return Fore.CYAN + "command line options changed" + Fore.WHITE
return changed
def list():

View File

@@ -26,8 +26,10 @@ import sys
import c14n_stl
from set_config import *
from deps import *
from shutil import copyfile
import shutil
import re
import time
import times
source_dirs = { "stl" : "platters", "dxf" : "panels" }
target_dirs = { "stl" : "printed", "dxf" : "routed" }
@@ -41,11 +43,14 @@ def plateup(target, part_type, usage = None):
target_dir = parts_dir + '/' + target_dirs[part_type]
source_dir1 = source_dirs[part_type]
source_dir2 = top_dir + source_dirs[part_type]
times.read_times(target_dir)
#
# Loop through source directories
#
used = []
all_used = []
all_sources = []
all_parts = []
for dir in [source_dir1, source_dir2]:
if not os.path.isdir(dir):
continue
@@ -54,9 +59,12 @@ def plateup(target, part_type, usage = None):
#
# Make the deps dir
#
deps_dir = dir + "/deps"
deps_dir = parts_dir + "/deps"
if not os.path.isdir(deps_dir):
os.makedirs(deps_dir)
if os.path.isdir(dir + '/deps'): #old deps
shutil.rmtree(dir + '/deps')
#
# Decide which files to make
#
@@ -65,40 +73,55 @@ def plateup(target, part_type, usage = None):
#
# Run OpenSCAD on the source files to make the targets
#
target_def = ['-D$target="%s"' % target] if target else []
cwd_def = ['-D$cwd="%s"' % os.getcwd().replace('\\', '/')]
for src in sources:
src_file = dir + '/' + src
part_file = target_dir + '/' + src[:-4] + part_type
part = src[:-4] + part_type
all_parts.append(part)
part_file = target_dir + '/' + part
uses_file = deps_dir + '/' + src[:-4] + 'txt'
dname = deps_name(deps_dir, src)
changed = check_deps(part_file, dname)
oldest = part_file if mtime(part_file) < mtime(uses_file) else uses_file
changed = check_deps(oldest, dname)
used = []
if changed:
print(changed)
openscad.run("-D$bom=1", "-d", dname, "-o", part_file, src_file)
t = time.time()
openscad.run_list(["-D$bom=1"] + target_def + cwd_def + ["-d", dname, "-o", part_file, src_file])
if part_type == 'stl':
c14n_stl.canonicalise(part_file)
times.add_time(part, t)
log_name = 'openscad.log'
#
# Add the files on the BOM to the used list
#
with open(log_name) as file:
for line in file.readlines():
match = re.match(r'^ECHO: "~(.*?\.' + part_type + r').*"$', line)
if match:
used.append(match.group(1))
with open(uses_file, "wt") as file:
for part in used:
print(part, file = file)
else:
log_name = 'openscad.echo'
openscad.run_silent("-D$bom=1", "-o", log_name, src_file)
#
# Add the files on the BOM to the used list
#
with open(log_name) as file:
for line in file.readlines():
match = re.match(r'^ECHO: "~(.*?\.' + part_type + r').*"$', line)
if match:
used.append(match.group(1))
with open(uses_file, "rt") as file:
for line in file:
used.append(line[:-1])
all_used += used
copied = []
if all_sources:
#
# Copy files that are not included
#
for file in os.listdir(parts_dir):
if file.endswith('.' + part_type) and not file in used:
if file.endswith('.' + part_type) and not file in all_used:
src = parts_dir + '/' + file
dst = target_dir + '/' + file
if mtime(src) > mtime(dst):
print("Copying %s to %s" % (src, dst))
copyfile(src, dst)
shutil.copyfile(src, dst)
copied.append(file)
#
# Remove any cruft
@@ -109,3 +132,12 @@ def plateup(target, part_type, usage = None):
if not file in targets and not file in copied:
print("Removing %s" % file)
os.remove(target_dir + '/' + file)
targets = [file[:-4] + 'txt' for file in all_sources]
for file in os.listdir(deps_dir):
if file.endswith('.' + 'txt'):
if not file in targets:
print("Removing %s" % file)
os.remove(deps_dir + '/' + file)
times.print_times(all_parts)

View File

@@ -30,6 +30,7 @@ from tests import do_cmd, update_image, colour_scheme, background
from deps import mtime
from colorama import init
import json
from tmpdir import *
def usage():
print("\nusage:\n\trender [target_config] - Render images of the stl and dxf files.");
@@ -40,6 +41,7 @@ def render(target, type):
# Make the target directory
#
top_dir = set_config(target, usage)
tmp_dir = mktmpdir(top_dir)
target_dir = top_dir + type + 's'
bom_dir = top_dir + 'bom'
if not os.path.isdir(target_dir):
@@ -80,7 +82,7 @@ def render(target, type):
# make a file to import the stl
#
if mtime(part_file) > mtime(png_name):
png_maker_name = "png.scad"
png_maker_name = tmp_dir + "/png.scad"
pp1 = [0, 146/255, 0]
colour = pp1
if part in colours:
@@ -88,15 +90,19 @@ def render(target, type):
if not '[' in colour:
colour = '"' + colour + '"'
with open(png_maker_name, "w") as f:
f.write('color(%s) import("%s");\n' % (colour, part_file))
f.write('color(%s) import("%s");\n' % (colour, reltmp(part_file, target)))
cam = "--camera=0,0,0,70,0,315,500" if type == 'stl' else "--camera=0,0,0,0,0,0,500"
render = "--preview" if type == 'stl' or colour != pp1 else "--render"
tmp_name = 'tmp.png'
tmp_name = tmp_dir + '/' + part[:-4] + '.png'
openscad.run(colour_scheme, "--projection=p", "--imgsize=4096,4096", cam, render, "--autocenter", "--viewall", "-o", tmp_name, png_maker_name);
do_cmd(("magick "+ tmp_name + " -trim -resize 280x280 -background %s -gravity Center -extent 280x280 -bordercolor %s -border 10 %s"
% (background, background, tmp_name)).split())
update_image(tmp_name, png_name)
os.remove(png_maker_name)
#
# Remove tmp dir
#
rmtmpdir(tmp_dir)
if __name__ == '__main__':
init()

View File

@@ -69,17 +69,22 @@ def set_config(target, usage = None):
sys.exit(1)
fname = source_dir + "/target.scad"
text = "include <config_%s.scad>\n" % target;
line = ""
text = ['include <config_%s.scad>\n' % target,
'$target = "%s";\n' % target,
'$cwd="%s";\n' % os.getcwd().replace('\\', '/')
]
lines = [""]
try:
with open(fname,"rt") as f:
line = f.read()
lines = f.readlines()
except:
pass
if line != text:
if lines != text:
with open(fname,"wt") as f:
f. write(text);
for t in text:
f. write(t);
return target + "/"
def usage():

View File

@@ -34,6 +34,7 @@ import shutil
from deps import *
from blurb import *
from colorama import Fore
from tmpdir import *
w = 4096
h = w
@@ -50,13 +51,16 @@ def do_cmd(cmd, output = sys.stdout):
return subprocess.call(cmd, stdout = output, stderr = output)
def compare_images(a, b, c):
if not os.path.isfile(b):
print(Fore.MAGENTA + "Failed to generate %s while making %s" % (b, a), Fore.WHITE)
sys.exit(1)
if not os.path.isfile(a):
return -1
log_name = 'magick.log'
with open(log_name, 'w') as output:
do_cmd(("magick compare -metric AE -fuzz %d%% %s %s %s" % (fuzz, a, b, c)).split(), output = output)
with open(log_name, 'r') as f:
pixels = int(f.read().strip())
pixels = int(float(f.read().strip()))
os.remove(log_name)
return pixels
@@ -91,6 +95,7 @@ def usage():
def tests(tests):
scad_dir = "tests"
tmp_dir = mktmpdir(scad_dir + '/')
deps_dir = scad_dir + "/deps"
png_dir = scad_dir + "/png"
bom_dir = scad_dir + "/bom"
@@ -126,14 +131,13 @@ def tests(tests):
#
# List of individual part files
#
scads = [i for i in sorted(os.listdir(scad_dir), key = lambda s: s.lower()) if i[-5:] == ".scad"]
types = []
for scad in scads:
base_name = scad[:-5]
if not tests or base_name in tests:
done.append(base_name)
print('\n'+base_name)
print(base_name)
cap_name = base_name[0].capitalize() + base_name[1:]
base_name = base_name.lower()
scad_name = scad_dir + '/' + scad
@@ -232,7 +236,7 @@ def tests(tests):
if changed:
print(changed)
t = time.time()
tmp_name = 'tmp.png'
tmp_name = tmp_dir + '/tmp.png'
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])
@@ -240,6 +244,7 @@ def tests(tests):
BOM = bom.parse_bom()
with open(bom_name, 'wt') as outfile:
json.dump(BOM.flat_data(), outfile, indent = 4)
print()
with open(bom_name, "rt") as bom_file:
BOM = json.load(bom_file)
@@ -300,6 +305,11 @@ def tests(tests):
with open(doc_base_name + ".html", "wt") as html_file:
do_cmd(("python -m markdown -x tables " + doc_name).split(), html_file)
times.print_times()
#
# Remove tmp dir
#
rmtmpdir(tmp_dir)
do_cmd(('codespell -L od ' + doc_name).split())
if __name__ == '__main__':

View File

@@ -44,7 +44,7 @@ def got_time(name):
def check_have_time(changed, name):
if not changed and not got_time(name):
changed = "no previous time"
changed = Fore.CYAN + "no previous time" + Fore.WHITE
return changed
def add_time(name, start):
@@ -52,23 +52,34 @@ def add_time(name, start):
del times[name.lower()]
times[name] = round(time.time() - start, 3)
def print_times():
write_times()
def print_times(files = None):
sorted_times = sorted(times.items(), key=lambda kv: kv[1])
total = 0
old_total = 0
for entry in sorted_times:
colour = Fore.WHITE
key = entry[0]
new = entry[1]
delta = 0
if key in last_times:
old = last_times[key]
delta = new - old
if delta > 0.3:
colour = Fore.RED
if delta < -0.3:
colour = Fore.GREEN
print(colour + "%5.1f %5.1f %s" % (new, delta, key))
total += new
if files and not key in files:
del times[key]
else:
new = entry[1]
delta = 0
colour = Fore.WHITE
if key in last_times:
old = last_times[key]
old_total += old
delta = new - old
if delta > 0.3:
colour = Fore.RED
if delta < -0.3:
colour = Fore.GREEN
print(colour + "%6.1f %5.1f %s" % (new, delta, key))
total += new
write_times()
if sorted_times:
print(Fore.WHITE + "%5.1f" % total)
colour = Fore.WHITE
delta = total - old_total
if delta > 1:
colour = Fore.RED
if delta < -1:
colour = Fore.GREEN
print(colour + "%6.1f %5.1f TOTAL%s" % (total, delta, Fore.WHITE))

40
scripts/tmpdir.py Normal file
View File

@@ -0,0 +1,40 @@
#
# NopSCADlib Copyright Chris Palmer 2021
# 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/>.
#
"""
Make a directory for tmp files.
"""
import os
import time
def mktmpdir(top_dir):
tmp_dir = top_dir + 'tmp'
if not os.path.isdir(tmp_dir):
os.makedirs(tmp_dir)
else:
for file in os.listdir(tmp_dir):
os.remove(tmp_dir + '/' + file)
return tmp_dir
def reltmp(dir, target):
return dir if os.path.isabs(dir) else '../../' + dir if target else '../' + dir
def rmtmpdir(tmp_dir):
os.rmdir(tmp_dir)
while os.path.isdir(tmp_dir):
time.sleep(0.1)

View File

@@ -36,7 +36,9 @@ import blurb
import bom
import shutil
import re
import copy
from colorama import Fore
from tmpdir import *
def is_assembly(s):
return s[-9:] == '_assembly' or s[-11:] == '_assemblies'
@@ -74,19 +76,17 @@ def bom_to_assemblies(bom_dir, bounds_map):
# Remove the main assembly if it is a shell
#
if flat_bom:
ass = flat_bom[-1]
ass = flat_bom[-1]
if len(ass["assemblies"]) < 2 and not ass["vitamins"] and not ass["printed"] and not ass["routed"]:
flat_bom = flat_bom[:-1]
return [assembly["name"] for assembly in flat_bom]
def eop(print_mode, doc_file, last = False, first = False):
if print_mode:
print('\n<div style="page-break-after: always;"></div>', file = doc_file)
else:
if not first:
print('[Top](#TOP)', file = doc_file)
if not last:
print("\n---", file = doc_file)
def eop(doc_file, last = False, first = False):
print('<span></span>', file = doc_file) # An invisable marker for page breaks because markdown takes much longer if the document contains a div
if not first:
print('[Top](#TOP)', file = doc_file)
if not last:
print("\n---", file = doc_file)
def pad(s, before, after = 0):
return '&nbsp;' * before + str(s) + '&nbsp;' * after
@@ -103,14 +103,36 @@ def usage():
print("\nusage:\n\t views [target_config] [<name1>_assembly] ... [<nameN>_assembly] - Create assembly images and readme.")
sys.exit(1)
types = ["vitamins", "printed", "routed"]
def merged(bom):
bom = copy.deepcopy(bom)
for aname in bom["assemblies"]:
count = bom["assemblies"][aname]
for ass in flat_bom:
if ass['name'] == aname and ass['ngb']:
merged_assembly = merged(ass)
total = ass['count']
for t in types:
for thing in merged_assembly[t]:
items = merged_assembly[t][thing]['count'] * count // total
if thing in bom[t]:
bom[t][thing]['count'] += items
else:
bom[t][thing] = merged_assembly[t][thing]
bom[t][thing]['count'] = items
break
return bom
def views(target, do_assemblies = None):
done_assemblies = []
#
# Make the target directory
#
top_dir = set_config(target, usage)
tmp_dir = mktmpdir(top_dir)
target_dir = top_dir + 'assemblies'
deps_dir = top_dir + "deps"
deps_dir = target_dir + "/deps"
bom_dir = top_dir + "bom"
if not os.path.isdir(target_dir):
os.makedirs(target_dir)
@@ -139,6 +161,7 @@ def views(target, do_assemblies = None):
# Find all the scad files
#
main_blurb = None
pngs = []
for dir in source_dirs(bom_dir):
if os.path.isdir(dir):
for filename in os.listdir(dir):
@@ -162,33 +185,43 @@ def views(target, do_assemblies = None):
#
for ass in flat_bom:
if ass["name"] == real_name:
zoomed = ass['zoomed']
if not "blurb" in ass:
ass["blurb"] = blurb.scrape_module_blurb(lines[:line_no])
break
if not do_assemblies or real_name in do_assemblies:
#
# Run openscad on the created file
#
dname = deps_name(deps_dir, filename)
for explode in [0, 1]:
#
# Run openscad on the created file
# Generate png name
#
dname = deps_name(deps_dir, filename)
for explode in [0, 1]:
png_name = target_dir + '/' + real_name + '.png'
if not explode:
png_name = png_name.replace('_assembly', '_assembled')
png_name = target_dir + '/' + real_name + '.png'
if not explode:
png_name = png_name.replace('_assembly', '_assembled')
pngs.append(png_name)
if not do_assemblies or real_name in do_assemblies:
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'
tmp_name = tmp_dir + '/' + real_name + '.png'
if changed:
print(changed)
#
# make a file to use the module
#
png_maker_name = 'png.scad'
png_maker_name = tmp_dir + '/png.scad'
with open(png_maker_name, "w") as f:
f.write("use <%s/%s>\n" % (dir, filename))
f.write("use <%s/%s>\n" % (reltmp(dir, target), filename))
f.write("%s();\n" % module);
t = time.time()
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]);
target_def = ['-D$target="%s"' % target] if target else []
cwd_def = ['-D$cwd="%s"' % os.getcwd().replace('\\', '/')]
view_def = ['--viewall', '--autocenter'] if not (zoomed & (1 << explode)) else ['--camera=0,0,0,55,0,25,140']
openscad.run_list(options.list() + target_def + cwd_def + view_def +["-D$pose=1", "-D$explode=%d" % explode, colour_scheme, "--projection=p", "--imgsize=4096,4096", "-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)
@@ -202,193 +235,221 @@ def views(target, do_assemblies = None):
if module == 'main_assembly':
main_blurb = blurb.scrape_module_blurb(lines[:line_no])
line_no += 1
times.print_times()
#
# Build the document
#
for print_mode in [True, False]:
doc_name = top_dir + "readme.md"
with open(doc_name, "wt") as doc_file:
#
# Title, description and picture
#
project = ' '.join(word[0].upper() + word[1:] for word in os.path.basename(os.getcwd()).split('_'))
print('<a name="TOP"></a>\n# %s' % project, file = doc_file)
main_file = bom.find_scad_file('main_assembly')
if not main_file:
raise Exception("can't find source for main_assembly")
text = blurb.scrape_blurb(source_dir + '/' + main_file)
blurbs = blurb.split_blurb(text)
if len(text):
print(blurbs[0], file = doc_file)
else:
if print_mode:
print(Fore.MAGENTA + "Missing project description" + Fore.WHITE)
#
# Only add the image if the first blurb section doesn't contain one.
#
if not re.search(r'\!\[.*\]\(.*\)', blurbs[0], re.MULTILINE):
print('![Main Assembly](assemblies/%s.png)\n' % flat_bom[-1]["name"].replace('_assembly', '_assembled'), file = doc_file)
eop(print_mode, doc_file, first = True)
#
# Build TOC
#
print('## Table of Contents', file = doc_file)
print('1. [Parts list](#Parts_list)', file = doc_file)
for ass in flat_bom:
name = ass["name"]
cap_name = titalise(name)
print('1. [%s](#%s)' % (cap_name, name), file = doc_file)
print(file = doc_file)
if len(blurbs) > 1:
print(blurbs[1], file = doc_file)
eop(print_mode, doc_file)
#
# Global BOM
#
print('<a name="Parts_list"></a>\n## Parts list', file = doc_file)
types = ["vitamins", "printed", "routed"]
headings = {"vitamins" : "vitamins", "printed" : "3D printed parts", "routed" : "CNC routed parts"}
things = {}
doc_name = top_dir + "readme.md"
with open(doc_name, "wt") as doc_file:
#
# Title, description and picture
#
project = ' '.join(word[0].upper() + word[1:] for word in os.path.basename(os.getcwd()).split('_'))
print('<a name="TOP"></a>', file = doc_file)
print('# %s' % project, file = doc_file)
main_file = bom.find_scad_file('main_assembly')
if not main_file:
raise Exception("can't find source for main_assembly")
text = blurb.scrape_blurb(source_dir + '/' + main_file)
blurbs = blurb.split_blurb(text)
if len(text):
print(blurbs[0], file = doc_file)
else:
print(Fore.MAGENTA + "Missing project description" + Fore.WHITE)
#
# Only add the image if the first blurb section doesn't contain one.
#
if not re.search(r'\!\[.*\]\(.*\)', blurbs[0], re.MULTILINE):
print('![Main Assembly](assemblies/%s.png)\n' % flat_bom[-1]["name"].replace('_assembly', '_assembled'), file = doc_file)
eop(doc_file, first = True)
#
# Build TOC
#
print('## Table of Contents', file = doc_file)
print('1. [Parts list](#Parts_list)', file = doc_file)
for ass in flat_bom:
name = ass["name"]
cap_name = titalise(name)
print('1. [%s](#%s)' % (cap_name, name), file = doc_file)
print(file = doc_file)
if len(blurbs) > 1:
print(blurbs[1], file = doc_file)
eop(doc_file)
#
# Global BOM
#
global_bom = [merged(ass) for ass in flat_bom if not ass['ngb']]
print('<a name="Parts_list"></a>\n## Parts list', file = doc_file)
headings = {"vitamins" : "vitamins", "printed" : "3D printed parts", "routed" : "CNC routed parts"}
things = {}
for t in types:
things[t] = {}
for ass in flat_bom:
for t in types:
things[t] = {}
for ass in flat_bom:
for t in types:
for thing in ass[t]:
if thing in things[t]:
things[t][thing] += ass[t][thing]["count"]
else:
things[t][thing] = ass[t][thing]["count"]
for ass in flat_bom:
name = titalise(ass["name"][:-9]).replace(' ','&nbsp;')
print('| <span style="writing-mode: vertical-rl; text-orientation: mixed;">%s</span> ' % name, file = doc_file, end = '')
print('| <span style="writing-mode: vertical-rl; text-orientation: mixed;">TOTALS</span> | |', file = doc_file)
for thing in ass[t]:
if thing in things[t]:
things[t][thing] += ass[t][thing]["count"]
else:
things[t][thing] = ass[t][thing]["count"]
for ass in global_bom:
name = titalise(ass["name"][:-9]).replace(' ','&nbsp;')
if ass["count"] > 1:
name = "%d x %s" % (ass["count"], name)
print('| <span style="writing-mode: vertical-rl; text-orientation: mixed;">%s</span> ' % name, file = doc_file, end = '')
print('| <span style="writing-mode: vertical-rl; text-orientation: mixed;">TOTALS</span> | |', file = doc_file)
print(('|---:' * len(global_bom) + '|---:|:---|'), file = doc_file)
print(('|---:' * len(flat_bom) + '|---:|:---|'), file = doc_file)
for t in types:
if things[t]:
totals = {}
heading = headings[t][0:1].upper() + headings[t][1:]
print(('| ' * len(flat_bom) + '| | **%s** |') % heading, file = doc_file)
for thing in sorted(things[t], key = lambda s: s.split(":")[-1]):
for ass in flat_bom:
count = ass[t][thing]["count"] if thing in ass[t] else 0
print('| %s ' % pad(count if count else '.', 2, 1), file = doc_file, end = '')
name = ass["name"]
if name in totals:
totals[name] += count
else:
totals[name] = count
print('| %s | %s |' % (pad(things[t][thing], 2, 1), pad(thing.split(":")[-1], 2)), file = doc_file)
grand_total = 0
for ass in flat_bom:
for t in types:
if things[t]:
totals = {}
grand_total2 = 0
heading = headings[t][0].upper() + headings[t][1:]
print(('| ' * len(global_bom) + '| | **%s** |') % heading, file = doc_file)
for thing in sorted(things[t], key = lambda s: s.split(":")[-1]):
for ass in global_bom:
count = ass[t][thing]["count"] if thing in ass[t] else 0
print('| %s ' % pad(count if count else '.', 2, 1), file = doc_file, end = '')
name = ass["name"]
total = totals[name] if name in totals else 0
print('| %s ' % pad(total if total else '.', 2, 1), file = doc_file, end = '')
grand_total += total
print("| %s | %s |" % (pad(grand_total, 2, 1), pad('Total %s count' % headings[t], 2)), file = doc_file)
if name in totals:
totals[name] += count
else:
totals[name] = count
grand_total2 += count
print('| %s | %s |' % (pad(things[t][thing], 2, 1), pad(thing.split(":")[-1], 2)), file = doc_file)
print(file = doc_file)
if len(blurbs) > 2:
print(blurbs[2], file = doc_file)
eop(print_mode, doc_file)
#
# Assembly instructions
#
for ass in flat_bom:
name = ass["name"]
cap_name = titalise(name)
if ass["count"] > 1:
print('<a name="%s"></a>\n## %d x %s' % (name, ass["count"], cap_name), file = doc_file)
else:
print('<a name="%s"></a>\n## %s' % (name, cap_name), file = doc_file)
vitamins = ass["vitamins"]
if vitamins:
print("### Vitamins", file = doc_file)
print("|Qty|Description|", file = doc_file)
print("|---:|:----------|", file = doc_file)
for v in sorted(vitamins, key = lambda s: s.split(":")[-1]):
print("|%d|%s|" % (vitamins[v]["count"], v.split(":")[1]), file = doc_file)
print("\n", file = doc_file)
printed = ass["printed"]
if printed:
print('### 3D Printed parts', file = doc_file)
keys = sorted(list(printed.keys()))
for i, p in enumerate(keys):
print('%s %d x %s |' % ('\n|' if not (i % 3) else '', printed[p]["count"], p), file = doc_file, end = '')
if (i % 3) == 2 or i == len(printed) - 1:
n = (i % 3) + 1
print('\n|%s' % ('---|' * n), file = doc_file)
for j in range(n):
part = keys[i - n + j + 1]
print('| ![%s](stls/%s) %s' % (part, part.replace('.stl','.png'), '|\n' if j == j - 1 else ''), end = '', file = doc_file)
print('\n', file = doc_file)
print('\n', file = doc_file)
routed = ass["routed"]
if routed:
print("### CNC Routed parts", file = doc_file)
keys = sorted(list(routed.keys()))
for i, r in enumerate(keys):
print('%s %d x %s |' % ('\n|' if not (i % 3) else '', routed[r]["count"], r), file = doc_file, end = '')
if (i % 3) == 2 or i == len(routed) - 1:
n = (i % 3) + 1
print('\n|%s' % ('---|' * n), file = doc_file)
for j in range(n):
part = keys[i - n + j + 1]
print('| ![%s](dxfs/%s) %s' % (part, part.replace('.dxf','.png'), '|\n' if j == j - 1 else ''), end = '', file = doc_file)
print('\n', file = doc_file)
print('\n', file = doc_file)
sub_assemblies = ass["assemblies"]
if sub_assemblies:
print("### Sub-assemblies", file = doc_file)
keys = sorted(list(sub_assemblies.keys()))
for i, a in enumerate(keys):
print('%s %d x %s |' % ('\n|' if not (i % 3) else '', sub_assemblies[a], a), file = doc_file, end = '')
if (i % 3) == 2 or i == len(keys) - 1:
n = (i % 3) + 1
print('\n|%s' % ('---|' * n), file = doc_file)
for j in range(n):
a = keys[i - n + j + 1].replace('_assembly', '_assembled')
print('| ![%s](assemblies/%s) %s' % (a, a + '_tn.png', '|\n' if j == j - 1 else ''), end = '', file = doc_file)
print('\n', file = doc_file)
print('\n', file = doc_file)
small = not ass["big"]
suffix = '_tn.png' if small else '.png'
print('### Assembly instructions', file = doc_file)
print('![%s](assemblies/%s)\n' % (name, name + suffix), file = doc_file)
if "blurb" in ass and ass["blurb"]:
print(ass["blurb"], file = doc_file)
else:
if print_mode:
print(Fore.MAGENTA + "Missing instructions for %s" % name, Fore.WHITE)
name = name.replace('_assembly', '_assembled')
print('![%s](assemblies/%s)\n' % (name, name + suffix), file = doc_file)
eop(print_mode, doc_file, last = ass == flat_bom[-1] and not main_blurb)
#
# If main module is suppressed print any blurb here
#
if main_blurb:
print(main_blurb, file = doc_file)
eop(print_mode, doc_file, last = True)
grand_total = 0
for ass in global_bom:
name = ass["name"]
total = totals[name] if name in totals else 0
print('| %s ' % pad(total if total else '.', 2, 1), file = doc_file, end = '')
grand_total += total
print("| %s | %s |" % (pad(grand_total, 2, 1), pad('Total %s count' % headings[t], 2)), file = doc_file)
assert grand_total == grand_total2
print(file = doc_file)
if len(blurbs) > 2:
print(blurbs[2], file = doc_file)
eop(doc_file)
#
# Convert to HTML
# Assembly instructions
#
html_name = "printme.html" if print_mode else "readme.html"
with open(top_dir + html_name, "wt") as html_file:
do_cmd(("python -m markdown -x tables -x sane_lists " + doc_name).split(), html_file)
for ass in flat_bom:
name = ass["name"]
cap_name = titalise(name)
print('<a name="%s"></a>' % name, file = doc_file)
if ass["count"] > 1:
print('## %d x %s' % (ass["count"], cap_name), file = doc_file)
else:
print('## %s' % cap_name, file = doc_file)
vitamins = ass["vitamins"]
if vitamins:
print("### Vitamins", file = doc_file)
print("|Qty|Description|", file = doc_file)
print("|---:|:----------|", file = doc_file)
for v in sorted(vitamins, key = lambda s: s.split(":")[-1]):
print("|%d|%s|" % (vitamins[v]["count"], v.split(":")[1]), file = doc_file)
print("\n", file = doc_file)
printed = ass["printed"]
if printed:
print('### 3D Printed parts', file = doc_file)
keys = sorted(list(printed.keys()))
for i, p in enumerate(keys):
print('%s %d x %s |' % ('\n|' if not (i % 3) else '', printed[p]["count"], p), file = doc_file, end = '')
if (i % 3) == 2 or i == len(printed) - 1:
n = (i % 3) + 1
print('\n|%s' % ('---|' * n), file = doc_file)
for j in range(n):
part = keys[i - n + j + 1]
print('| ![%s](stls/%s) %s' % (part, part.replace('.stl','.png'), '|\n' if j == j - 1 else ''), end = '', file = doc_file)
print('\n', file = doc_file)
print('\n', file = doc_file)
routed = ass["routed"]
if routed:
print("### CNC Routed parts", file = doc_file)
keys = sorted(list(routed.keys()))
for i, r in enumerate(keys):
print('%s %d x %s |' % ('\n|' if not (i % 3) else '', routed[r]["count"], r), file = doc_file, end = '')
if (i % 3) == 2 or i == len(routed) - 1:
n = (i % 3) + 1
print('\n|%s' % ('---|' * n), file = doc_file)
for j in range(n):
part = keys[i - n + j + 1]
print('| ![%s](dxfs/%s) %s' % (part, part.replace('.dxf','.png'), '|\n' if j == j - 1 else ''), end = '', file = doc_file)
print('\n', file = doc_file)
print('\n', file = doc_file)
sub_assemblies = ass["assemblies"]
if sub_assemblies:
print("### Sub-assemblies", file = doc_file)
keys = sorted(list(sub_assemblies.keys()))
for i, a in enumerate(keys):
print('%s %d x %s |' % ('\n|' if not (i % 3) else '', sub_assemblies[a], a), file = doc_file, end = '')
if (i % 3) == 2 or i == len(keys) - 1:
n = (i % 3) + 1
print('\n|%s' % ('---|' * n), file = doc_file)
for j in range(n):
a = keys[i - n + j + 1].replace('_assembly', '_assembled')
print('| ![%s](assemblies/%s) %s' % (a, a + '_tn.png', '|\n' if j == j - 1 else ''), end = '', file = doc_file)
print('\n', file = doc_file)
print('\n', file = doc_file)
small = not ass["big"]
suffix = '_tn.png' if small else '.png'
print('### Assembly instructions', file = doc_file)
print('![%s](assemblies/%s)\n' % (name, name + suffix), file = doc_file)
if "blurb" in ass and ass["blurb"]:
print(ass["blurb"], file = doc_file)
else:
print(Fore.MAGENTA + "Missing instructions for %s" % name, Fore.WHITE)
name = name.replace('_assembly', '_assembled')
print('![%s](assemblies/%s)\n' % (name, name + suffix), file = doc_file)
eop(doc_file, last = ass == flat_bom[-1] and not main_blurb)
#
# If main module is suppressed print any blurb here
#
if main_blurb:
print(main_blurb, file = doc_file)
eop(doc_file, last = True)
#
# Convert to HTML
#
html_name = top_dir + 'readme.html'
t = time.time()
with open(html_name, "wt") as html_file:
do_cmd(("python -m markdown -x tables -x sane_lists " + doc_name).split(), html_file)
times.add_time(html_name, t)
times.print_times(pngs + [html_name])
#
# Make the printme.html by replacing empty spans that invisbly mark the page breaks by page break divs.
#
with open(html_name, 'rt') as src:
lines = src.readlines()
i = 0
with open(top_dir + 'printme.html', 'wt') as dst:
while i < len(lines):
line = lines[i]
if line.startswith('<p><span></span>'): # Empty span used to mark page breaks
i += 1
if lines[i].startswith('<a href="#TOP">Top</a>'): # The first page break won't have one
i += 1
if i < len(lines) and lines[i] == '<hr />\n': # The last page break doesn't have one
dst.write('<div style="page-break-after: always;"></div>\n')
i += 1
else:
dst.write(line)
i += 1
#
# Remove tmp dir
#
rmtmpdir(tmp_dir)
#
# Spell check
#
do_cmd('codespell -L od readme.md'.split())
do_cmd(('codespell -L od ' + top_dir + 'readme.md').split())
#
# List the ones we didn't find
#

View File

@@ -30,7 +30,6 @@ sheet = PMMA3;
height = 10;
insert = screw_insert(screw);
washer = screw_washer(screw);
module widget(thickness) {
vitamin(str("widget(", thickness, "): Rivit like thing for ", thickness, "mm sheets"));
@@ -44,31 +43,29 @@ module widget(thickness) {
}
}
module widgit_stl() {
stl("widget");
module widget_stl() {
stl("widget")
union() {
rounded_rectangle([30, 30, 3], 2, true);
union() {
rounded_rectangle([30, 30, 3], 2);
render() insert_boss(insert, height, 2.2);
}
render() insert_boss(insert, height, 2.2);
}
}
module widgit_dxf() {
dxf("widget");
module widget_dxf() {
dxf("widget")
difference() {
sheet_2D(sheet, 20, 20, 1);
difference() {
sheet_2D(sheet, 20, 20, 1);
drill(screw_clearance_radius(screw), 0);
}
drill(screw_clearance_radius(screw), 0);
}
}
//! * Push the insert into the base with a soldering iron heated to 200&deg;C
module widgit_base_assembly()
assembly("widgit_base") {
module widget_base_assembly()
assembly("widget_base") {
stl_colour(pp1_colour)
widgit_stl();
widget_stl();
translate_z(height)
insert(insert);
@@ -81,18 +78,18 @@ assembly("widget_top") {
widget(sheet_thickness(sheet));
render_2D_sheet(sheet) // Must be last because it is transparent
widgit_dxf();
widget_dxf();
}
//! * Screw the two assemblies together
module widgit_assembly()
assembly("wigdit") {
module widget_assembly()
assembly("widget") {
widgit_base_assembly(); // Note this is not exloded because it is sub-assembly
widget_base_assembly(); // Note this is not exloded because it is sub-assembly
translate_z(height) {
translate_z(sheet_thickness(sheet))
screw_and_washer(screw, screw_longer_than(sheet_thickness(sheet) + 2 * washer_thickness(washer) + 3), true);
screw_and_washer(screw, screw_length(screw, sheet_thickness(sheet) + 3, 2, longer = true), true);
explode(5)
translate_z(sheet_thickness(sheet) / 2 + eps)
@@ -101,7 +98,7 @@ assembly("wigdit") {
}
module boms() {
widgit_assembly();
widget_assembly();
}
boms();

View File

@@ -21,8 +21,10 @@ include <../vitamins/pcbs.scad>
use <../utils/layout.scad>
function spacing(p) = let(w = pcb_width(p)) w < 22 ? w + 3 : w + 10;
module pcbs() {
layout([for(p = pcbs) pcb_width(p)], 10)
layout([for(p = pcbs) spacing(p)], 0)
translate([0, pcb_length(pcbs[$i]) / 2])
rotate(90)
pcb_assembly(pcbs[$i], 5 + $i, 3);
@@ -31,6 +33,10 @@ module pcbs() {
layout([for(p = perfboards) pcb_length(p)], 10)
translate([0, -pcb_width(perfboards[$i]) / 2])
pcb_assembly(perfboards[$i], 5 + $i, 3);
for(p = pcbs_not_shown)
hidden()
pcb(p);
}
if($preview)
pcbs();

View File

@@ -22,18 +22,15 @@ use <../utils/layout.scad>
include <../vitamins/blowers.scad>
module blowers()
layout([for(b = blowers) blower_width(b)], 10, true) let(b = blowers[$i]){
layout([for(b = blowers) blower_width(b)], 5, true) let(b = blowers[$i]){
screw = blower_screw(b);
washer = screw_washer(screw);
h = blower_lug(b);
blower(b);
blower_hole_positions(b)
translate_z(h)
screw_and_washer(screw, screw_longer_than(h + washer_thickness(washer) + 5));
screw_and_washer(screw, screw_length(screw, h + 5, 1, longer = true));
}
if($preview)

View File

@@ -56,7 +56,7 @@ module horiholes_stl(t = thickness) {
}
if(t == thickness)
translate([length / 2, 0])
rounded_rectangle([length + 2 * overlap_x, thickness + 2 * overlap_y, 2], 5);
rounded_rectangle([length + 2 * overlap_x, thickness + 2 * overlap_y, 2], 5, true);
}
module horiholes() {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 152 KiB

After

Width:  |  Height:  |  Size: 153 KiB

BIN
tests/png/pocket_handle.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 129 KiB

After

Width:  |  Height:  |  Size: 154 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 148 KiB

After

Width:  |  Height:  |  Size: 148 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 104 KiB

After

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 43 KiB

40
tests/pocket_handle.scad Normal file
View File

@@ -0,0 +1,40 @@
//
// NopSCADlib Copyright Chris Palmer 2021
// 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>
include <../vitamins/sheets.scad>
use <../printed/pocket_handle.scad>
show_holes = false;
handle = pocket_handle();
module pocket_handles() {
if($preview) {
pocket_handle_assembly(handle);
if(show_holes)
#pocket_handle_holes(handle);
}
else
pocket_handle(handle);
}
pocket_handles();

View File

@@ -0,0 +1,45 @@
//
// 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>
include <../vitamins/pulleys.scad>
include <../printed/printed_pulleys.scad>
use <../utils/layout.scad>
module printed_pulley_test(show_metal = false) {
layout([for (p = pulleys) pulley_flange_dia(p)]) let(p = pulleys[$i]) {
rotate(-145)
if($preview)
printed_pulley_assembly(p);
else
printed_pulley(p);
if(show_metal)
not_on_bom()
translate([0, 20])
rotate(-145)
pulley_assembly(p);
}
}
if($preview)
printed_pulley_test(true);
else
printed_pulley_test();

View File

@@ -23,7 +23,7 @@ include <../vitamins/pulleys.scad>
module pulleys()
layout([for(p = pulleys) pulley_flange_dia(p)])
rotate(-45)
rotate(-145)
pulley_assembly(pulleys[$i]);
if($preview)

View File

@@ -26,15 +26,16 @@ sheet = 3;
pos = 1; //[-1 : 0.1 : 1]
module rails()
layout([for(l = rails) carriage_width(rail_carriage(l))], 20)
layout([for(l = carriages) carriage_width(l)], 20)
rotate(-90) {
rail = rails[$i];
carriage = carriages[$i];
rail = carriage_rail(carriage);
length = 200;
screw = rail_screw(rail);
nut = screw_nut(screw);
washer = screw_washer(screw);
rail_assembly(rail, length, pos * rail_travel(rail, length) / 2, $i<2 ? grey(20) : "green", $i<2 ? grey(20) : "red");
rail_assembly(carriage, length, pos * carriage_travel(carriage, length) / 2, $i<2 ? grey(20) : "green", $i<2 ? grey(20) : "red");
rail_screws(rail, length, sheet + nut_thickness(nut, true) + washer_thickness(washer));

View File

@@ -27,10 +27,13 @@ module rounded_rectangles() {
rounded_rectangle([30, 20, 10], 3);
translate([80, 0])
rounded_rectangle_xz([30, 20, 10], 3);
rounded_cube_xy([30, 20, 10], 3);
translate([120, 0])
rounded_rectangle_yz([30, 20, 10], 3);
rounded_cube_xz([30, 20, 10], 3);
translate([160, 0])
rounded_cube_yz([30, 20, 10], 3);
}
rounded_rectangles();

View File

@@ -22,9 +22,9 @@ include <../vitamins/stepper_motors.scad>
use <../utils/layout.scad>
module stepper_motors()
layout([for(s = stepper_motors) NEMA_width(s)], 5) let(m = stepper_motors[$i]) {
layout([for(s = stepper_motors) NEMA_width(s)], 5, no_offset = true) let(m = stepper_motors[$i]) {
rotate(180)
NEMA(m, 0, m == NEMA17M || m == NEMA17M8);
NEMA(m, 0, m == NEMA17P || m == NEMA17M || m == NEMA17M8);
translate_z(4)
NEMA_screws(m, M3_pan_screw, n = $i, earth = $i > 4 ? undef : $i - 1);

View File

@@ -27,6 +27,9 @@ module tubes() {
translate([50, 10])
tube(10, 8, 30);
translate([100, 10])
rectangular_tube([10, 20, 30]);
}
tubes();

View File

@@ -25,16 +25,28 @@
//! parts are used.
//! This heuristic isn't always correct, so the default can be overridden by setting the `big` parameter of `assembly` to `true` or `false`.
//!
//! Setting the `ngb` parameter of `assembly` to `true` removes its column from the global BOM and merges it parts into its parent assembly column of the global BOM.
//! This is to prevent the global BOM page becoming too wide in large projects by having it include just the major assemblies.
//!
//! The example below shows how to define a vitamin and incorporate it into an assembly with sub-assemblies and make an exploded view.
//! The resulting flat BOM is shown but heirachical BOMs are also generated for real projects.
//!
//! If the code to make an STL or DXF is made a child of the `stl()` or `dxf()` module then the STL or DXF will be used in the assembly views generated by `views.py` instead of generating
//! it with code.
//! This can speed up the generation of the build instructions greatly but isn't compatible with STLs that include support structures.
//!
//! The `pose()` module allows assembly views in the readme to be posed differently to the default view in the GUI:
//!
//! * Setting the `exploded` parameter to `true` allows just the exploded version to be posed and setting to `false` allows just the assembled view to be posed, the default is both.
//! * If the `d` parameter is set to specify the camera distance then the normal `viewall` and `autocenter` options are supressed allowing a small section to be zoomed in to fill the view.
//! * To get the parameter values make the GUI window square, pose the view with the mouse and then copy the viewport parameters from the Edit menu and paste them into the pose invocation.
//! * Two `pose()` modules can be chained to allow different poses for exploded and assembled views.
//
function bom_mode(n = 1) = $_bom >= n && (is_undef($on_bom) || $on_bom); //! Current BOM mode, 0 = none, 1 = printed and routed parts and assemblies, 2 includes vitamins as well
function exploded() = is_undef($exploded_parent) ? $exploded : 0; //! Returns the value of `$exploded` if it is defined, else `0`
function show_supports() = !$preview || exploded(); //! True if printed support material should be shown
module no_explode() let($exploded_parent = true) children(); //! Prevent children being exploded
module no_pose() let($posed = true) children(); //! Force children not to be posed even if parent is
module explode(d, explode_children = false, offset = [0,0,0]) { //! Explode children by specified Z distance or vector `d`, option to explode grand children
v = is_list(d) ? d : [0, 0, d];
o = is_list(offset) ? offset : [0, 0, offset];
@@ -55,17 +67,29 @@ module explode(d, explode_children = false, offset = [0,0,0]) { //! Explode
children();
}
module pose(a = [55, 0, 25], t = [0, 0, 0], exploded = undef) //! Pose an STL or assembly for rendering to png by specifying rotation `a` and translation `t`, `exploded = true for` just the exploded view or `false` for unexploded only.
if(is_undef($pose) || !is_undef($posed) || (!is_undef(exploded) && exploded != !!exploded()))
children();
else
let($posed = true) // only pose the top level
rotate([55, 0, 25])
rotate([-a.x, 0, 0])
rotate([0, -a.y, 0])
rotate([0, 0, -a.z])
translate(-t)
children();
module no_pose() let($posed = true, $zoomed = undef) children(); //! Force children not to be posed even if parent is
module pose(a = [55, 0, 25], t = [0, 0, 0], exploded = undef, d = undef) //! Pose an STL or assembly for rendering to png by specifying rotation `a`, translation `t` and optionally `d`, `exploded = true for` just the exploded view or `false` for unexploded only.
let($zoomed = is_undef(d)
? is_undef($zoomed)
? undef
: $zoomed
: is_undef(exploded)
? 3
: exploded
? 2
: 1)
if(is_undef($pose) || !is_undef($posed) || (!is_undef(exploded) && exploded != !!exploded()))
children();
else
let($posed = true) // only pose the top level
rotate([55, 0, 25])
translate_z(is_undef(d) ? 0 : 140 - d)
rotate([-a.x, 0, 0])
rotate([0, -a.y, 0])
rotate([0, 0, -a.z])
translate(-t)
children();
module pose_hflip(exploded = undef) //! Pose an STL or assembly for rendering to png by flipping around the Y axis, `exploded = true for` just the exploded view or `false` for unexploded only.
if(is_undef($pose) || !is_undef($posed) || (!is_undef(exploded) && exploded != !!exploded()))
@@ -84,9 +108,11 @@ module pose_vflip(exploded = undef) //! Pose an STL or assembly for render
children();
module assembly(name, big = undef) { //! Name an assembly that will appear on the BOM, there needs to a module named `<name>_assembly` to make it. `big` can force big or small assembly diagrams.
module assembly(name, big = undef, ngb = false) { //! Name an assembly that will appear on the BOM, there needs to a module named `<name>_assembly` to make it. `big` can force big or small assembly diagrams.
if(bom_mode()) {
args = is_undef(big) ? "" : str("(big=", big, ")");
zoom = is_undef($zoomed) ? 0 : $zoomed;
arglist = str(arg(big, undef, "big"), arg(ngb, false, "ngb"), arg(zoom, 0, "zoomed"));
args = len(arglist) ? str("(", slice(arglist, 2), ")") : "";
echo(str("~", name, "_assembly", args, "{"));
}
no_pose()
@@ -108,21 +134,43 @@ module stl_colour(colour = pp1_colour, alpha = 1) { //! Colour an stl where it i
}
module stl(name) { //! Name an stl that will appear on the BOM, there needs to a module named `<name>_stl` to make it
if(bom_mode()) {
if(bom_mode() && is_undef($in_stl)) {
colour = is_undef($stl_colour) ? pp1_colour : $stl_colour;
echo(str("~", name, ".stl(colour='", colour, "')"));
}
if($children)
if(is_undef($pose))
let($in_stl = true)
children();
else {
path = is_undef($target) ? "/stls/" : str("/", $target, "/stls/");
import(str($cwd, path, name, ".stl"));
}
}
module dxf(name) { //! Name a dxf that will appear on the BOM, there needs to a module named `<name>_dxf` to make it
if(bom_mode()) {
if(bom_mode() && is_undef($in_dxf)) {
if(is_undef($dxf_colour))
echo(str("~", name, ".dxf"));
else
echo(str("~", name, ".dxf(colour='", $dxf_colour, "')"));
}
if($children)
if(is_undef($pose))
let($in_dfx = true)
children();
else {
path = is_undef($target) ? "/dxfs/" : str("/", $target, "/dxfs/");
import(str($cwd, path, name, ".dxf"));
}
}
module use_stl(name) //! Import an STL to make a build platter
assert(false); // Here for documentation only, real version in core.scad
module use_dxf(name) //! Import a DXF to make a build panel
assert(false); // Here for documentation only, real version in core.scad
function value_string(value) = is_string(value) ? str("\"", value, "\"") : str(value); //! Convert `value` to a string or quote it if it is already a string
function arg(value, default, name = "") = //! Create string for arg if not default, helper for `vitamin()`
@@ -130,7 +178,7 @@ function arg(value, default, name = "") = //! Create string for arg if not def
: name ? str(", ", name, " = ", value_string(value))
: str(", ", value_string(value));
module vitamin(description) { //! Describe a vitamin for the BOM entry and precede it with a module call that creates it, eg. "wigit(42): Type 42 widget"
module vitamin(description) { //! Describe a vitamin for the BOM entry and precede it with a module call that creates it, eg. "widget(42): Widget size 42"
if(bom_mode(2))
echo(str("~", description, !is_undef($hidden) ? " - not shown" : ""));
}

View File

@@ -28,12 +28,12 @@ use <global.scad>
module use_stl(name) { //! Import an STL to make a build platter
stl(name);
path = is_undef($target) ? "../stls/" : str("../", $target, "/stls/");
path = is_undef($target) ? "../stls/" : str($cwd, "/", $target, "/stls/");
import(str(path, name, ".stl"));
}
module use_dxf(name) { //! Import a DXF to make a build panel
dxf(name);
path = is_undef($target) ? "../dxfs/" : str("../", $target, "/dxfs/");
path = is_undef($target) ? "../dxfs/" : str($cwd, "/", $target, "/dxfs/");
import(str(path, name, ".dxf"));
}

View File

@@ -33,20 +33,20 @@
//! When `twist` is set the resulting cylinder is extended by `eps` at each end so that the exact length of the hole can be used without
//! leaving a scar on either surface.
//
function sides(r) = max(round(4 * r), 3); //! Optimium number of sides for specified radius
function corrected_radius(r, n = 0) = r / cos(180 / (n ? n : sides(r))); //! Adjusted radius to make flats lie on the circle
function corrected_diameter(d, n = 0) = d / cos(180 / (n ? n : sides(d / 2))); //! Adjusted diameter to make flats lie on the circle
function sides(r, n = undef) = is_undef(n) ? max(round(4 * r), 3) : n ? max(n, 3) : r2sides(r); //! Optimium number of sides for specified radius
function corrected_radius(r, n = undef) = r / cos(180 / sides(r, n)); //! Adjusted radius to make flats lie on the circle
function corrected_diameter(d, n = undef) = 2 * corrected_radius(d / 2 , n); //! Adjusted diameter to make flats lie on the circle
module poly_circle(r, sides = 0) { //! Make a circle adjusted to print the correct size
n = sides ? sides : sides(r);
circle(r = corrected_radius(r,n), $fn = n);
module poly_circle(r, sides = undef) { //! Make a circle adjusted to print the correct size
n = sides(r, sides);
circle(r = corrected_radius(r, n), $fn = n);
}
module poly_cylinder(r, h, center = false, sides = 0, chamfer = false, twist = 0) {//! Make a cylinder adjusted to print the correct size
module poly_cylinder(r, h, center = false, sides = undef, chamfer = false, twist = 0) {//! Make a cylinder adjusted to print the correct size
if(twist) {
slices = ceil(h / layer_height);
twists = min(twist + 1, slices);
sides = sides ? sides : sides(r);
sides = sides(r, sides);
rot = 360 / sides / twists * (twists < slices ? (1 + 1 / slices) : 1);
if(center)
for(side = [0, 1])
@@ -64,10 +64,10 @@ module poly_cylinder(r, h, center = false, sides = 0, chamfer = false, twist = 0
poly_circle(r, sides);
if(h && chamfer)
poly_cylinder(r + layer_height, center ? layer_height * 2 : layer_height, center, sides = sides ? sides : sides(r));
poly_cylinder(r + layer_height, center ? layer_height * 2 : layer_height, center, sides = sides(r, sides));
}
module poly_ring(or, ir, sides = 0) { //! Make a 2D ring adjusted to have the correct internal radius
module poly_ring(or, ir, sides = undef) { //! Make a 2D ring adjusted to have the correct internal radius
cir = corrected_radius(ir, sides);
filaments = (or - cir) / extrusion_width;
if(filaments > 3 + eps)

View File

@@ -22,26 +22,33 @@
//
module rounded_square(size, r, center = true) //! Like `square()` but with with rounded corners
{
assert(r < min(size.x, size.y) / 2);
$fn = r2sides4n(r);
offset(r) offset(-r) square(size, center = center);
}
module rounded_rectangle(size, r, center = true, xy_center = true) //! Like `cube()` but corners rounded in XY plane and separate centre options for xy and z.
module rounded_rectangle(size, r, center = false, xy_center = true) //! Like `cube()` but corners rounded in XY plane and separate centre options for xy and z.
{
linear_extrude(size.z, center = center)
extrude_if(size.z, center = center)
rounded_square([size.x, size.y], r, xy_center);
}
module rounded_rectangle_xz(size, r, center = true, xy_center = true) //! Like `cube()` but corners rounded in XZ plane and separate centre options for xy and z.
module rounded_cube_xy(size, r = 0, xy_center = false, z_center = false) //! Like `cube()` but corners rounded in XY plane and separate centre options for xy and z.
{
translate([xy_center ? 0 : size.x / 2, xy_center ? 0 : size.y / 2, center ? 0 : size.z / 2])
rotate([90, 0, 0])
rounded_rectangle([size.x, size.z, size.y], r, center = true, xy_center = true);
extrude_if(size.z, center = z_center)
rounded_square([size.x, size.y], r, xy_center);
}
module rounded_rectangle_yz(size, r, center = true, xy_center = true) //! Like `cube()` but corners rounded in YX plane and separate centre options for xy and z.
module rounded_cube_xz(size, r = 0, xy_center = false, z_center = false) //! Like `cube()` but corners rounded in XZ plane and separate centre options for xy and z.
{
translate([xy_center ? 0 : size.x / 2, xy_center ? 0 : size.y / 2, center ? 0 : size.z / 2])
rotate([90, 0, 90])
rounded_rectangle([size.y, size.z, size.x], r, center = true, xy_center = true);
translate([xy_center ? 0 : size.x / 2, xy_center ? 0 : size.y / 2, z_center ? 0 : size.z / 2])
rotate([90, 0, 0])
rounded_cube_xy([size.x, size.z, size.y], r, xy_center = true, z_center = true);
}
module rounded_cube_yz(size, r = 0, xy_center = false, z_center = false) //! Like `cube()` but corners rounded in YX plane and separate centre options for xy and z.
{
translate([xy_center ? 0 : size.x / 2, xy_center ? 0 : size.y / 2, z_center ? 0 : size.z / 2])
rotate([90, 0, 90])
rounded_cube_xy([size.y, size.z, size.x], r, xy_center = true, z_center = true);
}

View File

@@ -24,7 +24,7 @@
//! Using teardrop_plus() or setting the plus option on other modules will elongate the teardrop vertically by the layer height, so when sliced the staircase tips
//! do not intrude into the circle. See <https://hydraraptor.blogspot.com/2020/07/horiholes-2.html>
//
module teardrop(h, r, center = true, truncate = true, chamfer = 0, plus = false) { //! For making horizontal holes that don't need support material, set `truncate = false` to make traditional RepRap teardrops that don't even need bridging
module teardrop(h, r, center = true, truncate = true, chamfer = 0, chamfer_both_ends = true, plus = false) { //! For making horizontal holes that don't need support material, set `truncate = false` to make traditional RepRap teardrops that don't even need bridging
module teardrop_2d(r, truncate) {
er = layer_height / 2 - eps; // Extrustion edge radius
R = plus ? r + er : r; // Corrected radius
@@ -52,7 +52,7 @@ module teardrop(h, r, center = true, truncate = true, chamfer = 0, plus = false)
extrude_if(h, center)
teardrop_2d(r, truncate);
teardrop_chamfer(h, center, chamfer) {
teardrop_chamfer(h, center, chamfer, chamfer_both_ends) {
linear_extrude(eps, center = true)
teardrop_2d(r + chamfer / 2, truncate);
@@ -62,7 +62,7 @@ module teardrop(h, r, center = true, truncate = true, chamfer = 0, plus = false)
}
}
module semi_teardrop(h, r, d = undef, center = true, chamfer = 0, plus = false) { //! A semi teardrop in the positive Y domain
module semi_teardrop(h, r, d = undef, center = true, chamfer = 0, chamfer_both_ends = true, plus = false) { //! A semi teardrop in the positive Y domain
module semi_teardrop_2d(r, d)
intersection() {
R = is_undef(d) ? r : d / 2;
@@ -77,7 +77,7 @@ module semi_teardrop(h, r, d = undef, center = true, chamfer = 0, plus = false)
extrude_if(h, center)
semi_teardrop_2d(r, d);
teardrop_chamfer(h, center, chamfer) {
teardrop_chamfer(h, center, chamfer, chamfer_both_ends) {
linear_extrude(eps, center = true)
semi_teardrop_2d(r + chamfer / 2, d);
@@ -87,10 +87,10 @@ module semi_teardrop(h, r, d = undef, center = true, chamfer = 0, plus = false)
}
}
module teardrop_plus(h, r, center = true, truncate = true, chamfer = 0) //! Slightly elongated teardrop to allow for the 3D printing staircase effect
teardrop(h, r, center, truncate, chamfer, plus = true);
module teardrop_plus(h, r, center = true, truncate = true, chamfer = 0, chamfer_both_ends = true) //! Slightly elongated teardrop to allow for the 3D printing staircase effect
teardrop(h, r, center, truncate, chamfer, chamfer_both_ends, plus = true);
module tearslot(h, r, w, center = true, chamfer = 0, plus = false) { //! A horizontal slot that doesn't need support material
module tearslot(h, r, w, center = true, chamfer = 0, chamfer_both_ends = true, plus = false) { //! A horizontal slot that doesn't need support material
module tearslot_2d(r, w)
hull()
for(x = [-1, 1])
@@ -99,7 +99,7 @@ module tearslot(h, r, w, center = true, chamfer = 0, plus = false) { //! A horiz
extrude_if(h, center)
tearslot_2d(r, w);
teardrop_chamfer(h, center, chamfer) {
teardrop_chamfer(h, center, chamfer, chamfer_both_ends) {
linear_extrude(eps, center = true)
tearslot_2d(r + chamfer / 2, w);
@@ -109,7 +109,7 @@ module tearslot(h, r, w, center = true, chamfer = 0, plus = false) { //! A horiz
}
}
module vertical_tearslot(h, r, l, center = true, chamfer = 0, plus = false) { //! A vertical slot that doesn't need support material
module vertical_tearslot(h, r, l, center = true, chamfer = 0, chamfer_both_ends = true, plus = false) { //! A vertical slot that doesn't need support material
module vertical_tearslot_2d(r, l)
hull()
for(y = [-1, 1])
@@ -119,7 +119,7 @@ module vertical_tearslot(h, r, l, center = true, chamfer = 0, plus = false) { //
extrude_if(h, center)
vertical_tearslot_2d(r, l);
teardrop_chamfer(h, center, chamfer) {
teardrop_chamfer(h, center, chamfer, chamfer_both_ends) {
linear_extrude(eps, center = true)
vertical_tearslot_2d(r + chamfer / 2, l);
@@ -129,10 +129,10 @@ module vertical_tearslot(h, r, l, center = true, chamfer = 0, plus = false) { //
}
}
module teardrop_chamfer(h, center, chamfer) { //! Helper module for adding chamfer to a teardrop
module teardrop_chamfer(h, center, chamfer, chamfer_both_ends) { //! Helper module for adding chamfer to a teardrop
if(h && chamfer)
translate_z(center ? 0 : h / 2)
for(m = [0, 1])
for(m = chamfer_both_ends ? [0, 1] : [1])
mirror([0, 0, m])
translate_z((h - eps ) / 2)
hull()

View File

@@ -18,13 +18,14 @@
//
//
//! Draw a polygon with rounded corners. Each element of the vector is the XY coordinate and a radius. Radius can be negative for a concave corner.
//! Draw a polygon with rounded corners. Each element of the vector is the XY coordinate and a radius in clockwise order.
//! Radius can be negative for a concave corner.
//!
//! Because the tangents need to be calculated to find the length these can be calculated separately and re-used when drawing to save calculating them twice.
//
include <../utils/core/core.scad>
function circle_tangent(p1, p2) =
function circle_tangent(p1, p2) = //! Compute the clockwise tangent between two circles represented as [x,y,r]
let(
r1 = p1[2],
r2 = p2[2],
@@ -32,11 +33,8 @@ function circle_tangent(p1, p2) =
dy = p2.y - p1.y,
d = sqrt(dx * dx + dy * dy),
theta = atan2(dy, dx) + acos((r1 - r2) / d),
xa = p1.x +(cos(theta) * r1),
ya = p1.y +(sin(theta) * r1),
xb = p2.x +(cos(theta) * r2),
yb = p2.y +(sin(theta) * r2)
)[ [xa, ya], [xb, yb] ];
v = [cos(theta), sin(theta)]
)[ p1 + r1 * v, p2 + r2 * v ];
function rounded_polygon_tangents(points) = //! Compute the straight sections needed to draw and to compute the lengths
let(len = len(points))

View File

@@ -21,7 +21,7 @@
//! Draw a 3D right triangle with rounded edges. Intended to be embedded in other parts. Can be optionally offset by the filleted amount.
//
include <../utils/core/core.scad>
include <NopSCADlib/utils/core/rounded_rectangle.scad>
include <..//utils/core/rounded_rectangle.scad>
module rounded_right_triangle(x, y, z, fillet, center = true, offset = false) { //! Draw a 3D right triangle with rounded edges.
fillet = max(fillet, eps);
@@ -31,16 +31,15 @@ module rounded_right_triangle(x, y, z, fillet, center = true, offset = false) {
hull() {
translate([0, fillet, size.z / 2])
rotate([90, 90, 0])
rounded_rectangle([size.z, 2 * fillet, eps], fillet - eps, center = false, xy_center = false);
rounded_rectangle([size.z, 2 * fillet, eps], fillet - eps, xy_center = false);
translate([0, size.y, size.z / 2])
rotate([90, 90, 0])
rounded_rectangle([size.z, 2 * fillet, eps], fillet - eps, center = false, xy_center = false);
rounded_rectangle([size.z, 2 * fillet, eps], fillet - eps, xy_center = false);
translate([fillet, 0, size.z / 2])
rotate([0, 90, 0])
rounded_rectangle([size.z, 2 * fillet, eps], fillet - eps, center = false, xy_center = false);
rounded_rectangle([size.z, 2 * fillet, eps], fillet - eps, xy_center = false);
translate([size.x, 0, size.z / 2])
rotate([0, 90, 0])
rounded_rectangle([size.z, 2 * fillet, eps], fillet - eps, center = false, xy_center = false);
rounded_rectangle([size.z, 2 * fillet, eps], fillet - eps, xy_center = false);
}
}

View File

@@ -68,3 +68,11 @@ module woven_tube(or, ir, h, center= true, colour = grey(30), colour2, warp = 2,
}
}
}
module rectangular_tube(size, center = true, thickness = 1, fillet = 0.5) { //! Create a retangular tube with filleted corners
extrude_if(size.z, center = center)
difference() {
rounded_square([size.x, size.y], fillet);
rounded_square([size.x - 2 * thickness, size.y - 2 * thickness], fillet);
}
}

View File

@@ -128,7 +128,7 @@ module battery_contact(type, pos = true) { //! Draw a positive or negative batte
t = contact_thickness(type);
color("silver") {
rounded_rectangle([contact_width(type), h, t], r = 1, center = false);
rounded_rectangle([contact_width(type), h, t], r = 1);
translate([0, -h / 2, t])
rotate([90, 0, 0])

View File

@@ -40,8 +40,10 @@ function blower_base(type) = type[13]; //! Thickness of the base
function blower_top(type) = type[14]; //! Thickness of the top
function blower_wall(type) = type[15]; //! Side wall thickness
function blower_lug(type) = type[16]; //! Height of the lugs
function blower_wall_left(type) = type[15]; //! Left side wall thickness
function blower_wall_right(type) = type[17]; //! Right wall thickness (for square fans)
function blower_casing_is_square(type) = len(blower_screw_holes(type)) > 3; //! True for square radial fans, false for spiral shape radial blowers
function blower_casing_is_square(type) = blower_depth(type) < 15; //! True for square radial fans, false for spiral shape radial blowers
function blower_exit_offset(type) = blower_casing_is_square(type) ? blower_length(type) / 2 : blower_exit(type) / 2; //! Offset of exit's centre from the edge
fan_colour = grey(20);
@@ -74,41 +76,54 @@ module blower_fan(type, casing_is_square) {
module blower_square(type) { //! Draw a square blower
width = blower_width(type);
depth = blower_depth(type);
wall = blower_wall(type);
wall_left = blower_wall_left(type);
wall_right = blower_wall_right(type);
hole_count = len(blower_screw_holes(type));
hole_pitch = (blower_screw_holes(type)[1].x - blower_screw_holes(type)[0].x) / 2;
corner_radius = width / 2 - hole_pitch;
corner_inset = (width - blower_exit(type)) / 2;
corner_inset = (width - blower_exit(type) - wall_left - wall_right) / (hole_count == 2 ? 1 : 2);
module inset_corners()
translate([width / 2, width / 2])
for(i = hole_count == 2 ? [1, 3] : [0 : 3])
rotate(i * 90)
translate([-width / 2 - eps, -width/ 2 - eps])
quadrant(corner_inset, corner_inset - corner_radius);
module square_inset_corners(remove_center = false)
difference() {
//overall outside
square([width, width], center = false);
rounded_square([width, width], corner_radius, center = false);
if (remove_center) {
// cut out the inside, leaving the corners
translate([corner_inset + wall, -eps])
square([width - 2 * (wall + corner_inset), width - wall + eps], center = false);
translate([wall, corner_inset + wall])
square([width - 2 * wall, width - 2 * (wall + corner_inset)], center = false);
translate([hole_count == 2 ? wall_left : corner_inset + wall_left, -eps])
square([blower_exit(type), width / 2], center = false);
translate(blower_axis(type))
circle(d = blower_bore(type) + 1);
} else {
// cut out the bore for the fan
translate(blower_axis(type))
circle(d = blower_bore(type));
}
// corner inset
translate([width / 2, width / 2])
for(i = [0 : 3])
rotate(i * 90)
translate([-width / 2 - eps, -width/ 2 - eps])
quadrant(corner_inset, corner_inset - corner_radius);
inset_corners();
}
base_height = blower_base(type);
linear_extrude(base_height)
difference () {
rounded_square([width, width], corner_radius, center = false);
blower_hole_positions(type)
circle(d = blower_screw_hole(type));
}
// add the lugs which may be higher than the base
linear_extrude(blower_lug(type))
difference () {
intersection() {
rounded_square([width, width], corner_radius, center = false);
inset_corners();
}
blower_hole_positions(type)
circle(d = blower_screw_hole(type));
}

View File

@@ -24,8 +24,9 @@
// h h s t t
RB5015 = ["RB5015", "Blower Runda RB5015", 51.3, 51, 15, 31.5, M4_cap_screw, 26, [27.3, 25.4], 4.5, [[4.3, 45.4], [47.3,7.4]], 20, 14, 1.5, 1.3, 1.2, 15];
PE4020 = ["PE4020", "Blower Pengda Technology 4020", 40, 40, 20, 27.5, M3_cap_screw, 22, [21.5, 20 ], 3.2, [[37,3],[3,37],[37,37]], 29.3, 17, 1.7, 1.2, 1.3, 13];
BL40x10 =["BL40x10","Square radial 4010", 40, 40,9.5, 27, M2_cap_screw, 16, [24, 20 ], 2.4, [[2,2],[38,2],[2,38],[38,38]], 30 , 9.5, 1.5, 1.5, 1.1, 1.5];
BL30x10 =["BL30x10","Square radial fan 3010", 30, 30,10.1,25, M2_cap_screw, 16, [16, 15 ], 2.4, [[3,27],[27,3]], 21.2, 9.5, 1.1, 1.2, 2.5, 2.8, 0.9];
BL40x10 =["BL40x10","Square radial fan 4010", 40, 40,9.5, 27, M2_cap_screw, 16, [24, 20 ], 2.4, [[2,2],[38,2],[2,38],[38,38]], 27.8, 9.5, 1.5, 1.5, 1.1, 1.5, 1.1];
blowers = [BL40x10, PE4020, RB5015];
blowers = [BL30x10, BL40x10, PE4020, RB5015];
use <blower.scad>

View File

@@ -47,7 +47,7 @@ module square_button(type, colour = "yellow") { //! Draw square button with spec
stem = square_button_cap_stem(type);
color(grey(20)) {
rounded_rectangle([w, w, h - 0.5], r = wall, center = false);
rounded_rectangle([w, w, h - 0.5], r = wall);
for(x = [-1, 1], y = [-1, 1])
translate([x * pitch, y * pitch])

View File

@@ -37,7 +37,7 @@ module camera_lens(type, offset = 0, show_lens = true) //! Draw the lens stack,
r = p[1] + offset;
app = p[2];
if(size.x)
rounded_rectangle(size + [2 * offset, 2 * offset, round_to_layer(offset)], r, center = false);
rounded_rectangle(size + [2 * offset, 2 * offset, round_to_layer(offset)], r);
else
if (show_lens)
translate_z(size.y)
@@ -72,7 +72,7 @@ module camera(type, show_lens = true) { //! Draw specified PCB camera
pos = camera_connector_pos(type);
color(grey(20))
translate(pos)
rounded_rectangle(conn, 0.5, center = false);
rounded_rectangle(conn, 0.5);
flex = [5, 0.1];
color("orange")

View File

@@ -326,7 +326,7 @@ module panel_USBA() { //! Draw a panel mount USBA connector
dx = (length2 / 2 - r2);
dy = (width / 2 - r1);
translate_z(l)
rounded_rectangle([length2, width, 1], r = r1, center = false);
rounded_rectangle([length2, width, 1], r = r1);
translate([-dx, -dy, height2 - r2])
rotate([90, 0, 0])

View File

@@ -80,7 +80,7 @@ module display(type) { //! Draw specified display
translate_z(display_ts_thickness(type)) {
difference() {
color("silver")
rounded_rectangle([w, h, t], 0.5, center = false);
rounded_rectangle([w, h, t], 0.5);
color("black")
translate([aperture[0].x, aperture[0].y, - eps])

View File

@@ -73,39 +73,54 @@ SSD1963_4p3 = ["SSD1963_4p3", "LCD display SSD1963 4.3\"", 105.5, 67.2, 3.4, SSD
[[0, -34.5], [12, -31.5]],
];
/* Dimensions taken from:
https://github.com/bigtreetech/BIGTREETECH-TFT35-V3.0/blob/master/Hardware/TFT35%20V3.0-SIZE-TOP.pdf
and
https://github.com/bigtreetech/BIGTREETECH-TFT35-V3.0/blob/master/Hardware/TFT35%20V3.0-SIZE-BOT.pdf
*/
BigTreeTech_TFT35v3_0_PCB = ["", "",
110, 55.77, 1.6, 0, 3, 0, "green", false,
[ [-3.12, 3.17], [-3.12, -3.17], [3.12, -3.17], [3.12, 3.17] ],
[
[ 10, 7.5, 0, "-button_6mm" ],
[ 9, 43, 0, "-buzzer", 5, 9 ],
[ 9, 27, 0, "-potentiometer" ],
[ 102,28.82, 0, "uSD", [26.5, 16, 3] ],
[16.5, 5.9, 0, "2p54boxhdr", 5, 2 ],
[36.5, 5.9, 0, "2p54boxhdr", 5, 2 ],
[56.5, 5.9, 0, "2p54boxhdr", 5, 2 ],
[82.5, 4, 0, "jst_xh", 5 ],
[26.5, 52.8, 180, "jst_xh", 2 ],
[39.5, 52.8, 180, "jst_xh", 3 ],
[52.5, 52.8, 180, "jst_xh", 3 ],
[65.5, 52.8, 180, "jst_xh", 3 ],
[78.5, 52.8, 180, "jst_xh", 3 ],
[94.5, 52.8, 180, "jst_xh", 5 ],
[ 8, 43, 180, "usb_A" ],
[ 97, 4, 0, "chip", 9, 3.5, 1, grey(20) ],
// ESP-8266
[ 23, 28, 90, "2p54socket", 4, 2 ],
110, 55.77, 1.6, // size
0, // corner radius
3, // mounting hole diameter
0, // pad around mounting hole
"green", // color
false, // true if parts should be separate BOM items
[ // hole positions
[-3.12, 3.17], [-3.12, -3.17], [3.12, -3.17], [3.12, 3.17]
],
[]
[ // components
[ 9, -( 8.46 + 17.45)/2, 0, "-buzzer", 5, 9 ],
[ 9, -(23.76 + 34.94)/2, 0, "-potentiometer" ],
[ (6.84 + 12.85)/2, -(45.73 + 51.73)/2, 0, "-button_6mm" ],
[ 102, (15.57 + 42.07)/2, 0, "uSD", [26.5, 16, 3] ],
[ 8, -( 6.76 + 18.76)/2, 180, "usb_A" ],
[ 23, (23.32 + 33.64)/2, 90, "2p54socket", 4, 2 ], // ESP-8266
[ 16.5, 5.9, 0, "2p54boxhdr", 5, 2 ],
[ 36.5, 5.9, 0, "2p54boxhdr", 5, 2 ],
[ 56.5, 5.9, 0, "2p54boxhdr", 5, 2 ],
[ 82.5, 4, 0, "jst_xh", 5 ],
[ 26.5, 52.8, 180, "jst_xh", 2 ],
[ 39.5, 52.8, 180, "jst_xh", 3 ],
[ 52.5, 52.8, 180, "jst_xh", 3 ],
[ 65.5, 52.8, 180, "jst_xh", 3 ],
[ 78.5, 52.8, 180, "jst_xh", 3 ],
[ 94.5, 52.8, 180, "jst_xh", 5 ],
[ 97, 4, 0, "chip", 9, 3.5, 1, grey(20) ],
],
[] // accessories
];
BigTreeTech_TFT35v3_0 = ["BigTreeTech_TFT35v3_0", "BigTreeTech TFT35 v3.0",
84.5, 54.5, 4, BigTreeTech_TFT35v3_0_PCB,
[-6, 0, 0], // pcb offset
84.5, 54.5, 4, // size
BigTreeTech_TFT35v3_0_PCB, // pcb
[7 - (110 - 84.5)/2, 0, 0], // pcb offset from center
[[-40, -26.5], [41.5, 26.5, 0.5]], // aperture
[], // touch screen
0, // thread length
[], // clearance need for the ts ribbon
[], // touch screen position and size
0, // length that studs protrude from the PCB holes
[], // keep out region for ribbon cable
];

View File

@@ -151,10 +151,8 @@ function fan_screw_depth(type, full_depth = false) = fan_boss_d(type) || full_de
function fan_screw_length(type, thickness, full_depth = false) =
let(depth = fan_screw_depth(type, full_depth),
washers = depth == fan_depth(type) ? 2 : 1,
washer = screw_washer(fan_screw(type)),
nut = screw_nut(fan_screw(type)))
screw_longer_than(thickness + depth + washer_thickness(washer) * washers + nut_thickness(nut, true)); //! Screw length required
washers = depth == fan_depth(type) ? 2 : 1)
screw_length(fan_screw(type), thickness + depth, washers, nyloc = true); //! Screw length required
module fan_assembly(type, thickness, include_fan = true, screw = false, full_depth = false) { //! Fan with its fasteners
translate_z(-fan_depth(type) / 2) {

View File

@@ -31,7 +31,9 @@ gt_2p54 = ["gt_2p54", 2.54, 6.6, 10, 3, 6, 0.4, 6.4, 1, 1, 0.2, 2,
gt_3p5 = ["gt_3p5", 3.5, 7.3, 8.5, 4, 5, 0.4, 4, 0, 1.35, 0.4, 1.8, 2, 2, 0, 0, 0];
gt_5p08 = ["gt_5p08", 5.08, 7.9, 10, 5.0, 7, 0.0, 6.8, 1.45, 1.95, 0.5, 4.0, 5.4, 0.5, 0, 0, 0];
gt_6p35 = ["gt_6p35", 6.35, 12.6, 17.4, 6.8, 12, 0.4, 11, 2, 2.7, 0.8, 3.4, 4.2, 2, 1.8, 1.1, 21.4];
gt_5x11 = ["gt_5x11", 5, 8, 11, 5, 7, 0.4, 7, 1.5, 1.5, 1, 2.5, 6, 0, 0, 0, 0];
gt_5x17 = ["gt_5x17", 5, 10, 17, 5, 11, 0.4, 9, 2, 1.5, 1, 3, 6, 0, 0, 0, 0];
green_terminals = [gt_2p54, gt_3p5, gt_5p08, gt_6p35];
green_terminals = [gt_2p54, gt_3p5, gt_5p08, gt_6p35, gt_5x11, gt_5x17];
use <green_terminal.scad>

View File

@@ -34,15 +34,16 @@ hygrometer_hole_r = 21.3;
slot_w = 5.5;
module hygrometer_hole(h = 0) { //! Drill the hole for a hygrometer
round(cnc_bit_r) {
intersection() {
drill(hygrometer_hole_r, h);
extrude_if(h)
round(cnc_bit_r) {
intersection() {
drill(hygrometer_hole_r, 0);
rotate(30)
square([slot_w + 2 * cnc_bit_r, 100], center = true);
rotate(30)
square([slot_w + 2 * cnc_bit_r, 100], center = true);
}
drill((od + 0.2) / 2, 0);
}
drill((od + 0.2) / 2, h);
}
}
function hygrometer_or() = flange_d / 2; //! The outside radius of a hygrometer
@@ -54,13 +55,13 @@ module hygrometer() { //! Draw a hygrometer
color(grey(30))
rotate_extrude()
polygon([
[0, 0],
[aperture_d / 2, 0],
[aperture_d / 2, flange_t],
[flange_d2 / 2, flange_t2],
[flange_d / 2, flange_t],
[flange_d / 2, 0],
[od / 2, 0],
[0, 0],
[aperture_d / 2, 0],
[aperture_d / 2, flange_t],
[flange_d2 / 2, flange_t2],
[flange_d / 2, flange_t],
[flange_d / 2, 0],
[od / 2, 0],
[od / 2, -h],
[0, -h]
]);

View File

@@ -247,10 +247,7 @@ module iec_inserts(type) { //! Place the inserts
module iec_assembly(type, thickness) { //! Assembly with fasteners given panel thickness
screw = iec_screw(type);
washer = screw_washer(screw);
nut = screw_nut(screw);
insert = screw_insert(screw);
screw_length = thickness ? screw_longer_than(iec_flange_t(type) + thickness + washer_thickness(washer) + nut_thickness(nut, true))
screw_length = thickness ? screw_length(screw, iec_flange_t(type) + thickness, 1, nyloc = true)
: insert_screw_length;
iec(type);
@@ -262,6 +259,6 @@ module iec_assembly(type, thickness) { //! Assembly with fasteners given panel
if(thickness)
translate_z(-thickness)
vflip()
nut_and_washer(nut, true);
nut_and_washer(screw_nut(screw), true);
}
}

View File

@@ -194,12 +194,14 @@ module jhead_hot_end_assembly(type, filament, naked = false) { //! Assembly with
if(exploded())
heater_components();
else
intersection() {
heater_components();
if(naked) // hide the wires when not exploded
intersection() {
heater_components();
if(naked)
color("grey") cylinder(r = 12, h = 100, center = true);
else
cube(1, true); // hide the wires when not exploded
}
color("grey")
cylinder(r = 12, h = 100, center = true);
}
else
hidden() // hidden by the tape
heater_components();
}

View File

@@ -33,7 +33,7 @@ module magnet(type) { //! Draw specified magnet
h = magnet_h(type);
r = magnet_r(type);
//vitamin(str("magnet(", type[0], "): Magnet ", od, "mm diameter, ", h, "mm high", id ? str(", ", id, "mm bore") : "" ));
vitamin(str("magnet(", type[0], "): Magnet ", od, "mm diameter, ", h, "mm high", id ? str(", ", id, "mm bore") : "" ));
or = od / 2;
ir = id / 2;

View File

@@ -23,7 +23,7 @@
// od, id, h, r
MAG8x4x4p2 = ["MAG8x4x4p2", 8, 4.2, 4, 0.5];
MAG484 = ["MAG484", inch(1/4), inch(1/8), inch(1/4), 0.5];
MAG5x8 = ["MAG484", 8, 0, 5, 0.5];
MAG5x8 = ["MAG5x8", 8, 0, 5, 0.5];
magnets = [MAG8x4x4p2, MAG484, MAG5x8];

View File

@@ -18,7 +18,11 @@
//
//
//! Used for limit switches.
//! Used for limit switches. Currently only the button type is supported as the lever and roller types are less accurate.
//!
//! The switch is drawn with the button at the nominal operation point. This can be plus or minus `microswitch_op_tol(type)`.
//!
//! When the button is released it comes out by a maximum of `microswitch_fp_max(type)` from the nominal operating point.
//
include <../utils/core/core.scad>
@@ -32,15 +36,19 @@ function microswitch_hole_d(type) = type[6]; //! Screw hole diameter
function microswitch_holes(type) = type[7]; //! Hole positions
function microswitch_button_w(type) = type[8]; //! Button width
function microswitch_button_t(type) = type[9]; //! Button thickness
function microswitch_button_pos(type)= type[10]; //! Button position
function microswitch_legs(type) = type[11]; //! Leg positions
function microswitch_leg(type) = type[12]; //! Leg types
function microswitch_body_clr(type) = type[13]; //! Body colour
function microswitch_button_clr(type)= type[14]; //! Button colour
function microswitch_button_pos(type)= type[10]; //! Button position at operating point
function microswitch_op_tol(type) = type[11]; //! Operating position +/- tolerance
function microswitch_fp_max(type) = type[12]; //! Free position maximum
function microswitch_legs(type) = type[13]; //! Leg positions
function microswitch_leg(type) = type[14]; //! Leg types
function microswitch_body_clr(type) = type[15]; //! Body colour
function microswitch_button_clr(type)= type[16]; //! Button colour
function microswitch_lower_extent(type) = let(leg = microswitch_leg(type)) min([for(pos = microswitch_legs(type)) pos.y - leg.y / 2]); //! How far legs extend downwards
function microswitch_right_extent(type) = let(leg = microswitch_leg(type)) max([microswitch_length(type) / 2, for(pos = microswitch_legs(type)) pos.x + leg.x / 2]); //! How far legs extend right
function microswitch_size(type) = [microswitch_length(type), microswitch_width(type), microswitch_thickness(type)]; //! Body size
module microswitch_hole_positions(type) //! Place children at the hole positions
{
for(hole = microswitch_holes(type))

View File

@@ -23,10 +23,19 @@
small_leg = [0.9, 3.3, 0.4, 0];
medium_leg = [0.5, 3.9, 3.2, 1.6, [0, -0.5]];
large_leg = [11.4, 0.8, 6.3, 1.8, [1.7, 0]];
small_microswitch = ["small_microswitch", "DM1-00P-110-3", 5.8, 6.5, 12.8, 0, 2, [[-3.25, -1.65], [3.25, -1.65]], 2.9, 1.2, [-1.95, 3.75], [[-5.08, -4.95], [0, -4.9], [5.08, -4.9] ], small_leg, grey(20), "white" ];
medium_microswitch = ["medium_microswitch","SS-01 or SS-5GL", 6.4, 10.2, 19.8, 1, 2.35, [[-4.8, -2.6 ], [4.7, -2.6 ]], 3.2, 2, [-2.8, 5.8 ], [[-8.05, -7.05], [0.75, -7.05], [8.05, -7.05] ], medium_leg, grey(20), "burlywood" ];
large_microswitch = ["large_microswitch", "Saia G3 low force", 10.4, 15.9, 28.0, 2, 3.1, [[-11.1, -5.15], [11.2, 5.15]], 4, 2.75,[-9.1, 9.55], [[19.7, 2.19], [19.7, -3.45], [8.3, -10.45] ], large_leg, "ivory", "white" ];
// t w l r h h b b b o f l l b b
// h i e a o o u u u p p e e o u
// i d n d l l t t t g g d t
// c t g i e e t t t t m y t
// k h t u o o o o a p t o
// n h s d p n n n l x o y c n
// e i o s p l
// s a s w t p n e r c
// n n o s l
// s s r
small_microswitch = ["small_microswitch", "DM1-00P-110-3", 5.8, 6.5, 12.8, 0, 2, [[-3.25, -1.65], [3.25, -1.65]], 2.9, 1.2, [-1.95, 3.75], 0.2, 0.55, [[-5.08, -4.95], [0, -4.9], [5.08, -4.9] ], small_leg, grey(20), "white" ];
medium_microswitch = ["medium_microswitch","SS-01 or SS-5GL", 6.4, 10.2, 19.8, 1, 2.35, [[-4.8, -2.6 ], [4.7, -2.6 ]], 3.2, 2, [-2.8, 5.8 ], 0.5, 1.00, [[-8.05, -7.05], [0.75, -7.05], [8.05, -7.05] ], medium_leg, grey(20), "burlywood" ];
large_microswitch = ["large_microswitch", "Saia G3 low force", 10.4, 15.9, 28.0, 2, 3.1, [[-11.1, -5.15], [11.2, 5.15]], 4, 2.75,[-9.1, 9.55], 0.3, 1.2, [[19.7, 2.19], [19.7, -3.45], [8.3, -10.45] ], large_leg, "ivory", "white" ]; //G3M1T1PUL
microswitches = [small_microswitch, medium_microswitch, large_microswitch];

View File

@@ -129,15 +129,13 @@ module mod_screw_positions(type) //! Position children at the screw positions
module module_assembly(type, thickness) { //! Module with its fasteners in place
screw = mod_screw(type);
washer = screw_washer(screw);
nut = screw_nut(screw);
screw_length = screw_longer_than(thickness + mod_screw_z(type) + 2 * washer_thickness(washer) + nut_thickness(nut, true));
screw_length = screw_length(screw, thickness + mod_screw_z(type), 2, nyloc = true);
mod(type);
mod_screw_positions(type) {
translate_z(mod_screw_z(type))
nut_and_washer(nut, true);
nut_and_washer(screw_nut(screw), true);
translate_z(-thickness)
vflip()

View File

@@ -59,7 +59,7 @@ module panel_meter_button(type) { //! Draw panel meter button
color(pmeter_button_colour(type))
translate(pmeter_button_pos(type))
if(size.x)
rounded_rectangle(pmeter_button_size(type), r, center = false);
rounded_rectangle(pmeter_button_size(type), r);
else
cylinder(r = r, h = size.z);
}
@@ -93,8 +93,8 @@ module panel_meter(type) { //! Draw panel mounted LCD meter module
difference() {
if(is_list(bevel))
hull() {
rounded_rectangle([bezel.x - 2 * bevel.x, bezel.y - 2 * bevel.x, bezel.z], r - bevel.x, center = false);
rounded_rectangle([bezel.x, bezel.y, bevel[1]], r, center = false);
rounded_rectangle([bezel.x - 2 * bevel.x, bezel.y - 2 * bevel.x, bezel.z], r - bevel.x);
rounded_rectangle([bezel.x, bezel.y, bevel[1]], r);
}
else
hull() {
@@ -111,7 +111,7 @@ module panel_meter(type) { //! Draw panel mounted LCD meter module
cube([ap.x + ap.z, ap.y + ap.z, eps], center = true);
translate_z(bezel.z + eps)
rounded_rectangle([ap.x, ap.y, bezel.z * 2], r, center = true);
rounded_rectangle([ap.x, ap.y, bezel.z * 2], r, true);
}
}
//

View File

@@ -126,7 +126,7 @@ module usb_A(h, v_flange_l, bar, cutout) {
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);
h + 2 * h_flange_h + 2 * panel_clearance, 100], r = cnc_bit_r);
else {
color("silver") rotate([0, 90, 0]) {
linear_extrude(l, center = true)
@@ -1121,9 +1121,7 @@ module pcb_assembly(type, height, thickness) { //! Draw PCB assembly with spaces
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));
screw_length = screw_length(screw, height + thickness + pcb_thickness(type), 1, nyloc = true);
taper = screw_smaller_than(pcb_hole_d(type)) > 2 * screw_radius(screw); // Arduino?
pcb_screw_positions(type) {
@@ -1138,7 +1136,7 @@ module pcb_assembly(type, height, thickness) { //! Draw PCB assembly with spaces
translate_z(-thickness)
vflip()
nut_and_washer(nut, true);
nut_and_washer(screw_nut(screw), true);
}
}
}

View File

@@ -21,6 +21,7 @@ include <d_connectors.scad>
include <leds.scad>
include <axials.scad>
include <smds.scad>
include <green_terminals.scad>
//
// l w t r h l c b h
@@ -195,6 +196,312 @@ Duex5 = ["Duex5", "Duex5 expansion board",
]),
[]];
BTT_SKR_MINI_E3_V2_0 = [
"BTT_SKR_MINI_E3_V2_0", "BigTreeTech SKR Mini E3 v2.0",
100.75, 70.25, 1.6, // size
1, // corner radius
3, // mounting hole diameter
5, // pad around mounting hole
grey(30), // color
false, // true if parts should be separate BOM items
[ // hole positions
for (i = [ [0, 0], [62.15, 0] ])
(i + [20.3, -2.89]),
for (i = [ [0, -34.98], [31.80, -37.63], [95.68, -64.47] ])
(i + [2.535, -2.89])
],
[ // components
// cpu
[ 55, 33, 0, "chip", 10, 10, 1, grey(15) ],
// driver chips
for (x = [10.5, 30.5, 50.5, 70.5])
[ x, -17.5, 0, "chip", 5, 5, 1, grey(15) ],
// mock up heat sinks over the chips
for (x = [10.5, 30.5, 50.5, 70.5])
[ x, -17.5, 0, "block", 9, 8.5, 2, "DeepSkyBlue" ],
for(x = [10.5, 30.5, 50.5, 70.5], y = [-4,-2,0,2,4])
[ x, -17.5 + y, 0, "block", 9, 0.75, 11, "DeepSkyBlue" ],
// heat dissipation for drivers under board
[ 43, -17.5, 0, "-block", 85, 8, 0.1, gold ],
// heated bed
[ 26, 16, 0, "chip", 9.5, 8.5, 4, grey(15) ],
[ 27, 19, 0, "-block", 13, 14, 0.1, gold ],
// hotend
[ 37, 14, 0, "chip", 6, 6, 2.5, grey(15) ],
[ 40, 16, 0, "-block", 10, 8, 0.1, gold ],
// voltage regulator heat dissipation
[ 12, 28.5, 0, "-block", 11, 7, 0.1, gold ],
// terminals
[ 5.25, 5.3, 180, "gterm", gt_5x17, 2, undef, grey(20) ],
[ 18.1, 5.1, -90, "gterm", gt_5x17, 2, undef, grey(20) ],
[ 29.3, 5.1, -90, "gterm", gt_5x17, 2, undef, grey(20) ],
[ 40.5, 5.1, -90, "gterm", gt_5x11, 2, undef, grey(20) ],
// SD and USB
[ -3, -(22.27 + 29.92)/2, 0, "usb_uA" ],
[ -8, -( 2.13 + 17.17)/2, 0, "uSD", [17.17 - 2.13, 16, 2] ],
// EXP
[ -4.5, 17, -90, "2p54boxhdr", 5, 2 ],
// TFT
[ 66.1, 21.7, 0, "2p54header", 5, 1 ],
// FAN0
[ 50.25, 3.8, 0, "jst_xh", 2, false, grey(20) ],
// FAN1
[ 49.9, 16.1, 0, "jst_xh", 2, false, grey(20) ],
// PS-ON
[ 58.1, 16.1, 0, "jst_xh", 2, false, grey(20) ],
// PWR-DET
[ 67.5, 16.0, 0, "jst_xh", 3, false, grey(20) ],
// E0-STOP
[ 78.2, 16.0, 0, "jst_xh", 3, false, grey(20) ],
// Z-PROBE
[ 87.2, 20.5, -90,"jst_xh", 5, false, grey(20) ],
// NEO Pixel
[ 78.2, 27.1, 0, "jst_xh", 3, false, grey(20) ],
// end stops
[ 58.60, 3.8, 0, "jst_xh", 2, false, grey(20) ],
[ 66.70, 3.8, 0, "jst_xh", 2, false, grey(20) ],
[ 74.90, 3.8, 0, "jst_xh", 2, false, grey(20) ],
// thermistors
[ 83.00, 3.8, 0, "jst_xh", 2, false, grey(20) ],
[ 91.10, 3.8, 0, "jst_xh", 2, false, grey(20) ],
// motor connections
[ 10.15, -4.2, 0, "jst_xh", 4, false, grey(20) ],
[ 30.35, -4.2, 0, "jst_xh", 4, false, grey(20) ],
[ 43.90, -4.2, 0, "jst_xh", 4, false, grey(20) ],
[ 57.25, -4.2, 0, "jst_xh", 4, false, grey(20) ],
[ 70.75, -4.2, 0, "jst_xh", 4, false, grey(20) ],
// motor jumpers
[ 20.6, 44.1, 0, "2p54header", 2, 1 ],
[ 39.6, 44.2, 0, "2p54header", 2, 1 ],
[ 60.1, 44.1, 0, "2p54header", 2, 1 ],
[ 80.3, 44.1, 0, "2p54header", 2, 1 ],
// SWD
[ 43.9, 39.2, 0, "2p54header", 1, 5 ],
// SPI
[ -3.1, 31.9, 0, "2p54header", 2, 3 ],
// PWR-1
[ -12.8, 30.3, 0, "2p54header", 3, 1 ],
// VOUT
[ -14.0, 34.4, 0, "2p54header", 2, 2 ],
// VIN
[ 17.3, 19.6, 0, "2p54header", 2, 2 ],
],
[] // accessories
];
BTT_SKR_E3_TURBO = [
"BTT_SKR_E3_TURBO", "BigTreeTech SKR E3 Turbo",
102, 90.25, 1.6, // size
1, // corner radius
3.5, // mounting hole diameter
5, // pad around mounting hole
grey(30), // color
false, // true if parts should be separate BOM items
[ // hole positions
for ( i=[ [0, 0], [62.15, 0.25] ])
(i + [21.6, -13.3]),
for( i=[ [0, -34.98 ], [31.80, -37.62 ], [95.68, -64.47] ])
(i + [3.75, -13.25])
],
[ // components
// cpu
[ 62.8, 42.5, 0, "chip", 14, 14, 1, grey(15) ],
// driver chips
for (x = [8.5, 27.5, 43.2, 58.5, 74])
[x, -20, 0, "chip", 5, 5, 1, grey(15)],
// mock up heat sinks over the chips
for (x = [8.5, 27.5, 43.2, 58.5, 74])
[x, -20, 0, "chip", 9, 8.5, 2, "DeepSkyBlue" ],
for (x = [8.5, 27.5, 43.2, 58.5, 74], y = [-4,-2,0,2,4])
[x, -20 + y, 0, "chip", 9, 0.75, 11, "DeepSkyBlue" ],
// heat dissipation for drivers under board
[ 43, -21, 0, "-block", 85, 8, 0.1, gold ],
// hotend and heated bed
[ 25.5, 20, 0, "chip", 10, 8.5, 4, grey(15) ],
[ 25.5, 20, 0, "-block", 11, 11, 0.1, gold ],
[ 36.25, 16.75, 0, "chip", 6.5, 6, 2.5, grey(15) ],
[ 36.25, 17, 0, "-block", 7.5, 7.5, 0.1, gold ],
[ 44.25, 16.75, 0, "chip", 6.5, 6, 2.5, grey(15) ],
[ 44.25, 17, 0, "-block", 7.5, 7.5, 0.1, gold ],
// voltage regulator
[ 15.1, 44.2, 0, "chip", 4, 5, 2, grey(15) ],
[ 12.1, 44.2, 0, "-block", 10, 10, 0.1, gold ],
// terminals
[ 5.25, 5.3, 180, "gterm", gt_5x17, 2, undef, grey(20) ],
[ 16.25, 5.4, -90, "gterm", gt_5x17, 2, undef, grey(20) ],
[ 26.25, 5.4, -90, "gterm", gt_5x17, 2, undef, grey(20) ],
[ 36.1, 6.7, -90, "gterm", gt_5x11, 2, undef, "lightgreen" ],
[ 45.0, 6.7, -90, "gterm", gt_5x11, 2, undef, "lightgreen" ],
[ -3, -(32.27 + 39.92)/2, 0, "usb_uA" ],
[ -8, -(12.13 + 27.17)/2, 0, "uSD", [17.17 - 2.13, 16, 2] ],
[ -22.2, 51.6, 0, "button_6mm" ],
// EXP
[ -4.45, 27.2, -90, "2p54boxhdr", 5, 2 ],
// AUX-2
[ -3.4, 42.5, -90, "2p54header", 4, 2 ],
// TFT
[ 73.7, 21, 0, "2p54header", 5, 1 ],
// FAN0
[ 52.1, 15.3, 180, "jst_xh", 2, false, grey(20) ],
// FAN1
[ 60.1, 15.3, 180, "jst_xh", 2, false, grey(20) ],
// PS-ON
[ 67.9, 15.3, 180, "jst_xh", 2, false, grey(20) ],
// E0-STOP
[ 77.1, 15.3, 180, "jst_xh", 3, false, grey(20) ],
// E1-STOP
[ 87.5, 15.3, 180, "jst_xh", 3, false, grey(20) ],
// Z-PROBE
[ 85.05, 34.6, 180, "jst_xh", 5, false, grey(20) ],
// NEO Pixel
[ 77, 26.8, 180, "jst_xh", 3, false, grey(20) ],
// PWR-DET
[ 87.7, 26.8, 180, "jst_xh", 3, false, grey(20) ],
// FAN2
[ 52.1, 3.8, 0, "2p54header", 1, 2],
// end stops and thermistors
for (x = [58.5 : 7.9 : 98.1])
[x, 3.7, 180, "jst_xh", 2, false, grey(20)],
// motor connections
for (x = [7, 27.1, 47.3, 67.5, 87.9])
[x, -3.9, 0, "jst_xh", 4, false, grey(20)],
[47.3, -10.4, 0, "jst_xh", 4, false, grey(20)], // second Z connector
// motor jumpers
for (x = [9.4, 26.4, 42.5, 58.7, 75.3])
[x, -33.7, 0, "2p54header", 2, 1],
// SWD
[ 45.4, 35.7, 0, "2p54header", 5, 1 ],
// USB power jumber
[ -12.6, 40.3, 0, "2p54header", 3, 1 ],
// VOUT
[ -13.9, 44.5, 0, "2p54header", 2, 2 ],
// VIN
[ 18.6, 29.8, 0, "2p54header", 2, 2 ],
],
[] // accessories
];
TMC2130 = [
"TMC2130", "TMC2130",
20, 14, 1.6, // size
0, 0, 0, // corner radius, mounting hole diameter, pad around mounting hole
grey(95), // colour
false, // true if parts should be separate BOM items
[], // hole positions
[
[ 10, 1, 0, "-2p54header", 8, 1 ],
[ 10, 13, 0, "-2p54header", 8, 1 ],
[ 12, 7, 0, "-chip", 6, 4, 1, grey(20) ],
// mock up a heat sink
[ 10, 7, 0, "block", 9, 8.5, 2, "DeepSkyBlue" ],
for (y = [-4,-2,0,2,4]) [ 10, 7 + y, 0, "block", 9, 0.75, 11, "DeepSkyBlue" ],
],
[]
];
BTT_SKR_V1_4_TURBO = [
"BTT_SKR_V1_4_TURBO", "BigTreeTech SKR v1.4 Turbo",
110, 85, 1.6, // size
1, // corner radius
3, // mounting hole diameter
4, // pad around mounting hole
grey(30), // colour
false, // true if parts should be separate BOM items
[ // hole positions
[-4, 4], [-4, -4], [4, -4], [4, 4]
],
[ // components
[ (29.15+31.5)/2, 8, -90, "usb_B" ],
[ (46.9+51.55)/2, 7, -90, "uSD", [14, 14, 2] ],
[ 105, 13, 0, "button_6mm" ],
[ 58, 43, 0, "chip", 15, 15, 1, grey(20) ],
// ESP-01 socket
[ 69.8, 4, 0, "2p54socket", 4, 2 ],
// terminals
[ 5.3, 13.2, 180, "gterm", gt_5x17, 2, undef, grey(20)],
[ 5.3, 25.8, 180, "gterm", gt_5x17, 2, undef, grey(20)],
[ 5.3, 37.2, 180, "gterm", gt_5x11, 2, undef, grey(20)],
[ 5.3, 47.2, 180, "gterm", gt_5x11, 2, undef, grey(20)],
[ 2.8, 56.7, -90, "jst_xh", 2, false, grey(20) ],
[ 10.9, 56.7, 90, "jst_xh", 2, false, grey(20) ],
[ 82, 4, 0, "jst_xh", 2, false, grey(20) ],
[ 90, 4, 0, "jst_xh", 2, false, grey(20) ],
[ 98, 4, 0, "jst_xh", 2, false, grey(20) ],
[ 87.7, 29.0, -90, "jst_xh", 3, false, grey(20) ],
[ 87.7, 39.5, -90, "jst_xh", 3, false, grey(20) ],
[ 87.7, 50.1, -90, "jst_xh", 3, false, grey(20) ],
[ 95.3, 29.0, -90, "jst_xh", 3, false, grey(20) ],
[ 95.3, 39.5, -90, "jst_xh", 3, false, grey(20) ],
[ 95.3, 50.1, -90, "jst_xh", 3, false, grey(20) ],
[ 85.7, 18.2, 180, "jst_xh", 3, false, grey(20) ],
[ 94.9, 18.2, 180, "jst_xh", 2, false, grey(20) ],
[ 77.2, 19.6, -90, "jst_xh", 3, false, grey(20) ],
[ 69.8, 11.0, 0, "jst_xh", 5, false, grey(20) ],
[ 69.0, 19.2, 0, "2p54header", 4, 1 ],
[ 57.8, 18.0, 0, "2p54header", 3, 2 ],
[ 28.0, 19.7, 0, "2p54header", 2, 2 ],
[ 37.6, 28.8, 0, "2p54header", 1, 3, undef, "red" ],
[ 77.8, 27.5, 0, "2p54header", 2, 2 ],
[ 81.8, 26.4, 0, "2p54header", 1, 3, undef, "red" ],
[ 43.8, 42.8, 0, "2p54header", 1, 5 ],
// EXP1 & EXP2
[ -6.6, 29.4, 90, "2p54boxhdr", 5, 2 ],
[ -6.6, 50.4, 90, "2p54boxhdr", 5, 2 ],
// motor axes connections
[ 11.2, -3.75, 180, "jst_xh", 2, false, grey(20) ],
[ 21.8, -3.75, 180, "jst_xh", 4, false, grey(20) ],
[ 35.0, -3.75, 180, "jst_xh", 4, false, grey(20) ],
[ 48.2, -3.75, 180, "jst_xh", 4, false, grey(20) ],
[ 61.4, -3.75, 180, "jst_xh", 4, false, grey(20) ],
[ 74.7, -3.75, 180, "jst_xh", 4, false, grey(20) ],
[ 87.9, -3.75, 180, "jst_xh", 4, false, grey(20) ],
[ 98.5, -3.75, 180, "jst_xh", 2, false, grey(20) ],
// stepper drivers
[ 11.5, 62.5, 0, "2p54socket", 8, 1, undef, undef, undef, "red" ],
[ 11.5, 75.2, 0, "2p54socket", 8, 1 ],
[ 2.6, 66.3, 90, "2p54socket", 2, 1, undef, undef, undef, "red" ],
[ 11.5, 68.85, 0, "pcb", 11, TMC2130 ],
[ 33.1, 62.5, 0, "2p54socket", 8, 1, undef, undef, undef, "red" ],
[ 33.1, 75.2, 0, "2p54socket", 8, 1 ],
[ 24.2, 66.3, 90, "2p54socket", 2, 1, undef, undef, undef, "red" ],
[ 33.1, 68.85, 0, "pcb", 11, TMC2130 ],
[ 54.8, 62.5, 0, "2p54socket", 8, 1, undef, undef, undef, "red" ],
[ 54.8, 75.2, 0, "2p54socket", 8, 1 ],
[ 45.9, 66.3, 90, "2p54socket", 2, 1, undef, undef, undef, "red" ],
[ 54.8, 68.85, 0, "pcb", 11, TMC2130 ],
[ 76.4, 62.5, 0, "2p54socket", 8, 1, undef, undef, undef, "red" ],
[ 76.4, 75.2, 0, "2p54socket", 8, 1 ],
[ 67.5, 66.3, 90, "2p54socket", 2, 1, undef, undef, undef, "red" ],
[ 76.4, 68.85, 0, "pcb", 11, TMC2130 ],
[ 98.1, 62.5, 0, "2p54socket", 8, 1, undef, undef, undef, "red" ],
[ 98.1, 75.2, 0, "2p54socket", 8, 1 ],
[ 89.2, 66.3, 90, "2p54socket", 2, 1, undef, undef, undef, "red" ],
// closed loop pins
[ 24.4, 57.5, 0, "2p54header", 6, 1 ],
[ 40.6, 57.5, 0, "2p54header", 6, 1 ],
[ 56.7, 57.5, 0, "2p54header", 6, 1 ],
[ 72.9, 57.5, 0, "2p54header", 6, 1 ],
[ 89.1, 57.5, 0, "2p54header", 6, 1 ],
],
[] // accessories
];
Melzi = ["Melzi", "Melzi electronics", 203.2, 49.53, 1.6, 3.81, 3.1, 6, "green", false, [[3.81, 3.81], [-3.81, 3.81], [-3.81, -3.81], [3.81, -3.81]],
[],
@@ -414,8 +721,35 @@ RAMPSEndstop = ["RAMPSEndstop", "RAMPS Endstop Switch",
],
[]];
ESP_01 = [
"ESP-01", "ESP-01",
24.8, 14.6, 1, // size
0, // corner radius
0, // mounting hole diameter
0, // pad around mounting hole
grey(25), // color
false, // true if parts should be separate BOM items
[], // hole positions
[ // components
[ 2.8, -7.25, 0, "-2p54header", 2, 4 ],
[ -14.55, -11.3, 0, "chip", 5.25, 5.25, 2.25, grey(15) ],
[ -14, -5.2, 0, "chip", 4.5, 4.75, 1.1, grey(15) ],
// antenna
for (y = [ 2.8 : 2.3 : 7.4 ]) [ -0.7, -y, 0, "block", 0.7, 1.75, 0.1, gold ],
for (y = [ 4 : 2.3 : 10.6 ]) [ -4.3, -y, 0, "block", 0.7, 1.75, 0.1, gold ],
for (y = [ 3.4 : 2.3 : 10.1 ]) [ -2.5, -y, 0, "block", 4.3, 0.7, 0.1, gold ],
for (y = [ 4.55 : 2.3 : 11.2 ]) [ -2.5, -y, 0, "block", 4.3, 0.7, 0.1, gold ],
pcbs = [MP1584EN, TP4056, MT3608, RAMPSEndstop, ExtruderPCB, PI_IO, ZC_A0591, RPI0, EnviroPlus, ArduinoUno3, ArduinoLeonardo, Keyes5p1, PSU12V1A, WD2002SJ, RPI3, RPI4, DuetE, Duex2, Duex5];
[ -0.7, -10.85, 0, "block", 0.7,3.75, 0.1, gold ],
[ -6.6, -5.8, 0, "block", 0.7, 7.5, 0.1, gold ],
[ -4.8, -2.3, 0, "block", 8.8, 0.7, 0.1, gold ],
],
[] // accessories
];
pcbs = [MP1584EN, TP4056, ESP_01, RAMPSEndstop, MT3608, PI_IO, ExtruderPCB, ZC_A0591, RPI0, EnviroPlus, ArduinoUno3, ArduinoLeonardo, WD2002SJ, RPI3, RPI4, BTT_SKR_MINI_E3_V2_0, BTT_SKR_E3_TURBO, BTT_SKR_V1_4_TURBO, DuetE, Duex5];
pcbs_not_shown = [Melzi, Duex2, PSU12V1A, Keyes5p1];
perfboards = [PERF74x51, PERF70x50, PERF60x40, PERF70x30, PERF80x20];

View File

@@ -53,7 +53,7 @@ function pulley_extent(type) = max(pulley_flange_dia(type), pulley_hub_dia(type)
T_angle = 40;
GT_r = 0.555;
module pulley(type) { //! Draw a pulley
module pulley(type, colour = silver) { //! Draw a pulley
teeth = pulley_teeth(type);
od = pulley_od(type);
@@ -64,6 +64,7 @@ module pulley(type) { //! Draw a pulley
hl = pulley_hub_length(type);
w = pulley_width(type);
r1 = pulley_bore(type) / 2;
screw_z = pulley_screw_z(type);
or = od / 2;
ir = pulley_ir(type);
@@ -100,39 +101,48 @@ module pulley(type) { //! Draw a pulley
}
}
module screw_holes() {
if(pulley_screws(type))
translate_z(pulley_screw_z(type))
for(i = [0 : pulley_screws(type) - 1])
rotate([-90, 0, i * -90])
cylinder(r = screw_radius(pulley_screw(type)), h = 100);
}
module hub()
rotate_extrude() translate([r1, 0]) {
if(hl)
square([pulley_hub_dia(type) / 2 - r1, hl]);
color("silver") {
render() difference() {
rotate_extrude() translate([r1, 0]) {
if(hl)
square([pulley_hub_dia(type) / 2 - r1, hl]);
for(z = [pulley_hub_length(type), hl + ft + w])
translate([0, z])
square([pulley_flange_dia(type) / 2 - r1, ft]);
}
if(pulley_screw_z(type) < hl)
screw_holes();
for(z = [pulley_hub_length(type), hl + ft + w])
translate([0, z])
square([pulley_flange_dia(type) / 2 - r1, ft]);
}
render() difference() { // T5 pulleys have screw through the teeth
module screw_holes()
translate_z(screw_z)
for(i = [0 : pulley_screws(type) - 1])
rotate([-90, 0, i * -90])
cylinder(r = screw_radius(pulley_screw(type)), h = 100);
color(colour) {
if(screw_z && screw_z < hl)
render()
difference() {
hub();
screw_holes();
}
else
hub();
if(screw_z && screw_z > hl) // T5 pulleys have screw through the teeth
render()
difference() {
core();
screw_holes();
}
else
core();
if(pulley_screw_z(type) > hl)
screw_holes();
}
}
}
module pulley_assembly(type) { //! Draw a pulley with its grub screws in place
module pulley_assembly(type, colour = silver) { //! Draw a pulley with its grub screws in place
translate_z(pulley_offset(type)) {
pulley(type);
pulley(type, colour);
if(pulley_screws(type))
translate_z(pulley_screw_z(type))

View File

@@ -31,10 +31,11 @@ function rail_bore(type) = type[5]; //! Counter bore diameter for screw
function rail_hole(type) = type[6]; //! Screw hole diameter
function rail_bore_depth(type) = type[7]; //! Counter bore depth
function rail_screw(type) = type[8]; //! Screw type
function rail_carriage(type) = type[9]; //! Carriage type
function rail_end_screw(type) = type[10]; //! Screw used for ends only (Countersink used for better location)
function rail_end_screw(type) = type[9]; //! Screw used for ends only (Countersink used for better location)
function rail_groove_offset(type)=type[10]; //! Offset of centre of groove from top of rail
function rail_groove_width(type)=type[11]; //! Groove width
function rail_screw_height(type, screw) = rail_height(type) - rail_bore_depth(type) + screw_head_depth(screw, rail_hole(type)); //! Position screw taking into account countersink into counterbored hole
function rail_travel(type, length) = length - carriage_length(rail_carriage(type)); //! How far the carriage can travel
function carriage_length(type) = type[0]; //! Overall length
function carriage_block_length(type) = type[1]; //! Length of the metal part
@@ -45,7 +46,9 @@ function carriage_clearance(type) = type[4]; //! Gap under the carriage
function carriage_pitch_x(type) = type[5]; //! Screw hole x pitch
function carriage_pitch_y(type) = type[6]; //! Screw hole y pitch
function carriage_screw(type) = type[7]; //! Carriage screw type
function carriage_rail(type) = type[8]; //! Rail type
function carriage_screw_depth(type) = 2 * screw_radius(carriage_screw(type)); //! Carriage thread depth
function carriage_travel(type, rail_length) = rail_length - carriage_length(type); //! How far the carriage can travel on a given length rail
function rail_holes(type, length) = //! Number of holes in a rail given its `length`
floor((length - 2 * rail_end(type)) / rail_pitch(type)) + 1;
@@ -53,7 +56,7 @@ function rail_holes(type, length) = //! Number of holes in a rail given its `len
module rail_hole_positions(type, length, first = 0, screws = 100, both_ends = true) { //! Position children over screw holes
pitch = rail_pitch(type);
holes = rail_holes(type, length);
last = first + screws;
last = first + min(screws, both_ends ? ceil(holes / 2) : holes);
for(i = [first : holes - 1], j = holes - 1 - i)
if(i < last || both_ends && (j >= first && j < last))
translate([i * pitch - length / 2 + (length - (holes - 1) * pitch) / 2, 0])
@@ -70,7 +73,7 @@ module carriage_hole_positions(type) { //! Position children over screw holes
children();
}
module carriage(type, rail, end_colour = grey(20), wiper_colour = grey(20)) { //! Draw the specified carriage
module carriage(type, end_colour = grey(20), wiper_colour = grey(20)) { //! Draw the specified carriage
total_l = carriage_length(type);
block_l = carriage_block_length(type);
block_w = carriage_width(type);
@@ -82,9 +85,9 @@ module carriage(type, rail, end_colour = grey(20), wiper_colour = grey(20)) { //
screw_depth = carriage_screw_depth(type);
module cutout() {
w = rail_width(rail) + 0.4;
w = rail_width(carriage_rail(type)) + 0.4;
translate([-w / 2, 0])
square([w , rail_height(rail) + 0.2]);
square([w , rail_height(carriage_rail(type)) + 0.2]);
}
color(grey(90)) {
@@ -134,66 +137,68 @@ module carriage(type, rail, end_colour = grey(20), wiper_colour = grey(20)) { //
carriage_end(type, end_w, end_h, end_l);
}
module rail(type, length) { //! Draw the specified rail
module rail(type, length, colour = grey(90), use_polycircles = false) { //! Draw the specified rail
width = rail_width(type);
height = rail_height(type);
vitamin(str("rail(", type[0], ", ", length, "): Linear rail ", type[0], " x ", length, "mm"));
color(grey(90)) {
color(colour) {
rbr = rail_bore(type) / 2;
w = corrected_radius(rbr) * 2 + 2 * eps; // width of core big enough for the holes
linear_extrude(height - rail_bore_depth(type)) difference() {
square([length, width], center = true);
square([length, w], center = true);
rail_hole_positions(type, length)
circle(d = rail_hole(type));
if (use_polycircles)
poly_circle(rail_hole(type) / 2);
else
circle(d = rail_hole(type));
}
translate_z(rail_height(type) - rail_bore_depth(type))
linear_extrude(rail_bore_depth(type)) difference() {
square([length, w], center = true);
translate_z(rail_height(type) - rail_bore_depth(type)) {
h1 = rail_bore_depth(type) > 2 ? rail_bore_depth(type) / 3 : rail_bore_depth(type) / 2;
h0 = rail_bore_depth(type) > 2 ? (rail_bore_depth(type) - h1) / 2 : 0;
h2 = rail_bore_depth(type) - h1 - h0;
linear_extrude(h0) difference() {
square([length, width], center = true);
rail_hole_positions(type, length)
circle(d = rail_bore(type));
if (use_polycircles)
poly_circle(rbr);
else
circle(rbr);
}
translate_z(h0)
linear_extrude(h1) difference() {
w1 = max(width - 2, rail_bore(type));
square([length, w1], center = true);
rail_hole_positions(type, length)
circle(d = rail_bore(type));
}
translate_z(h0 + h1)
linear_extrude(h2) difference() {
square([length, width], center = true);
rail_hole_positions(type, length)
circle(d = rail_bore(type));
}
}
go = height - rail_groove_offset(type);
gw = rail_groove_width(type);
gd = gw / 2;
sw = (width - w) / 2;
for (m = [0, 1])
mirror([0, m, 0])
translate([0, -width / 2])
rotate([0, -90, 0])
linear_extrude(length, center = true)
polygon([ [0, 0], [0, sw], [height, sw], [height, 0], [go + gw/2, 0], [go, gd], [go - gw/2, 0] ]);
}
}
module rail_assembly(type, length, pos, carriage_end_colour = grey(20), carriage_wiper_colour = grey(20)) { //! Rail and carriage assembly
rail(type, length);
module rail_assembly(carriage, length, pos, carriage_end_colour = grey(20), carriage_wiper_colour = grey(20)) { //! Rail and carriage assembly
rail(carriage_rail(carriage), length);
translate([pos, 0])
carriage(rail_carriage(type), type, carriage_end_colour, carriage_wiper_colour);
carriage(carriage, carriage_end_colour, carriage_wiper_colour);
}
module rail_screws(type, length, thickness, screws = 100) { //! Place screws in the rail
module rail_screws(type, length, thickness, screws = 100, index_screws = undef) { //! Place screws in the rail
screw = rail_screw(type);
end_screw = rail_end_screw(type);
screw_len = screw_longer_than(rail_screw_height(type, screw) + thickness);
end_screw_len = screw_longer_than(rail_screw_height(type, end_screw) + thickness);
index_screws = screws > 2 ? 1 : 2;
index_screws = is_undef(index_screws) ? screws > 2 ? 1 : 2 : index_screws;
translate_z(rail_screw_height(type, end_screw))
rail_hole_positions(type, length, 0, index_screws)
screw(end_screw, end_screw_len);
translate_z(rail_screw_height(type, screw))
rail_hole_positions(type, length, index_screws, min(screws, rail_holes(type, length)) - 2 * index_screws)
rail_hole_positions(type, length, index_screws, screws - index_screws)
screw(screw, screw_len);
}

View File

@@ -17,30 +17,29 @@
// If not, see <https://www.gnu.org/licenses/>.
//
//
// Carriages
//
// L L1 W H H1 C B
MGN5_carriage = [ 16, 9.6, 12, 6, 1.5, 0, 8 , M2_cap_screw ];
MGN7_carriage = [ 23, 14.3, 17, 8, 1.5, 8, 12, M2_cap_screw ];
MGN9_carriage = [ 29.7, 20.8, 20, 10, 2, 10, 15, M3_cap_screw ];
MGN12_carriage = [ 34.7, 21.7, 27, 13, 3, 15, 20, M3_cap_screw ];
MGN12H_carriage= [ 45.4, 32.4, 27, 13, 3, 20, 20, M3_cap_screw ];
MGN15_carriage = [ 43.3, 27.7, 32, 16, 4, 20, 25, M3_cap_screw ];
SSR15_carriage = [ 40.3, 23.3, 34, 24, 4.5, 0, 26, M4_cap_screw ];
//
// Rails
//
// Wr Hr E P D d h go gw
MGN5 = [ "MGN5", 5, 3.6, 5, 15, 3.6, 2.4, 0.8, M2_cs_cap_screw, M2_cs_cap_screw, 1, 1 ]; // Screw holes too small for M2 heads
MGN7 = [ "MGN7", 7, 5, 5, 15, 4.3, 2.4, 2.6, M2_cap_screw, M2_cs_cap_screw, 1.5, 1.5 ];
MGN9 = [ "MGN9", 9, 6, 5, 20, 6.0, 3.5, 3.5, M3_cap_screw, M3_cs_cap_screw, 1.5, 1.5 ];
MGN12 =[ "MGN12", 12, 8, 10, 25, 6.0, 3.5, 4.5, M3_cap_screw, M3_cs_cap_screw, 2.25, 2.75];
MGN15 =[ "MGN15", 15, 10, 10, 40, 6.0, 3.5, 5.0, M3_cap_screw, M3_cs_cap_screw, 2.5, 2.75 ];
SSR15= [ "SSR15", 15, 12.5, 10, 60, 7.5, 4.5, 5.3, M4_cap_screw, M4_cs_cap_screw, 2.5, 2.75 ];
//
// Wr Hr E P D d h
MGN5 = [ "MGN5", 5, 3.6, 5, 15, 3.6, 2.4, 0.8, M2_cs_cap_screw, MGN5_carriage, M2_cs_cap_screw ]; // Screw holes too small for M2 heads
MGN7 = [ "MGN7", 7, 5, 5, 15, 4.3, 2.4, 2.6, M2_cap_screw, MGN7_carriage, M2_cs_cap_screw ];
MGN9 = [ "MGN9", 9, 6, 7.5, 20, 6.0, 3.5, 3.5, M3_cap_screw, MGN9_carriage, M3_cs_cap_screw ];
MGN12= [ "MGN12", 12, 8, 10, 25, 6.0, 3.5, 4.5, M3_cap_screw, MGN12_carriage, M3_cs_cap_screw ];
MGN12H=[ "MGN12H",12, 8, 10, 25, 6.0, 3.5, 4.5, M3_cap_screw, MGN12H_carriage,M3_cs_cap_screw ];
MGN15= [ "MGN15", 15, 10, 10, 40, 6.0, 3.5, 5.0, M3_cap_screw, MGN15_carriage, M3_cs_cap_screw ];
SSR15= [ "SSR15", 15, 12.5,10, 60, 7.5, 4.5, 5.3, M4_cap_screw, SSR15_carriage, M4_cs_cap_screw ];
// Carriages
//
// L L1 W H H1 C B
MGN5_carriage = [ 16, 9.6, 12, 6, 1.5, 0, 8, M2_cap_screw, MGN5 ];
MGN7C_carriage = [ 23, 14.3, 17, 8, 1.5, 8, 12, M2_cap_screw, MGN7 ];
MGN9C_carriage = [ 29.7, 20.8, 20, 10, 2, 10, 15, M3_cap_screw, MGN9 ];
MGN12C_carriage = [ 34.7, 21.7, 27, 13, 3, 15, 20, M3_cap_screw, MGN12 ];
MGN12H_carriage = [ 45.4, 32.4, 27, 13, 3, 20, 20, M3_cap_screw, MGN12 ];
MGN15C_carriage = [ 43.3, 27.7, 32, 16, 4, 20, 25, M3_cap_screw, MGN15 ];
SSR15_carriage = [ 40.3, 23.3, 34, 24, 4.5, 0, 26, M4_cap_screw, SSR15 ];
rails = [MGN5, MGN7, MGN9, MGN12, MGN12H, MGN15, SSR15];
carriages = [MGN5_carriage, MGN7C_carriage, MGN9C_carriage, MGN12C_carriage, MGN12H_carriage, MGN15C_carriage, SSR15_carriage];
use <rail.scad>

View File

@@ -128,7 +128,7 @@ module ring_terminal_assembly(type, thickness, top = false) { //! Earthing assem
screw = ringterm_screw(type);
washer = screw_washer(screw);
nut = screw_nut(screw);
screw_length = screw_longer_than(thickness + 2 * washer_thickness(washer) + nut_thickness(nut, true) + ringterm_thickness(type));
screw_length = screw_length(screw, thickness + ringterm_thickness(type), 2, nyloc = true);
explode(10, true) star_washer(washer)
if(top)

View File

@@ -48,7 +48,7 @@ function screw_head_depth(type, d = 0) = //! How far a counter sink
? 0
: let(r = screw_radius(type)) screw_head_radius(type) - max(r, d / 2) + r / 5;
function screw_longer_than(x) = x <= 5 ? 5 : //! Returns shortest screw length longer or equal to x
function screw_longer_than(x) = x <= 5 ? 5 : //! Returns the length of the shortest screw length longer or equal to x
x <= 6 ? 6 :
x <= 8 ? 8 :
x <= 10 ? 10 :
@@ -56,7 +56,7 @@ function screw_longer_than(x) = x <= 5 ? 5 : //! Returns shortest screw length
x <= 16 ? 16 :
ceil(x / 5) * 5;
function screw_shorter_than(x) = x >= 20 ? floor(x / 5) * 5 : //! Returns longest screw length shorter than or equal to x
function screw_shorter_than(x) = x >= 20 ? floor(x / 5) * 5 : //! Returns the length of the longest screw shorter than or equal to x
x >= 16 ? 16 :
x >= 12 ? 12 :
x >= 10 ? 10 :
@@ -64,6 +64,14 @@ function screw_shorter_than(x) = x >= 20 ? floor(x / 5) * 5 : //! Returns longes
x >= 6 ? 6 :
5;
function screw_length(screw, thickness, washers, insert = false, nyloc = false, nut = false, longer = false) = //! Returns the length of the longest or shortest screw that will got through `thickness` and `washers` and possibly an `insert`, `nut` or `nyloc`
let(washer = washers ? washers * washer_thickness(screw_washer(screw)) : 0,
insert = insert ? insert_length(screw_insert(screw)) : 0,
nut = nut || nyloc ? nut_thickness(screw_nut(screw), nyloc) : 0,
total = thickness + washer + insert + nut
)
longer || nut || nyloc ? screw_longer_than(total) : screw_shorter_than(total);
function screw_smaller_than(d) = d >= 2.5 && d < 3 ? 2.5 : floor(d); // Largest diameter screw less than or equal to specified diameter
function screw_insert(screw, i = 0) = let(d = screw_radius(screw) * 2)
@@ -262,7 +270,7 @@ module screw_countersink(type, drilled = true) { //! Countersink shape
if(drilled)
cylinder(h = head_height + eps, r1 = 0, r2 = head_rad + head_t);
else
intersection() {
render() intersection() {
cylinder(h = head_height + eps, r1 = 0, r2 = head_rad + head_t);
cylinder(h = head_height + eps, r = head_rad + eps);

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