Compare commits
273 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
82502eb470 | ||
|
b541298eae | ||
|
9884160ed5 | ||
|
7b111c016a | ||
|
38c973b316 | ||
|
042d809ed0 | ||
|
3864839e52 | ||
|
2ba2c2c115 | ||
|
e3716ce8f9 | ||
|
c4f24974ab | ||
|
61dae9c7a4 | ||
|
41a26c453c | ||
|
bab4c8e8af | ||
|
a5c4bf05ad | ||
|
a65add65ac | ||
|
c449dd0a24 | ||
|
f16f7ddb09 | ||
|
9b5ec6af1a | ||
|
50958b064d | ||
|
c37373c920 | ||
|
700f5a2205 | ||
|
4993c3e82d | ||
|
c6b280f0e8 | ||
|
6012787781 | ||
|
30db66034c | ||
|
d6f344be3d | ||
|
f6aa3b3426 | ||
|
91c8c7bf4d | ||
|
dc93b8dcdf | ||
|
c9c094248e | ||
|
119c2cb6f4 | ||
|
24b391578b | ||
|
ec49ce1a6c | ||
|
f0c25d37b0 | ||
|
588a1edf62 | ||
|
3299aad5c8 | ||
|
74c52aac04 | ||
|
726d9ed2dc | ||
|
8a838dd1ce | ||
|
181c6ac624 | ||
|
e952aa7840 | ||
|
466ee31e10 | ||
|
4c926c529b | ||
|
edb1eccbf1 | ||
|
061812cc8b | ||
|
ce0c97b45e | ||
|
696b14699c | ||
|
2166a9be6a | ||
|
511729008d | ||
|
5111ec04bc | ||
|
cef3a620a6 | ||
|
da5191e52c | ||
|
d9af5b7f70 | ||
|
c30d7f1ad9 | ||
|
a5382cbe04 | ||
|
00c5c90a5e | ||
|
01c26d8a34 | ||
|
ef2102420b | ||
|
540f841163 | ||
|
1045502efb | ||
|
485184f092 | ||
|
b893c9069a | ||
|
69f4ced29d | ||
|
5c1aa849fe | ||
|
9d65f69bf3 | ||
|
515b99fdc0 | ||
|
631d052c68 | ||
|
1247303cb9 | ||
|
290be4beb6 | ||
|
24e941799d | ||
|
6a556c5879 | ||
|
14ab1bb8b6 | ||
|
be53547728 | ||
|
ba7d7d32ad | ||
|
d3049bc81b | ||
|
df35e14fc7 | ||
|
21c2aa5d62 | ||
|
c982876ebc | ||
|
5ccda42e5b | ||
|
92d0444e5f | ||
|
b239c1462e | ||
|
6413b7b2a0 | ||
|
0b0ce66c85 | ||
|
d38055c15c | ||
|
cf99418a19 | ||
|
0cd0e72d92 | ||
|
2c4a498a7a | ||
|
451101fcd6 | ||
|
c7a6d8164f | ||
|
8d7c44b80d | ||
|
dcfe4262c5 | ||
|
fe3b84f672 | ||
|
d1a17bd4ac | ||
|
b8efa11fd9 | ||
|
3bc8f35e37 | ||
|
39c11ef3b2 | ||
|
5a8a1da880 | ||
|
3147862212 | ||
|
4fc8a7f47d | ||
|
a9ed9944c3 | ||
|
9cd2dbc316 | ||
|
f3bfbbfcf2 | ||
|
baaa85ffed | ||
|
f1a49d4e28 | ||
|
0eed0673b0 | ||
|
9a4cc7ec42 | ||
|
2fb1185edf | ||
|
a782d43e67 | ||
|
ae934d47c7 | ||
|
823f3b936e | ||
|
3027b942a6 | ||
|
749a1f0648 | ||
|
5c898df217 | ||
|
7a566cc856 | ||
|
20d799a3c1 | ||
|
2ee95bba65 | ||
|
f49bb63266 | ||
|
258109811b | ||
|
b39fd536c2 | ||
|
a5a87d260d | ||
|
b09efb10e0 | ||
|
53acaac379 | ||
|
9b40e0dcef | ||
|
00ca412441 | ||
|
1e6d7f5dd6 | ||
|
ec07d95657 | ||
|
0dab0dca08 | ||
|
6e6cd45295 | ||
|
3a7fde6c56 | ||
|
c5bb898856 | ||
|
11ebe2225d | ||
|
a1e25bb878 | ||
|
9689683b7e | ||
|
08946e3d70 | ||
|
15c2946e91 | ||
|
34019196cd | ||
|
436fc71cf3 | ||
|
fd67c166f7 | ||
|
634deab911 | ||
|
e2feceb608 | ||
|
d1258e0b0c | ||
|
bd61a1dc55 | ||
|
055e83902f | ||
|
feec1e7ae5 | ||
|
be76af2fc4 | ||
|
9c1a9bf357 | ||
|
9647fb474b | ||
|
49fdfea792 | ||
|
ac0bacfeda | ||
|
6288059d99 | ||
|
0f1dff230a | ||
|
e379fa8ada | ||
|
313d7508df | ||
|
083caca4e8 | ||
|
49329df00c | ||
|
edc0b86bb1 | ||
|
5fbff060b0 | ||
|
b94ca4ad3a | ||
|
bc5515d35e | ||
|
44d213deaa | ||
|
145c5d9b1a | ||
|
7abbbd9b96 | ||
|
5b160cee88 | ||
|
3f31607840 | ||
|
1efed649cf | ||
|
b70c2f993c | ||
|
56e252f3dc | ||
|
f12b36ea04 | ||
|
bd5811e69b | ||
|
ede4da6f1d | ||
|
51cc2fd679 | ||
|
4ce2f53e20 | ||
|
e338c47e73 | ||
|
8328a70f42 | ||
|
cc794cd7c3 | ||
|
df28bd5116 | ||
|
61de6041d8 | ||
|
b2d712bca9 | ||
|
f3376edaf1 | ||
|
c073419c0b | ||
|
608168de8e | ||
|
fc45a40bd3 | ||
|
52e9c1d7fd | ||
|
ca1b34e9ca | ||
|
cbab9cea02 | ||
|
69cf998862 | ||
|
08bce9ec03 | ||
|
4aa7dbb416 | ||
|
7c7c2e5d3f | ||
|
f6f6664c0d | ||
|
2fd2e118a0 | ||
|
22c6fef113 | ||
|
dcf0c949b9 | ||
|
9ded315801 | ||
|
42e03679b4 | ||
|
d2c795f5f5 | ||
|
83b4ab2374 | ||
|
573c50774b | ||
|
4b93623492 | ||
|
d496898c80 | ||
|
544e69c71b | ||
|
240334784d | ||
|
516b225275 | ||
|
e46e6b6e5b | ||
|
4925979519 | ||
|
298d1f9284 | ||
|
fcf2f5f7f0 | ||
|
491c3b4ea8 | ||
|
94cb50f725 | ||
|
1d8275c061 | ||
|
3c605d608b | ||
|
9ba48c7e1a | ||
|
a6ebc5267b | ||
|
e9554ccffe | ||
|
0d179f3728 | ||
|
a94e462f34 | ||
|
7ce991e625 | ||
|
3e15be852f | ||
|
7c1c8e92f2 | ||
|
54c3b4f600 | ||
|
d80fc5709e | ||
|
30236046a8 | ||
|
93aeb4cf2c | ||
|
f62ca35c86 | ||
|
2320cbdbb8 | ||
|
769cb44207 | ||
|
f327df95a3 | ||
|
09956b6219 | ||
|
f8c9adca5a | ||
|
b83e56713f | ||
|
4c12d5fca4 | ||
|
da4f9fbdc3 | ||
|
614e5f3a72 | ||
|
a7eae4f549 | ||
|
3cd5769708 | ||
|
7b770abe12 | ||
|
31ab8562a7 | ||
|
db703379a3 | ||
|
cd925bc049 | ||
|
4a2951e22f | ||
|
a93a8f99fb | ||
|
73c436ee15 | ||
|
c69100bd71 | ||
|
e0b89359aa | ||
|
041d720c39 | ||
|
03a0c2fe98 | ||
|
7c2df8d36d | ||
|
8474718884 | ||
|
fe0f32ddc5 | ||
|
f191b9b0f4 | ||
|
2b3908b6fd | ||
|
0a84bf0927 | ||
|
da825b17ab | ||
|
ca153c971d | ||
|
0199587907 | ||
|
60350eb228 | ||
|
4f9729cf86 | ||
|
26f1338ca2 | ||
|
fc44b43638 | ||
|
182f39876a | ||
|
055e90cbb3 | ||
|
832380f893 | ||
|
929d082b25 | ||
|
57212b5701 | ||
|
1c3f136657 | ||
|
cfd2fd32a1 | ||
|
f573a91a09 | ||
|
d75aff2ccd | ||
|
491d85156c | ||
|
c89ce6843f | ||
|
1915dae034 | ||
|
c4fe1d1098 | ||
|
22b7aa956c |
2077
CHANGELOG.md
Normal file
@@ -1,7 +1,7 @@
|
||||
# NopSCADlib usage
|
||||
|
||||
## Requirements
|
||||
1. OpenSCAD 2019.05 or later, download it from here: https://www.openscad.org/downloads.html
|
||||
1. OpenSCAD 2021.01 or later, download it from here: https://www.openscad.org/downloads.html
|
||||
1. Python 2.7+ or 3.6+ from https://www.python.org/downloads/
|
||||
1. ImageMagick 7 www.imagemagick.org
|
||||
|
||||
@@ -270,6 +270,22 @@ The target config file is selected by generating `target.scad` that includes `co
|
||||
The rest of the project includes `target.scad` to use the configuration.
|
||||
Additionally all the generated file directories (assemblies, bom, stls, dxfs, etc.) are placed in a sub-directory called `<target_name>`.
|
||||
|
||||
The build system will look for a `<target_name>_assembly` module and use it as the top level module instead of `main_assembly` if it it exists.
|
||||
That allows the project description to be target specific if the top level modules are in different scad files.
|
||||
The top level assembly instructions and assembly contents could also be different if appropriate.
|
||||
|
||||
If the top level module is just a shell wrapper that simply includes one other assembly, with no additional parts, then it is removed from the build instructions and
|
||||
the assembly it calls becomes the top level. This allows a different project description for each target but only one set of top level instructions without repeating them.
|
||||
|
||||
### Costed BOMs
|
||||
|
||||
A costed bill of materials can be made by opening the generated file `bom/bom.csv` in a spreadsheet program using a single quote as the string delimiter and comma as the field separator.
|
||||
That gets a list of part descriptions and quantities to which prices can be added to get the total cost and perhaps a URL of where to buy each part.
|
||||
|
||||
If a Python file called `parts.py` is found then `bom.py` will attempt to call functions for each part to get a price and URL.
|
||||
Any functions not found are printed, so you can see the format expected.
|
||||
The function are passed the quantity to allow them to calculate volume discounts, etc.
|
||||
|
||||
### Other libraries
|
||||
|
||||
The build scripts need to be able to locate the source files where the modules to generate the STL files and assemblies reside. They will search all the scad files
|
||||
|
Before Width: | Height: | Size: 96 KiB After Width: | Height: | Size: 96 KiB |
Before Width: | Height: | Size: 108 KiB After Width: | Height: | Size: 108 KiB |
Before Width: | Height: | Size: 105 KiB After Width: | Height: | Size: 105 KiB |
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 138 KiB After Width: | Height: | Size: 137 KiB |
Before Width: | Height: | Size: 121 KiB After Width: | Height: | Size: 121 KiB |
Before Width: | Height: | Size: 201 KiB After Width: | Height: | Size: 201 KiB |
Before Width: | Height: | Size: 124 KiB After Width: | Height: | Size: 123 KiB |
Before Width: | Height: | Size: 135 KiB After Width: | Height: | Size: 135 KiB |
16
examples/MainsBreakOutBox/bom/bom.csv
Normal file
@@ -0,0 +1,16 @@
|
||||
'Ferrule for 1.5mm^2 wire - not shown', 3
|
||||
'Wire blue 30/0.25mm strands, length 150mm - not shown', 2
|
||||
'Wire brown 30/0.25mm strands, length 150mm - not shown', 2
|
||||
'Wire green & yellow 30/0.25mm strands, length 150mm - not shown', 2
|
||||
'IEC inlet for ATX', 1
|
||||
'Heatfit insert M3', 2
|
||||
'4mm shielded jack socket blue', 2
|
||||
'4mm shielded jack socket brown', 1
|
||||
'4mm shielded jack socket green', 2
|
||||
'Mains socket 13A', 1
|
||||
'Nut M3 x 2.4mm nyloc', 6
|
||||
'Screw M3 cs cap x 12mm', 2
|
||||
'Screw M3 cs cap x 20mm', 2
|
||||
'Screw M3 dome x 10mm', 4
|
||||
'Heatshrink sleeving ID 3.2mm x 15mm - not shown', 8
|
||||
'Washer M3 x 7mm x 0.5mm', 10
|
|
@@ -3,6 +3,7 @@
|
||||
"name": "base_assembly",
|
||||
"big": null,
|
||||
"ngb": false,
|
||||
"zoomed": 0,
|
||||
"count": 1,
|
||||
"assemblies": {},
|
||||
"vitamins": {
|
||||
@@ -22,6 +23,7 @@
|
||||
"name": "feet_assembly",
|
||||
"big": null,
|
||||
"ngb": false,
|
||||
"zoomed": 0,
|
||||
"count": 1,
|
||||
"assemblies": {
|
||||
"base_assembly": 1
|
||||
@@ -49,6 +51,7 @@
|
||||
"name": "mains_in_assembly",
|
||||
"big": null,
|
||||
"ngb": false,
|
||||
"zoomed": 0,
|
||||
"count": 1,
|
||||
"assemblies": {
|
||||
"feet_assembly": 1
|
||||
@@ -86,6 +89,7 @@
|
||||
"name": "main_assembly",
|
||||
"big": null,
|
||||
"ngb": false,
|
||||
"zoomed": 0,
|
||||
"count": 1,
|
||||
"assemblies": {
|
||||
"mains_in_assembly": 1
|
||||
|
11
examples/MainsBreakOutBox/platters/all.scad
Normal file
@@ -0,0 +1,11 @@
|
||||
include <NopSCADlib/core.scad>
|
||||
|
||||
*use_stl("socket_box"); // Importing the STL gives a CGAL error although NetFabb finds nothing wrong with it.
|
||||
|
||||
use <../scad/bob_main.scad>
|
||||
|
||||
render() socket_box_stl();
|
||||
|
||||
for(i = [0 : 3])
|
||||
translate([i * 25 - 1.5 * 25, -70])
|
||||
use_stl("foot");
|
@@ -31,7 +31,8 @@
|
||||
//! while its earth is disconnected. Don't be tempted to float the earth of an oscilloscope this way, use a mains isolation transformer to power the DUT instead.
|
||||
//! Earth leakage can be measured Canadian CSA style by disconnected the neutral link from the left socket and linking the central neutral to the live.
|
||||
//
|
||||
$extrusion_width = 0.5;
|
||||
$extrusion_width = 0.4;
|
||||
$layer_height = 0.2;
|
||||
$pp1_colour = "dimgrey";
|
||||
$pp2_colour = [0.9, 0.9, 0.9];
|
||||
|
||||
|
5
examples/MainsBreakOutBox/stls/deps/all.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
socket_box.stl
|
||||
foot.stl
|
||||
foot.stl
|
||||
foot.stl
|
||||
foot.stl
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
87250
examples/MainsBreakOutBox/stls/printed/all.stl
Normal file
Before Width: | Height: | Size: 121 KiB After Width: | Height: | Size: 121 KiB |
BIN
gallery/IOT_LOAD.png
Normal file
After Width: | Height: | Size: 245 KiB |
Before Width: | Height: | Size: 287 KiB After Width: | Height: | Size: 287 KiB |
Before Width: | Height: | Size: 121 KiB After Width: | Height: | Size: 121 KiB |
BIN
gallery/PSU_cover.png
Normal file
After Width: | Height: | Size: 279 KiB |
BIN
gallery/PotBox.png
Normal file
After Width: | Height: | Size: 231 KiB |
Before Width: | Height: | Size: 202 KiB After Width: | Height: | Size: 202 KiB |
@@ -1,40 +1,35 @@
|
||||
# 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.
|
||||
|
||||

|
||||
|
||||
|
||||
<a name="TOP"></a>
|
||||
## EnviroPlus
|
||||
Environmental monitor using Enviro+ sensor board and a Raspberry Pi Zero.
|
||||
|
||||

|
||||
|
||||
|
||||
<a name="TOP"></a>
|
||||
## FilamentDryBox
|
||||
A small fan oven with a spool holder to keep the filament warm and dry.
|
||||
|
||||

|
||||
|
||||
|
||||
<a name="TOP"></a>
|
||||
## HydraBot
|
||||
Current state of HydraRaptor after being modified for laser engraving.
|
||||
|
||||

|
||||
|
||||
|
||||
<a name="TOP"></a>
|
||||
## IOT 50V PSU
|
||||
WiFi controllable PSU
|
||||
|
||||

|
||||
|
||||
## IOT LOAD
|
||||
WiFi controllable programmable load
|
||||
|
||||

|
||||
|
||||
<a name="TOP"></a>
|
||||
## Lab ATX PSU
|
||||
Bench power supply built around an ATX PSU.
|
||||
|
||||
@@ -47,15 +42,11 @@ Bench power supply built around an ATX PSU.
|
||||
|
||||
|
||||
|
||||
|
||||
<a name="TOP"></a>
|
||||
## Laser Load
|
||||
15kV dummy load for testing CO2 laser PSUs
|
||||
|
||||

|
||||
|
||||
|
||||
<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 +63,6 @@ Earth leakage can be measured Canadian CSA style by disconnected the neutral lin
|
||||
|
||||

|
||||
|
||||
|
||||
<a name="TOP"></a>
|
||||
## Mains Box
|
||||
Mains isolated and variable supply with metering.
|
||||
|
||||
@@ -81,15 +70,21 @@ Mains isolated and variable supply with metering.
|
||||
|
||||
|
||||
|
||||
## PSU Cover
|
||||
A base and shroud to make PSU safe to sit on a desk
|
||||
|
||||

|
||||
|
||||
## PotBox
|
||||
Potentiometer box with course and fine controls and three 4mm binding posts
|
||||
|
||||

|
||||
|
||||
<a name="TOP"></a>
|
||||
## SunBot
|
||||
A solar tracker to keep a solar panel pointing at the sun.
|
||||
|
||||

|
||||
|
||||
|
||||
<a name="TOP"></a>
|
||||
## Turntable
|
||||
WiFi enabled remote control turntable for photography
|
||||
|
||||
@@ -97,8 +92,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 +99,3 @@ Motorised variac with WiFi control, see [hydraraptor.blogspot.com/2018/04/esp826
|
||||
|
||||
|
||||
|
||||
|
||||
|
@@ -24,22 +24,22 @@
|
||||
// bom defaults to 0
|
||||
// Setting $bom on the command line or in the main file before including lib.scad overrides it everywhere.
|
||||
// Setting $bom after including lib overrides bom in the libs but not in the local file.
|
||||
// Setting $_bom in the local file overrides it in the local file but not in the libs.
|
||||
//
|
||||
rr_green = [0, 146/255, 0]; // RepRap logo colour
|
||||
crimson = [220/255, 20/255, 60/255];
|
||||
|
||||
$_bom = is_undef($bom) ? 0 : $bom; // 0 no bom, 1 assemblies and stls, 2 vitamins as well
|
||||
$exploded = is_undef($explode) ? 0 : $explode; // 1 for exploded view
|
||||
layer_height = is_undef($layer_height) ? 0.25 : $layer_height; // layer heigth when printing
|
||||
layer_height = is_undef($layer_height) ? 0.25 : $layer_height; // layer height when printing
|
||||
extrusion_width = is_undef($extrusion_width) ? 0.5 : $extrusion_width; // filament width when printing
|
||||
nozzle = is_undef($nozzle) ? 0.45 : $nozzle; // 3D printer nozzle
|
||||
cnc_bit_r = is_undef($cnc_bit_r) ? 1.2 : $cnc_bit_r; // minimum tool radius when milling 2D objects
|
||||
pp1_colour = is_undef($pp1_colour) ? rr_green : $pp1_colour; // printed part colour 1, RepRap logo colour
|
||||
pp2_colour = is_undef($pp2_colour) ? "Crimson" : $pp2_colour; // printed part colour 2
|
||||
pp3_colour = is_undef($pp3_colour) ? "SteelBlue" : $pp3_colour; // printed part colour 3
|
||||
pp4_colour = is_undef($pp4_colour) ? "darkorange" : $pp4_colour;// printed part colour 4
|
||||
show_rays = is_undef($show_rays) ? false : $show_rays; // show camera sight lines and light direction
|
||||
show_threads = is_undef($show_threads) ? false : $show_threads; // show screw threads
|
||||
show_plugs = is_undef($show_plugs) ? false : $show_plugs; // plugs on headers
|
||||
pp1_colour = is_undef($pp1_colour) ? rr_green : $pp1_colour;// printed part colour 1, RepRap logo colour
|
||||
pp2_colour = is_undef($pp2_colour) ? crimson : $pp2_colour;// printed part colour 2
|
||||
pp3_colour = is_undef($pp3_colour) ? "SteelBlue" : $pp3_colour;// printed part colour 3
|
||||
pp4_colour = is_undef($pp4_colour) ? "darkorange" : $pp4_colour;// printed part colour 4
|
||||
|
||||
|
||||
// Minimum wall is about two filaments wide but we extrude it closer to get better bonding
|
||||
squeezed_wall = $preview ? 2 * extrusion_width - layer_height * (1 - PI / 4)
|
||||
@@ -50,12 +50,14 @@ eps = 1/128; // small fudge factor to stop CSG barfing on coincident faces.
|
||||
$fa = 6;
|
||||
$fs = extrusion_width / 2;
|
||||
|
||||
function round_to_layer(z) = ceil(z / layer_height) * layer_height;
|
||||
function round_to_layer(z) = ceil(z / layer_height) * layer_height; //! Round up to a multiple of layer_height.
|
||||
|
||||
// Some additional named colours
|
||||
function grey(n) = [0.01, 0.01, 0.01] * n; //! Generate a shade of grey to pass to color().
|
||||
gold = [255/255, 215/255, 0/255];
|
||||
brass = [255/255, 220/255, 100/255];
|
||||
silver = [0.75, 0.75, 0.75];
|
||||
function grey(n) = [0.01, 0.01, 0.01] * n; //! Generate a shade of grey to pass to color().
|
||||
silver = [0.75, 0.75, 0.75];
|
||||
gold = [255, 215, 0] / 255;
|
||||
brass = [255, 220, 100] / 255;
|
||||
copper = [230, 140, 51] / 255;
|
||||
|
||||
/*
|
||||
* Enums
|
||||
@@ -71,11 +73,6 @@ hs_grub = 4; // pulley set screw
|
||||
hs_cs_cap = 5;
|
||||
hs_dome = 6;
|
||||
//
|
||||
// Hot end descriptions
|
||||
//
|
||||
jhead = 1;
|
||||
e3d = 2;
|
||||
//
|
||||
// Face enumeration
|
||||
//
|
||||
f_bottom = 0;
|
||||
|
9
lib.scad
@@ -26,7 +26,10 @@ include <vitamins/psus.scad>
|
||||
include <vitamins/pcbs.scad>
|
||||
|
||||
include <vitamins/batteries.scad>
|
||||
include <vitamins/bearing_blocks.scad>
|
||||
include <vitamins/blowers.scad>
|
||||
include <vitamins/bldc_motors.scad>
|
||||
include <vitamins/box_sections.scad>
|
||||
include <vitamins/bulldogs.scad>
|
||||
include <vitamins/buttons.scad>
|
||||
include <vitamins/cameras.scad>
|
||||
@@ -37,7 +40,6 @@ include <vitamins/extrusion_brackets.scad>
|
||||
include <vitamins/geared_steppers.scad>
|
||||
include <vitamins/hot_ends.scad>
|
||||
include <vitamins/inserts.scad>
|
||||
include <vitamins/kp_pillow_blocks.scad>
|
||||
include <vitamins/ldrs.scad>
|
||||
include <vitamins/leadnuts.scad>
|
||||
include <vitamins/led_meter.scad>
|
||||
@@ -47,12 +49,13 @@ include <vitamins/mains_sockets.scad>
|
||||
include <vitamins/modules.scad>
|
||||
include <vitamins/panel_meters.scad>
|
||||
include <vitamins/pillars.scad>
|
||||
include <vitamins/pillow_blocks.scad>
|
||||
include <vitamins/pin_headers.scad>
|
||||
include <vitamins/pulleys.scad>
|
||||
include <vitamins/ring_terminals.scad>
|
||||
include <vitamins/rails.scad>
|
||||
include <vitamins/rod.scad>
|
||||
include <vitamins/scs_bearing_blocks.scad>
|
||||
include <vitamins/servo_motors.scad>
|
||||
include <vitamins/shaft_couplings.scad>
|
||||
include <vitamins/sheets.scad>
|
||||
include <vitamins/sk_brackets.scad>
|
||||
@@ -89,7 +92,7 @@ use <utils/gears.scad>
|
||||
use <utils/hanging_hole.scad>
|
||||
use <utils/fillet.scad>
|
||||
use <utils/rounded_polygon.scad>
|
||||
use <utils/rounded_right_triangle.scad>
|
||||
use <utils/rounded_triangle.scad>
|
||||
use <utils/layout.scad>
|
||||
use <utils/round.scad>
|
||||
use <utils/offset.scad>
|
||||
|
BIN
libtest.png
Before Width: | Height: | Size: 882 KiB After Width: | Height: | Size: 932 KiB |
87
libtest.scad
@@ -33,16 +33,22 @@
|
||||
//!
|
||||
//! See [usage](docs/usage.md) for requirements, installation instructions and a usage guide.
|
||||
//!
|
||||
//! A list of changes classified as breaking, additions or fixes is maintained in [CHANGELOG.md](CHANGELOG.md).
|
||||
//!
|
||||
//! <img src="libtest.png" width="100%"/>
|
||||
//
|
||||
// This file shows all the parts in the library.
|
||||
//
|
||||
include <lib.scad>
|
||||
|
||||
use <tests/7_segments.scad>
|
||||
use <tests/ball_bearings.scad>
|
||||
use <tests/batteries.scad>
|
||||
use <tests/bearing_blocks.scad>
|
||||
use <tests/belts.scad>
|
||||
use <tests/BLDC_motors.scad>
|
||||
use <tests/blowers.scad>
|
||||
use <tests/box_sections.scad>
|
||||
use <tests/bulldogs.scad>
|
||||
use <tests/buttons.scad>
|
||||
use <tests/cable_strips.scad>
|
||||
@@ -62,7 +68,6 @@ use <tests/hot_ends.scad>
|
||||
use <tests/IECs.scad>
|
||||
use <tests/inserts.scad>
|
||||
use <tests/jack.scad>
|
||||
use <tests/KP_pillow_blocks.scad>
|
||||
use <tests/leadnuts.scad>
|
||||
use <tests/LDRs.scad>
|
||||
use <tests/LEDs.scad>
|
||||
@@ -78,6 +83,8 @@ use <tests/opengrab.scad>
|
||||
use <tests/panel_meters.scad>
|
||||
use <tests/PCBs.scad>
|
||||
use <tests/pillars.scad>
|
||||
use <tests/pillow_blocks.scad>
|
||||
use <tests/potentiometers.scad>
|
||||
use <tests/press_fit.scad>
|
||||
use <tests/PSUs.scad>
|
||||
use <tests/pulleys.scad>
|
||||
@@ -86,8 +93,8 @@ use <tests/ring_terminals.scad>
|
||||
use <tests/rockers.scad>
|
||||
use <tests/rod.scad>
|
||||
use <tests/screws.scad>
|
||||
use <tests/SCS_bearing_blocks.scad>
|
||||
use <tests/sealing_strip.scad>
|
||||
use <tests/servo_motors.scad>
|
||||
use <tests/shaft_couplings.scad>
|
||||
use <tests/sheets.scad>
|
||||
use <tests/SK_brackets.scad>
|
||||
@@ -117,6 +124,7 @@ 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>
|
||||
@@ -180,13 +188,15 @@ translate([x5, cable_grommets_y + 250])
|
||||
translate([950, 600])
|
||||
box_test();
|
||||
|
||||
translate([890, 750])
|
||||
translate([900, 750])
|
||||
pocket_handles();
|
||||
|
||||
translate([900, 850])
|
||||
printed_boxes();
|
||||
|
||||
translate([850, 1330])
|
||||
translate([850, 1330 + 85])
|
||||
bbox_test();
|
||||
|
||||
|
||||
inserts_y = 0;
|
||||
nuts_y = inserts_y + 20;
|
||||
washers_y = nuts_y + 120;
|
||||
@@ -198,13 +208,14 @@ sealing_strip_y = springs_y + 20;
|
||||
tubings_y = sealing_strip_y + 20;
|
||||
pillars_y = tubings_y + 20;
|
||||
ball_bearings_y = pillars_y + 40;
|
||||
pulleys_y = ball_bearings_y +40;
|
||||
hot_ends_y = pulleys_y + 60;
|
||||
linear_bearings_y = hot_ends_y + 50;
|
||||
sheets_y = linear_bearings_y + 100;
|
||||
pcbs_y = sheets_y + 40;
|
||||
displays_y = pcbs_y + 170;
|
||||
fans_y = displays_y + 80;
|
||||
pulleys_y = ball_bearings_y + 40;
|
||||
leadnuts_y = pulleys_y + 60;
|
||||
linear_bearings_y = leadnuts_y + 50;
|
||||
steppers_y = linear_bearings_y + 110;
|
||||
sheets_y = steppers_y + 55;
|
||||
pcbs_y = sheets_y + 60;
|
||||
displays_y = pcbs_y + 140;
|
||||
fans_y = displays_y + 110;
|
||||
transformers_y = fans_y + 120;
|
||||
psus_y = transformers_y + 190;
|
||||
|
||||
@@ -247,13 +258,16 @@ translate([x0, ball_bearings_y])
|
||||
translate([x0, pulleys_y])
|
||||
pulleys();
|
||||
|
||||
translate([x0, leadnuts_y])
|
||||
leadnuts();
|
||||
|
||||
translate([x0, linear_bearings_y]) {
|
||||
linear_bearings();
|
||||
rods();
|
||||
}
|
||||
|
||||
translate([x0 + 10, hot_ends_y])
|
||||
hot_ends();
|
||||
translate([x0, steppers_y])
|
||||
stepper_motors();
|
||||
|
||||
translate([x0, sheets_y])
|
||||
sheets();
|
||||
@@ -271,7 +285,7 @@ translate([x0, fans_y]) {
|
||||
fan_guards();
|
||||
}
|
||||
|
||||
translate([x0, transformers_y])
|
||||
translate([760, fans_y])
|
||||
variacs();
|
||||
|
||||
translate([x0, psus_y]) {
|
||||
@@ -283,7 +297,6 @@ translate([x0, psus_y]) {
|
||||
zipties_y = 0;
|
||||
bulldogs_y = zipties_y + 30;
|
||||
swiss_clips_y = bulldogs_y + 35;
|
||||
leadnuts_y = swiss_clips_y + 50;
|
||||
|
||||
translate([x1, zipties_y])
|
||||
zipties();
|
||||
@@ -294,10 +307,6 @@ translate([x1, bulldogs_y])
|
||||
translate([x1, swiss_clips_y])
|
||||
swiss_clips();
|
||||
|
||||
translate([x1, leadnuts_y])
|
||||
leadnuts();
|
||||
|
||||
|
||||
leds_y = 0;
|
||||
carriers_y = leds_y + 40;
|
||||
magnets_y = carriers_y + 40;
|
||||
@@ -354,18 +363,18 @@ iecs_y = d_connectors_y + 80;
|
||||
modules_y = iecs_y + 60;
|
||||
ssrs_y = modules_y + 80;
|
||||
blowers_y = ssrs_y + 60;
|
||||
batteries_y = blowers_y + 100;
|
||||
steppers_y = batteries_y + 55;
|
||||
panel_meters_y = steppers_y + 70;
|
||||
hot_ends_y = blowers_y + 100;
|
||||
batteries_y = hot_ends_y + 55;
|
||||
panel_meters_y = batteries_y + 70;
|
||||
extrusions_y = panel_meters_y + 80;
|
||||
|
||||
translate([x3, veroboard_y])
|
||||
veroboard_test();
|
||||
|
||||
translate([x3 + 70, veroboard_y + 30])
|
||||
translate([x3 + 60, veroboard_y + 20])
|
||||
geared_steppers();
|
||||
|
||||
translate([x3 + 140, veroboard_y + 20])
|
||||
translate([x3 + 160, ssrs_y])
|
||||
pcb_mounts();
|
||||
|
||||
translate([x3 + 170, veroboard_y + 16])
|
||||
@@ -401,8 +410,8 @@ translate([x3, blowers_y])
|
||||
translate([x3, batteries_y])
|
||||
batteries();
|
||||
|
||||
translate([x2, steppers_y]) // interloper
|
||||
stepper_motors();
|
||||
translate([x3 + 10, hot_ends_y])
|
||||
hot_ends();
|
||||
|
||||
translate([x2, panel_meters_y])
|
||||
panel_meters();
|
||||
@@ -410,7 +419,7 @@ translate([x2, panel_meters_y])
|
||||
translate([x2, extrusions_y])
|
||||
extrusions();
|
||||
|
||||
translate([x3, transformers_y])
|
||||
translate([400, transformers_y])
|
||||
transformers();
|
||||
|
||||
|
||||
@@ -418,15 +427,21 @@ belts_y = 0;
|
||||
rails_y = belts_y + 200;
|
||||
extrusion_brackets_y = rails_y + 250;
|
||||
sk_brackets_y = extrusion_brackets_y + 80;
|
||||
kp_pillow_blocks_y = sk_brackets_y + 50;
|
||||
kp_pillow_blocks_y = sk_brackets_y + 60;
|
||||
scs_bearing_blocks_y = kp_pillow_blocks_y + 60;
|
||||
box_sections_y = batteries_y;
|
||||
BLDC_y = scs_bearing_blocks_y + 120;
|
||||
pot_y = BLDC_y + 40;
|
||||
cable_strip_y = pot_y + 50;
|
||||
|
||||
translate([0, transformers_y])
|
||||
servo_motors();
|
||||
|
||||
translate([x4 + 200, belts_y + 58]) {
|
||||
belt_test();
|
||||
|
||||
translate([0, 60])
|
||||
opengrab_test();
|
||||
|
||||
}
|
||||
|
||||
translate([x4 + 175, belts_y, -20])
|
||||
@@ -435,7 +450,7 @@ translate([x4 + 175, belts_y, -20])
|
||||
translate([x4, rails_y + 130])
|
||||
rails();
|
||||
|
||||
translate([770, fans_y + 50])
|
||||
translate([x4, cable_strip_y])
|
||||
cable_strips();
|
||||
|
||||
translate([x4, kp_pillow_blocks_y])
|
||||
@@ -447,12 +462,20 @@ translate([x4, sk_brackets_y])
|
||||
translate([x4, extrusion_brackets_y])
|
||||
extrusion_brackets();
|
||||
|
||||
translate([x4 + 120, extrusion_brackets_y])
|
||||
translate([x1, swiss_clips_y + 50])
|
||||
shaft_couplings();
|
||||
|
||||
translate([x4, scs_bearing_blocks_y])
|
||||
scs_bearing_blocks();
|
||||
|
||||
translate([x4, BLDC_y])
|
||||
bldc_motors();
|
||||
|
||||
translate([x4, pot_y])
|
||||
potentiometers();
|
||||
|
||||
translate([x2, box_sections_y])
|
||||
box_sections();
|
||||
|
||||
translate([x6, 125])
|
||||
light_strips();
|
||||
|
@@ -31,9 +31,11 @@
|
||||
//!
|
||||
//! Normally the side sheets are the same type but they can be overridden individually as long as the substitute has the same thickness.
|
||||
//
|
||||
include <../core.scad>
|
||||
include <../utils/core/core.scad>
|
||||
use <../vitamins/sheet.scad>
|
||||
use <../vitamins/insert.scad>
|
||||
use <../vitamins/screw.scad>
|
||||
use <../vitamins/washer.scad>
|
||||
use <../utils/quadrant.scad>
|
||||
use <../utils/round.scad>
|
||||
|
||||
@@ -52,8 +54,8 @@ function box_width(type) = type[7]; //! Internal width
|
||||
function box_depth(type) = type[8]; //! Internal depth
|
||||
function box_height(type) = type[9]; //! Internal height
|
||||
|
||||
function box(screw, wall, sheets, top_sheet, base_sheet, size, feet = false, shelf_screw = M3_dome_screw) = //! Construct a property list for a box.
|
||||
concat([screw, shelf_screw, wall, sheets, top_sheet, base_sheet, feet], size);
|
||||
function box(screw, wall, sheets, top_sheet, base_sheet, size, feet = false, shelf_screw = undef) = //! Construct a property list for a box.
|
||||
concat([screw, is_undef(shelf_screw) ? screw : shelf_screw, wall, sheets, top_sheet, base_sheet, feet], size);
|
||||
|
||||
function box_bezel_clearance(type) = bezel_clearance;
|
||||
|
||||
@@ -227,7 +229,7 @@ module box_bezel(type, bottom) { //! Generates top and bottom bezel STLs
|
||||
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);
|
||||
rounded_rectangle([tw, td, feet ? foot_height : height], box_corner_rad(type));
|
||||
//
|
||||
// Remove edges between the feet
|
||||
//
|
||||
@@ -264,7 +266,7 @@ module box_bezel(type, bottom) { //! Generates top and bottom bezel STLs
|
||||
// recess for top / bottom panel
|
||||
//
|
||||
translate_z(cgap)
|
||||
rounded_rectangle([w + bezel_clearance, d + bezel_clearance, height], inner_r + bezel_clearance / 2, false);
|
||||
rounded_rectangle([w + bezel_clearance, d + bezel_clearance, height], inner_r + bezel_clearance / 2);
|
||||
//
|
||||
// leave plastic over the corner profiles
|
||||
//
|
||||
@@ -588,9 +590,26 @@ module box_back_blank(type, sheet = false) { //! Generates a 2D template for the
|
||||
sheet_2D(subst_sheet(type, sheet), box_width(type) - sheet_reduction(type), box_height(type) - sheet_reduction(type), 1);
|
||||
}
|
||||
|
||||
module box_base(type) render_2D_sheet(box_base_sheet(type)) box_base_blank(type); //! Default base, can be overridden to customise
|
||||
module box_top(type) render_2D_sheet(box_top_sheet(type)) box_top_blank(type); //! Default top, can be overridden to customise
|
||||
module box_back(type) render_2D_sheet(box_sheets(type)) box_back_blank(type); //! Default back, can be overridden to customise
|
||||
module box_front(type) render_2D_sheet(box_sheets(type)) box_front_blank(type); //! Default front, can be overridden to customise
|
||||
module box_left(type) render_2D_sheet(box_sheets(type)) box_left_blank(type); //! Default left side, can be overridden to customise
|
||||
module box_right(type) render_2D_sheet(box_sheets(type)) box_right_blank(type); //! Default right side, can be overridden to customise
|
||||
module box_base(type) //! Default base, can be overridden to customise
|
||||
render_2D_sheet(box_base_sheet(type))
|
||||
box_base_blank(type);
|
||||
|
||||
module box_top(type) //! Default top, can be overridden to customise
|
||||
render_2D_sheet(box_top_sheet(type))
|
||||
box_top_blank(type);
|
||||
|
||||
module box_back(type) //! Default back, can be overridden to customise
|
||||
render_2D_sheet(box_sheets(type))
|
||||
box_back_blank(type);
|
||||
|
||||
module box_front(type) //! Default front, can be overridden to customise
|
||||
render_2D_sheet(box_sheets(type))
|
||||
box_front_blank(type);
|
||||
|
||||
module box_left(type) //! Default left side, can be overridden to customise
|
||||
render_2D_sheet(box_sheets(type))
|
||||
box_left_blank(type);
|
||||
|
||||
module box_right(type) //! Default right side, can be overridden to customise
|
||||
render_2D_sheet(box_sheets(type))
|
||||
box_right_blank(type);
|
||||
|
@@ -28,7 +28,7 @@ assembly("box") {
|
||||
|
||||
t = sheet_thickness(box_sheets(type));
|
||||
|
||||
for(corner = [0 : corners - 1]) {
|
||||
for(corner = [0 : 1 : corners - 1]) {
|
||||
x = [-1,1,1,-1][corner];
|
||||
y = [-1,-1,1,1][corner];
|
||||
translate([x * (box_width(type) / 2 + 25 * exploded()), y * (box_depth(type) / 2 + 25 * exploded())])
|
||||
|
@@ -54,7 +54,7 @@ function bbox(screw, sheets, base_sheet, top_sheet, span, size, name = "bbox", s
|
||||
[ screw, sheets, base_sheet, top_sheet, span, size.x, size.y, size.z, name, skip_blocks, star_washers ];
|
||||
|
||||
function bbox_volume(type) = bbox_width(type) * bbox_depth(type) * bbox_height(type) / 1000000; //! Internal volume in litres
|
||||
function bbox_area(type) = let(w = bbox_width(type), d = bbox_depth(type), h = bbox_height(type)) //! Internal surdface area in m^2
|
||||
function bbox_area(type) = let(w = bbox_width(type), d = bbox_depth(type), h = bbox_height(type)) //! Internal surface area in m^2
|
||||
2 * (w * d + w * h + d * h) / 1000000;
|
||||
|
||||
module bbox_shelf_blank(type) { //! 2D template for a shelf
|
||||
@@ -198,12 +198,29 @@ module bbox_back_blank(type, sheet = false) { //! 2D template for the back
|
||||
}
|
||||
}
|
||||
|
||||
module bbox_base(type) render_2D_sheet(bbox_base_sheet(type)) bbox_base_blank(type); //! Default base, can be overridden to customise
|
||||
module bbox_top(type) render_2D_sheet(bbox_top_sheet(type)) bbox_top_blank(type); //! Default top, can be overridden to customise
|
||||
module bbox_back(type) render_2D_sheet(bbox_sheets(type)) bbox_back_blank(type); //! Default back, can be overridden to customise
|
||||
module bbox_front(type) render_2D_sheet(bbox_sheets(type)) bbox_front_blank(type); //! Default front, can be overridden to customise
|
||||
module bbox_left(type) render_2D_sheet(bbox_sheets(type)) bbox_left_blank(type); //! Default left side, can be overridden to customise
|
||||
module bbox_right(type) render_2D_sheet(bbox_sheets(type)) bbox_right_blank(type); //! Default right side, can be overridden to customise
|
||||
module bbox_base(type) //! Default base, can be overridden to customise
|
||||
render_2D_sheet(bbox_base_sheet(type))
|
||||
bbox_base_blank(type);
|
||||
|
||||
module bbox_top(type) //! Default top, can be overridden to customise
|
||||
render_2D_sheet(bbox_top_sheet(type))
|
||||
bbox_top_blank(type);
|
||||
|
||||
module bbox_back(type) //! Default back, can be overridden to customise
|
||||
render_2D_sheet(bbox_sheets(type))
|
||||
bbox_back_blank(type);
|
||||
|
||||
module bbox_front(type) //! Default front, can be overridden to customise
|
||||
render_2D_sheet(bbox_sheets(type))
|
||||
bbox_front_blank(type);
|
||||
|
||||
module bbox_left(type) //! Default left side, can be overridden to customise
|
||||
render_2D_sheet(bbox_sheets(type))
|
||||
bbox_left_blank(type);
|
||||
|
||||
module bbox_right(type) //! Default right side, can be overridden to customise
|
||||
render_2D_sheet(bbox_sheets(type))
|
||||
bbox_right_blank(type);
|
||||
|
||||
module _bbox_assembly(type, top = true, base = true, left = true, right = true, back = true, front = true) { //! The box assembly, wrap with a local copy without parameters
|
||||
width = bbox_width(type);
|
||||
|
@@ -116,10 +116,10 @@ module MT3608_carrier_stl() { //! Generate the STL for an MT3608 carrier, two re
|
||||
difference() {
|
||||
hull() {
|
||||
translate([offset, 0, height - eps / 2])
|
||||
rounded_rectangle([width, pcb_width - 2, eps], 1);
|
||||
rounded_rectangle([width, pcb_width - 2, eps], 1, true);
|
||||
|
||||
translate_z(eps / 2)
|
||||
rounded_rectangle([width, pcb_width - 2, eps], 1);
|
||||
rounded_rectangle([width, pcb_width - 2, eps], 1, true);
|
||||
}
|
||||
for(side = [-1, 1])
|
||||
hull() {
|
||||
|
@@ -45,7 +45,7 @@ function door_hinge_stat_screw() = stat_screw; //! Screw use to fas
|
||||
function door_hinge_stat_width() = stat_width; //! Width of the stationary part
|
||||
function door_hinge_stat_length() = stat_length; //! Length of the stationary part
|
||||
|
||||
module door_hinge_hole_positions(dir = 0) { //! Position chidren at the door hole positions
|
||||
module door_hinge_hole_positions(dir = 0) { //! Position children at the door hole positions
|
||||
hole_pitch = width - 10;
|
||||
|
||||
for(side = [-1, 1])
|
||||
|
@@ -44,7 +44,7 @@ module door_latch_stl() { //! Generates the STL for the printed part
|
||||
difference() {
|
||||
union() {
|
||||
hull() {
|
||||
rounded_rectangle([length, width, thickness - tan(30) * (width - ridge) / 2], rad, center = false);
|
||||
rounded_rectangle([length, width, thickness - tan(30) * (width - ridge) / 2], rad);
|
||||
|
||||
translate_z(thickness / 2)
|
||||
cube([length, ridge, thickness], center = true);
|
||||
@@ -57,7 +57,7 @@ module door_latch_stl() { //! Generates the STL for the printed part
|
||||
}
|
||||
}
|
||||
|
||||
module door_latch_assembly(sheet_thickness = 3) { //! The assembly for a specified sheet thickess
|
||||
module door_latch_assembly(sheet_thickness = 3) { //! The assembly for a specified sheet thickness
|
||||
washer = screw_washer(screw);
|
||||
nut = screw_nut(screw);
|
||||
|
||||
|
@@ -20,7 +20,7 @@
|
||||
//
|
||||
//! Parametric cable drag chain to limit the bend radius of a cable run.
|
||||
//!
|
||||
//! Each link has a maximum bend angle of 45°, so the mininium radius is proportional to the link length.
|
||||
//! Each link has a maximum bend angle of 45°, so the minimum radius is proportional to the link length.
|
||||
//!
|
||||
//! The travel property is how far it can move in each direction, i.e. half the maximum travel if the chain is mounted in the middle of the travel.
|
||||
//!
|
||||
|
@@ -17,7 +17,7 @@
|
||||
// If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//
|
||||
//! Pintable fan finger guard to match the specified fan. To be `include`d, not `use`d.
|
||||
//! Printable fan finger guard to match the specified fan. To be `include`d, not `use`d.
|
||||
//!
|
||||
//! The ring spacing as well as the number of spokes can be specified, if zero a gasket is generated instead of a guard.
|
||||
//
|
||||
@@ -29,7 +29,7 @@ function fan_guard_wall() = extrusion_width - layer_height / 2 + nozzle / 2 + ex
|
||||
function fan_guard_corner_r(type) = washer_diameter(screw_washer(fan_screw(type))) / 2 + 0.5; //! Corner radius of the guard
|
||||
function fan_guard_width(type) = max(2 * (fan_hole_pitch(type) + fan_guard_corner_r(type)), fan_bore(type) + 4 * fan_guard_wall()); //! Width of the guard
|
||||
|
||||
module fan_guard(type, name = false, thickness = fan_guard_thickness(), spokes = 4, finger_width = 7, grill = false) { //! Generate the STL
|
||||
module fan_guard(type, name = false, thickness = fan_guard_thickness(), spokes = 4, finger_width = 7, grill = false, screws = true) { //! Generate the STL
|
||||
if(thickness)
|
||||
stl(name ? name : str("fan_guard_", fan_width(type)));
|
||||
hole_pitch = fan_hole_pitch(type);
|
||||
@@ -54,7 +54,7 @@ module fan_guard(type, name = false, thickness = fan_guard_thickness(), spokes =
|
||||
difference() {
|
||||
rounded_square([width, width], r = width / 2 - hole_pitch);
|
||||
|
||||
fan_holes(type, !grill, !grill, h = 0);
|
||||
fan_holes(type, !grill, !grill && screws, h = 0);
|
||||
}
|
||||
if(spokes) {
|
||||
intersection() {
|
||||
|
@@ -105,7 +105,8 @@ module fixing_block(screw = def_screw) { //! Generate the STL
|
||||
}
|
||||
}
|
||||
|
||||
module fixing_block_assembly(screw = def_screw) pose([55, 180, 25], [0, 4.8, 4.8]) //! Printed part with the inserts inserted
|
||||
module fixing_block_assembly(screw = def_screw) //! Printed part with the inserts inserted
|
||||
pose([55, 180, 25], [0, 4.8, 4.8])
|
||||
assembly(str("fixing_block_M", 20 * screw_radius(screw)), ngb = true) {
|
||||
translate_z(fixing_block_height(screw))
|
||||
rotate([0, 180, 0])
|
||||
|
@@ -40,7 +40,7 @@ function hinge_knuckles(type) = type[6]; //! How many knuckles
|
||||
function hinge_screw(type) = type[7]; //! Screw type to mount it
|
||||
function hinge_screws(type) = type[8]; //! How many screws
|
||||
function hinge_clearance(type) = type[9]; //! Clearance between knuckles
|
||||
function hinge_margin(type) = type[10]; //! How far to keep the screws from the knuckes
|
||||
function hinge_margin(type) = type[10]; //! How far to keep the screws from the knuckles
|
||||
|
||||
function flat_hinge(name, size, pin_d, knuckle_d, knuckles, screw, screws, clearance, margin) = //! Construct the property list for a flat hinge.
|
||||
[name, size.x, size.y, size.z, pin_d, knuckle_d, knuckles, screw, screws, clearance, margin];
|
||||
@@ -73,7 +73,7 @@ module hinge_male(type, female = false) { //! The half with the stationary
|
||||
assert(kr > pr, "knuckle diameter must be bigger than the pin diameter");
|
||||
|
||||
n = hinge_knuckles(type);
|
||||
assert(n >= 3, "must be at least three knuckes");
|
||||
assert(n >= 3, "must be at least three knuckles");
|
||||
mn = ceil(n / 2); // Male knuckles
|
||||
fn = floor(n / 2); // Female knuckles
|
||||
gap = hinge_clearance(type);
|
||||
|
@@ -67,18 +67,18 @@ module foot(type = foot) { //! Generate STL
|
||||
}
|
||||
}
|
||||
|
||||
module foot_assembly(t = 0, type = foot, flip = false) { //! Assembly with fasteners in place for specified sheet thickness
|
||||
module foot_assembly(t = 0, type = foot, flip = false, no_washer = false) { //! Assembly with fasteners in place for specified sheet thickness
|
||||
screw = foot_screw(type);
|
||||
nut = screw_nut(screw);
|
||||
squeeze = 0.5;
|
||||
screw_length = screw_length(screw, foot_thickness(type) + t - squeeze, 2, nyloc = true);
|
||||
screw_length = screw_length(screw, foot_thickness(type) + t - squeeze, no_washer ? 1 : 2, nyloc = true);
|
||||
|
||||
vflip() explode(15, true) {
|
||||
stl_colour(pp4_colour) foot(type);
|
||||
|
||||
if(t)
|
||||
explode(15, true)
|
||||
translate_z(foot_thickness(type))
|
||||
translate_z(foot_thickness(type) - squeeze)
|
||||
if(flip)
|
||||
nut_and_washer(nut, true);
|
||||
else
|
||||
@@ -87,9 +87,15 @@ module foot_assembly(t = 0, type = foot, flip = false) { //! Assembly with faste
|
||||
if(t)
|
||||
translate_z(t)
|
||||
if(flip)
|
||||
screw_and_washer(screw, screw_length);
|
||||
if(no_washer)
|
||||
screw(screw, screw_length);
|
||||
else
|
||||
screw_and_washer(screw, screw_length);
|
||||
else
|
||||
nut_and_washer(nut, true);
|
||||
if(no_washer)
|
||||
nut(nut, true);
|
||||
else
|
||||
nut_and_washer(nut, true);
|
||||
}
|
||||
|
||||
module insert_foot(type = insert_foot) { //! Generate STL for foot with insert
|
||||
|
@@ -79,7 +79,8 @@ module handle_stl() { //! generate the STL
|
||||
//
|
||||
//! 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
|
||||
module handle_assembly() //! Printed part with inserts in place
|
||||
pose([225, 0, 150], [0, 0, 14])
|
||||
assembly("handle", ngb = true) {
|
||||
translate_z(handle_height())
|
||||
stl_colour(pp1_colour) vflip() handle_stl();
|
||||
|
154
printed/pocket_handle.scad
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
@@ -22,7 +22,7 @@
|
||||
//!
|
||||
//! Add solvent or glue to make a permanent fixture.
|
||||
//
|
||||
include <../core.scad>
|
||||
include <../utils/core/core.scad>
|
||||
|
||||
interference = 0.0;
|
||||
|
||||
|
@@ -26,7 +26,9 @@
|
||||
//!
|
||||
//! It can also have printed feet on the base with the screws doubling up to hold the base on.
|
||||
//
|
||||
include <../core.scad>
|
||||
include <../utils/core/core.scad>
|
||||
use <../vitamins/screw.scad>
|
||||
use <../vitamins/washer.scad>
|
||||
use <../vitamins/insert.scad>
|
||||
use <foot.scad>
|
||||
|
||||
@@ -182,7 +184,7 @@ module pbox(type) { //! Generate the STL for the main case
|
||||
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);
|
||||
rounded_rectangle([pbox_width(type) + 2 * outset, pbox_depth(type) + 2 * outset, ledge_h], 1);
|
||||
|
||||
hull() {
|
||||
linear_extrude(ledge_h + eps)
|
||||
|
@@ -21,8 +21,8 @@
|
||||
//! Creative Commons - Attribution - Share Alike license (see <https://creativecommons.org/licenses/by-sa/3.0/>)
|
||||
//
|
||||
|
||||
include <../core.scad>
|
||||
include <../vitamins/pulleys.scad>
|
||||
include <../utils/core/core.scad>
|
||||
use <../vitamins/pulley.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]];
|
||||
|
||||
|
@@ -41,6 +41,7 @@ overlap = 6;
|
||||
cable_tie_inset = wall + 4;
|
||||
|
||||
function psu_shroud_extent(type) = 15 + wall; //! How far it extends beyond the PSU to clear the connections
|
||||
function psu_shroud_wall(type) = wall; //! The wall thickness
|
||||
function psu_shroud_depth(type) = //! Outside depth of the shroud
|
||||
psu_left_bay(type) + overlap + psu_shroud_extent(type);
|
||||
|
||||
@@ -110,7 +111,7 @@ module psu_shroud(type, cable_d, name, cables = 1) { //! Generate the STL file f
|
||||
stl(str("psu_shroud_", name)) {
|
||||
// base and sides
|
||||
translate([centre_x, -centre_y]) {
|
||||
rounded_rectangle([depth - eps, width - eps, top], rad, center = false);
|
||||
rounded_rectangle([depth - eps, width - eps, top], rad);
|
||||
|
||||
linear_extrude(height)
|
||||
difference() {
|
||||
@@ -154,7 +155,7 @@ assembly(str("PSU_shroud_", name), ngb = true) {
|
||||
insert(insert);
|
||||
}
|
||||
|
||||
module psu_shroud_fastened_assembly(type, cable_d, thickness, name, cables = 1) //! Assembly with screws in place
|
||||
module psu_shroud_fastened_assembly(type, cable_d, thickness, name, cables = 1, screw = screw) //! Assembly with screws in place
|
||||
{
|
||||
screw_length = screw_length(screw,thickness + counter_bore, 2, true);
|
||||
|
||||
|
@@ -81,8 +81,9 @@ module ribbon_clamp(ways, screw = screw) { //! Generate STL for given number of
|
||||
}
|
||||
}
|
||||
|
||||
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) : ""), ngb = true) {
|
||||
module ribbon_clamp_assembly(ways, screw = screw) //! Printed part with inserts in place
|
||||
pose([55, 180, 25])
|
||||
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);
|
||||
|
||||
|
@@ -71,7 +71,7 @@ module ssr_shroud(type, cable_d, name) { //! Generate the STL file for a spec
|
||||
stl(str("ssr_shroud_", name)) {
|
||||
// base and sides
|
||||
translate([center_x, 0]) {
|
||||
rounded_rectangle([depth - eps, width - eps, top], rad, center = false);
|
||||
rounded_rectangle([depth - eps, width - eps, top], rad);
|
||||
|
||||
linear_extrude(height) difference() {
|
||||
round(or = wall / 2 - eps, ir = 0) difference() {
|
||||
|
@@ -81,7 +81,7 @@ def scrape_code(scad_file):
|
||||
match = re.match(r'^function (.*?\(.*?\)).*?(?://! ?(.*))$', line)
|
||||
if match:
|
||||
functions[match.group(1)] = match.group(2)
|
||||
match = re.match(r'^module (.*?\(.*?\)).*?(?://! ?(.*))$', line)
|
||||
match = re.match(r'^module (.*?\(.*\)).*?(?://! ?(.*))$', line)
|
||||
if match:
|
||||
modules[match.group(1)] = match.group(2)
|
||||
|
||||
|
@@ -31,6 +31,12 @@ from set_config import *
|
||||
import json
|
||||
import re
|
||||
|
||||
try:
|
||||
import parts
|
||||
got_parts_py = True
|
||||
except:
|
||||
got_parts_py = False
|
||||
|
||||
def find_scad_file(mname):
|
||||
for filename in os.listdir(source_dir):
|
||||
if filename[-5:] == ".scad":
|
||||
@@ -46,6 +52,18 @@ def find_scad_file(mname):
|
||||
return filename
|
||||
return None
|
||||
|
||||
def main_assembly(target):
|
||||
file = None
|
||||
if target:
|
||||
assembly = target + "_assembly"
|
||||
file = find_scad_file(assembly)
|
||||
if not file:
|
||||
assembly = "main_assembly"
|
||||
file = find_scad_file(assembly)
|
||||
if not file:
|
||||
raise Exception("can't find source for " + assembly)
|
||||
return assembly, file
|
||||
|
||||
class Part:
|
||||
def __init__(self, args):
|
||||
self.count = 1
|
||||
@@ -61,6 +79,7 @@ class BOM:
|
||||
self.name = name
|
||||
self.big = None
|
||||
self.ngb = False
|
||||
self.zoomed = 0
|
||||
self.count = 1
|
||||
self.vitamins = {}
|
||||
self.printed = {}
|
||||
@@ -75,6 +94,7 @@ class BOM:
|
||||
"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},
|
||||
@@ -115,6 +135,33 @@ class BOM:
|
||||
return ass
|
||||
return ass.replace("assembly", "assemblies")
|
||||
|
||||
def print_CSV(self, file = None):
|
||||
i = 0
|
||||
for part in sorted(self.vitamins):
|
||||
i += 1
|
||||
if ': ' in part:
|
||||
part_no, description = part.split(': ')
|
||||
else:
|
||||
part_no, description = "", part
|
||||
qty = self.vitamins[part].count
|
||||
if got_parts_py:
|
||||
match = re.match(r'^.*\((.*?)[,\)].*$', part_no)
|
||||
if match and not match.group(1).startswith('"'):
|
||||
part_no = part_no.replace('(' + match.group(1), '_' + match.group(1) + '(').replace('(, ', '(')
|
||||
func = 'parts.' + part_no.replace('(', '(%d, ' % qty).replace(', )', ')')
|
||||
func = func.replace('true', 'True').replace('false', 'False').replace('undef', 'None')
|
||||
try:
|
||||
price, url = eval(func)
|
||||
print("'%s',%3d,%.2f,'=B%d*C%d',%s" % (description, qty, price, i, i, url), file=file)
|
||||
except:
|
||||
if part_no:
|
||||
print("%s not found in parts.py" % func)
|
||||
print("'%s',%3d" % (description, qty), file=file)
|
||||
else:
|
||||
print("'%s',%3d" % (description, qty), file=file)
|
||||
if got_parts_py:
|
||||
print(",'=SUM(B1:B%d)',,'=SUM(D1:D%d)'" %(i, i), file=file)
|
||||
|
||||
def print_bom(self, breakdown, file = None):
|
||||
if self.vitamins:
|
||||
print("Vitamins:", file=file)
|
||||
@@ -219,28 +266,20 @@ def parse_bom(file = "openscad.log", name = None):
|
||||
return main
|
||||
|
||||
def usage():
|
||||
print("\nusage:\n\tbom [target_config] [<accessory_name>_assembly] - Generate BOMs for a project or an accessory to a project.")
|
||||
print("\nusage:\n\tbom [target_config] - Generate BOMs for a project.")
|
||||
sys.exit(1)
|
||||
|
||||
def boms(target = None, assembly = None):
|
||||
def boms(target = None):
|
||||
try:
|
||||
bom_dir = set_config(target, usage) + "bom"
|
||||
if assembly:
|
||||
bom_dir += "/accessories"
|
||||
if not os.path.isdir(bom_dir):
|
||||
os.makedirs(bom_dir)
|
||||
else:
|
||||
assembly = "main_assembly"
|
||||
if os.path.isdir(bom_dir):
|
||||
shutil.rmtree(bom_dir)
|
||||
sleep(0.1)
|
||||
os.makedirs(bom_dir)
|
||||
if os.path.isdir(bom_dir):
|
||||
shutil.rmtree(bom_dir)
|
||||
sleep(0.1)
|
||||
os.makedirs(bom_dir)
|
||||
#
|
||||
# Find the scad file that makes the module
|
||||
# Find the scad file that makes the main assembly
|
||||
#
|
||||
scad_file = find_scad_file(assembly)
|
||||
if not scad_file:
|
||||
raise Exception("can't find source for " + assembly)
|
||||
assembly, scad_file = main_assembly(target)
|
||||
#
|
||||
# make a file to use the module
|
||||
#
|
||||
@@ -257,8 +296,9 @@ def boms(target = None, assembly = None):
|
||||
|
||||
main = parse_bom("openscad.echo", assembly)
|
||||
|
||||
if assembly == "main_assembly":
|
||||
main.print_bom(True, open(bom_dir + "/bom.txt","wt"))
|
||||
main.print_bom(True, open(bom_dir + "/bom.txt","wt"))
|
||||
|
||||
main.print_CSV(open(bom_dir + "/bom.csv","wt"))
|
||||
|
||||
for ass in main.assemblies:
|
||||
with open(bom_dir + "/" + ass + ".txt", "wt") as f:
|
||||
@@ -276,20 +316,8 @@ def boms(target = None, assembly = None):
|
||||
sys.exit(1)
|
||||
|
||||
if __name__ == '__main__':
|
||||
if len(sys.argv) > 3: usage()
|
||||
if len(sys.argv) > 2: usage()
|
||||
|
||||
if len(sys.argv) == 3:
|
||||
target, assembly = sys.argv[1], sys.argv[2]
|
||||
else:
|
||||
if len(sys.argv) == 2:
|
||||
if sys.argv[1][-9:] == "_assembly":
|
||||
target, assembly = None, sys.argv[1]
|
||||
else:
|
||||
target, assembly = sys.argv[1], None
|
||||
else:
|
||||
target, assembly = None, None
|
||||
target = sys.argv[1] if len(sys.argv) == 2 else None
|
||||
|
||||
if assembly:
|
||||
if assembly[-9:] != "_assembly": usage()
|
||||
|
||||
boms(target, assembly)
|
||||
boms(target)
|
||||
|
166
scripts/changelog.py
Normal file
@@ -0,0 +1,166 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
#
|
||||
# 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/>.
|
||||
#
|
||||
#! Creates the changelog from the git log
|
||||
|
||||
from __future__ import print_function
|
||||
import sys
|
||||
import subprocess
|
||||
import re
|
||||
from tests import do_cmd
|
||||
|
||||
filename = 'CHANGELOG.md'
|
||||
|
||||
def tag_version(t):
|
||||
""" Format a version tag """
|
||||
return 'v%d.%d.%d' % t
|
||||
|
||||
def initials(name):
|
||||
""" Convert full name to initials with a tooltip """
|
||||
i = ''.join([n[0].upper() + '.' for n in name.split(' ')])
|
||||
return '[%s](# "%s")' % (i, name)
|
||||
|
||||
def get_remote_url():
|
||||
""" Get the git remote URL for the repository """
|
||||
url = subprocess.check_output(["git", "config", "--get", "remote.origin.url"]).decode("utf-8").strip("\n")
|
||||
if url.startswith("git@"):
|
||||
url = url.replace(":", "/", 1).replace("git@", "https://", 1)
|
||||
if url.endswith(".git"):
|
||||
url = url[:-4]
|
||||
return url
|
||||
|
||||
def iscode(word):
|
||||
""" try to guess if the word is code """
|
||||
endings = ['()', '*']
|
||||
starts = ['$', '--']
|
||||
anywhere = ['.', '_', '=', '[', '/']
|
||||
words = ['center', 'false', 'true', 'ngb']
|
||||
|
||||
for w in words:
|
||||
if word == w:
|
||||
return True
|
||||
|
||||
for end in endings:
|
||||
if word.endswith(end):
|
||||
return True
|
||||
|
||||
for start in starts:
|
||||
if word.startswith(start):
|
||||
return True
|
||||
|
||||
for any in anywhere:
|
||||
if word.find(any) >= 0:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def codify(word, url):
|
||||
""" if a word is deemed code enclose it backticks """
|
||||
if word:
|
||||
if re.match(r'#[0-9]+', word):
|
||||
return '[%s](%s "show issue")' % (word, url + '/issues/' + word[1:])
|
||||
if iscode(word):
|
||||
return '`' + word + '`'
|
||||
return word
|
||||
|
||||
|
||||
def fixup_comment(comment, url):
|
||||
""" markup code words and fix new paragraphs """
|
||||
result = ''
|
||||
word = ''
|
||||
code = False
|
||||
for i, c in enumerate(comment):
|
||||
if c == '`' or code: # Already a code block
|
||||
result += c # Copy verbatim
|
||||
if c == '`': code = not code # Keep track of state
|
||||
else:
|
||||
if c in ' \n' or (c == '.' and (i + 1 == len(comment) or comment[i + 1] in ' \n')): # if a word terminator
|
||||
result += codify(word, url) + c # Add codified word before terminator
|
||||
word = ''
|
||||
else:
|
||||
word += c # Accumulate next word
|
||||
result += codify(word, url) # In case comment ends without a terminator
|
||||
return result.replace('\n\n','\n\n * ') # Give new paragraphs a bullet point
|
||||
|
||||
class Commit(): # members dynamically added from commit_fields
|
||||
pass
|
||||
|
||||
blurb = """
|
||||
# %s Changelog
|
||||
This changelog is generated by `changelog.py` using manually added semantic version tags to classify commits as breaking changes, additions or fixes.
|
||||
|
||||
"""
|
||||
|
||||
if __name__ == '__main__':
|
||||
url = get_remote_url()
|
||||
|
||||
commit_fields = {
|
||||
'hash': "%H|", # commit commit_hash
|
||||
'tag': "%D|", # tag
|
||||
'author': "%aN|", # author name
|
||||
'date': " %as|", # author date short form
|
||||
'comment': "%B~" # body
|
||||
}
|
||||
|
||||
# Produce the git log
|
||||
format = ''.join([v for k, v in commit_fields.items()])
|
||||
text = subprocess.check_output(["git", "log", "--topo-order", "--format=" + format]).decode("utf-8")
|
||||
|
||||
# Process the log into a list of Commit objects
|
||||
commits = []
|
||||
for line in text.split('~'):
|
||||
line = line.strip('\n')
|
||||
if line:
|
||||
fields = line.split('|')
|
||||
commit = Commit()
|
||||
for i, k in enumerate(commit_fields):
|
||||
exec('commit.%s = """%s"""' % (k, fields[i]), locals())
|
||||
# Convert version tag to tuple
|
||||
if commit.tag:
|
||||
match = re.match(r'.*tag: v([0-9]+)\.([0-9]+)\.([0-9]+).*', commit.tag)
|
||||
commit.tag = (int(match.group(1)), int(match.group(2)), int(match.group(3))) if match else ''
|
||||
commits.append(commit)
|
||||
|
||||
# Format the results from the Commit objects
|
||||
with open(filename, "wt") as file:
|
||||
print(blurb % url.split('/')[-1], file = file)
|
||||
for i, c in enumerate(commits):
|
||||
if c.tag:
|
||||
ver = tag_version(c.tag)
|
||||
level, type = (3, 'Fixes') if c.tag[2] else (2, 'Additions') if c.tag[1] else (1, 'Breaking Changes') if c.tag[0] else (1, 'First publicised version')
|
||||
|
||||
# Find the previous tagged commit
|
||||
j = i + 1
|
||||
diff = ''
|
||||
while j < len(commits):
|
||||
if commits[j].tag:
|
||||
last_ver = tag_version(commits[j].tag)
|
||||
diff = '[...](%s "diff with %s")' % (url + '/compare/' + last_ver + '...' + ver, last_ver)
|
||||
break
|
||||
j += 1
|
||||
|
||||
# Print verson info
|
||||
print('%s [%s](%s "show release") %s %s' % ('#' * (level + 1), ver, url + '/releases/tag/' + ver, type, diff), file = file)
|
||||
|
||||
# Print commits excluding merges
|
||||
|
||||
if not c.comment.startswith('Merge branch') and not c.comment.startswith('Merge pull') and not re.match(r'U..ated changelog.*', c.comment):
|
||||
print('* %s [`%s`](%s "show commit") %s %s\n' % (c.date, c.hash[:7], url + '/commit/' + c.hash, initials(c.author), fixup_comment(c.comment, url)), file = file)
|
||||
do_cmd(('codespell -w -L od ' + filename).split())
|
@@ -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):
|
||||
|
@@ -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,12 +65,20 @@ 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
|
||||
@@ -120,18 +131,19 @@ 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("include <NopSCADlib/global_defs.scad>\n")
|
||||
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)
|
||||
openscad.run("-o", part_file, part_maker_name, "-D$bom=1", "-d", dname)
|
||||
times.add_time(part, t)
|
||||
if part_type == 'stl':
|
||||
bounds = c14n_stl.canonicalise(part_file)
|
||||
@@ -145,6 +157,10 @@ 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:
|
||||
|
@@ -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:
|
||||
|
@@ -25,19 +25,25 @@ from __future__ import print_function
|
||||
import subprocess, sys
|
||||
|
||||
def run_list(args, silent = False, verbose = False):
|
||||
cmd = ["openscad", "--hardwarnings"] + args
|
||||
cmd = ["openscad"] + args + ["--hardwarnings"]
|
||||
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)
|
||||
|
||||
|
@@ -17,9 +17,10 @@
|
||||
# If not, see <https://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
# Set command line options from enviroment variables and check if they have changed
|
||||
# Set command line options from environment 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():
|
||||
|
@@ -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,22 +43,32 @@ 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]
|
||||
|
||||
#
|
||||
# Loop through source directories
|
||||
#
|
||||
used = []
|
||||
all_used = []
|
||||
all_sources = []
|
||||
all_parts = []
|
||||
read_times = False
|
||||
for dir in [source_dir1, source_dir2]:
|
||||
if not os.path.isdir(dir):
|
||||
continue
|
||||
if not os.path.isdir(target_dir):
|
||||
os.makedirs(target_dir)
|
||||
|
||||
if not read_times:
|
||||
times.read_times(target_dir)
|
||||
read_times = True
|
||||
#
|
||||
# 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,42 +77,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)
|
||||
target_def = ['-D$target="%s"' % target] if target else []
|
||||
cwd_def = ['-D$cwd="%s"' % os.getcwd().replace('\\', '/')]
|
||||
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
|
||||
@@ -111,3 +136,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)
|
||||
|
@@ -8,6 +8,7 @@ They should work with both Python 2 and Python 3.
|
||||
|:---|:---|
|
||||
| `bom.py` | Generates BOM files for the project. |
|
||||
| `c14n_stl.py` | OpenSCAD produces randomly ordered STL files. This script re-orders them consistently so that GIT can tell if they have changed or not. |
|
||||
| `changelog.py` | Creates the changelog from the git log |
|
||||
| `doc_scripts.py` | Makes this document and doc/usage.md. |
|
||||
| `dxfs.py` | Generates DXF files for all the routed parts listed on the BOM or a specified list. |
|
||||
| `gallery.py` | Finds projects and adds them to the gallery. |
|
||||
|
@@ -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,21 @@ 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'
|
||||
openscad.run(colour_scheme, "--projection=p", "--imgsize=4096,4096", cam, render, "--autocenter", "--viewall", "-o", tmp_name, png_maker_name);
|
||||
tmp_name = tmp_dir + '/' + part[:-4] + '.png'
|
||||
dummy_deps_name = tmp_dir + '/tmp.deps' # work around for OpenSCAD issue #3879
|
||||
openscad.run("-o", tmp_name, png_maker_name, colour_scheme, "--projection=p", "--imgsize=4096,4096", cam, render, "--autocenter", "--viewall", "-d", dummy_deps_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)
|
||||
os.remove(dummy_deps_name)
|
||||
#
|
||||
# Remove tmp dir
|
||||
#
|
||||
rmtmpdir(tmp_dir)
|
||||
|
||||
if __name__ == '__main__':
|
||||
init()
|
||||
|
@@ -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():
|
||||
|
@@ -34,6 +34,7 @@ import shutil
|
||||
from deps import *
|
||||
from blurb import *
|
||||
from colorama import Fore
|
||||
from tmpdir import *
|
||||
|
||||
w = 4096
|
||||
h = w
|
||||
@@ -59,7 +60,8 @@ def compare_images(a, b, c):
|
||||
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(float(f.read().strip()))
|
||||
pixels = f.read().strip()
|
||||
pixels = int(float(pixels if pixels.isnumeric() else -1))
|
||||
os.remove(log_name)
|
||||
return pixels
|
||||
|
||||
@@ -70,6 +72,8 @@ def update_image(tmp_name, png_name):
|
||||
if pixels < 0 or pixels > threshold:
|
||||
shutil.copyfile(tmp_name, png_name)
|
||||
print(Fore.YELLOW + png_name + " updated" + Fore.WHITE, pixels if pixels > 0 else '')
|
||||
if png_name.endswith('_tn.png') and os.path.isfile(diff_name):
|
||||
os.remove(diff_name)
|
||||
else:
|
||||
os.utime(png_name, None)
|
||||
os.remove(diff_name)
|
||||
@@ -94,6 +98,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"
|
||||
@@ -114,7 +119,7 @@ def tests(tests):
|
||||
libtest = True
|
||||
lib_blurb = scrape_blurb(scad_name)
|
||||
if not os.path.isfile(png_name):
|
||||
openscad.run(colour_scheme, "--projection=p", "--imgsize=%d,%d" % (w, h), "--camera=0,0,0,50,0,340,500", "--autocenter", "--viewall", "-o", png_name, scad_name);
|
||||
openscad.run(scad_name, "-o", png_name, colour_scheme, "--projection=p", "--imgsize=%d,%d" % (w, h), "--camera=0,0,0,50,0,340,500", "--autocenter", "--viewall");
|
||||
do_cmd(["magick", png_name, "-trim", "-resize", "1280", "-bordercolor", background, "-border", "10", png_name])
|
||||
else:
|
||||
#
|
||||
@@ -170,7 +175,7 @@ def tests(tests):
|
||||
impl_name = None
|
||||
|
||||
if libtest:
|
||||
vsplit = "AJR" + chr(ord('Z') + 1)
|
||||
vsplit = "AIR" + chr(ord('Z') + 1)
|
||||
vtype = locations[0][1]
|
||||
types = [vtype + ' ' + vsplit[i] + '-' + chr(ord(vsplit[i + 1]) - 1) for i in range(len(vsplit) - 1)] + [loc[1] for loc in locations[1 :]]
|
||||
if type == vtype:
|
||||
@@ -234,8 +239,8 @@ def tests(tests):
|
||||
if changed:
|
||||
print(changed)
|
||||
t = time.time()
|
||||
tmp_name = '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]);
|
||||
tmp_name = tmp_dir + '/tmp.png'
|
||||
openscad.run_list([scad_name, "-o", tmp_name] + 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]);
|
||||
times.add_time(scad_name, t)
|
||||
do_cmd(["magick", tmp_name, "-trim", "-resize", "1000x600", "-bordercolor", background, "-border", "10", tmp_name])
|
||||
update_image(tmp_name, png_name)
|
||||
@@ -303,6 +308,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__':
|
||||
|
@@ -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):
|
||||
|
41
scripts/tmpdir.py
Normal file
@@ -0,0 +1,41 @@
|
||||
#
|
||||
# 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):
|
||||
time.sleep(0.1)
|
||||
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)
|
@@ -38,6 +38,7 @@ 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'
|
||||
@@ -76,12 +77,12 @@ def bom_to_assemblies(bom_dir, bounds_map):
|
||||
#
|
||||
if flat_bom:
|
||||
ass = flat_bom[-1]
|
||||
if len(ass["assemblies"]) < 2 and not ass["vitamins"] and not ass["printed"] and not ass["routed"]:
|
||||
if len(ass["assemblies"]) == 1 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(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
|
||||
print('<span></span>', file = doc_file) # An invisible 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:
|
||||
@@ -129,8 +130,9 @@ def views(target, do_assemblies = None):
|
||||
# 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)
|
||||
@@ -159,6 +161,7 @@ def views(target, do_assemblies = None):
|
||||
# Find all the scad files
|
||||
#
|
||||
main_blurb = None
|
||||
main_assembly, main_file = bom.main_assembly(target)
|
||||
pngs = []
|
||||
for dir in source_dirs(bom_dir):
|
||||
if os.path.isdir(dir):
|
||||
@@ -183,6 +186,7 @@ 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
|
||||
@@ -204,20 +208,22 @@ def views(target, do_assemblies = None):
|
||||
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("include <NopSCADlib/global_defs.scad>\n")
|
||||
f.write("use <%s/%s>\n" % (reltmp(dir, target), filename))
|
||||
f.write("%s();\n" % module);
|
||||
t = time.time()
|
||||
target_def = ['-D$target="%s"' % target] if target else []
|
||||
cwd_def = ['-D$cwd="%s"' % os.getcwd().replace('\\', '/')]
|
||||
openscad.run_list(options.list() + target_def + cwd_def + ["-D$pose=1", "-D$explode=%d" % explode, colour_scheme, "--projection=p", "--imgsize=4096,4096", "--autocenter", "--viewall", "-d", dname, "-o", tmp_name, png_maker_name]);
|
||||
view_def = ['--viewall', '--autocenter'] if not (zoomed & (1 << explode)) else ['--camera=0,0,0,55,0,25,140']
|
||||
openscad.run_list(["-o", tmp_name, png_maker_name] + options.list() + target_def + cwd_def + view_def + ["-D$pose=1", "-D$explode=%d" % explode, colour_scheme, "--projection=p", "--imgsize=4096,4096", "-d", dname]);
|
||||
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)
|
||||
@@ -228,7 +234,7 @@ def views(target, do_assemblies = None):
|
||||
update_image(tmp_name, tn_name)
|
||||
done_assemblies.append(real_name)
|
||||
else:
|
||||
if module == 'main_assembly':
|
||||
if module == main_assembly:
|
||||
main_blurb = blurb.scrape_module_blurb(lines[:line_no])
|
||||
line_no += 1
|
||||
#
|
||||
@@ -242,9 +248,6 @@ def views(target, do_assemblies = None):
|
||||
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):
|
||||
@@ -439,6 +442,10 @@ def views(target, do_assemblies = None):
|
||||
dst.write(line)
|
||||
i += 1
|
||||
#
|
||||
# Remove tmp dir
|
||||
#
|
||||
rmtmpdir(tmp_dir)
|
||||
#
|
||||
# Spell check
|
||||
#
|
||||
do_cmd(('codespell -L od ' + top_dir + 'readme.md').split())
|
||||
|
29
tests/7_segments.scad
Normal file
@@ -0,0 +1,29 @@
|
||||
//
|
||||
// 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 <../utils/core/core.scad>
|
||||
use <../utils/layout.scad>
|
||||
|
||||
include <../vitamins/7_segments.scad>
|
||||
|
||||
module 7_segments()
|
||||
layout([for(s = 7_segments) 7_segment_size(s).x * 2], 5) let(s = 7_segments[$i])
|
||||
7_segment_digits(s, 2);
|
||||
|
||||
if($preview)
|
||||
7_segments();
|
31
tests/BLDC_motors.scad
Normal file
@@ -0,0 +1,31 @@
|
||||
//
|
||||
// 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>
|
||||
use <../utils/layout.scad>
|
||||
|
||||
include <../vitamins/bldc_motors.scad>
|
||||
|
||||
module bldc_motors()
|
||||
layout([for(b = bldc_motors) BLDC_diameter(b)])
|
||||
rotate(-90)
|
||||
BLDC(bldc_motors[$i]);
|
||||
|
||||
if($preview)
|
||||
let($show_threads = 1)
|
||||
bldc_motors();
|
@@ -20,10 +20,10 @@
|
||||
//
|
||||
//! BOM and assembly demonstration
|
||||
//
|
||||
$explode = 1; // Normally set on the command line when generating assembly views with views.py
|
||||
include <../core.scad>
|
||||
include <../vitamins/sheets.scad>
|
||||
use <../vitamins/insert.scad>
|
||||
$explode = 1; // Normally set on the command line when generating assembly views with views.py
|
||||
|
||||
screw = M3_cap_screw;
|
||||
sheet = PMMA3;
|
||||
@@ -46,7 +46,7 @@ module widget(thickness) {
|
||||
module widget_stl() {
|
||||
stl("widget")
|
||||
union() {
|
||||
rounded_rectangle([30, 30, 3], 2);
|
||||
rounded_rectangle([30, 30, 3], 2, true);
|
||||
|
||||
render() insert_boss(insert, height, 2.2);
|
||||
}
|
||||
|
@@ -16,7 +16,7 @@
|
||||
// You should have received a copy of the GNU General Public License along with NopSCADlib.
|
||||
// If not, see <https://www.gnu.org/licenses/>.
|
||||
//
|
||||
include <../core.scad>
|
||||
include <../utils/core/core.scad>
|
||||
use <../vitamins/dip.scad>
|
||||
|
||||
dips = [[6, "OPTO"], [8, "NE555"], [14, "74HC00"], [16, "ULN2003"], [18, "ULN2803"], [20, "74HC245"], [28, "ATMEGA328"]];
|
||||
|
@@ -16,6 +16,7 @@
|
||||
// You should have received a copy of the GNU General Public License along with NopSCADlib.
|
||||
// If not, see <https://www.gnu.org/licenses/>.
|
||||
//
|
||||
include <../utils/core/core.scad>
|
||||
include <../vitamins/ldrs.scad>
|
||||
|
||||
use <../utils/layout.scad>
|
||||
|
@@ -22,6 +22,8 @@ include <../vitamins/d_connectors.scad>
|
||||
include <../vitamins/leds.scad>
|
||||
include <../vitamins/axials.scad>
|
||||
include <../vitamins/smds.scad>
|
||||
include <../vitamins/7_segments.scad>
|
||||
include <../vitamins/potentiometers.scad>
|
||||
|
||||
use <../vitamins/pcb.scad>
|
||||
|
||||
@@ -46,7 +48,7 @@ TMC2130 = ["TMC2130", "TMC2130",
|
||||
[]
|
||||
];
|
||||
|
||||
test_pcb = ["TestPCB", "Test PCB",
|
||||
test_pcb = ["test_pcb", "Test PCB",
|
||||
100, 250, 1.6, // length, width, thickness
|
||||
3, // Corner radius
|
||||
2.75, // Mounting hole diameter
|
||||
@@ -64,21 +66,25 @@ test_pcb = ["TestPCB", "Test PCB",
|
||||
[ 16, 2, 90, "smd_res", RES1206, "1K"],
|
||||
[ 19, 2, 90, "smd_res", RES0805, "1K"],
|
||||
[ 22, 2, 90, "smd_res", RES0603, "1K"],
|
||||
[ 25, 2, 90, "smd_cap", CAP1206, 1.5],
|
||||
[ 28, 2, 90, "smd_cap", CAP0805, 1.0],
|
||||
[ 31, 2, 90, "smd_cap", CAP0603, 0.7],
|
||||
|
||||
[ 10, 10, 0, "2p54header", 4, 1],
|
||||
[ 25, 10, 0, "2p54header", 5, 1, false, "blue" ],
|
||||
[ 10, 20, 0, "2p54boxhdr", 4, 2],
|
||||
[ 10, 30, 0, "2p54socket", 6, 1],
|
||||
[ 25, 30, 0, "2p54socket", 4, 1, false, 0, false, "red" ],
|
||||
[ 10, 40, 0, "chip", 10, 5, 1, grey(20)],
|
||||
[ 5, 50, 0, "led", LED3mm, "red"],
|
||||
[ 12, 50, 0, "led", LED5mm, "orange"],
|
||||
[ 25, 50, 0, "led", LED10mm, "yellow"],
|
||||
[ 10, 65, 180, "rj45"],
|
||||
[ 8, 85, 180, "usb_A"],
|
||||
[ 65, 50, 0, "led", LED3mm, "red"],
|
||||
[ 75, 50, 0, "led", LED5mm, "orange"],
|
||||
[ 90, 50, 0, "led", LED10mm, "yellow"],
|
||||
[ 10, 45, 180, "rj45"],
|
||||
[ 8, 65, 180, "usb_A"],
|
||||
[ 8, 105, 180, "usb_Ax2"],
|
||||
[ 7, 85, 180, "molex_usb_Ax1"],
|
||||
[ 8.5,125, 180, "molex_usb_Ax2"],
|
||||
[ 3, 140, 180, "usb_uA"],
|
||||
[ 8, 155, 180, "usb_B"],
|
||||
[ 8.5, 125, 180, "molex_usb_Ax2"],
|
||||
[ 25, 200, 0, "buzzer", 4.5, 8.5],
|
||||
[ 25, 218, 0, "buzzer"],
|
||||
[ 8, 190, 180, "jack"],
|
||||
@@ -91,6 +97,8 @@ test_pcb = ["TestPCB", "Test PCB",
|
||||
[ 65, 12, 0, "ax_res", res1_8, 1000],
|
||||
[ 65, 17, 0, "ax_res", res1_4, 10000],
|
||||
[ 65, 22, 0, "ax_res", res1_2, 100000],
|
||||
[ 55, 22, 0, "vero_pin"],
|
||||
[ 55, 17, 0, "vero_pin", true],
|
||||
|
||||
[ 80, 9, 0, "link", inch(0.2), inch(0.4)],
|
||||
[ 80, 12, 0, "ax_res", res1_8, 1000000, 1, inch(0.1)],
|
||||
@@ -127,11 +135,14 @@ test_pcb = ["TestPCB", "Test PCB",
|
||||
[ 52, 200, 0, "pcb", 11, TMC2130 ],
|
||||
[ 80, 200, 0, "pdip", 24, "27C32", true, inch(0.6) ],
|
||||
[ 80, 170, 0, "pdip", 8, "NE555" ],
|
||||
[ 80, 150, 0, "chip", 10, 5, 1, grey(20)],
|
||||
|
||||
[ 52, 206, 0, "2p54socket", 8, 1 ],
|
||||
[ 52, 194, 0, "2p54socket", 8, 1, false, 0, false, "red" ],
|
||||
[ 50, 220, 0, "standoff", 5, 4.5, 12.5, 2.54],
|
||||
[ 50, 240, 0, "potentiometer"],
|
||||
[ 75, 240, 0, "potentiometer", 7, 8],
|
||||
[ 75, 240, 0, "potentiometer", KY_040_encoder, 8],
|
||||
[ 30, 85, -90, "7seg", WT5011BSR, 2],
|
||||
],
|
||||
// accessories
|
||||
[]
|
||||
|
@@ -21,7 +21,7 @@ include <../vitamins/pcbs.scad>
|
||||
|
||||
use <../utils/layout.scad>
|
||||
|
||||
function spacing(p) = let(w = pcb_width(p)) w < 22 ? w + 3 : w + 10;
|
||||
function spacing(p) = let(w = pcb_width(p)) w < 22 ? w + 3 : w + 7;
|
||||
|
||||
module pcbs() {
|
||||
layout([for(p = pcbs) spacing(p)], 0)
|
||||
@@ -29,6 +29,11 @@ module pcbs() {
|
||||
rotate(90)
|
||||
pcb_assembly(pcbs[$i], 5 + $i, 3);
|
||||
|
||||
translate([0, 65])
|
||||
layout([for(p = tiny_pcbs) pcb_length(p)], 3)
|
||||
translate([0, -pcb_width(tiny_pcbs[$i]) / 2])
|
||||
pcb_assembly(tiny_pcbs[$i], 5 + $i, 3);
|
||||
|
||||
translate([0, 120])
|
||||
layout([for(p = perfboards) pcb_length(p)], 10)
|
||||
translate([0, -pcb_width(perfboards[$i]) / 2])
|
||||
|
@@ -22,18 +22,20 @@ include <../vitamins/extrusions.scad>
|
||||
|
||||
use <../utils/layout.scad>
|
||||
|
||||
module sk_brackets() {
|
||||
module sk_brackets(examples = false) {
|
||||
screws = [M4_dome_screw, M4_cap_screw, M5_cap_screw, M5_cap_screw];
|
||||
nuts = [M4_hammer_nut, M4_sliding_t_nut, M5_sliding_t_nut, undef];
|
||||
// channel depth = 6 for 2020 extrusion, 9 for 3030 extrusion
|
||||
depths = [6, 6, 9, 0];
|
||||
layout([for(s = sk_brackets) 1.5 * sk_size(s)[1]]) {
|
||||
sk_bracket_assembly(sk_brackets[$i], screw_type = screws[$i], nut_type = nuts[$i], max_screw_depth = depths[$i]);
|
||||
translate([0, -sk_hole_offset(sk_brackets[$i]) - extrusion_width($i < 2 ? E2020 : E3030) / 2, 0])
|
||||
rotate([0, 90, 0])
|
||||
extrusion($i < 2 ? E2020 : E3030, 20, false);
|
||||
|
||||
if(examples)
|
||||
translate([0, -sk_hole_offset(sk_brackets[$i]) - extrusion_width($i < 2 ? E2020 : E3030) / 2, 0])
|
||||
rotate([0, 90, 0])
|
||||
extrusion($i < 2 ? E2020 : E3030, 20, false);
|
||||
}
|
||||
}
|
||||
|
||||
if($preview)
|
||||
sk_brackets();
|
||||
sk_brackets(true);
|
||||
|
@@ -28,6 +28,11 @@ module smds() {
|
||||
translate([0, 3])
|
||||
layout([for(l = smd_leds) smd_led_size(l).x], 1)
|
||||
smd_led(smd_leds[$i], ["green", "blue", "red"][$i % 3]);
|
||||
|
||||
translate([0, 6])
|
||||
layout([for(c = smd_capacitors) smd_cap_size(c).x], 1)
|
||||
let(c = smd_capacitors[$i])
|
||||
smd_capacitor(c, smd_cap_size(c).y * 0.8);
|
||||
}
|
||||
|
||||
if($preview)
|
||||
|
@@ -16,7 +16,7 @@
|
||||
// You should have received a copy of the GNU General Public License along with NopSCADlib.
|
||||
// If not, see <https://www.gnu.org/licenses/>.
|
||||
//
|
||||
include <../core.scad>
|
||||
include <../utils/core/core.scad>
|
||||
include <../vitamins/ssrs.scad>
|
||||
|
||||
use <../utils/layout.scad>
|
||||
|
@@ -16,7 +16,7 @@
|
||||
// You should have received a copy of the GNU General Public License along with NopSCADlib.
|
||||
// If not, see <https://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
include <../utils/core/core.scad>
|
||||
use <../utils/layout.scad>
|
||||
|
||||
include <../vitamins/ball_bearings.scad>
|
||||
|
@@ -17,7 +17,7 @@
|
||||
// If not, see <https://www.gnu.org/licenses/>.
|
||||
//
|
||||
include <../core.scad>
|
||||
include <../vitamins/scs_bearing_blocks.scad>
|
||||
include <../vitamins/bearing_blocks.scad>
|
||||
|
||||
use <../utils/layout.scad>
|
||||
|
@@ -25,9 +25,9 @@ use <../utils/layout.scad>
|
||||
module belt_test() {
|
||||
p2 = [-75, -50];
|
||||
p3 = [-75, 100];
|
||||
p4 = [75, 100];
|
||||
p4 = [ 75, 100];
|
||||
|
||||
p5 = [75 + pulley_pr(GT2x20ob_pulley) - pulley_pr(GT2x16_plain_idler), +pulley_pr(GT2x16_plain_idler)];
|
||||
p5 = [ 75 + pulley_pr(GT2x20ob_pulley) - pulley_pr(GT2x16_plain_idler), +pulley_pr(GT2x16_plain_idler)];
|
||||
p6 = [-75 + pulley_pr(GT2x20ob_pulley) + pulley_pr(GT2x16_plain_idler), -pulley_pr(GT2x16_plain_idler)];
|
||||
|
||||
module pulleys(flip = false) {
|
||||
@@ -52,19 +52,21 @@ module belt_test() {
|
||||
translate(p6) pulley_assembly(GT2x16_plain_idler);
|
||||
}
|
||||
|
||||
path = [ [p5.x, p5.y, pulley_pr(GT2x16_plain_idler)],
|
||||
path = [ [-40, 0, 0],
|
||||
[p6.x, p6.y, -pulley_pr(GT2x16_plain_idler)],
|
||||
[p2.x, p2.y, pulley_pr(GT2x20ob_pulley)],
|
||||
[p3.x, p3.y, pulley_pr(GT2x20ob_pulley)],
|
||||
[p4.x, p4.y, pulley_pr(GT2x20ob_pulley)]
|
||||
[p4.x, p4.y, pulley_pr(GT2x20ob_pulley)],
|
||||
[p5.x, p5.y, pulley_pr(GT2x16_plain_idler)],
|
||||
[40, 0, 0],
|
||||
];
|
||||
|
||||
belt = GT2x6;
|
||||
belt(belt, path, 80, [0, 0]);
|
||||
belt(belt, path, open = true);
|
||||
pulleys();
|
||||
translate_z(20)
|
||||
hflip() {
|
||||
belt(belt, path, 80, [0, 0], belt_colour = grey(90), tooth_colour = grey(50));
|
||||
belt(belt, path, open = true, belt_colour = grey(90), tooth_colour = grey(50));
|
||||
pulleys(flip=true);
|
||||
}
|
||||
|
||||
@@ -72,6 +74,31 @@ module belt_test() {
|
||||
layout([for(b = belts) belt_width(b)], 10)
|
||||
rotate([0, 90, 0])
|
||||
belt(belts[$i], [[0, 0, 20], [0, 1, 20]], belt_colour = $i%2==0 ? grey(90) : grey(20), tooth_colour = $i%2==0 ? grey(70) : grey(50));
|
||||
|
||||
// new example with open loop - this is a simplified example of the style used for example for the BLV 3D printer
|
||||
pulley = GT2x20ob_pulley;
|
||||
idler = GT2x16_plain_idler;
|
||||
corners = [[-75,-50],[75,100]];
|
||||
carriagepos = [0,0];
|
||||
carriagew = 80;
|
||||
|
||||
points = [
|
||||
[carriagepos.x - carriagew / 2, carriagepos.y, 0],
|
||||
[corners[0].x + belt_pulley_pr(belt, pulley) + belt_pulley_pr(belt, idler), carriagepos.y - belt_pulley_pr(belt, idler), idler],
|
||||
[corners[0].x, corners[0].y, pulley],
|
||||
[corners[0].x, corners[1].y, idler],
|
||||
[corners[1].x, corners[1].y, idler],
|
||||
[corners[1].x, carriagepos.y + belt_pulley_pr(belt, idler), idler],
|
||||
[carriagepos.x + carriagew / 2, carriagepos.y, 0]
|
||||
];
|
||||
translate_z(-30) {
|
||||
belt(belt, points, open=true, auto_twist=true);
|
||||
for (p = points)
|
||||
if (is_list(p.z))
|
||||
translate([p.x, p.y, 0])
|
||||
pulley_assembly(p.z);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if($preview)
|
||||
|
30
tests/box_sections.scad
Normal file
@@ -0,0 +1,30 @@
|
||||
//
|
||||
// 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 <../utils/core/core.scad>
|
||||
use <../utils/layout.scad>
|
||||
|
||||
include <../vitamins/box_sections.scad>
|
||||
|
||||
module box_sections() {
|
||||
layout([for(b = box_sections) box_section_size(b).x], 20)
|
||||
box_section(box_sections[$i], 100);
|
||||
}
|
||||
|
||||
if($preview)
|
||||
box_sections();
|
@@ -16,7 +16,7 @@
|
||||
// You should have received a copy of the GNU General Public License along with NopSCADlib.
|
||||
// If not, see <https://www.gnu.org/licenses/>.
|
||||
//
|
||||
include <../core.scad>
|
||||
include <../utils/core/core.scad>
|
||||
use <../utils/layout.scad>
|
||||
|
||||
use <../printed/camera_housing.scad>
|
||||
|
@@ -42,6 +42,9 @@ module components() {
|
||||
TO220("Generic TO220 package");
|
||||
|
||||
translate([40, 50])
|
||||
TO247("Generic TO247 package");
|
||||
|
||||
translate([40, 80])
|
||||
panel_USBA();
|
||||
|
||||
translate([80, 50])
|
||||
|
133
tests/core_xy.scad
Normal file
@@ -0,0 +1,133 @@
|
||||
//
|
||||
// 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 <../vitamins/stepper_motors.scad>
|
||||
include <../vitamins/washers.scad>
|
||||
|
||||
include <../utils/core_xy.scad>
|
||||
|
||||
|
||||
module coreXY_belts_test() {
|
||||
coreXY_type = coreXY_GT2_20_16;
|
||||
plain_idler = coreXY_plain_idler(coreXY_type);
|
||||
toothed_idler = coreXY_toothed_idler(coreXY_type);
|
||||
|
||||
coreXYPosBL = [0, 0, 0];
|
||||
coreXYPosTR = [200, 150, 0];
|
||||
separation = [0, coreXY_coincident_separation(coreXY_type).y, pulley_height(plain_idler) + washer_thickness(M3_washer)];
|
||||
pos = [100, 50];
|
||||
|
||||
upper_drive_pulley_offset = [40, 10];
|
||||
lower_drive_pulley_offset = [0, 0];
|
||||
|
||||
coreXY_belts(coreXY_type,
|
||||
carriagePosition = pos,
|
||||
coreXYPosBL = coreXYPosBL,
|
||||
coreXYPosTR = coreXYPosTR,
|
||||
separation = separation,
|
||||
x_gap = 10,
|
||||
upper_drive_pulley_offset = upper_drive_pulley_offset,
|
||||
lower_drive_pulley_offset = lower_drive_pulley_offset,
|
||||
show_pulleys = true);
|
||||
|
||||
|
||||
translate([coreXYPosBL.x + separation.x/2, coreXYPosTR.y + upper_drive_pulley_offset.y, separation.z/2]) {
|
||||
// add the upper drive pulley stepper motor
|
||||
translate([coreXY_drive_pulley_x_alignment(coreXY_type) + upper_drive_pulley_offset.x, 0, -pulley_height(coreXY_drive_pulley(coreXY_type))])
|
||||
NEMA(NEMA17M);
|
||||
|
||||
// add the screws for the upper drive offset idler pulleys if required
|
||||
if (upper_drive_pulley_offset.x > 0) {
|
||||
translate(coreXY_drive_plain_idler_offset(coreXY_type))
|
||||
translate_z(-pulley_offset(plain_idler))
|
||||
screw(M3_cap_screw, 20);
|
||||
translate(coreXY_drive_toothed_idler_offset(coreXY_type))
|
||||
translate_z(-pulley_offset(toothed_idler))
|
||||
screw(M3_cap_screw, 20);
|
||||
} else if (upper_drive_pulley_offset.x < 0) {
|
||||
translate([-pulley_od(plain_idler), coreXY_drive_plain_idler_offset(coreXY_type).y])
|
||||
translate_z(-pulley_offset(plain_idler))
|
||||
screw(M3_cap_screw, 20);
|
||||
translate([2*coreXY_drive_pulley_x_alignment(coreXY_type), coreXY_drive_toothed_idler_offset(coreXY_type).y])
|
||||
translate_z(-pulley_offset(toothed_idler))
|
||||
screw(M3_cap_screw, 20);
|
||||
}
|
||||
}
|
||||
|
||||
translate([coreXYPosTR.x - separation.x/2, coreXYPosTR.y + lower_drive_pulley_offset.y, -separation.z/2]) {
|
||||
// add the lower drive pulley stepper motor
|
||||
translate([-coreXY_drive_pulley_x_alignment(coreXY_type) + lower_drive_pulley_offset.x, 0, -pulley_height(coreXY_drive_pulley(coreXY_type))])
|
||||
NEMA(NEMA17M);
|
||||
|
||||
// add the screws for the lower drive offset idler pulleys if required
|
||||
if (lower_drive_pulley_offset.x < 0) {
|
||||
translate([-coreXY_drive_plain_idler_offset(coreXY_type).x, coreXY_drive_plain_idler_offset(coreXY_type).y])
|
||||
translate_z(-pulley_offset(plain_idler))
|
||||
screw(M3_cap_screw, 20);
|
||||
translate(coreXY_drive_toothed_idler_offset(coreXY_type))
|
||||
translate_z(-pulley_offset(toothed_idler))
|
||||
screw(M3_cap_screw, 20);
|
||||
} else if (lower_drive_pulley_offset.x > 0) {
|
||||
translate([pulley_od(plain_idler), coreXY_drive_plain_idler_offset(coreXY_type).y])
|
||||
translate_z(-pulley_offset(plain_idler))
|
||||
screw(M3_cap_screw, 20);
|
||||
translate([-2*coreXY_drive_pulley_x_alignment(coreXY_type), coreXY_drive_toothed_idler_offset(coreXY_type).y])
|
||||
translate_z(-pulley_offset(toothed_idler))
|
||||
screw(M3_cap_screw, 20);
|
||||
}
|
||||
}
|
||||
|
||||
// add the screw for the left upper idler pulley
|
||||
translate([coreXYPosBL.x + separation.x/2, coreXYPosBL.y, separation.z])
|
||||
screw(M3_cap_screw, 20);
|
||||
|
||||
// add the screw for the right upper idler pulley
|
||||
translate([coreXYPosTR.x + separation.x/2, coreXYPosBL.y, separation.z])
|
||||
screw(M3_cap_screw, 20);
|
||||
|
||||
if (separation.x != 0) {
|
||||
// add the screw for the left lower idler pulley
|
||||
translate([coreXYPosBL.x - separation.x/2, coreXYPosBL.y, 0])
|
||||
screw(M3_cap_screw, 20);
|
||||
|
||||
// add the screw for the right lower idler pulley
|
||||
translate([coreXYPosTR.x - separation.x/2, coreXYPosBL.y, 0])
|
||||
screw(M3_cap_screw, 20);
|
||||
}
|
||||
|
||||
translate([-separation.x/2, pos.y + coreXYPosBL.y -separation.y/2, -separation.z/2 + pulley_height(plain_idler)/2]) {
|
||||
// add the screw for the left Y carriage toothed idler
|
||||
translate([coreXYPosBL.x, coreXY_toothed_idler_offset(coreXY_type).y, 0])
|
||||
screw(M3_cap_screw, 20);
|
||||
// add the screw for the left Y carriage plain idler
|
||||
translate([coreXYPosBL.x + separation.x + coreXY_plain_idler_offset(coreXY_type).x, separation.y + coreXY_plain_idler_offset(coreXY_type).y, separation.z])
|
||||
screw(M3_cap_screw, 20);
|
||||
// add the screw for the right Y carriage toothed idler
|
||||
translate([coreXYPosTR.x + separation.x, coreXY_toothed_idler_offset(coreXY_type).y, separation.z])
|
||||
screw(M3_cap_screw, 20);
|
||||
// add the screw for the right Y carriage plain idler
|
||||
translate([coreXYPosTR.x - coreXY_plain_idler_offset(coreXY_type).x, separation.y + coreXY_plain_idler_offset(coreXY_type).y, 0])
|
||||
screw(M3_cap_screw, 20);
|
||||
}
|
||||
}
|
||||
|
||||
if ($preview)
|
||||
coreXY_belts_test();
|
@@ -16,6 +16,7 @@
|
||||
// You should have received a copy of the GNU General Public License along with NopSCADlib.
|
||||
// If not, see <https://www.gnu.org/licenses/>.
|
||||
//
|
||||
include <../core.scad>
|
||||
use <../utils/layout.scad>
|
||||
|
||||
include <../vitamins/displays.scad>
|
||||
@@ -23,7 +24,10 @@ use <../vitamins/pcb.scad>
|
||||
|
||||
module displays()
|
||||
layout([for(d = displays) pcb_length(display_pcb(d))], 10)
|
||||
display(displays[$i]);
|
||||
translate([0, pcb_width(displays[$i]) / 2])
|
||||
vflip()
|
||||
display(displays[$i]);
|
||||
|
||||
if($preview)
|
||||
displays();
|
||||
let($show_threads = true)
|
||||
displays();
|
||||
|
@@ -16,13 +16,51 @@
|
||||
// You should have received a copy of the GNU General Public License along with NopSCADlib.
|
||||
// If not, see <https://www.gnu.org/licenses/>.
|
||||
//
|
||||
include <../utils/core/core.scad>
|
||||
include <../core.scad>
|
||||
|
||||
include <../vitamins/extrusion_brackets.scad>
|
||||
include <../vitamins/extrusions.scad>
|
||||
include <../vitamins/extrusion_brackets.scad>
|
||||
include <../vitamins/washers.scad>
|
||||
include <../vitamins/nuts.scad>
|
||||
|
||||
module inner_bracket_test(bracket, backwards = false)
|
||||
rotate([90, 0, 180]) {
|
||||
extrusion = extrusion_inner_corner_bracket_extrusion(bracket);
|
||||
eWidth = extrusion_width(extrusion);
|
||||
size = extrusion_inner_corner_bracket_size(bracket);
|
||||
tnut = extrusion_inner_corner_bracket_tnut(bracket);
|
||||
|
||||
translate([backwards ? -eWidth : 0, 0])
|
||||
extrusion_inner_corner_bracket(bracket, backwards = backwards);
|
||||
|
||||
translate([-eWidth / 2, 0])
|
||||
rotate([-90, 0, 0])
|
||||
extrusion(extrusion, size.x - nut_thickness(tnut) - extrusion_tab_thickness(extrusion), false, cornerHole = eWidth > 20);
|
||||
|
||||
translate([-eWidth, -eWidth / 2])
|
||||
rotate([0, 90, 0])
|
||||
extrusion(extrusion, eWidth + size.y - nut_thickness(tnut) - extrusion_tab_thickness(extrusion), false, cornerHole = eWidth > 20);
|
||||
}
|
||||
|
||||
|
||||
module bracket_test(bracket)
|
||||
rotate([90, 0, 180]) {
|
||||
extrusion = extrusion_corner_bracket_extrusion(bracket);
|
||||
eWidth = extrusion_width(extrusion);
|
||||
size = extrusion_corner_bracket_size(bracket);
|
||||
|
||||
extrusion_corner_bracket_assembly(bracket);
|
||||
|
||||
translate([-eWidth / 2, 0])
|
||||
rotate([-90, 0, 0])
|
||||
extrusion(extrusion, size.y, false, cornerHole = eWidth > 20);
|
||||
|
||||
translate([-eWidth, -eWidth / 2])
|
||||
rotate([0, 90, 0])
|
||||
extrusion(extrusion, eWidth + size.x, false, cornerHole = eWidth > 20);
|
||||
}
|
||||
|
||||
|
||||
module extrusion_brackets(examples = false) {
|
||||
extrusion_inner_corner_bracket(E20_inner_corner_bracket);
|
||||
|
||||
@@ -32,34 +70,30 @@ module extrusion_brackets(examples = false) {
|
||||
translate([60, 0])
|
||||
extrusion_corner_bracket_assembly(E20_corner_bracket);
|
||||
|
||||
eWidth = extrusion_width(E2020);
|
||||
translate([110, 0])
|
||||
extrusion_inner_corner_bracket(E40_inner_corner_bracket);
|
||||
|
||||
translate([140, 0])
|
||||
extrusion_corner_bracket_assembly(E40_corner_bracket);
|
||||
|
||||
if(examples) {
|
||||
translate([20, 60, 10]) rotate([90, 0, 180]) {
|
||||
extrusion_inner_corner_bracket(E20_inner_corner_bracket);
|
||||
translate([20, 50, 10])
|
||||
inner_bracket_test(E20_inner_corner_bracket, true);
|
||||
|
||||
translate([-eWidth / 2, 0, 0])
|
||||
rotate([-90, 0, 0])
|
||||
extrusion(E2020, 20, false);
|
||||
translate([20, 80, 10])
|
||||
inner_bracket_test(E20_inner_corner_bracket);
|
||||
|
||||
translate([-eWidth, -eWidth / 2, 0])
|
||||
rotate([0, 90, 0])
|
||||
extrusion(E2020, 40, false);
|
||||
}
|
||||
translate([20, 120, 10])
|
||||
bracket_test(E20_corner_bracket);
|
||||
|
||||
translate([100, 60, 10]) rotate([90, 0, 180]) {
|
||||
extrusion_corner_bracket_assembly(E20_corner_bracket);
|
||||
translate([100, 70, 10])
|
||||
inner_bracket_test(E40_inner_corner_bracket);
|
||||
|
||||
translate([-eWidth / 2, 0, 0])
|
||||
rotate([-90, 0, 0])
|
||||
extrusion(E2020, 30, false);
|
||||
|
||||
translate([-eWidth, -eWidth / 2, 0])
|
||||
rotate([0, 90, 0])
|
||||
extrusion(E2020, 50, false);
|
||||
}
|
||||
translate([100, 130, 10])
|
||||
bracket_test(E40_corner_bracket);
|
||||
}
|
||||
}
|
||||
|
||||
if($preview)
|
||||
extrusion_brackets(true);
|
||||
let($show_threads = true)
|
||||
extrusion_brackets(true);
|
||||
|
@@ -21,9 +21,24 @@ use <../utils/layout.scad>
|
||||
|
||||
include <../vitamins/extrusions.scad>
|
||||
|
||||
gap = 10;
|
||||
|
||||
module extrusions()
|
||||
layout([for(e = extrusions) extrusion_width(e)], 10)
|
||||
extrusion(extrusions[$i], 80, cornerHole = extrusion_width(extrusions[$i]) > 20);
|
||||
layout([for(e = extrusions) is_list(e[0]) ? extrusion_width(e[0]) : extrusion_width(e)], gap)
|
||||
let(e = extrusions[$i])
|
||||
if(is_list(e[0])) {
|
||||
list = e;
|
||||
heights = [for(e = list) extrusion_height(e)];
|
||||
l = len(heights) - 1;
|
||||
offset = (heights * [for(i = [0 : l]) 1] + l * gap) / 2;
|
||||
translate([0, -offset])
|
||||
rotate(90)
|
||||
layout(heights, gap)
|
||||
rotate(-90)
|
||||
extrusion(list[$i], 80, cornerHole = extrusion_width(list[$i]) > 20);
|
||||
}
|
||||
else
|
||||
extrusion(e, 80, cornerHole = extrusion_width(e) > 20);
|
||||
|
||||
if ($preview)
|
||||
extrusions();
|
||||
|
@@ -16,12 +16,13 @@
|
||||
// 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/geared_steppers.scad>
|
||||
|
||||
use <../utils/layout.scad>
|
||||
|
||||
module geared_steppers()
|
||||
layout([for(g = geared_steppers) gs_diameter(g)], 5)
|
||||
layout([for(g = geared_steppers) max(gs_diameter(g), gs_pitch(g) + gs_lug_w(g) / 2)], 5)
|
||||
geared_stepper(geared_steppers[$i]);
|
||||
|
||||
geared_steppers();
|
||||
|
@@ -16,6 +16,7 @@
|
||||
// You should have received a copy of the GNU General Public License along with NopSCADlib.
|
||||
// If not, see <https://www.gnu.org/licenses/>.
|
||||
//
|
||||
include <../core.scad>
|
||||
use <../utils/layout.scad>
|
||||
|
||||
include <../vitamins/green_terminals.scad>
|
||||
|
@@ -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() {
|
||||
|
@@ -16,6 +16,7 @@
|
||||
// You should have received a copy of the GNU General Public License along with NopSCADlib.
|
||||
// If not, see <https://www.gnu.org/licenses/>.
|
||||
//
|
||||
include <../core.scad>
|
||||
use <../vitamins/hygrometer.scad>
|
||||
|
||||
if($preview)
|
||||
|
@@ -22,12 +22,15 @@ use <../vitamins/jack.scad>
|
||||
|
||||
module jacks() {
|
||||
translate([0, 0])
|
||||
jack_4mm("blue",3, "royalblue");
|
||||
jack_4mm_plastic("black",3, grey(20));
|
||||
|
||||
translate([20, 0])
|
||||
jack_4mm_shielded("brown", 3, "sienna");
|
||||
jack_4mm("blue",3, "royalblue");
|
||||
|
||||
translate([40, 0])
|
||||
jack_4mm_shielded("brown", 3, "sienna");
|
||||
|
||||
translate([60, 0])
|
||||
post_4mm("red",3);
|
||||
}
|
||||
|
||||
|
@@ -16,6 +16,7 @@
|
||||
// You should have received a copy of the GNU General Public License along with NopSCADlib.
|
||||
// If not, see <https://www.gnu.org/licenses/>.
|
||||
//
|
||||
include <../utils/core/core.scad>
|
||||
use <../vitamins/microview.scad>
|
||||
|
||||
microview(!$preview);
|
||||
|
@@ -52,6 +52,12 @@ module nuts() {
|
||||
|
||||
if(n == M5_nut)
|
||||
sliding_t_nut(M5_sliding_t_nut);
|
||||
|
||||
if(n == M6_nut)
|
||||
sliding_t_nut(M6_sliding_t_nut);
|
||||
|
||||
if(n == M8_nut)
|
||||
sliding_t_nut(M8_sliding_ball_t_nut);
|
||||
}
|
||||
|
||||
translate([0, 80]) {
|
||||
|
@@ -16,6 +16,7 @@
|
||||
// You should have received a copy of the GNU General Public License along with NopSCADlib.
|
||||
// If not, see <https://www.gnu.org/licenses/>.
|
||||
//
|
||||
include <../core.scad>
|
||||
use <../vitamins/o_ring.scad>
|
||||
|
||||
module o_rings()
|
||||
|
@@ -17,7 +17,7 @@
|
||||
// If not, see <https://www.gnu.org/licenses/>.
|
||||
//
|
||||
include <../core.scad>
|
||||
include <../vitamins/kp_pillow_blocks.scad>
|
||||
include <../vitamins/pillow_blocks.scad>
|
||||
|
||||
use <../utils/layout.scad>
|
||||
|
@@ -64,8 +64,9 @@ module pin_headers() {
|
||||
pin_socket(pin_headers[$i], 3, 3, right_angle = true);
|
||||
}
|
||||
|
||||
for(i = [0, 1], p = [5, 2][i], j = [0 , 1]) {
|
||||
h = [jst_ph_header, jst_xh_header][j];
|
||||
headers = [jst_zh_header, jst_ph_header, jst_xh_header];
|
||||
for(i = [0, 1], p = [5, 2][i], j = [0 : len(headers) - 1]) {
|
||||
h = headers[j];
|
||||
translate([-20 * (i + 1), 0 + j * 40])
|
||||
jst_xh_header(h, p);
|
||||
|
||||
|
BIN
tests/png/7_segments.png
Normal file
After Width: | Height: | Size: 37 KiB |
Before Width: | Height: | Size: 6.5 KiB After Width: | Height: | Size: 6.5 KiB |