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

Compare commits

...

377 Commits

Author SHA1 Message Date
Chris Palmer
1928ec6fb1 Box can now be named to allow more than one in a project.
box_hole_inset(type) documented.
2022-01-23 09:08:27 +00:00
Chris Palmer
f4b9ab961c Fixed blower_exit_offset() for square blowers with 2 screws. 2022-01-23 09:04:46 +00:00
Chris Palmer
ac7c4403b9 Updated changelog. 2022-01-10 23:55:40 +00:00
Chris Palmer
b7b40ba6a4 Merge branch 'ggabbiani-fix-grid-origin-offsets' 2022-01-10 23:52:33 +00:00
Chris Palmer
317b485ee1 Updated the image. 2022-01-10 23:52:00 +00:00
Chris Palmer
6218287e2a Merge branch 'fix-grid-origin-offsets' of https://github.com/ggabbiani/NopSCADlib into ggabbiani-fix-grid-origin-offsets 2022-01-10 23:36:51 +00:00
Chris Palmer
d04f2bc8d1 Updated changelog. 2022-01-10 23:34:08 +00:00
Chris Palmer
49c26079fe Added M3x6_hex_pillar. 2022-01-10 23:32:01 +00:00
Chris Palmer
b5ee63bfc4 Added more documentation for microswitches. 2022-01-10 23:31:02 +00:00
Chris Palmer
a5bc80c0e8 Added D_plug_d() function. 2022-01-10 23:28:33 +00:00
Chris Palmer
bf8014fba0 Added tubing_ir() function. 2022-01-10 23:20:04 +00:00
Giampiero Gabbiani
ccf2b8e21b Reverted PERF74x51 2022-01-11 00:00:16 +01:00
Giampiero Gabbiani
99f277de8d Fixed offset calculations 2022-01-08 00:10:57 +01:00
Giampiero Gabbiani
fe1ab5d59a Fixed grid origin offsets 2022-01-07 13:47:00 +01:00
Chris Palmer
e06b485d3e Updated changelog. 2021-12-14 21:37:54 +00:00
Chris Palmer
72d9c398bc Merge branch 'martinbudden-teardrop_angle' 2021-12-14 21:35:37 +00:00
Chris Palmer
608f0b2db0 Simplified teardrop top length calculation. 2021-12-14 21:22:29 +00:00
Chris Palmer
7f8dfb9e73 Merge branch 'teardrop_angle' of https://github.com/martinbudden/NopSCADlib into martinbudden-teardrop_angle 2021-12-14 20:50:39 +00:00
Chris Palmer
c9de51fbbb Updated changelog. 2021-12-14 17:57:36 +00:00
Chris Palmer
30b7d966a1 Merge branch 'martinbudden-camera_fov' 2021-12-14 17:55:06 +00:00
Chris Palmer
abe1b1db01 Updated readme. 2021-12-14 17:53:10 +00:00
Chris Palmer
8835fa0b7d Merge branch 'camera_fov' of https://github.com/martinbudden/NopSCADlib into martinbudden-camera_fov 2021-12-14 17:49:08 +00:00
Martin Budden
71f935de8e Corrected FOV handling. 2021-12-14 12:11:03 +00:00
Chris Palmer
b0a6a873c0 Merge branch 'martinbudden-core_xy_improvements' 2021-12-12 23:21:27 +00:00
Chris Palmer
0771d4742c Updated changelog. 2021-12-12 23:18:28 +00:00
Chris Palmer
970c538496 Updated images and readme. 2021-12-12 23:16:09 +00:00
Chris Palmer
4d44eae16a Merge branch 'core_xy_improvements' of https://github.com/martinbudden/NopSCADlib into martinbudden-core_xy_improvements 2021-12-12 23:07:20 +00:00
Martin Budden
cec790ec09 Fixed y-carriage plain pulley and test. 2021-12-12 10:32:18 +00:00
Chris Palmer
3c9ec5455b Merge branch 'core_xy_improvements' of https://github.com/martinbudden/NopSCADlib into martinbudden-core_xy_improvements 2021-12-12 08:43:45 +00:00
Chris Palmer
5be85f5c25 Updated changelog. 2021-12-12 08:42:26 +00:00
Chris Palmer
e6254daaf1 Merge branch 'martinbudden-belt_gt2x9' 2021-12-12 08:40:51 +00:00
Chris Palmer
c31f58a4fd Udpated images and readme. 2021-12-12 08:40:34 +00:00
Chris Palmer
46fc574e7a Merge branch 'belt_gt2x9' of https://github.com/martinbudden/NopSCADlib into martinbudden-belt_gt2x9 2021-12-11 21:08:56 +00:00
Chris Palmer
6ee0fad2e1 Updated changelog. 2021-12-11 20:57:48 +00:00
Chris Palmer
6e76c2ce89 Merge branch 'martinbudden-drag_chain_links' 2021-12-11 20:54:08 +00:00
Chris Palmer
a2dfaef2b5 Updated readme. 2021-12-11 20:53:01 +00:00
Chris Palmer
2c197be193 Merge branch 'drag_chain_links' of https://github.com/martinbudden/NopSCADlib into martinbudden-drag_chain_links 2021-12-11 20:51:38 +00:00
Chris Palmer
05a67d1b2e Updated changelog 2021-12-11 20:50:37 +00:00
Chris Palmer
be4dc0c57a Merge branch 'martinbudden-drag_chain_no_support_v2' 2021-12-11 20:48:02 +00:00
Chris Palmer
c4895f84c7 Updated image and readme. 2021-12-11 18:34:38 +00:00
Chris Palmer
72700a0acb Merge branch 'drag_chain_no_support_v2' of https://github.com/martinbudden/NopSCADlib into martinbudden-drag_chain_no_support_v2 2021-12-11 13:10:07 +00:00
Chris Palmer
43c78fd1a3 Anual image changes due to change of computer. 2021-12-11 13:01:57 +00:00
Martin Budden
8682d0a470 Allow configuration of teardrop angle. 2021-12-11 09:34:49 +00:00
Martin Budden
e71db80093 Improvements to core_xy
1. Better default parameters
2. Changed plain_idler_offset to work in x and y, to facilitate larger idler pulleys
2021-11-27 15:07:36 +00:00
Martin Budden
a280e1fcbd Added GT2x9 belt. 2021-11-27 11:06:56 +00:00
Martin Budden
b1ad206ce4 Rotated conical horihole. 2021-11-20 09:51:19 +00:00
Martin Budden
da55f86536 Added variant of drag chain without supports.
Unsupported drag chain has conical pin and corresponding horihole and is printed with cutout facing upwards.

Also made clearance a property of the drag chain so it can be altered for printing chain assemblies
2021-11-20 07:21:09 +00:00
Martin Budden
9790bdda11 Added function returning number of links in drag chain. 2021-11-16 05:41:16 +00:00
Chris Palmer
59c3f984c5 Updated changelog. 2021-11-13 18:35:06 +00:00
Chris Palmer
9c2dd1c37b Merge branch 'martinbudden-screw_socket_visibility' 2021-11-13 18:32:35 +00:00
Chris Palmer
74e569896b Updated images. 2021-11-13 18:32:16 +00:00
Chris Palmer
3a87d7afde Merge branch 'screw_socket_visibility' of https://github.com/martinbudden/NopSCADlib into martinbudden-screw_socket_visibility 2021-11-13 18:11:05 +00:00
Martin Budden
ed6f8cf5c0 Added shading to base of screw sockets to increase visibility. 2021-11-01 10:18:28 +00:00
Chris Palmer
1c9945d978 Updated changelog. 2021-10-29 12:38:48 +01:00
Chris Palmer
9464ad5dbf Fixed knob for pots with split shaft.
Changed the order of knob_for_pot() parameters.
2021-10-29 12:37:12 +01:00
Chris Palmer
370ad8a2d1 Updated changelog. 2021-10-28 13:15:02 +01:00
Chris Palmer
b424bea622 Added printed knobs for pots. 2021-10-28 12:50:22 +01:00
Chris Palmer
c8d9bb7d09 Potentiometers now create a BOM entry and have a value specified. 2021-10-28 12:43:53 +01:00
Chris Palmer
c35c732324 Updated changlog. 2021-10-26 12:28:37 +01:00
Chris Palmer
f5528c5a9a Single 7_segment objects can now have multiple digits.
This is deduced from the digit size compared to the overall size.
The decimal point is now suppressed if there are not enough pins.
Added 02531A and 02352A 3 digit displays.
2021-10-26 12:27:22 +01:00
Chris Palmer
09bce09a85 Typo 2021-10-26 08:47:35 +01:00
Chris Palmer
389e2f9c2e Updated changelog. 2021-10-24 13:52:47 +01:00
Chris Palmer
c35e263113 Merge branch 'martinbudden-magnet_name' 2021-10-24 13:50:17 +01:00
Chris Palmer
bad33da95e Updated images and readme. 2021-10-24 13:49:21 +01:00
Chris Palmer
f727e1d27d Merge branch 'magnet_name' of https://github.com/martinbudden/NopSCADlib into martinbudden-magnet_name 2021-10-24 13:36:33 +01:00
Chris Palmer
5ddd9f6324 Updated changelog. 2021-10-24 13:35:39 +01:00
Chris Palmer
f5d0bfb6c8 Fixed drill center parameter in poly_drill(). 2021-10-24 13:33:51 +01:00
Chris Palmer
b2117fa99a atx_psu_cutout(type) now parametric and can be shown in the test.
ATX300 PSU now has a correct cutout and more accurate grill holes.
The four margins around grill holes can now be specified.
2021-10-24 13:32:46 +01:00
Chris Palmer
6687a4a7c6 Added jack_4mm_flange_radius(). 2021-10-24 13:24:25 +01:00
Chris Palmer
8524ddd34d Foot now lowered by squeeze distance so the washer is visible. 2021-10-24 13:23:45 +01:00
Martin Budden
427ef610de Allowed naming of magnets. Added radial encoder magnet. 2021-10-21 10:37:56 +01:00
Chris Palmer
c8869fc415 Updated changelog. 2021-10-20 20:38:12 +01:00
Chris Palmer
21c06667a3 Added ATX300 PSU model. 2021-10-20 20:35:45 +01:00
Chris Palmer
d19fad3f9f PSU grills can now have different holes sizes, spacing, round or heaxagonal and avoid a list of rectangular regions. 2021-10-20 20:33:52 +01:00
Chris Palmer
172bfb16d8 Added lugless pressfit IEC inlet. 2021-10-20 12:50:35 +01:00
Chris Palmer
491dbae13b screw_shorter_than() will return 4 or 3 for short grub screws. 2021-10-09 12:05:13 +01:00
Chris Palmer
99ebfffd2b Updated changelog. 2021-10-06 10:14:18 +01:00
Chris Palmer
f04486a040 Merge branch 'martinbudden-extrusion_convexity' 2021-10-06 10:12:54 +01:00
Chris Palmer
42a7d222b5 Merge branch 'extrusion_convexity' of https://github.com/martinbudden/NopSCADlib into martinbudden-extrusion_convexity 2021-10-06 10:08:08 +01:00
Chris Palmer
598a01295f Updated changelog. 2021-10-06 10:05:49 +01:00
Chris Palmer
5f72a12125 Nuts shown on jacks and fuseholders only shown threaded when exploded. 2021-10-06 07:32:50 +01:00
Chris Palmer
82502eb470 Added pot_nut() module to draw potentiometer nuts and washers. 2021-10-06 07:31:47 +01:00
Chris Palmer
b541298eae Printed foot assembly can now omit the top washer when space is at a premium.
Now correctly shows the screw in the squeezed position.
2021-10-05 12:33:55 +01:00
Chris Palmer
9884160ed5 Updated the gallery 2021-10-02 20:45:15 +01:00
Martin Budden
046c475e18 Set convexity to 8 for linear_extrude of extrusion. 2021-10-02 09:20:51 +01:00
Chris Palmer
7b111c016a Updated changelog. 2021-10-01 12:37:49 +01:00
Chris Palmer
38c973b316 FR4 veroboard made the correct colour.
veroboard track cuts made slightly bigger.
2021-10-01 12:34:49 +01:00
Chris Palmer
042d809ed0 Resistor and thermistor wires made more round. 2021-10-01 12:33:35 +01:00
Chris Palmer
3864839e52 Fixed encoder breakout descripion typo. 2021-10-01 12:32:47 +01:00
Chris Palmer
2ba2c2c115 Removed some unused dependencies. 2021-10-01 12:32:01 +01:00
Chris Palmer
e3716ce8f9 Updated changelog. 2021-09-29 11:36:36 +01:00
Chris Palmer
c4f24974ab Merge branch 'martinbudden-hotend_includes' 2021-09-29 11:33:33 +01:00
Chris Palmer
61dae9c7a4 Merge branch 'hotend_includes' of https://github.com/martinbudden/NopSCADlib into martinbudden-hotend_includes 2021-09-29 11:03:22 +01:00
Chris Palmer
41a26c453c Updated changelog. 2021-09-29 10:46:45 +01:00
Chris Palmer
bab4c8e8af TO247_size() now also returns lead height and the length of the wide bit.
TO247 leads fixed at 3.
Lead length removed from TO220 and TO247 vitamin string.
2021-09-29 10:42:37 +01:00
Martin Budden
a5c4bf05ad Added hot end style string literals following discussion. 2021-09-28 17:54:42 +01:00
Martin Budden
a65add65ac Removed hotend global enums. 2021-09-28 16:08:57 +01:00
Chris Palmer
c449dd0a24 Updated changelog. 2021-09-27 17:50:00 +01:00
Chris Palmer
f16f7ddb09 Images reverted to last OpenSCAD release versions.
Mainly text spacing changes.
2021-09-27 17:45:57 +01:00
Chris Palmer
9b5ec6af1a Fixed new rounded_polygon to work with last OpenSCAD release.
Trainling commas in let().
2021-09-27 17:16:36 +01:00
Chris Palmer
50958b064d Added $show_plugs to show crude reprentations of housings on pin_headers and Molex KK headers. 2021-09-27 16:36:47 +01:00
Chris Palmer
c37373c920 Added TO247() and TO247_size() to component.scad. 2021-09-27 16:21:37 +01:00
Chris Palmer
700f5a2205 fanguard() can now be made without screw holes to get just the grill. 2021-09-27 16:19:38 +01:00
Chris Palmer
4993c3e82d Module blurb parenthesis parsing is now greedy to handle args that default to function calls.
This means that library modules cannot be one liners.
2021-09-27 16:17:08 +01:00
Chris Palmer
c6b280f0e8 _box_assembly() fix for corners = 0. 2021-09-26 11:26:01 +01:00
Chris Palmer
6012787781 Added jack_4mm_plastic(). 2021-09-26 11:25:08 +01:00
Chris Palmer
30db66034c Rounded_polygons are now generated by a function returning a point list.
The module version simply passes this to polygon.
The arcs now sections of a circle4n() rather than a circle().
2021-09-26 10:54:01 +01:00
Chris Palmer
d6f344be3d Updated changelog. 2021-09-16 23:36:47 +01:00
Chris Palmer
f6aa3b3426 fuseholder_hole() now makes a poly_hole when cnc_bit+_r is 0. 2021-09-16 22:15:26 +01:00
Chris Palmer
91c8c7bf4d cnc_bit_r is now set to zero in stl(), so holes are suitable for 3D printing rather than routing. 2021-09-16 22:14:30 +01:00
Chris Palmer
dc93b8dcdf Added platters and extrusion overrides to the example project. 2021-09-16 22:11:57 +01:00
Chris Palmer
c9c094248e Updated changelog 2021-09-14 10:12:30 +01:00
Chris Palmer
119c2cb6f4 Can now make perfboards with screws holes only at one end.
I.e. for making models of chopped down boards.
2021-09-14 10:09:58 +01:00
Chris Palmer
24b391578b Fixed recently created bug trying to delete non-existent thumbnail diffs. 2021-09-14 10:08:13 +01:00
Chris Palmer
ec49ce1a6c Updated changelog. 2021-09-12 18:04:22 +01:00
Chris Palmer
f0c25d37b0 Workarounds for bugs in the OpenSCAD snapshots. 2021-09-12 18:02:43 +01:00
Chris Palmer
588a1edf62 Updated changelog. 2021-09-11 12:02:53 +01:00
Chris Palmer
3299aad5c8 Parametric potentiometers added, changes PCB "potentiometer" parameters.
The first one is now the type that defaults to the previous BigTreeTech version.
The second parameter is the shaft length overrride.

Added ESP32_DOIT_V1, ArduinoNano and KY_040 breakout PCBs.
2021-09-11 12:01:04 +01:00
Chris Palmer
74c52aac04 Can now make perfboard without screw holes.
Fixed missing items from last commit.
2021-09-11 11:54:26 +01:00
Chris Palmer
726d9ed2dc Can now draw right angle Molex KK connectors and can skip pins to allow high voltage. 2021-09-11 11:51:24 +01:00
Chris Palmer
8a838dd1ce Added pcb_grid_components() module for placing parts on a perfboard. 2021-09-11 11:46:25 +01:00
Chris Palmer
181c6ac624 Added vero_pin PCB component. 2021-09-11 11:44:36 +01:00
Chris Palmer
e952aa7840 PCB chip compoment can now be round if width is zero to fake round buttons. 2021-09-11 11:28:21 +01:00
Chris Palmer
466ee31e10 Added Jack_4mm_shielded_nut_radius(). 2021-09-11 11:21:58 +01:00
Chris Palmer
4c926c529b Fixed axial lead min pitch bug. 2021-09-11 11:20:37 +01:00
Chris Palmer
edb1eccbf1 TFT128x160 LCD display added. 2021-09-11 11:19:24 +01:00
Chris Palmer
061812cc8b PMMA1p25 sheet added. 2021-09-11 11:16:43 +01:00
Chris Palmer
ce0c97b45e 7_segment displays added as PCB component. 2021-09-11 11:15:39 +01:00
Chris Palmer
696b14699c Updated changelog. 2021-09-05 10:26:53 +01:00
Chris Palmer
2166a9be6a extrusion_corner_bracket_assembly() and extrusion_inner_corner_bracket() can now be passed the extrusion type.
E2020t and E4040t thinner extrusions added to work with the brackets.
Extrusions can now have recessed channels, round or square centre sections and holes.
Fixed the shape of extrusion centre section spars.
T-nuts now have 45 degree chamfers instead of a fixed 1mm minimum thickness.
2021-09-05 10:24:42 +01:00
Chris Palmer
511729008d Added missing documentation for sliding_t_nut(). 2021-09-03 15:47:15 +01:00
Chris Palmer
5111ec04bc E40_corner_bracket, E40_corner_bracket and M8_sliding_ball_t_nut added.
Inner corner brackets now show the long arm with chamfered ridges rather
than a normal T-nut and the grub screws are inserted to meet the extrusion.
2021-09-03 09:23:24 +01:00
Chris Palmer
cef3a620a6 Updated changelog 2021-08-31 23:41:34 +01:00
Chris Palmer
da5191e52c Merge branch 'martinbudden-M2p5_dome_screw' 2021-08-31 23:40:51 +01:00
Chris Palmer
d9af5b7f70 Updated images and readme. 2021-08-31 23:38:34 +01:00
Chris Palmer
c30d7f1ad9 Merge branch 'M2p5_dome_screw' of https://github.com/martinbudden/NopSCADlib into martinbudden-M2p5_dome_screw 2021-08-31 23:15:56 +01:00
Chris Palmer
a5382cbe04 Updated changelog. 2021-08-31 23:03:22 +01:00
Chris Palmer
00c5c90a5e Updated big picture 2021-08-31 23:00:58 +01:00
Chris Palmer
01c26d8a34 Added Lichuan servo motors contributed by Niclas Hedhman. 2021-08-31 22:51:24 +01:00
Chris Palmer
ef2102420b Added NEMA8 and NEMA8BH stepper motors.
Steppers can now have dual shafts, hollow shafts and black end caps.
2021-08-31 22:43:37 +01:00
Chris Palmer
540f841163 Added crude representation of JST ZH connectors. 2021-08-31 22:25:31 +01:00
Chris Palmer
1045502efb Added more aluminium sheet thickness 2021-08-31 22:12:30 +01:00
Chris Palmer
485184f092 Added HGH15CA and HGH20CA rails. 2021-08-31 22:04:12 +01:00
Chris Palmer
b893c9069a Added SFU1610 ballscrew nut 2021-08-31 21:56:20 +01:00
Chris Palmer
69f4ced29d Added M8_cs_cap_screw, M5_grub_screw and M6_grub_screw.
Fixed M6_cs_cap_screw and M4_grub_screw socket sizes.
2021-08-31 21:50:43 +01:00
Chris Palmer
5c1aa849fe New layout for big picture. 2021-08-31 21:34:28 +01:00
Martin Budden
9d65f69bf3 Added M2p5_dome_screw. 2021-08-31 20:05:47 +01:00
Chris Palmer
515b99fdc0 Merge branch 'martinbudden-rpi_pico' 2021-08-27 16:18:22 +01:00
Chris Palmer
631d052c68 Updated changelog 2021-08-27 16:18:04 +01:00
Chris Palmer
1247303cb9 Updated images and readme. 2021-08-27 16:15:42 +01:00
Chris Palmer
290be4beb6 Merge branch 'rpi_pico' of https://github.com/martinbudden/NopSCADlib into martinbudden-rpi_pico 2021-08-27 15:04:23 +01:00
Chris Palmer
24e941799d Udpated changelog. 2021-08-27 14:27:29 +01:00
Chris Palmer
6a556c5879 Merge branch 'martinbudden-bldc_propshaft_fix' 2021-08-27 14:20:14 +01:00
Martin Budden
14ab1bb8b6 Added Raspberry Pi Pico. 2021-08-13 10:05:27 +01:00
Martin Budden
be53547728 Fixed display of BLDC prop shaft when thread lengh = 0. 2021-08-09 15:17:30 +01:00
Martin Budden
4138ed438e Added ability to display camera field of view. 2021-08-09 15:10:59 +01:00
Chris Palmer
ba7d7d32ad Updated chnagelog. 2021-07-04 08:39:47 +01:00
Chris Palmer
d3049bc81b Merge branch 'martinbudden-pcb_plating_colour' 2021-07-04 08:38:20 +01:00
Martin Budden
df35e14fc7 Improved handling of pcb plating colour. 2021-07-01 22:49:35 +01:00
Chris Palmer
21c2aa5d62 Updated changelog. 2021-06-29 11:44:48 +01:00
Chris Palmer
c982876ebc Can now specify the screw used for PSU shrouds and get the wall thickness. 2021-06-29 11:42:20 +01:00
Chris Palmer
5ccda42e5b Updated changelog. 2021-06-17 16:17:09 +01:00
Chris Palmer
92d0444e5f Changelog now runs codespell to fix the spellings in the commit comments. 2021-06-17 16:15:46 +01:00
Chris Palmer
b239c1462e Updated changelog. 2021-06-17 16:01:31 +01:00
Chris Palmer
6413b7b2a0 Merge branch 'martinbudden-spelling_corrections' 2021-06-17 15:58:32 +01:00
Chris Palmer
0b0ce66c85 Updated changelog. 2021-06-17 15:56:09 +01:00
Chris Palmer
d38055c15c Updated readme. 2021-06-17 15:53:59 +01:00
Chris Palmer
cf99418a19 Merge branch 'spelling_corrections' of https://github.com/martinbudden/NopSCADlib into martinbudden-spelling_corrections 2021-06-17 15:15:37 +01:00
Chris Palmer
0cd0e72d92 Merge branch 'martinbudden-typos' 2021-06-17 15:15:04 +01:00
Chris Palmer
2c4a498a7a Merge branch 'typos' of https://github.com/martinbudden/NopSCADlib into martinbudden-typos 2021-06-17 15:12:31 +01:00
Chris Palmer
451101fcd6 Updated changelog. 2021-06-17 15:11:03 +01:00
Chris Palmer
c7a6d8164f Added molex_usb_Ax1() and now shows SMT caps in the PCB test. 2021-06-17 15:08:53 +01:00
Martin Budden
8d7c44b80d Spelling corrections. 2021-06-15 10:01:32 +01:00
Martin Budden
dcfe4262c5 Fixed typos. 2021-06-11 20:39:01 +01:00
Chris Palmer
fe3b84f672 Updated changelog 2021-06-08 08:17:37 +01:00
Chris Palmer
d1a17bd4ac Added LIPO fuel gauge PCB. 2021-06-08 08:09:08 +01:00
Chris Palmer
b8efa11fd9 Added SMD capacitors. 2021-06-08 08:08:35 +01:00
Chris Palmer
3bc8f35e37 Can now put jst_ph connectors on PCBs 2021-06-07 17:32:23 +01:00
Chris Palmer
39c11ef3b2 Added 2p54joiner to represent cropped headers joining PCBs. 2021-06-07 17:31:44 +01:00
Chris Palmer
5a8a1da880 Added Seeeduino XIAO.
Tiny PCBs now shown in a third line.
2021-06-07 12:23:29 +01:00
Chris Palmer
3147862212 PCB lands can be rounded and can specify colour.
Holes can be positioned on the edge to make surface mountable connections.
2021-06-07 10:59:47 +01:00
Chris Palmer
4fc8a7f47d Fixed z-fighting between transparent LEDs and PCB. 2021-06-07 10:56:32 +01:00
Chris Palmer
a9ed9944c3 Added PERF70x51. 2021-06-06 17:18:37 +01:00
Chris Palmer
9cd2dbc316 Added copper colour constant.
Copper PCB pads and veroboard tracks now use copper colour.
2021-06-06 17:17:33 +01:00
Chris Palmer
f3bfbbfcf2 Fixed Python error when top level assembly is empty. 2021-06-06 16:53:06 +01:00
Chris Palmer
baaa85ffed Updated readme. 2021-06-06 16:51:32 +01:00
Chris Palmer
f1a49d4e28 Better description of pcb_grid(). 2021-06-06 16:49:33 +01:00
Chris Palmer
0eed0673b0 Updated changelog. 2021-06-04 18:48:38 +01:00
Chris Palmer
9a4cc7ec42 Ziptie BOM entries no longer segregated by radius wrapped around. 2021-06-04 18:46:31 +01:00
Chris Palmer
2fb1185edf Updated changelog. 2021-06-04 17:49:17 +01:00
Chris Palmer
a782d43e67 bom.py now generates bom.csv to allow costed BOMs to be made using a spreadsheet. 2021-06-04 17:47:29 +01:00
Chris Palmer
ae934d47c7 Updated changelog. 2021-06-03 11:59:54 +01:00
Chris Palmer
823f3b936e Add the ability to have a target specific top level module in place of main_assembly(). 2021-06-03 11:58:10 +01:00
Chris Palmer
3027b942a6 Updated changelog. 2021-06-02 16:07:19 +01:00
Chris Palmer
749a1f0648 Fixed male thread z-fighting bug. 2021-06-02 16:05:51 +01:00
Chris Palmer
5c898df217 More readable code in rounded_polygon. 2021-06-01 09:53:46 +01:00
Chris Palmer
7a566cc856 Updated changelog. 2021-06-01 08:20:44 +01:00
Chris Palmer
20d799a3c1 IEC_320_C14_switched_fused_inlet now shows the correct object name in the example. 2021-06-01 08:18:57 +01:00
Chris Palmer
2ee95bba65 Updated changelog. 2021-05-31 17:24:31 +01:00
Chris Palmer
f49bb63266 Merge branch 'martinbudden-bldc_motors' 2021-05-31 17:22:43 +01:00
Chris Palmer
258109811b Added uppercase version of BLCD_motors.scad. 2021-05-31 17:21:49 +01:00
Chris Palmer
b39fd536c2 Removed lower case version of bldc_motors.scad. 2021-05-31 17:21:03 +01:00
Chris Palmer
a5a87d260d Updated images and readme. 2021-05-31 17:19:56 +01:00
Chris Palmer
b09efb10e0 Merge branch 'bldc_motors' of https://github.com/martinbudden/NopSCADlib into martinbudden-bldc_motors 2021-05-31 16:25:23 +01:00
Chris Palmer
53acaac379 Updated changelog 2021-05-31 16:22:52 +01:00
Chris Palmer
9b40e0dcef Merge branch 'martinbudden-thread_colour_assert' 2021-05-31 16:20:29 +01:00
Martin Budden
00ca412441 Added BLDC3548 motor. 2021-05-30 18:58:55 +01:00
Martin Budden
1e6d7f5dd6 Brushless DC motors. 2021-05-30 18:55:32 +01:00
Martin Budden
ec07d95657 Added assertion to check colour format in module thread. 2021-05-30 16:00:13 +01:00
Chris Palmer
0dab0dca08 Added missing includes core.scad which generates warnings with latest OpenSCAD snapshots.
Note, however, NopSCADlib does not work with the current OpenSCAD snapshot.
2021-05-19 17:54:31 +01:00
Chris Palmer
6e6cd45295 Updated changelog 2021-05-18 23:21:40 +01:00
Chris Palmer
3a7fde6c56 Merge branch 'master' of https://github.com/nophead/NopSCADlib.git 2021-05-18 23:18:18 +01:00
Chris Palmer
c5bb898856 Updated changelog. 2021-05-18 23:16:15 +01:00
Chris Palmer
11ebe2225d Removed spurious convexity in difference from rounded_polygon(). 2021-05-18 23:14:34 +01:00
Chris
a1e25bb878 Merge pull request #180 from martinbudden/global_defs_typo
Typo in global_defs.
2021-05-15 14:36:58 +01:00
Martin Budden
9689683b7e Typo in global_defs. 2021-05-15 11:42:24 +01:00
Chris Palmer
08946e3d70 Updated changelog. 2021-05-02 17:16:21 +01:00
Chris Palmer
15c2946e91 Merge branch 'martinbudden-blower_size' 2021-05-02 17:14:28 +01:00
Chris Palmer
34019196cd Updated readme 2021-05-02 17:14:14 +01:00
Martin Budden
436fc71cf3 Added blower_size function. 2021-05-02 15:27:44 +01:00
Chris Palmer
fd67c166f7 Updated changelog 2021-04-26 00:02:59 +01:00
Chris Palmer
634deab911 Merge branch 'martinbudden-core_xy_orientation' 2021-04-26 00:01:40 +01:00
Chris Palmer
e2feceb608 Updated readme 2021-04-26 00:00:41 +01:00
Chris Palmer
d1258e0b0c Merge branch 'core_xy_orientation' of https://github.com/martinbudden/NopSCADlib into martinbudden-core_xy_orientation 2021-04-25 23:57:44 +01:00
Chris Palmer
bd61a1dc55 Updated changelog 2021-04-25 23:56:47 +01:00
Chris Palmer
055e83902f Merge branch 'martinbudden-leadnut_typo' 2021-04-25 23:38:27 +01:00
Chris Palmer
feec1e7ae5 Updated readme. 2021-04-25 23:37:48 +01:00
Martin Budden
be76af2fc4 Fixed typo in leadnut.scad. 2021-04-25 18:31:51 +01:00
Martin Budden
9c1a9bf357 Add facility to orient core_xy with left motor being lower or upper motor. 2021-04-25 17:56:24 +01:00
Chris Palmer
9647fb474b Updated changelog 2021-04-25 00:08:57 +01:00
Chris Palmer
49fdfea792 Added 35BYGHJ75 geared stepper. 2021-04-25 00:07:22 +01:00
Chris Palmer
ac0bacfeda Removed echo in rails test. 2021-04-25 00:02:05 +01:00
Chris Palmer
6288059d99 Updated changelog. 2021-04-13 15:07:09 +01:00
Chris Palmer
0f1dff230a Merge branch 'martinbudden-pcb_component' 2021-04-13 15:05:18 +01:00
Chris Palmer
e379fa8ada Updated readme. 2021-04-13 15:05:12 +01:00
Chris Palmer
313d7508df Merge branch 'pcb_component' of https://github.com/martinbudden/NopSCADlib into martinbudden-pcb_component 2021-04-13 15:01:27 +01:00
Chris Palmer
083caca4e8 Updated changelog. 2021-04-13 15:00:37 +01:00
Chris Palmer
49329df00c Merge branch 'martinbudden-box_section' 2021-04-13 14:57:35 +01:00
Chris Palmer
edc0b86bb1 Updated images and readme. 2021-04-13 14:56:08 +01:00
Martin Budden
5fbff060b0 Added a pcb_component function. 2021-04-13 14:42:00 +01:00
Chris Palmer
b94ca4ad3a Merge branch 'box_section' of https://github.com/martinbudden/NopSCADlib into martinbudden-box_section 2021-04-12 22:35:01 +01:00
Chris Palmer
bc5515d35e Updated changelog. 2021-04-12 22:31:23 +01:00
Chris Palmer
44d213deaa Merge branch 'martinbudden-psu_size' 2021-04-12 22:29:41 +01:00
Chris Palmer
145c5d9b1a Updated readme. 2021-04-12 22:29:20 +01:00
Chris Palmer
7abbbd9b96 Merge branch 'psu_size' of https://github.com/martinbudden/NopSCADlib into martinbudden-psu_size 2021-04-12 22:26:25 +01:00
Chris Palmer
5b160cee88 Updated changelog. 2021-04-12 22:23:58 +01:00
Chris Palmer
3f31607840 Added No8 screws. 2021-04-12 22:22:25 +01:00
Martin Budden
1efed649cf Added PSU size function. 2021-04-12 17:52:57 +01:00
Martin Budden
b70c2f993c Added box sections. 2021-04-12 17:47:35 +01:00
Chris Palmer
56e252f3dc Updated changelog 2021-04-05 16:54:31 +01:00
Chris Palmer
f12b36ea04 Corrected MGN12 rail end value.
Added assert for rail end value too big.
2021-04-05 16:45:23 +01:00
Chris Palmer
bd5811e69b Updated changelog 2021-04-03 12:17:54 +01:00
Chris Palmer
ede4da6f1d Merge branch 'martinbudden-MGN7Hand9H_carriages' 2021-04-03 12:16:07 +01:00
Chris Palmer
51cc2fd679 Carriages now appear on the BOM and both variants are shown in the rail test. 2021-04-03 12:14:36 +01:00
Chris Palmer
4ce2f53e20 Merge branch 'MGN7Hand9H_carriages' of https://github.com/martinbudden/NopSCADlib into martinbudden-MGN7Hand9H_carriages 2021-04-02 19:53:41 +01:00
Chris Palmer
e338c47e73 Updated changelog 2021-04-02 19:52:15 +01:00
Chris Palmer
8328a70f42 Merge branch 'martinbudden-pulley_children' 2021-04-02 19:49:27 +01:00
Chris Palmer
cc794cd7c3 Updated readme. 2021-04-02 19:48:35 +01:00
Chris Palmer
df28bd5116 Merge branch 'pulley_children' of https://github.com/martinbudden/NopSCADlib into martinbudden-pulley_children 2021-04-02 19:39:28 +01:00
Chris Palmer
61de6041d8 Updated changelog. 2021-04-02 19:31:33 +01:00
Chris Palmer
b2d712bca9 Added quadratic_real_roots() and cubic_real_roots(). 2021-04-02 19:30:38 +01:00
Chris Palmer
f3376edaf1 Documented xor() function. 2021-04-02 19:28:49 +01:00
Chris Palmer
c073419c0b Added opengrab_screw_depth() function. 2021-04-02 19:25:42 +01:00
Martin Budden
608168de8e Added MGN7H and MGN9H carriages. 2021-03-31 01:46:18 +01:00
Martin Budden
fc45a40bd3 Added translated children to pulley. 2021-03-31 01:40:06 +01:00
Chris Palmer
52e9c1d7fd Updated changelog 2021-03-22 16:15:09 +00:00
Chris Palmer
ca1b34e9ca Added sink parameter to screw_polysink() to recess the head. 2021-03-22 16:11:51 +00:00
Chris Palmer
cbab9cea02 Fixed M6_cs_cap_screw. 2021-03-22 12:27:11 +00:00
Chris Palmer
69cf998862 Updated changelog 2021-03-21 18:50:14 +00:00
Chris Palmer
08bce9ec03 Updated changelog 2021-03-21 18:45:01 +00:00
Chris Palmer
4aa7dbb416 Added M6_cs_cap_screw. 2021-03-21 18:37:17 +00:00
Chris Palmer
7c7c2e5d3f Pixel changes due to switch to summer computer. 2021-03-21 17:57:46 +00:00
Chris Palmer
f6f6664c0d Updated OpenSCAD version required. 2021-03-15 00:24:14 +00:00
Chris Palmer
2fd2e118a0 Updated changelog 2021-03-14 19:04:00 +00:00
Chris Palmer
22c6fef113 Updated changelog 2021-03-14 18:56:50 +00:00
Chris Palmer
dcf0c949b9 Merge branch 'SmoothieAq-open_belt' 2021-03-14 18:54:28 +00:00
Chris Palmer
9ded315801 Removed the belt gap options and changed the tests to use open loops instead.
Note previous belt lengths were incorrect with negative turns.
Fixed spelling typos.
_belt_length() no longer needs belt type.
Uptated images and readme.
2021-03-14 18:53:37 +00:00
Chris Palmer
42e03679b4 Merge branch 'open_belt' of https://github.com/SmoothieAq/NopSCADlib into SmoothieAq-open_belt 2021-03-14 14:39:05 +00:00
SmoothieAq
d2c795f5f5 fix nan angle (hopefully) 2021-03-14 14:18:05 +01:00
Chris Palmer
83b4ab2374 Merge branch 'open_belt' of https://github.com/SmoothieAq/NopSCADlib into SmoothieAq-open_belt 2021-03-14 12:33:46 +00:00
SmoothieAq
573c50774b changes after review 2021-03-14 12:48:14 +01:00
Chris Palmer
4b93623492 changelog.py now omits "Updated changelog" commits. 2021-03-13 11:19:59 +00:00
Chris Palmer
d496898c80 Updated changelog 2021-03-13 10:46:30 +00:00
Chris Palmer
544e69c71b pulley_pr() now has an optional belt type for non-standard belt over smooth pulleys. 2021-03-13 10:45:54 +00:00
SmoothieAq
240334784d Extension to belt.scad
Can now:
- render open loops
- twist the belt
- use pulleys instead of radius in the points list

Fixes some precision a few places
Breaking change in belt_length(); now requires a type argument
2021-03-11 13:40:17 +01:00
SmoothieAq
516b225275 Merge pull request #1 from nophead/master
update fork
2021-03-10 09:11:48 +01:00
Chris Palmer
e46e6b6e5b Fixed markdown numbered points in core_xy. 2021-03-08 22:57:00 +00:00
Chris Palmer
4925979519 Updated changelog. 2021-03-06 21:41:15 +00:00
Chris Palmer
298d1f9284 Interface is the same but filenames to be included or used changed.
Changlog upated.
2021-03-06 21:31:53 +00:00
Chris Palmer
fcf2f5f7f0 Merge branch 'martinbudden-rounded_triangle_rename' 2021-03-06 21:25:25 +00:00
Chris Palmer
491c3b4ea8 Updated readme, lib.scad and image. 2021-03-06 21:24:57 +00:00
Chris Palmer
94cb50f725 Merge branch 'rounded_triangle_rename' of https://github.com/martinbudden/NopSCADlib into martinbudden-rounded_triangle_rename 2021-03-06 20:17:00 +00:00
Chris Palmer
1d8275c061 Merge branch 'martinbudden-scs_bearing_blocks_rename' 2021-03-06 20:14:42 +00:00
Chris Palmer
3c605d608b Updated path, readme and image 2021-03-06 20:11:55 +00:00
Chris Palmer
9ba48c7e1a Merge branch 'scs_bearing_blocks_rename' of https://github.com/martinbudden/NopSCADlib into martinbudden-scs_bearing_blocks_rename 2021-03-06 17:03:25 +00:00
Chris Palmer
a6ebc5267b Merge branch 'martinbudden-pillow_blocks_rename' 2021-03-06 17:00:46 +00:00
Chris Palmer
e9554ccffe Fixed paths and image. 2021-03-06 17:00:16 +00:00
Chris Palmer
0d179f3728 Merge branch 'pillow_blocks_rename' of https://github.com/martinbudden/NopSCADlib into martinbudden-pillow_blocks_rename 2021-03-06 16:49:21 +00:00
Chris Palmer
a94e462f34 Merge branch 'martinbudden-coreXY_belts' 2021-03-06 16:39:44 +00:00
Chris Palmer
7ce991e625 Updated readme for pulleys on BOM. 2021-03-06 16:37:54 +00:00
Chris Palmer
3e15be852f Merge branch 'coreXY_belts' of https://github.com/martinbudden/NopSCADlib into martinbudden-coreXY_belts 2021-03-06 16:35:52 +00:00
Martin Budden
7c1c8e92f2 Removed green code. 2021-03-06 16:35:46 +00:00
Chris Palmer
54c3b4f600 Fixed path, updated readme and picture. 2021-03-06 16:35:44 +00:00
Martin Budden
d80fc5709e Left pulleys on BOM when show_pulleys true. 2021-03-06 16:32:36 +00:00
Martin Budden
30236046a8 Renamed rounded_right_triangle files to rounded_triangle. 2021-03-06 16:22:41 +00:00
Martin Budden
93aeb4cf2c Renamed scs_bearing_blocks files to bearing_blocks. 2021-03-06 16:16:43 +00:00
Chris Palmer
f62ca35c86 Merge branch 'coreXY_belts' of https://github.com/martinbudden/NopSCADlib into martinbudden-coreXY_belts 2021-03-06 16:14:23 +00:00
Martin Budden
2320cbdbb8 Renamed kp_pillow_blocks files to pillow_blocks. 2021-03-06 16:13:09 +00:00
Martin Budden
769cb44207 Renamed core_xy files. 2021-03-06 16:06:25 +00:00
Chris
f327df95a3 Merge pull request #162 from martinbudden/tests_py
Improved resilience of compare_images.
2021-03-06 15:58:38 +00:00
Martin Budden
09956b6219 Improved resilience of compare_images. 2021-03-06 15:36:49 +00:00
Chris
f8c9adca5a Merge pull request #161 from martinbudden/cmdline_reorder
Reordered openscad command line parameters to put output name first.
2021-03-06 15:06:03 +00:00
Martin Budden
b83e56713f Reordered openscad command line parameters. 2021-03-06 14:30:35 +00:00
Martin Budden
4c12d5fca4 Added parameterised CoreXY. 2021-03-06 10:10:28 +00:00
Chris Palmer
da4f9fbdc3 Typo in changlog.py doc string. 2021-03-04 09:14:27 +00:00
Chris Palmer
614e5f3a72 Issues in the changelog now link to to the issue. 2021-03-03 19:27:25 +00:00
Chris Palmer
a7eae4f549 Neater changlog format. 2021-03-03 19:10:27 +00:00
Chris Palmer
3cd5769708 Merge branch 'martinbudden-cf_contrast' 2021-03-03 14:32:19 +00:00
Chris Palmer
7b770abe12 Udpated changelog 2021-03-03 14:31:38 +00:00
Chris Palmer
31ab8562a7 Updated images 2021-03-03 14:29:32 +00:00
Chris Palmer
db703379a3 Merge branch 'cf_contrast' of https://github.com/martinbudden/NopSCADlib into martinbudden-cf_contrast 2021-03-03 14:17:48 +00:00
Chris Palmer
cd925bc049 Added changelog link to readme. 2021-03-03 14:12:21 +00:00
Chris Palmer
4a2951e22f Fixed changelog.py for when HEAD doesn't have tag. 2021-03-03 13:51:22 +00:00
Chris Palmer
a93a8f99fb Added CHANGELOG.md for #154 2021-03-03 13:47:09 +00:00
Martin Budden
73c436ee15 Improved contrast of carbon fiber sheets. 2021-02-27 16:34:27 +00:00
Chris Palmer
c69100bd71 Added spring steel and silicone sheets. 2021-02-22 15:26:19 +00:00
Chris Palmer
e0b89359aa Fixed plateup using target dir when no panels or platters. 2021-02-21 14:18:41 +00:00
Chris Palmer
041d720c39 Updated example bom.json. 2021-02-21 14:17:09 +00:00
Chris Palmer
03a0c2fe98 Fixed typo. 2021-02-20 20:13:36 +00:00
Chris Palmer
7c2df8d36d The pose module can now specify the camera distance supressing viewall and
autocentre.
2021-02-20 19:28:52 +00:00
Chris Palmer
8474718884 Added printed pocket_handle(). 2021-02-17 13:20:39 +00:00
Chris Palmer
fe0f32ddc5 Merge branch 'martinbudden-polyholes' 2021-02-11 09:41:27 +00:00
Chris Palmer
f191b9b0f4 Updated readme 2021-02-11 09:40:18 +00:00
Chris Palmer
2b3908b6fd Merge branch 'polyholes' of https://github.com/martinbudden/NopSCADlib into martinbudden-polyholes 2021-02-11 09:11:42 +00:00
Chris Palmer
0a84bf0927 plateup.py now saves the used files to speed up processing when a part hasn't changed.
Added times to plateup.py.
2021-02-11 09:10:15 +00:00
Chris Palmer
da825b17ab Added colorama.init() to plateup.py to handle new coloured changed messages. 2021-02-10 10:22:38 +00:00
Chris Palmer
ca153c971d Fixed platters and panels not working in the GUI, a regression.
set_config() now puts $cwd in target.scad.
use_stl() and use_dxf() included again instead of used.
2021-02-10 10:17:03 +00:00
Martin Budden
0199587907 Allow poly_shapes to collapse to non-poly form. 2021-02-10 08:29:15 +00:00
Chris Palmer
60350eb228 Updated gallery.py for new page break format. 2021-02-09 23:44:03 +00:00
Chris Palmer
4f9729cf86 Now shows what changed to trigger an openscad invocation in cyan. 2021-02-09 23:32:53 +00:00
Chris Palmer
26f1338ca2 Fixed removal of old deps 2021-02-09 14:34:27 +00:00
Chris Palmer
fc44b43638 Temporary files used during make_all and tests now in tmp dir. 2021-02-09 09:52:26 +00:00
Chris Palmer
182f39876a Moved deps directories to separate stl deps from views deps. 2021-02-09 09:18:30 +00:00
Chris Palmer
055e90cbb3 /stls/ and /dxfs/ excluded from deps to prevent circular dependencies. 2021-02-08 22:44:21 +00:00
Chris Palmer
832380f893 Fixed set_config always writing to target.scad. 2021-02-08 20:31:10 +00:00
Chris Palmer
929d082b25 openscad.py now quits if there are errors or warnings in the log.
This is because the exit status is not always set correctly.
2021-02-08 16:03:59 +00:00
Chris Palmer
57212b5701 set_config.py now defines $target. 2021-02-08 15:00:44 +00:00
Chris Palmer
1c3f136657 Fixed $cwd and $target not defined during silent run. 2021-02-08 15:00:01 +00:00
Chris Palmer
cfd2fd32a1 Now checks openscad.echo for warnings when used instead of openscad.log. 2021-02-08 14:58:50 +00:00
Chris Palmer
f573a91a09 Removed redundant rounded_rectangle center = false. 2021-02-08 09:41:07 +00:00
Chris Palmer
d75aff2ccd rounded_retangle() centre now defaults to false. 2021-02-08 09:24:00 +00:00
Chris Palmer
491d85156c Merge branch 'martinbudden-rounded_cubes' 2021-02-08 08:29:50 +00:00
Chris Palmer
c89ce6843f Updated images and readme. 2021-02-08 08:29:08 +00:00
Chris Palmer
1915dae034 Merge branch 'rounded_cubes' of https://github.com/martinbudden/NopSCADlib into martinbudden-rounded_cubes 2021-02-07 22:17:22 +00:00
Chris Palmer
05e8055ce2 Merge branch 'martinbudden-btt_skr_e3_turbo' 2021-02-07 22:01:41 +00:00
Chris Palmer
21822b9abb Updated pictures and readme. 2021-02-07 22:01:26 +00:00
Chris Palmer
d83d4b89bf Merge branch 'btt_skr_e3_turbo' of https://github.com/martinbudden/NopSCADlib into martinbudden-btt_skr_e3_turbo 2021-02-07 21:48:16 +00:00
Chris Palmer
613152f589 Merge branch 'martinbudden-bl30x10' 2021-02-07 21:46:28 +00:00
Chris Palmer
d90c00d140 Updated images and readme. 2021-02-07 21:46:15 +00:00
Chris Palmer
b52ca9589a Merge branch 'bl30x10' of https://github.com/martinbudden/NopSCADlib into martinbudden-bl30x10 2021-02-07 21:25:53 +00:00
Martin Budden
0d024060fc Added BTT_SKR_E3_TURBO. 2021-02-07 07:51:10 +00:00
Martin Budden
c4fe1d1098 Added assertion to check r value. Used extrud_if. 2021-02-07 07:29:02 +00:00
Chris Palmer
a3ced6de45 Merge branch 'martinbudden-mgn9_correction' 2021-02-06 15:29:51 +00:00
Chris Palmer
1cdfe3267c Merge branch 'mgn9_correction' of https://github.com/martinbudden/NopSCADlib into martinbudden-mgn9_correction 2021-02-06 15:28:49 +00:00
Chris Palmer
b67cf4ce97 Library printed parts now make use of stl() child. 2021-02-06 15:24:19 +00:00
Chris Palmer
5bac2bf46d stl() and dxf() can now have the code to make the STL or DXF as a child.
This allows them to be replaced by the STL or DXF when making assembly views.

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

Corrected the spelling of widget in BOM test.
2021-02-06 15:23:10 +00:00
Chris Palmer
079168142b Views.py and plateup.py now define $cwd and $target. 2021-02-06 15:12:21 +00:00
Chris Palmer
cb30f0c63d Times for parts that no longer exist pruned from build times.
Now shows changes to the total time.
2021-02-06 10:39:39 +00:00
Martin Budden
812fbc106c Updated screw hole position. 2021-02-04 19:59:28 +00:00
Martin Budden
dd38fa6e5d Added 30x10 square radial fan. 2021-02-04 18:26:44 +00:00
Martin Budden
5cdcd4ad37 Corrected MGN9 rail end value. 2021-02-03 11:24:44 +00:00
Chris Palmer
4cb324ed37 Merge branch 'martinbudden-rails_rename' 2021-02-03 07:10:27 +00:00
Chris Palmer
eb997aa18c Updated readme for rails. Note interface change. 2021-02-03 07:10:07 +00:00
Chris Palmer
f09343a285 Merge branch 'rails_rename' of https://github.com/martinbudden/NopSCADlib into martinbudden-rails_rename 2021-02-03 06:38:07 +00:00
Martin Budden
22b7aa956c Renamed rounded_rectangle_* to rounded_cube_*. 2021-02-02 17:32:44 +00:00
Martin Budden
f760aaa20a Changed carriage to specify its rail type. 2021-02-02 12:23:03 +00:00
Martin Budden
1c445385b4 Made C version of linear rails and carriages explicit. 2021-02-01 19:21:50 +00:00
270 changed files with 109589 additions and 13562 deletions

2200
CHANGELOG.md Normal file

File diff suppressed because it is too large Load Diff

View 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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 108 KiB

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 105 KiB

After

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 138 KiB

After

Width:  |  Height:  |  Size: 137 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 121 KiB

After

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 201 KiB

After

Width:  |  Height:  |  Size: 201 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 124 KiB

After

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 135 KiB

After

Width:  |  Height:  |  Size: 135 KiB

View 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
1 'Ferrule for 1.5mm^2 wire - not shown', 3
2 'Wire blue 30/0.25mm strands, length 150mm - not shown', 2
3 'Wire brown 30/0.25mm strands, length 150mm - not shown', 2
4 'Wire green & yellow 30/0.25mm strands, length 150mm - not shown', 2
5 'IEC inlet for ATX', 1
6 'Heatfit insert M3', 2
7 '4mm shielded jack socket blue', 2
8 '4mm shielded jack socket brown', 1
9 '4mm shielded jack socket green', 2
10 'Mains socket 13A', 1
11 'Nut M3 x 2.4mm nyloc', 6
12 'Screw M3 cs cap x 12mm', 2
13 'Screw M3 cs cap x 20mm', 2
14 'Screw M3 dome x 10mm', 4
15 'Heatshrink sleeving ID 3.2mm x 15mm - not shown', 8
16 'Washer M3 x 7mm x 0.5mm', 10

View File

@@ -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

View 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");

View File

@@ -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];

View File

@@ -0,0 +1,5 @@
socket_box.stl
foot.stl
foot.stl
foot.stl
foot.stl

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 121 KiB

After

Width:  |  Height:  |  Size: 121 KiB

BIN
gallery/IOT_LOAD.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 259 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 287 KiB

After

Width:  |  Height:  |  Size: 287 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 121 KiB

After

Width:  |  Height:  |  Size: 121 KiB

BIN
gallery/PSU_cover.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 KiB

BIN
gallery/PotBox.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 164 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 252 KiB

After

Width:  |  Height:  |  Size: 390 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 202 KiB

After

Width:  |  Height:  |  Size: 202 KiB

View File

@@ -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.
![](ArduinoThermostat.png)
<a name="TOP"></a>
## EnviroPlus
Environmental monitor using Enviro+ sensor board and a Raspberry Pi Zero.
![](EnviroPlus.png)
<a name="TOP"></a>
## FilamentDryBox
A small fan oven with a spool holder to keep the filament warm and dry.
![](FilamentDryBox.png)
<a name="TOP"></a>
## HydraBot
Current state of HydraRaptor after being modified for laser engraving.
![](HydraBot.png)
<a name="TOP"></a>
## IOT 50V PSU
WiFi controllable PSU
![](IOT_50V_PSU.png)
## IOT LOAD
WiFi controllable programmable load
![](IOT_LOAD.png)
<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
![](Laser_load.png)
<a name="TOP"></a>
## MainsBreakOutBox
13A socket break out box with 4mm jacks to measure voltage and / or load current and earth leakage current.
@@ -72,8 +63,6 @@ Earth leakage can be measured Canadian CSA style by disconnected the neutral lin
![](MainsBreakOutBox.png)
<a name="TOP"></a>
## Mains Box
Mains isolated and variable supply with metering.
@@ -81,15 +70,21 @@ Mains isolated and variable supply with metering.
## PSU Cover
A base and shroud to make PSU safe to sit on a desk
![](PSU_cover.png)
## PotBox
Potentiometer box with course and fine controls and three 4mm binding posts
![](PotBox.png)
<a name="TOP"></a>
## SunBot
A solar tracker to keep a solar panel pointing at the sun.
![](SunBot.png)
<a name="TOP"></a>
## Turntable
WiFi enabled remote control turntable for photography
@@ -97,8 +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

View File

@@ -24,22 +24,23 @@
// 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
teardrop_angle = is_undef($teardrop_angle) ? 45 : $teardrop_angle; // teardrop angle
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 +51,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 +74,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;

View File

@@ -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>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 875 KiB

After

Width:  |  Height:  |  Size: 945 KiB

View File

@@ -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>
@@ -116,7 +123,9 @@ use <tests/fixing_block.scad>
use <tests/flat_hinge.scad>
use <tests/foot.scad>
use <tests/handle.scad>
use <tests/knob.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>
@@ -165,28 +174,33 @@ translate([x5, cable_grommets_y + 470]) {
flat_hinges();
}
translate([x5, cable_grommets_y + 370])
translate([x5, cable_grommets_y + 380])
no_explode() socket_boxes();
translate([x5 + 60, cable_grommets_y + 200])
strap_handles();
translate([640, cable_grommets_y + 200])
printed_pulley_test();
translate([x5, cable_grommets_y + 250])
translate([x5, cable_grommets_y + 200])
knobs();
translate([x5 + 60, cable_grommets_y + 250])
strap_handles();
translate([x5, cable_grommets_y + 300])
handle();
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 +212,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 +262,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 +289,7 @@ translate([x0, fans_y]) {
fan_guards();
}
translate([x0, transformers_y])
translate([760, fans_y])
variacs();
translate([x0, psus_y]) {
@@ -283,7 +301,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 +311,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 +367,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 +414,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 +423,7 @@ translate([x2, panel_meters_y])
translate([x2, extrusions_y])
extrusions();
translate([x3, transformers_y])
translate([400, transformers_y])
transformers();
@@ -418,15 +431,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 +454,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 +466,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();

View File

@@ -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>
@@ -48,12 +50,13 @@ function box_sheets(type) = type[3]; //! Sheet type used for the sides
function box_top_sheet(type) = type[4]; //! Sheet type for the top
function box_base_sheet(type) = type[5]; //! Sheet type for the bottom
function box_feet(type) = type[6]; //! True to enable feet on the bottom bezel
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_name(type) = type[7]; //! Name for projects with more than one box
function box_width(type) = type[8]; //! Internal width
function box_depth(type) = type[9]; //! Internal depth
function box_height(type) = type[10];//! 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, name = "box") = //! Construct a property list for a box.
concat([screw, is_undef(shelf_screw) ? screw : shelf_screw, wall, sheets, top_sheet, base_sheet, feet, name], size);
function box_bezel_clearance(type) = bezel_clearance;
@@ -64,7 +67,7 @@ function box_washer(type) = screw_washer(box_screw(type));
function box_insert(type) = screw_insert(box_screw(type));
function box_shelf_insert(type) = screw_insert(box_shelf_screw(type));
function box_hole_inset(type) = washer_radius(box_washer(type)) + 1;
function box_hole_inset(type) = washer_radius(box_washer(type)) + 1; //! Screw inset from the corner of the internal dimensions
function box_insert_r(type) = insert_hole_radius(box_insert(type));
function box_insert_l(type) = insert_length(box_insert(type));
function box_boss_r(type) = ceil(corrected_radius(box_insert_r(type)) + box_wall(type));
@@ -89,6 +92,8 @@ function box_bezel_height(type, bottom) = //! Bezel height for top or bottom
let(t1 = sheet_thickness(box_base_sheet(type)), t2 = sheet_thickness(box_top_sheet(type)))
box_corner_rad(type) + box_profile_overlap(type) + (bottom ? max(t1, t2) : t2) - sheet_thickness(box_sheets(type));
function box_bc_name(type, suffix) = let(name = box_name(type)) name == "box" ? suffix : str(name, "_", suffix); // Backwards compatibale name
grill_hole = 5;
grill_gap = 1.9;
@@ -139,17 +144,17 @@ module box_corner_profile_2D(type) { //! The 2D shape of the corner profile.
}
module box_corner_profile(type) { //! Generates the corner profile STL for 3D printing.
stl("box_corner_profile");
length = box_height(type) - 2 * box_margin(type);
difference() {
linear_extrude(length, center = true, convexity = 5)
box_corner_profile_2D(type);
for(z = [-1, 1])
translate([box_hole_inset(type), box_hole_inset(type), z * length / 2])
insert_hole(box_insert(type), 5);
}
stl(str(box_name(type), "_corner_profile"))
difference() {
linear_extrude(length, center = true, convexity = 5)
box_corner_profile_2D(type);
for(z = [-1, 1])
translate([box_hole_inset(type), box_hole_inset(type), z * length / 2])
insert_hole(box_insert(type), 5);
}
}
module box_corner_profile_section(type, section, sections) { //! Generates interlocking sections of the corner profile to allow it to be taller than the printer
@@ -190,7 +195,7 @@ module box_corner_profile_section(type, section, sections) { //! Generates inter
}
module box_corner_profile_sections(type, section, sections) { //! Generate four copies of a corner profile section
stl("box_corner_profile");
stl(str(box_name(type), "_corner_profile"));
offset = box_boss_r(type) + 1;
for(i = [0 : 3])
rotate(i * 90)
@@ -209,7 +214,6 @@ module box_corner_quadrants(type, width, depth)
}
module box_bezel(type, bottom) { //! Generates top and bottom bezel STLs
stl(bottom ? "bottom_bezel" : "top_bezel");
feet = bottom && box_feet(type);
t = box_sheet_slot(type);
outset = box_outset(type);
@@ -221,66 +225,67 @@ module box_bezel(type, bottom) { //! Generates top and bottom bezel STLs
height = box_bezel_height(type, bottom);
foot_extension = foot_height - height;
difference() {
w = box_width(type);
d = box_depth(type);
translate_z(-box_profile_overlap(type)) difference() {
tw = w + 2 * outset;
td = d + 2 * outset;
rounded_rectangle([tw, td, feet ? foot_height : height], box_corner_rad(type), false);
//
// Remove edges between the feet
//
if(feet)
hull() {
translate_z(height + 0.5)
cube([w - 2 * foot_length, td + 1, 1], center = true);
stl(box_bc_name(type, bottom ? "bottom_bezel" : "top_bezel"))
difference() {
w = box_width(type);
d = box_depth(type);
translate_z(-box_profile_overlap(type)) difference() {
tw = w + 2 * outset;
td = d + 2 * outset;
rounded_rectangle([tw, td, feet ? foot_height : height], box_corner_rad(type));
//
// Remove edges between the feet
//
if(feet)
hull() {
translate_z(height + 0.5)
cube([w - 2 * foot_length, td + 1, 1], center = true);
translate_z(foot_height + 1)
cube([w - 2 * (foot_length - foot_extension), td + 1, 1], center = true);
}
if(feet)
hull() {
translate_z(height + 0.5)
cube([tw + 1, d - 2 * foot_length, 1], center = true);
translate_z(foot_height + 1)
cube([tw + 1, d - 2 * (foot_length - foot_extension), 1], center = true);
}
}
//
// slots for side panels
//
translate_z(-box_profile_overlap(type))
linear_extrude(2 * box_profile_overlap(type), center = true)
for(i = [-1, 1]) {
translate([i * (w + t - sheet_slot_clearance) / 2, 0])
square([t, d - 2 * cgap], center = true);
translate([0, i * (d + t - sheet_slot_clearance) / 2])
square([w - 2 * cgap, t], center = true);
}
//
// recess for top / bottom panel
//
translate_z(cgap)
rounded_rectangle([w + bezel_clearance, d + bezel_clearance, height], inner_r + bezel_clearance / 2, false);
//
// leave plastic over the corner profiles
//
translate_z(-box_profile_overlap(type) - 1)
linear_extrude(box_profile_overlap(type) + cgap + 2)
union() {
difference() {
square([w - 2 * inset,
d - 2 * inset], center = true);
box_corner_quadrants(type, w, d);
translate_z(foot_height + 1)
cube([w - 2 * (foot_length - foot_extension), td + 1, 1], center = true);
}
box_screw_hole_positions(type)
poly_circle(screw_clearance_radius(box_screw(type)));
}
}
if(feet)
hull() {
translate_z(height + 0.5)
cube([tw + 1, d - 2 * foot_length, 1], center = true);
translate_z(foot_height + 1)
cube([tw + 1, d - 2 * (foot_length - foot_extension), 1], center = true);
}
}
//
// slots for side panels
//
translate_z(-box_profile_overlap(type))
linear_extrude(2 * box_profile_overlap(type), center = true)
for(i = [-1, 1]) {
translate([i * (w + t - sheet_slot_clearance) / 2, 0])
square([t, d - 2 * cgap], center = true);
translate([0, i * (d + t - sheet_slot_clearance) / 2])
square([w - 2 * cgap, t], center = true);
}
//
// recess for top / bottom panel
//
translate_z(cgap)
rounded_rectangle([w + bezel_clearance, d + bezel_clearance, height], inner_r + bezel_clearance / 2);
//
// leave plastic over the corner profiles
//
translate_z(-box_profile_overlap(type) - 1)
linear_extrude(box_profile_overlap(type) + cgap + 2)
union() {
difference() {
square([w - 2 * inset,
d - 2 * inset], center = true);
box_corner_quadrants(type, w, d);
}
box_screw_hole_positions(type)
poly_circle(screw_clearance_radius(box_screw(type)));
}
}
}
dowel_length = 20;
@@ -353,7 +358,6 @@ module box_bezel_section(type, bottom, rows, cols, x, y) { //! Generates interlo
translate([0, bw2 / 2, dh2 / 2])
cube([eps, bw2 - 2 * dowel_wall + 2 * extrusion_width, dh2], center = true);
}
}
}
@@ -438,7 +442,7 @@ module box_screw_hole_positions(type) {
}
module box_base_blank(type) { //! Generates a 2D template for the base sheet
dxf("box_base");
dxf(str(box_name(type), "_base"));
difference() {
sheet_2D(box_base_sheet(type), box_width(type), box_depth(type), box_sheet_r(type));
@@ -449,7 +453,7 @@ module box_base_blank(type) { //! Generates a 2D template for the base sheet
}
module box_top_blank(type) { //! Generates a 2D template for the top sheet
dxf("box_top");
dxf(str(box_name(type), "_top"));
difference() {
sheet_2D(box_top_sheet(type), box_width(type), box_depth(type), box_sheet_r(type));
@@ -464,7 +468,7 @@ function subst_sheet(type, sheet) =
sheet ? assert(sheet_thickness(sheet) == sheet_thickness(s)) sheet : s;
module box_shelf_blank(type, sheet = false) { //! Generates a 2D template for a shelf sheet
dxf("box_shelf");
dxf(str(box_name(type), "_shelf"));
difference() {
sheet_2D(subst_sheet(type, sheet), box_width(type) - bezel_clearance, box_depth(type) - bezel_clearance, 1);
@@ -485,7 +489,6 @@ module box_shelf_screw_positions(type, screw_positions, thickness = 0, wall = un
}
module box_shelf_bracket(type, screw_positions, wall = undef) { //! Generates a shelf bracket, the first optional child is a 2D cutout and the second 3D cutouts
stl("shelf_bracket");
w = is_undef(wall) ? box_wall(type) : wall;
insert = box_shelf_insert(type);
lip = 2 * insert_boss_radius(insert, w);
@@ -513,44 +516,45 @@ module box_shelf_bracket(type, screw_positions, wall = undef) { //! Generates a
square([lip, eps]);
}
difference() {
union() {
linear_extrude(w)
difference() {
shape()
if($children)
children(0);
round(2) offset(-width)
stl(box_bc_name(type, "shelf_bracket"))
difference() {
union() {
linear_extrude(w)
difference() {
shape()
if($children)
children(0);
}
linear_extrude(lip)
difference() {
shape()
if($children)
children(0);
round(2) offset(-width)
shape()
if($children)
children(0);
}
offset(-w)
linear_extrude(lip)
difference() {
shape()
if($children)
children(0);
}
offset(-w)
shape()
if($children)
children(0);
}
hflip()
box_shelf_screw_positions(type, screw_positions, 0, w)
boss();
}
if($children > 1)
hflip()
children(1);
hflip()
box_shelf_screw_positions(type, screw_positions, 0, w)
boss();
insert_hole(insert, counterbore = 1, horizontal = true);
}
if($children > 1)
hflip()
children(1);
hflip()
box_shelf_screw_positions(type, screw_positions, 0, w)
insert_hole(insert, counterbore = 1, horizontal = true);
}
}
module box_shelf_bracket_section(type, rows, cols, x, y) { //! Generates sections of the shelf bracket to allow it to be bigger than the printer
@@ -565,32 +569,49 @@ module box_shelf_bracket_section(type, rows, cols, x, y) { //! Generates section
}
module box_left_blank(type, sheet = false) { //! Generates a 2D template for the left sheet, `sheet` can be set to override the type
dxf("box_left");
dxf(str(box_name(type), "_left"));
sheet_2D(subst_sheet(type, sheet), box_depth(type) - sheet_reduction(type), box_height(type) - sheet_reduction(type), 1);
}
module box_right_blank(type, sheet = false) { //! Generates a 2D template for the right sheet, `sheet` can be set to override the type
dxf("box_right");
dxf(str(box_name(type), "_right"));
sheet_2D(subst_sheet(type, sheet), box_depth(type) - sheet_reduction(type), box_height(type) - sheet_reduction(type), 1);
}
module box_front_blank(type, sheet = false) { //! Generates a 2D template for the front sheet, `sheet` can be set to override the type
dxf("box_front");
dxf(str(box_name(type), "_front"));
sheet_2D(subst_sheet(type, sheet), box_width(type) - sheet_reduction(type), box_height(type) - sheet_reduction(type), 1);
}
module box_back_blank(type, sheet = false) { //! Generates a 2D template for the back sheet, `sheet` can be set to override the type
dxf("box_back");
dxf(str(box_name(type), "_back"));
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);

View File

@@ -23,12 +23,12 @@
// parameters to make the assembly views. E.g. module box_assembly() _box_assembly(box);
//
module _box_assembly(type, top = true, base = true, left = true, right = true, back = true, front = true, bezels = true, corners = 4)
assembly("box") {
assembly(box_name(type)) {
echo("Box:", box_width(type), box_depth(type), box_height(type));
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())])

View File

@@ -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);

View File

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

View File

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

View File

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

View File

@@ -72,8 +72,6 @@ module corner_block_holes(screw = def_screw) //! Place children at all the holes
children();
module corner_block(screw = def_screw, name = false) { //! Generate the STL for a printed corner block
stl(name ? name : str("corner_block", "_M", screw_radius(screw) * 20));
r = 1;
cb_width = corner_block_width(screw);
cb_height = cb_width;
@@ -81,39 +79,41 @@ module corner_block(screw = def_screw, name = false) { //! Generate the STL for
insert = screw_insert(screw);
corner_rad = insert_outer_d(insert) / 2 + wall;
offset = corner_block_hole_offset(screw);
difference() {
hull() {
translate([r, r])
rounded_cylinder(r = r, h = cb_height, r2 = r);
translate([r, cb_depth - r])
cylinder(r = r, h = cb_height - corner_rad);
stl(name ? name : str("corner_block", "_M", screw_radius(screw) * 20))
difference() {
hull() {
translate([r, r])
rounded_cylinder(r = r, h = cb_height, r2 = r);
translate([cb_width - r, r])
cylinder(r = r, h = cb_height - corner_rad);
translate([r, cb_depth - r])
cylinder(r = r, h = cb_height - corner_rad);
translate([offset, offset, offset])
sphere(corner_rad);
translate([cb_width - r, r])
cylinder(r = r, h = cb_height - corner_rad);
translate([offset, offset])
cylinder(r = corner_rad, h = offset);
translate([offset, offset, offset])
sphere(corner_rad);
translate([offset, r, offset])
rotate([-90, 0, 180])
rounded_cylinder(r = corner_rad, h = r, r2 = r);
translate([offset, offset])
cylinder(r = corner_rad, h = offset);
translate([r, offset, offset])
rotate([0, 90, 180])
rounded_cylinder(r = corner_rad, h = r, r2 = r);
translate([offset, r, offset])
rotate([-90, 0, 180])
rounded_cylinder(r = corner_rad, h = r, r2 = r);
translate([r, offset, offset])
rotate([0, 90, 180])
rounded_cylinder(r = corner_rad, h = r, r2 = r);
}
corner_block_v_hole(screw)
insert_hole(insert, overshoot);
corner_block_h_holes(screw)
insert_hole(insert, overshoot, true);
children();
}
corner_block_v_hole(screw)
insert_hole(insert, overshoot);
corner_block_h_holes(screw)
insert_hole(insert, overshoot, true);
children();
}
}
module corner_block_assembly(screw = def_screw, name = false) //! The printed block with inserts

View File

@@ -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])
@@ -54,44 +54,44 @@ module door_hinge_hole_positions(dir = 0) { //! Position chidren
}
module door_hinge(door_thickness) { //! Generates STL for the moving part of the hinge
stl(str("door_hinge_", door_thickness));
hole_pitch = width - 10;
union() {
rotate([90, 0, 0])
linear_extrude(width, center = true)
stl(str("door_hinge_", door_thickness))
union() {
rotate([90, 0, 0])
linear_extrude(width, center = true)
difference() {
hull() {
translate([dia / 2, thickness + door_thickness / 2])
intersection() {
rotate(180)
teardrop(r = dia / 2, h = 0, truncate = false);
square([dia + 1, 2 * thickness + door_thickness], center = true);
}
square([1, thickness + door_thickness]);
}
translate([dia / 2, thickness + door_thickness / 2])
teardrop_plus(r = screw_clearance_radius(pin_screw), h = 0);
}
linear_extrude(thickness)
difference() {
hull() {
translate([dia / 2, thickness + door_thickness / 2])
intersection() {
rotate(180)
teardrop(r = dia / 2, h = 0, truncate = false);
translate([0, -width / 2])
square([1, width]);
square([dia + 1, 2 * thickness + door_thickness], center = true);
}
square([1, thickness + door_thickness]);
for(side = [-1, 1])
translate([-width + rad, side * (width / 2 - rad)])
circle4n(rad);
}
translate([dia / 2, thickness + door_thickness / 2])
teardrop_plus(r = screw_clearance_radius(pin_screw), h = 0);
rotate(180)
vflip()
door_hinge_hole_positions()
poly_circle(screw_clearance_radius(screw));
}
linear_extrude(thickness)
difference() {
hull() {
translate([0, -width / 2])
square([1, width]);
for(side = [-1, 1])
translate([-width + rad, side * (width / 2 - rad)])
circle4n(rad);
}
rotate(180)
vflip()
door_hinge_hole_positions()
poly_circle(screw_clearance_radius(screw));
}
}
}
}
module door_hinge_6_stl() door_hinge(6);

View File

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

View File

@@ -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&deg;, so the mininium radius is proportional to the link length.
//! Each link has a maximum bend angle of 45&deg;, 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.
//!
@@ -35,18 +35,17 @@ include <../core.scad>
use <../utils/horiholes.scad>
use <../utils/maths.scad>
clearance = 0.1;
function drag_chain_name(type) = type[0]; //! The name to allow more than one in a project
function drag_chain_size(type) = type[1]; //! The internal size and link length
function drag_chain_travel(type) = type[2]; //! X travel
function drag_chain_wall(type) = type[3]; //! Side wall thickness
function drag_chain_bwall(type) = type[4]; //! Bottom wall
function drag_chain_twall(type) = type[5]; //! Top wall
function drag_chain_screw(type) = type[6]; //! Mounting screw for the ends
function drag_chain_screw_lists(type) = type[7]; //! Two lists of four bools to say which screws positions are used
function drag_chain_clearance(type) = type[6]; //! Clearance around joints
function drag_chain_supports(type) = type[7]; //! Whether to print version of chain with or without supports
function drag_chain_screw(type) = type[8]; //! Mounting screw for the ends
function drag_chain_screw_lists(type) = type[9]; //! Two lists of four bools to say which screws positions are used
function drag_chain_clearance() = clearance; //! Clearance around joints.
function drag_chain_radius(type) = //! The bend radius at the pivot centres
let(s = drag_chain_size(type))
@@ -56,12 +55,15 @@ function drag_chain_z(type) = //! Outside dimension of a 180 bend
let(os = drag_chain_outer_size(type), s = drag_chain_size(type))
2 * drag_chain_radius(type) + os.z;
function drag_chain(name, size, travel, wall = 1.6, bwall = 1.5, twall = 1.5, screw = M2_cap_screw, screw_lists = [[1,0,0,1],[1,0,0,1]]) = //! Constructor
[name, size, travel, wall, bwall, twall, screw, screw_lists];
function drag_chain(name, size, travel, wall = 1.6, bwall = 1.5, twall = 1.5, clearance = 0.1, supports = true, screw = M2_cap_screw, screw_lists = [[1,0,0,1],[1,0,0,1]]) = //! Constructor
[name, size, travel, wall, bwall, twall, clearance, supports, screw, screw_lists];
function drag_chain_outer_size(type) = //! Link outer dimensions
let(s = drag_chain_size(type), z = s.z + drag_chain_bwall(type) + drag_chain_twall(type))
[s.x + z, s.y + 4 * drag_chain_wall(type) + 2 * clearance, z];
[s.x + z, s.y + 4 * drag_chain_wall(type) + 2 * drag_chain_clearance(type), z];
function drag_chain_links(type) = //! Number of links in chain
ceil(drag_chain_travel(type) / drag_chain_size(type).x) + 4;
function screw_lug_radius(screw) = //! Radius of a screw lug
corrected_radius(screw_clearance_radius(screw)) + 3.1 * extrusion_width;
@@ -85,6 +87,7 @@ module drag_chain_screw_positions(type, end) { //! Place children at the screw p
r = screw_lug_radius(drag_chain_screw(type));
s = drag_chain_size(type);
os = drag_chain_outer_size(type);
clearance = drag_chain_clearance(type);
R = os.z / 2;
x0 = end ? R + norm([drag_chain_cam_x(type), R - drag_chain_twall(type)]) + clearance + r : r;
x1 = end ? os.x - r : os.x - 2 * R - clearance - r;
@@ -99,7 +102,7 @@ function drag_chain_cam_x(type) = // how far the cam sticks out
let(s = drag_chain_size(type),
r = drag_chain_outer_size(type).z / 2,
wall = drag_chain_wall(type),
cam_r = s.x - 2 * clearance - wall - r, // inner_x_normal - clearance - r
cam_r = s.x - 2 * drag_chain_clearance(type) - wall - r, // inner_x_normal - clearance - r
twall = drag_chain_twall(type)
) min(sqrt(max(sqr(cam_r) - sqr(r - twall), 0)), r);
@@ -111,8 +114,15 @@ module drag_chain_link(type, start = false, end = false, check_kids = true) { //
bwall = drag_chain_bwall(type);
twall = drag_chain_twall(type);
os = drag_chain_outer_size(type);
clearance = drag_chain_clearance(type);
supports = drag_chain_supports(type);
r = os.z / 2;
pin_r = r / 2;
// initial estimates of pin_r and pin_h
pin_r0 = r / 2 - 0.2;
pin_h0 = min(wall + clearance, 2 * pin_r0 - 1);
// for conical pin: ensure minimum radius of top of pin and pin does not overlap cutout
pin_r = supports ? r / 2 : min(r / 2 - 0.2, (os.z - 2 * twall - 3 * pin_h0 / 4 - 0.2) / 2);
pin_h = min(wall + clearance, 2 * pin_r - 1);
socket_x = r;
pin_x = socket_x + s.x;
@@ -123,44 +133,51 @@ module drag_chain_link(type, start = false, end = false, check_kids = true) { //
inner_x = start ? 0 : outer_normal_x - wall; // s.x - clearance - wall
roof_x_normal = 2 * r - twall;
roof_x = start ? 0 : roof_x_normal;
floor_x = start ? 0 : 2 * r;
cam_x = drag_chain_cam_x(type);
assert(r + norm([drag_chain_cam_x(type), r - drag_chain_twall(type)]) + clearance <= inner_x || start, "Link must be longer");
vflip(!supports)
difference() {
union() {
for(side = [-1, 1])
rotate([90, 0, 0]) {
// Outer cheeks
translate_z(side * (os.y / 2 - wall / 2))
linear_extrude(wall, center = true)
difference() {
difference() {
linear_extrude(wall, center = true)
hull() {
if(start)
square([eps, os.z]);
else
translate([socket_x, r])
rotate(180)
rotate(supports ? 180 : 0)
teardrop(r = r, h = 0);
translate([outer_end_x - eps, 0])
square([eps, os.z]);
}
if(!start)
translate([socket_x, r])
horihole(pin_r, r);
if(supports)
translate([socket_x, r, 0])
horihole(pin_r, r, wall + 2*eps);
else
translate([socket_x, r, -side * (wall / 2 + clearance)])
rotate(180)
hull() {
horihole(r = pin_r + pin_h / 2, z = r, h = eps);
translate_z(side * pin_h)
horihole(r = pin_r - pin_h / 2, z = r, h = eps);
}
}
// Inner cheeks
translate_z(side * (s.y / 2 + wall / 2))
translate_z(side * (s.y / 2 + wall / 2)) {
linear_extrude(wall, center = true)
difference() {
union() {
hull() {
if(!end) {
translate([pin_x, r])
rotate(180)
rotate(supports ? 180 : 0)
teardrop(r = r, h = 0);
translate([pin_x, twall])
@@ -186,31 +203,39 @@ module drag_chain_link(type, start = false, end = false, check_kids = true) { //
square(os.z);
}
}
// Pin
if(!end)
translate([pin_x, r, side * (s.y / 2 + wall + clearance)])
horicylinder(r = pin_r, z = r, h = 2 * wall);
// Pin
if(!end)
if(supports)
translate([pin_x, r, side * (wall / 2 + clearance)])
horicylinder(r = pin_r, z = r, h = 2 * wall + eps);
else
translate([pin_x, r, side * wall / 2])
vflip(side == -1)
cylinder(r1 = pin_r + pin_h / 2, r2 = pin_r - pin_h / 2, h = pin_h + eps);
}
// Cheek joint
translate([inner_x, 0, side * (s.y / 2 + wall) - 0.5])
cube([outer_end_x - inner_x, os.z, 1]);
}
// Roof, actually the floor when printed
// Roof, actually the floor when printed with supports
roof_x = start ? 0 : roof_x_normal;
roof_end = end ? s.x + 2 * r : s.x + r - twall - clearance;
translate([roof_x, -s.y / 2 - 0.5])
cube([roof_end - roof_x , s.y + 1, twall]);
translate([roof_x, -s.y / 2 - wall, 0]) {
cube([roof_end - roof_x, s.y + 2 * wall, twall]);
translate([0, -wall, 0])
cube([s.x - roof_x - clearance, s.y + 4 * wall, twall]);
}
translate([roof_x, -os.y / 2 + 0.5])
cube([s.x - clearance - roof_x, os.y - 1, twall]);
// Floor, actually the roof when printed
// Floor, actually the roof when printed with supports
floor_x = start ? 0 : 2 * r;
floor_end = end ? s.x + 2 * r : s.x + r;
translate([floor_x, -s.y / 2 - wall, os.z - bwall])
translate([floor_x, -s.y / 2 - wall, os.z - bwall]) {
cube([floor_end - floor_x, s.y + 2 * wall, bwall]);
translate([floor_x, -os.y / 2 + 0.5, os.z - bwall])
cube([s.x - floor_x - clearance, os.y -1, bwall]);
translate([0, -wall, 0])
cube([s.x - floor_x - clearance, s.y + 4 * wall, bwall]);
}
if(start || end) {
drag_chain_screw_positions(type, end)
@@ -223,16 +248,16 @@ module drag_chain_link(type, start = false, end = false, check_kids = true) { //
}
children();
}
}
} // end union
if(start || end)
translate_z(-eps)
drag_chain_screw_positions(type, end)
rotate($a)
poly_cylinder(r = screw_clearance_radius(drag_chain_screw(type)), h = os.z + 2 * eps, center = false);
} // end difference
}
if(show_supports() && !end) {
if(supports && show_supports() && !end) {
for(side = [-1, 1]) {
w = 2.1 * extrusion_width;
translate([s.x + r + cam_x - w / 2, side * (s.y / 2 + wall / 2), twall / 2])
@@ -255,16 +280,15 @@ module _drag_chain_assembly(type, pos = 0, render = false) {
s = drag_chain_size(type);
x = (1 + exploded()) * s.x;
r = drag_chain_radius(type) * x / s.x;
travel = drag_chain_travel(type);
links = ceil(travel / s.x);
actual_travel = links * s.x;
links = drag_chain_links(type);
actual_travel = (links - 4) * s.x;
z = drag_chain_outer_size(type).z;
zb = z / 2; // z of bottom track
c = [actual_travel / 2 + pos / 2, 0, r + zb]; // centre of bend
points = [ // Calculate list of hinge points
for(i = 0, p = [0, 0, z / 2 + 2 * r]; i < links + 5;
for(i = 0, p = [0, 0, z / 2 + 2 * r]; i < links + 1;
i = i + 1,
dx = p.z > c.z ? x : -x,
p = max(p.x + dx, p.x) <= c.x ? p + [dx, 0, 0] // Straight sections
@@ -277,11 +301,12 @@ module _drag_chain_assembly(type, pos = 0, render = false) {
module link(n) // Position and colour link with origin at the hinge hole
translate([-z / 2, 0, -z / 2]) {
stl_colour(n < 0 || n == npoints - 1 ? pp3_colour : n % 2 ? pp1_colour : pp2_colour)
render_if(render)
drag_chain_link(type, start = n == -1, end = n == npoints - 1, check_kids = false)
let($fasteners = 0)
children();
vflip(!drag_chain_supports(type))
stl_colour(n < 0 || n == npoints - 1 ? pp3_colour : n % 2 ? pp1_colour : pp2_colour)
render_if(render)
drag_chain_link(type, start = n == -1, end = n == npoints - 1, check_kids = false)
let($fasteners = 0)
children();
let($fasteners = 1) children();
}

View File

@@ -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() {

View File

@@ -71,41 +71,42 @@ module fixing_block_h_hole_2D(screw = def_screw) //! Position 2D child on the ho
children();
module fixing_block(screw = def_screw) { //! Generate the STL
stl(str("fixing_block_M", screw_radius(screw) * 20));
r = 1;
r = 1;
insert = screw_insert(screw);
corner_rad = insert_outer_d(insert) / 2 + wall;
fb_width = fixing_block_width(screw);
fb_height = fixing_block_height(screw);
fb_depth = fixing_block_depth(screw);
difference() {
union() {
linear_extrude(fb_height, convexity = 5)
difference() {
hull() {
for(side = [-1, 1]) {
translate([side * (fb_width / 2 - corner_rad), fb_depth - corner_rad])
circle4n(corner_rad);
stl(str("fixing_block_M", screw_radius(screw) * 20))
difference() {
union() {
linear_extrude(fb_height, convexity = 5)
difference() {
hull() {
for(side = [-1, 1]) {
translate([side * (fb_width / 2 - corner_rad), fb_depth - corner_rad])
circle4n(corner_rad);
translate([side * (fb_width / 2 - r), r])
circle4n(r);
translate([side * (fb_width / 2 - r), r])
circle4n(r);
}
}
fixing_block_v_holes(screw)
poly_circle(screw_clearance_radius(screw));
}
fixing_block_v_holes(screw)
poly_circle(screw_clearance_radius(screw));
}
}
translate_z(fb_height)
fixing_block_v_holes(screw)
insert_hole(insert);
}
translate_z(fb_height)
fixing_block_v_holes(screw)
insert_hole(insert);
fixing_block_h_hole(screw)
insert_hole(insert, 10, true);
}
fixing_block_h_hole(screw)
insert_hole(insert, 10, true);
}
}
module fixing_block_assembly(screw = def_screw) pose([55, 180, 25], [0, 4.8, 4.8]) //! Printed part with the inserts inserted
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])

View File

@@ -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];
@@ -65,8 +65,6 @@ module hinge_screw_positions(type) { //! Place children at the screw positions
}
module hinge_male(type, female = false) { //! The half with the stationary pin
stl(str("hinge_", female ? "fe": "", "male_", type[0]));
r = hinge_radius(type);
w = hinge_width(type);
t = hinge_thickness(type);
@@ -75,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);
@@ -85,37 +83,40 @@ module hinge_male(type, female = false) { //! The half with the stationary
teardrop_r = kr / cos(22.5); // The corner on the teardrop
inset = sqrt(sqr(teardrop_r + gap) - sqr(kr - t)) - kr;
linear_extrude(t)
difference() {
hull() {
for(side = [-1, 1])
translate([side * (w / 2 - r), hinge_depth(type) - r])
circle4n(r);
stl(str("hinge_", female ? "fe": "", "male_", type[0]))
union() {
linear_extrude(t)
difference() {
hull() {
for(side = [-1, 1])
translate([side * (w / 2 - r), hinge_depth(type) - r])
circle4n(r);
translate([-w / 2, inset])
square([w, eps]);
}
hinge_screw_positions(type)
poly_circle(screw_clearance_radius(hinge_screw(type)));
translate([-w / 2, inset])
square([w, eps]);
}
hinge_screw_positions(type)
poly_circle(screw_clearance_radius(hinge_screw(type)));
}
pitch = mw + gap + fw + gap;
dir = female ? -1 : 1;
translate([0, -kr, kr])
rotate([90, 0, -90])
for(z = [0 : (female ? fn : mn) - 1])
translate_z(-dir * w / 2 + z * dir * pitch + (female ? -fw - mw - gap : 0))
linear_extrude(female ? fw : mw)
difference() {
hull() {
rotate(180)
teardrop(r = kr, h = 0);
translate([-kr - 1, -kr])
square(1);
}
teardrop_plus(r = pr + (female ? gap : 0), h = 0);
}
}
pitch = mw + gap + fw + gap;
dir = female ? -1 : 1;
translate([0, -kr, kr])
rotate([90, 0, -90])
for(z = [0 : (female ? fn : mn) - 1])
translate_z(-dir * w / 2 + z * dir * pitch + (female ? -fw - mw - gap : 0))
linear_extrude(female ? fw : mw)
difference() {
hull() {
rotate(180)
teardrop(r = kr, h = 0);
translate([-kr - 1, -kr])
square(1);
}
teardrop_plus(r = pr + (female ? gap : 0), h = 0);
}
}
module hinge_female(type) hinge_male(type, true);

View File

@@ -39,7 +39,6 @@ function foot_screw(type = foot) = type[4]; //! Screw type
function foot_slant(type = foot) = type[5]; //! Taper angle
module foot(type = foot) { //! Generate STL
stl("foot");
h = foot_height(type);
t = foot_thickness(type);
r1 = washer_radius(screw_washer(foot_screw(type)));
@@ -47,38 +46,40 @@ module foot(type = foot) { //! Generate STL
r2 = r3 - h * tan(foot_slant(type));
r = foot_rad(type);
union() {
rotate_extrude(convexity = 3) {
hull() {
translate([r1, 0])
square([r3 - r1, eps]);
stl("foot")
union() {
rotate_extrude(convexity = 3) {
hull() {
translate([r1, 0])
square([r3 - r1, eps]);
for(x = [r1 + r, r2 - r])
translate([x, h - r])
circle4n(r);
for(x = [r1 + r, r2 - r])
translate([x, h - r])
circle4n(r);
}
}
linear_extrude(t)
difference() {
circle(r1 + eps);
poly_circle( screw_clearance_radius(foot_screw(type)));
}
}
linear_extrude(t)
difference() {
circle(r1 + eps);
poly_circle( screw_clearance_radius(foot_screw(type)));
}
}
}
module foot_assembly(t = 0, type = foot, flip = false) { //! Assembly with fasteners in place for specified sheet thickness
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);
translate_z(-squeeze)
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,13 +88,18 @@ 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
stl("insert_foot");
h = foot_height(type);
r3 = foot_diameter(type) / 2;
r2 = r3 - h * tan(foot_slant(type));
@@ -103,30 +109,31 @@ module insert_foot(type = insert_foot) { //! Generate STL for foot with insert
h2 = insert_hole_length(insert);
r4 = insert_hole_radius(insert);
r5 = r4 + 1;
union() {
rotate_extrude() {
union() {
hull() {
translate([r5, 0]) {
square([r3 - r5, eps]);
square([eps, h]);
}
stl("insert_foot")
union() {
rotate_extrude() {
union() {
hull() {
translate([r5, 0]) {
square([r3 - r5, eps]);
square([eps, h]);
}
translate([r2 - r, h - r])
circle4n(r);
translate([r2 - r, h - r])
circle4n(r);
}
}
}
linear_extrude(h2 + eps)
difference() {
circle(r5 + eps);
poly_circle(r4);
}
translate_z(h2)
cylinder(r = r5 + eps, h = h - h2);
}
linear_extrude(h2 + eps)
difference() {
circle(r5 + eps);
poly_circle(r4);
}
translate_z(h2)
cylinder(r = r5 + eps, h = h - h2);
}
}
//
//! Place the insert in the bottom of the foot and push home with a soldering iron with a conical bit heated to 200&deg;C.

View File

@@ -46,8 +46,6 @@ module handle_holes(h = 100) //! Drills holes for the screws
drill(screw_clearance_radius(screw), h);
module handle_stl() { //! generate the STL
stl("handle");
module end(end)
translate([end * pitch / 2, 0])
rotate_extrude()
@@ -59,28 +57,30 @@ module handle_stl() { //! generate the STL
square([dia / 2 + 1, dia + 1]);
}
translate_z(dia / 2)
union() {
hull() {
end(-1);
stl("handle")
translate_z(dia / 2)
union() {
hull() {
end(-1);
end(1);
}
handle_screw_positions()
render() difference() {
h = height + dia / 2;
cylinder(d = dia, h = h);
translate_z(h)
insert_hole(insert, 6);
end(1);
}
}
handle_screw_positions()
render() difference() {
h = height + dia / 2;
cylinder(d = dia, h = h);
translate_z(h)
insert_hole(insert, 6);
}
}
}
//
//! Place inserts in the bottom of the posts and push them home with a soldering iron with a conical bit heated to 200&deg;C.
//
module handle_assembly() pose([225, 0, 150], [0, 0, 14]) //! Printed part with inserts in place
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();

171
printed/knob.scad Normal file
View File

@@ -0,0 +1,171 @@
//
// NopSCADlib Copyright Chris Palmer 221
// 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/>.
//
//
//! Parametric knobs for potentiometers and encoders.
//!
//! A knob can be constructed by specififying all the parameters or the potentiometer can be specified to customise it for its shaft with a recess to clear the nut, washer and thread.
//! An optional skirt and / or a pointer can be specified.
//!
//! The STL includes a support membrane that needs to be cut out and a thread needs to be tapped for the grub screw.
//
include <../core.scad>
use <../utils/hanging_hole.scad>
use <../utils/rounded_polygon.scad>
use <../vitamins/potentiometer.scad>
clearance = 0.2;
function knob_name(type) = type[0]; //! Name for the stl maker
function knob_top_d(type) = type[1]; //! Diameter at the top
function knob_bot_d(type) = type[2]; //! Diameter at the bottom
function knob_height(type) = type[3]; //! Height
function knob_corner_r(type) = type[4]; //! Rounded top corner
function knob_shaft_d(type) = type[5]; //! Shaft diameter
function knob_shaft_len(type)= type[6]; //! Shaft length
function knob_flat_d(type) = type[7]; //! The shaft diameter at the flat
function knob_flat_h(type) = type[8]; //! The length of the flat
function knob_screw(type) = type[9]; //! The grub screw type
function knob_skirt(type) = type[10]; //! Skirt diameter and thickness
function knob_recess(type) = type[11]; //! Recess diameter and thickness to clear nut and thread, diameter, nut height, thread height
function knob_pointer(type) = type[12]; //! Pointer outside radius, [point width, back width] and height height
function knob(name = "knob", top_d = 12, bot_d = 15, height = 18, shaft_length, skirt = [20, 2], pointer = false, corner_r = 2, screw = M3_grub_screw, shaft_d, flat_d, flat_h, recess) = //! Constructor
[
name, top_d, bot_d, height, corner_r, shaft_d, shaft_length, flat_d, flat_h, screw, skirt, recess, pointer
];
function knob_for_pot(pot, thickness, z = 1, washer = true, top_d = 12, bot_d = 15, height = 0, shaft_length = undef, skirt = [20, 2], pointer = false, corner_r = 2, screw = M3_grub_screw) = //! Construct a knob to fit specified pot
let(s = pot_shaft(pot),
washer = washer && pot_washer(pot) ? pot_washer(pot) : [0, 0],
nut = pot_nut(pot) ? pot_nut(pot) : [pot_thread_d(pot) * cos(30), pot_thread_h(pot) - thickness],
shaft_length = is_undef(shaft_length) ? s.z : min(shaft_length, s.z),
h = round_to_layer(shaft_length + pot_thread_h(pot) - thickness - z),
height = max(height, h + 1),
recess = [(z > washer.y ? nut.x / cos(30) : washer.x) + 0.4, round_to_layer(nut.y + washer.y - z + layer_height), round_to_layer(pot_thread_h(pot) - z - thickness + 2 * layer_height)],
flat_d = s.y + 0.06,
flat_h = min(s[3], shaft_length)
)
knob(name = str(pot[0], "_knob"),
top_d = top_d,
bot_d = bot_d,
height = height,
corner_r = corner_r,
screw = screw,
skirt = skirt,
pointer = pointer,
shaft_d = s.x,
shaft_length = h,
flat_d = flat_d,
flat_h = flat_h,
recess = recess);
function knob_screw_z(type) = knob_shaft_len(type) - knob_flat_h(type) / 2;
module knob(type, supports = true) { //! Generate the STL for a knob
r_top = knob_top_d(type) / 2;
r_bot = knob_bot_d(type) / 2;
h = knob_height(type);
r = knob_corner_r(type);
screw = knob_screw(type);
sr = knob_shaft_d(type) / 2 + (screw ? clearance : 0);
top_wall = h - knob_shaft_len(type);
fr = knob_flat_d(type) - sr + 2 * clearance;
fh = knob_flat_h(type);
skirt = knob_skirt(type);
recess = knob_recess(type);
pointer = knob_pointer(type);
stl(knob_name(type))
{
difference() {
union() {
rotate_extrude() {
rounded_polygon([
[0, h, 0],
[r_top - r, h - r, r],
[r_bot, 0, 0],
[0, 0, 0],
]);
if(skirt)
square([skirt.x / 2, skirt.y]);
}
if(pointer)
linear_extrude(pointer.z)
rotate(-90)
hull() {
translate([pointer.x, 0])
square([eps, pointer.y[0]], center = true);
translate([r_bot, 0])
square([eps, pointer.y[1]], center = true);
}
}
shaft_z = recess ? recess.z + (supports ? layer_height : -eps) : -eps;
translate_z(shaft_z) {
h = h - top_wall - shaft_z;
linear_extrude(h)
difference() {
poly_circle(sr);
if(fr > 0)
translate([-sr, fr])
square([2 * sr, sr]);
}
if(h > fh)
poly_cylinder(sr, round_to_layer(h - fh), center = false);
}
if(recess)
translate_z(-eps)
hull() {
poly_cylinder(r = recess.x / 2, h = recess.y + eps, center = false);
linear_extrude(recess.z + eps)
offset(min(-(recess.z - recess.y), 0))
poly_circle(recess.x / 2);
}
if(screw)
translate_z(knob_screw_z(type))
rotate([90, 0, 180])
teardrop_plus(r = screw_pilot_hole(screw), h = max(r_top, r_bot) + eps, center = false);
}
}
}
//! Knob with grub screw in place
module knob_assembly(type) explode(40, explode_children = true) { //! Assembly with the grub screw in place
sr = knob_shaft_d(type) / 2;
fr = knob_flat_d(type) < sr ? knob_flat_d(type) - sr : sr;
r_top = knob_top_d(type) / 2;
r_bot = knob_bot_d(type) / 2;
screw_length = screw_shorter_than(min(r_top, r_bot) - fr);
screw = knob_screw(type);
stl_colour(pp1_colour) render() knob(type, supports = false);
if(screw)
translate([0, (fr + screw_length), knob_screw_z(type)])
rotate([90, 0, 180])
screw(screw, screw_length);
}

View File

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

154
printed/pocket_handle.scad Normal file
View File

@@ -0,0 +1,154 @@
//
// NopSCADlib Copyright Chris Palmer 2021
// nop.head@gmail.com
// hydraraptor.blogspot.com
//
// This file is part of NopSCADlib.
//
// NopSCADlib is free software: you can redistribute it and/or modify it under the terms of the
// GNU General Public License as published by the Free Software Foundation, either version 3 of
// the License, or (at your option) any later version.
//
// NopSCADlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along with NopSCADlib.
// If not, see <https://www.gnu.org/licenses/>.
//
//
//! Customisable pocket handle
//
include <../core.scad>
function pocket_handle(hand_size = [90, 40, 40], slant = 35, screw = M3_cs_cap_screw, panel_t = 3, wall = 4, rad = 4) = //! Construct a pocket_handle property list
[hand_size, slant, screw, panel_t, wall, rad];
function pocket_handle_hand_size(type) = type[0]; //! Size of the hole for the fingers
function pocket_handle_slant(type) = type[1]; //! Upward slant of the hand hole
function pocket_handle_screw(type) = type[2]; //! Screw type, can be countersunk or not
function pocket_handle_panel_t(type) = type[3]; //! Thickness of the panel it is mounted in
function pocket_handle_wall(type) = type[4]; //! Wall thickness
function pocket_handle_rad(type) = type[5]; //! Min corner rad
function pocket_handle_flange(type) = //! Size of the flange
let(w = pocket_handle_wall(type),
f = washer_diameter(screw_washer(pocket_handle_screw(type))) + 2 + w,
s = pocket_handle_hand_size(type))
[s.x + 2 * f, s.y + 2 * f, w];
module pocket_handle_hole_positions(type) { //! Place children at screw hole positions
f = pocket_handle_flange(type);
h = pocket_handle_hand_size(type);
x_pitch = (f.x + h.x) / 4;
y_pitch = (f.y + h.y) / 4;
for(x = [-1, 1], y = [-1, 1])
translate([x * x_pitch, y * y_pitch])
children();
}
module pocket_handle_holes(type, h = 0) { //! Panel cutout and screw holes
hand = pocket_handle_hand_size(type);
w = pocket_handle_wall(type);
slot = [hand.x + 2 * w, hand.y + 2 * w];
t = pocket_handle_panel_t(type);
clearance = norm([slot.y, t]) - slot.y + 0.2; // has to be enough clearance for the diagonal to swing it in
extrude_if(h) {
pocket_handle_hole_positions(type)
drill(screw_clearance_radius(pocket_handle_screw(type)), 0);
rounded_square([slot.x + clearance, slot.y + clearance], pocket_handle_rad(type) + w + clearance / 2);
}
}
module pocket_handle(type) { //! Generate STL for pocket_handle
f = pocket_handle_flange(type);
r = pocket_handle_rad(type);
s = pocket_handle_slant(type);
o = f.z * tan(s);
h = pocket_handle_hand_size(type);
t = pocket_handle_panel_t(type);
w = pocket_handle_wall(type);
screw = pocket_handle_screw(type) ;
stl("pocket_handle")
union() {
difference() {
hull() {
rounded_rectangle(f, r);
translate_z(f.z - eps)
rounded_rectangle([f.x + 2 * o, f.y + 2 * o, eps], r + o);
}
hull() {
rounded_rectangle([h.x, h.y, f.z + eps], r);
translate_z(-eps)
rounded_rectangle([h.x + 2 * o, h.y + 2 * o, eps], r + o);
}
pocket_handle_hole_positions(type) {
if(screw_head_height(screw))
translate_z(-eps)
poly_cylinder(r = screw_clearance_radius(screw), h = f.z + 2 * eps, center = false);
else
screw_polysink(screw, h = 2 * f.z + eps, alt = true);
}
}
translate_z(f.z)
linear_extrude(t)
difference() {
rounded_square([h.x + 2 * w, h.y + 2 * w], r + w);
rounded_square([h.x, h.y], r);
}
translate_z(f.z + t)
difference() {
height = h.z - f.z - t;
hull() {
rounded_rectangle([h.x + 2 * w, h.y + 2 * w, eps], r + w);
translate((height + w) * [0, sin(s), cos(s)])
rounded_rectangle([h.x + 2 * w, h.y + 2 * w, eps], r + w);
}
hull() {
translate_z(-eps)
rounded_rectangle([h.x, h.y, eps], r);
translate(height * [0, sin(s), cos(s)])
rounded_rectangle([h.x, h.y, eps], r);
}
}
}
}
module pocket_handle_assembly(type) { //! Assembly with fasteners in place
f = pocket_handle_flange(type);
screw = pocket_handle_screw(type);
nut = screw_nut(screw);
t = pocket_handle_panel_t(type);
washers = screw_head_height(screw) ? 2 : 1;
screw_length = screw_length(screw, f.z + t, washers, nyloc = true);
translate_z(f.z + t / 2) hflip() {
stl_colour(pp1_colour)
pocket_handle(type);
pocket_handle_hole_positions(type) {
translate_z(f.z + t)
explode(15, true)
nut_and_washer(nut, true);
vflip()
if(washers == 2)
screw_and_washer(screw, screw_length);
else
screw(screw, screw_length);
}
}
}

View File

@@ -22,7 +22,7 @@
//!
//! Add solvent or glue to make a permanent fixture.
//
include <../core.scad>
include <../utils/core/core.scad>
interference = 0.0;

View File

@@ -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>
@@ -129,28 +131,27 @@ module pbox_outer_shape(type) //! 2D outer shape of the box
offset(pbox_wall(type) / 2) pbox_mid_shape(type);
module pbox_base(type) { //! Generate the STL for the base
stl(str(pbox_name(type),"_base"));
t = pbox_base(type);
difference() {
union() {
linear_extrude(t)
offset(base_outset - 0.2)
pbox_inner_shape(type);
if($children > 0)
children(0);
stl(str(pbox_name(type),"_base"))
difference() {
union() {
linear_extrude(t)
offset(base_outset - 0.2)
pbox_inner_shape(type);
if($children > 0)
children(0);
}
pbox_screw_positions(type)
poly_cylinder(r = screw_clearance_radius(pbox_screw(type)), h = 2 * t + eps, center = true);
if($children > 1)
children(1);
}
pbox_screw_positions(type)
poly_cylinder(r = screw_clearance_radius(pbox_screw(type)), h = 2 * t + eps, center = true);
if($children > 1)
children(1);
}
}
module pbox(type) { //! Generate the STL for the main case
stl(pbox_name(type));
height = pbox_height(type);
total_height = pbox_total_height(type);
top_thickness = pbox_top(type);
@@ -159,60 +160,61 @@ module pbox(type) { //! Generate the STL for the main case
ledge_inset = base_outset - base_overlap;
ledge_h = pbox_base(type) ? (ledge_outset - ledge_inset) * 2 : 0;
difference() {
union() {
linear_extrude(total_height)
pbox_outer_shape(type);
if($children > 2)
children(2);
}
stl(pbox_name(type))
difference() {
translate_z(top_thickness)
union() {
linear_extrude(height + eps)
offset(-wall / 2) pbox_mid_shape(type);
union() {
linear_extrude(total_height)
pbox_outer_shape(type);
translate_z(height) // Recess for the base
linear_extrude(total_height - height)
offset(base_outset)
pbox_inner_shape(type);
}
// Ledge to support the lid
if(ledge_h)
translate_z(top_thickness + height - ledge_h)
difference() {
rounded_rectangle([pbox_width(type) + 2 * outset, pbox_depth(type) + 2 * outset, ledge_h], 1, center = false);
if($children > 2)
children(2);
}
difference() {
translate_z(top_thickness)
union() {
linear_extrude(height + eps)
offset(-wall / 2) pbox_mid_shape(type);
hull() {
linear_extrude(ledge_h + eps)
offset(ledge_inset)
translate_z(height) // Recess for the base
linear_extrude(total_height - height)
offset(base_outset)
pbox_inner_shape(type);
linear_extrude(eps)
offset(ledge_outset)
pbox_inner_shape(type);
}
pbox_screw_positions(type)
insert_hole(pbox_insert(type));
}
// Ledge to support the lid
if(ledge_h)
translate_z(top_thickness + height - ledge_h)
difference() {
rounded_rectangle([pbox_width(type) + 2 * outset, pbox_depth(type) + 2 * outset, ledge_h], 1);
// Corner lugs for inserts
outset = wall + pbox_ridges(type).y;
or = pbox_radius(type) + outset;
inset = pbox_screw_inset(type) + outset;
br = insert_boss_radius(pbox_insert(type), wall);
ext = sqrt(2) * inset - or * (sqrt(2) - 1) - br;
translate_z(height + top_thickness)
pbox_screw_positions(type)
insert_lug(pbox_insert(type), wall, counter_bore = 0, extension = ext, corner_r = or);
hull() {
linear_extrude(ledge_h + eps)
offset(ledge_inset)
pbox_inner_shape(type);
if($children > 0)
children(0);
linear_extrude(eps)
offset(ledge_outset)
pbox_inner_shape(type);
}
pbox_screw_positions(type)
insert_hole(pbox_insert(type));
}
// Corner lugs for inserts
outset = wall + pbox_ridges(type).y;
or = pbox_radius(type) + outset;
inset = pbox_screw_inset(type) + outset;
br = insert_boss_radius(pbox_insert(type), wall);
ext = sqrt(2) * inset - or * (sqrt(2) - 1) - br;
translate_z(height + top_thickness)
pbox_screw_positions(type)
insert_lug(pbox_insert(type), wall, counter_bore = 0, extension = ext, corner_r = or);
if($children > 0)
children(0);
}
if($children > 1)
children(1);
}
if($children > 1)
children(1);
}
}
module pbox_inserts(type) //! Place the inserts for the base screws

View File

@@ -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]];
@@ -93,7 +93,6 @@ module printed_pulley(type) { //! Draw a printable pulley
or = pulley_od(type) / 2;
screw_z = pulley_screw_z(type);
stl(str("printed_pulley_", type[0]));
module core() {
translate_z(pulley_hub_length(type) + ft)
@@ -129,54 +128,55 @@ module printed_pulley(type) { //! Draw a printable pulley
circle(d = pulley_bore(type));
}
translate_z(printed_pulley_inverted(type) ? - hl : 0) {
// hub
if(hl)
translate_z(printed_pulley_inverted(type) ? hl + w + 2 * ft : 0)
if(screw_z && screw_z < hl)
render()
difference() {
hub();
stl(str("printed_pulley_", type[0]))
translate_z(printed_pulley_inverted(type) ? - hl : 0) {
// hub
if(hl)
translate_z(printed_pulley_inverted(type) ? hl + w + 2 * ft : 0)
if(screw_z && screw_z < hl)
render()
difference() {
hub();
screw_holes();
}
else
hub();
// bottom flange
translate_z(hl)
linear_extrude(ft)
difference() {
circle(d = pulley_flange_dia(type));
circle(d = pulley_bore(type));
}
// top flange
translate_z(hl + ft + w) {
// inner part, supported by core
linear_extrude(ft)
difference() {
circle(r = or);
circle(d = pulley_bore(type));
}
// outer part at 45 degrees for printing
rotate_extrude()
translate([or - eps, ft])
vflip()
right_triangle(ft, ft);
}
if(screw_z && screw_z > hl)
render()
difference() { // T5 pulleys have screws through the teeth
core();
translate_z(printed_pulley_inverted(type) ? pulley_height(type) + hl - 2 * screw_z : 0)
screw_holes();
}
}
else
hub();
// bottom flange
translate_z(hl)
linear_extrude(ft)
difference() {
circle(d = pulley_flange_dia(type));
circle(d = pulley_bore(type));
}
// top flange
translate_z(hl + ft + w) {
// inner part, supported by core
linear_extrude(ft)
difference() {
circle(r = or);
circle(d = pulley_bore(type));
}
// outer part at 45 degrees for printing
rotate_extrude()
translate([or - eps, ft])
vflip()
right_triangle(ft, ft);
}
if(screw_z && screw_z > hl)
render()
difference() { // T5 pulleys have screws through the teeth
core();
translate_z(printed_pulley_inverted(type) ? pulley_height(type) + hl - 2 * screw_z : 0)
screw_holes();
}
else
core();
}
}
}
module printed_pulley_assembly(type, colour = pp1_colour) //! Draw a printed pulley with its grub screws in place

View File

@@ -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);
@@ -79,8 +80,6 @@ module psu_shroud_holes(type, cable_d, cables = 1) {
}
module psu_shroud(type, cable_d, name, cables = 1) { //! Generate the STL file for a specified ssr and cable
stl(str("psu_shroud_", name));
extent = psu_shroud_extent(type);
depth = psu_shroud_depth(type);
width = psu_shroud_width(type);
@@ -109,38 +108,40 @@ module psu_shroud(type, cable_d, name, cables = 1) { //! Generate the STL file f
}
}
// base and sides
translate([centre_x, -centre_y]) {
rounded_rectangle([depth - eps, width - eps, top], rad, center = false);
stl(str("psu_shroud_", name)) {
// base and sides
translate([centre_x, -centre_y]) {
rounded_rectangle([depth - eps, width - eps, top], rad);
linear_extrude(height)
difference() {
linear_extrude(height)
difference() {
shape();
translate([depth / 2, width / 2 - 5])
square([2 * (depth - extent + terminal_clearance), 10], center = true);
}
linear_extrude(height - terminal_block_height(tb) - psu_terminal_block_z(type) - terminal_clearance)
shape();
translate([depth / 2, width / 2 - 5])
square([2 * (depth - extent + terminal_clearance), 10], center = true);
}
linear_extrude(height - terminal_block_height(tb) - psu_terminal_block_z(type) - terminal_clearance)
shape();
}
// cable slots
for(i = [0 : 1 : cables - 1])
translate([centre_x - depth / 2 + wall / 2, -centre_y + (i - cables / 2 + 0.5) * psu_shroud_cable_pitch(cable_d), height / 2])
rotate([90, 0, 90])
linear_extrude(wall, center = true)
difference() {
square([cable_d + eps, height], center = true);
// cable slots
for(i = [0 : 1 : cables - 1])
translate([centre_x - depth / 2 + wall / 2, -centre_y + (i - cables / 2 + 0.5) * psu_shroud_cable_pitch(cable_d), height / 2])
rotate([90, 0, 90])
linear_extrude(wall, center = true)
difference() {
square([cable_d + eps, height], center = true);
translate([0, height / 2])
vertical_tearslot(h = 0, r = cable_d / 2, l = cable_d);
}
// insert lugs
mirror([0, 1, 0])
psu_shroud_hole_positions(type)
translate_z(height)
rotate($side * 90)
insert_lug(insert, wall, counter_bore);
}
translate([0, height / 2])
vertical_tearslot(h = 0, r = cable_d / 2, l = cable_d);
}
// insert lugs
mirror([0, 1, 0])
psu_shroud_hole_positions(type)
translate_z(height)
rotate($side * 90)
insert_lug(insert, wall, counter_bore);
}
}
module psu_shroud_assembly(type, cable_d, name, cables = 1) //! The printed parts with inserts fitted
assembly(str("PSU_shroud_", name), ngb = true) {
@@ -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);

View File

@@ -47,7 +47,6 @@ module ribbon_clamp_holes(ways, h = 20, screw = screw) //! Drill screw holes
module ribbon_clamp(ways, screw = screw) { //! Generate STL for given number of ways
screw_d = screw_radius(screw) * 2;
stl(str("ribbon_clamp_", ways, screw_d != 3 ? str("_", screw_d) : ""));
pitch = ribbon_clamp_hole_pitch(ways, screw);
d = ribbon_clamp_width(screw);
@@ -55,34 +54,36 @@ module ribbon_clamp(ways, screw = screw) { //! Generate STL for given number of
t = round_to_layer(ribbon_clamp_slot_depth() + wall);
insert = screw_insert(screw);
difference() {
union() {
hull() {
translate_z(h - t / 2)
cube([ribbon_clamp_hole_pitch(ways, screw), d, t], center = true);
stl(str("ribbon_clamp_", ways, screw_d != 3 ? str("_", screw_d) : ""))
difference() {
union() {
hull() {
translate_z(h - t / 2)
cube([ribbon_clamp_hole_pitch(ways, screw), d, t], center = true);
translate_z(1)
cube([pitch, max(wall, d - 2 * (h - t)), 2], center = true);
translate_z(1)
cube([pitch, max(wall, d - 2 * (h - t)), 2], center = true);
}
ribbon_clamp_hole_positions(ways, screw, -1)
cylinder(d = d, h = h);
ribbon_clamp_hole_positions(ways, screw, 1)
cylinder(d = d, h = h);
}
ribbon_clamp_hole_positions(ways, screw, -1)
cylinder(d = d, h = h);
ribbon_clamp_hole_positions(ways, screw, 1)
cylinder(d = d, h = h);
}
translate_z(h)
cube([ribbon_clamp_slot(ways), d + 1, ribbon_clamp_slot_depth() * 2], center = true);
ribbon_clamp_hole_positions(ways, screw)
translate_z(h)
rotate(22.5)
insert_hole(insert, ribbon_clamp_screw_depth(screw) - insert_length(insert));
}
cube([ribbon_clamp_slot(ways), d + 1, ribbon_clamp_slot_depth() * 2], center = true);
ribbon_clamp_hole_positions(ways, screw)
translate_z(h)
rotate(22.5)
insert_hole(insert, ribbon_clamp_screw_depth(screw) - insert_length(insert));
}
}
module ribbon_clamp_assembly(ways, screw = screw) pose([55, 180, 25]) //! Printed part with inserts in place
assembly(let(screw_d = screw_radius(screw) * 2)str("ribbon_clamp_", ways, screw_d != 3 ? str("_", screw_d) : ""), 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);

View File

@@ -34,27 +34,26 @@ knob_height = knob_stem_h + knob_thickness;
function knob_height() = knob_height;
module screw_knob(screw) { //! Generate the STL for a knob to fit the specified hex screw
stl(str("screw_knob_M", screw_radius(screw) * 20));
knob_stem_r = nut_trap_radius(screw_nut(screw)) + knob_wall;
function wave(a) = knob_r + sin(a * knob_waves) * knob_wave;
union() {
render() difference() {
cylinder(r = knob_stem_r, h = knob_thickness + knob_stem_h);
stl(str("screw_knob_M", screw_radius(screw) * 20))
union() {
render() difference() {
cylinder(r = knob_stem_r, h = knob_thickness + knob_stem_h);
hanging_hole(knob_nut_trap_depth(screw), screw_clearance_radius(screw))
rotate(45)
circle(r = nut_trap_radius(screw_nut(screw)), $fn = 6);
}
linear_extrude(knob_thickness, convexity = 3)
difference() {
polygon(points = [for(a = [0 : 359]) [wave(a) * sin(a), wave(a) * cos(a)]]);
circle(knob_stem_r - eps);
hanging_hole(knob_nut_trap_depth(screw), screw_clearance_radius(screw))
rotate(45)
circle(r = nut_trap_radius(screw_nut(screw)), $fn = 6);
}
}
linear_extrude(knob_thickness, convexity = 3)
difference() {
polygon(points = [for(a = [0 : 359]) [wave(a) * sin(a), wave(a) * cos(a)]]);
circle(knob_stem_r - eps);
}
}
}
//! Place the screw through the printed part

View File

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

View File

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

View File

@@ -75,32 +75,29 @@ module strap_holes(length, type = strap, h = 100) //! The panel cut outs
strap_boss_shape(type);
module strap(length, type = strap) { //! Generate the STL for the rubber strap
stl("strap");
len = length - 2 * (wall + clearance);
w = strap_width(type);
linear_extrude(strap_thickness(type), convexity = 3)
difference() {
rounded_square([len, w], w / 2 - eps);
stl("strap")
linear_extrude(strap_thickness(type), convexity = 3)
difference() {
rounded_square([len, w], w / 2 - eps);
for(end = [-1, 1])
translate([end * (len / 2 - strap_min_width(type) - strap_boss_r(type) - clearance), 0])
rotate(end * 90 + 90)
hull() {
offset(clearance)
strap_boss_shape(type);
translate([strap_extension(type) / 2, 0])
for(end = [-1, 1])
translate([end * (len / 2 - strap_min_width(type) - strap_boss_r(type) - clearance), 0])
rotate(end * 90 + 90)
hull() {
offset(clearance)
strap_boss_shape(type);
}
}
translate([strap_extension(type) / 2, 0])
offset(clearance)
strap_boss_shape(type);
}
}
}
module strap_end(type = strap) { //! Generate the STL for end piece
stl("strap_end");
z1 = strap_height(type) - strap_thickness(type) - clearance;
z2 = strap_height(type) + strap_key(type);
r1 = strap_boss_r(type) - 1;
@@ -121,42 +118,43 @@ module strap_end(type = strap) { //! Generate the STL for end piece
circle(r1);
}
union() {
linear_extrude(z1)
with_hole()
outer();
translate_z(z1)
linear_extrude(strap_height(type) - z1)
difference() {
stl("strap_end")
union() {
linear_extrude(z1)
with_hole()
outer();
hull() {
translate([0, -strap_width(type) / 2 - clearance])
square([strap_boss_r(type) + overlap, strap_width(type) + 2 * clearance]);
translate_z(z1)
linear_extrude(strap_height(type) - z1)
difference() {
outer();
translate([-strap_extension(type) / 2, 0])
circle(d = strap_width(type) + 2 * clearance);
hull() {
translate([0, -strap_width(type) / 2 - clearance])
square([strap_boss_r(type) + overlap, strap_width(type) + 2 * clearance]);
translate([-strap_extension(type) / 2, 0])
circle(d = strap_width(type) + 2 * clearance);
}
}
}
linear_extrude(strap_height(type) - layer_height)
with_hole()
strap_boss_shape(type);
linear_extrude(strap_height(type) - layer_height)
with_hole()
strap_boss_shape(type);
linear_extrude(z2)
with_hole()
offset(cnc_bit_r)
offset(-step - cnc_bit_r)
strap_boss_shape(type);
linear_extrude(z2)
with_hole()
offset(cnc_bit_r)
offset(-step - cnc_bit_r)
strap_boss_shape(type);
render() difference() {
cylinder(r = r1 + eps, h = z2);
render() difference() {
cylinder(r = r1 + eps, h = z2);
translate_z(z2)
insert_hole(strap_insert(type), counterbore);
translate_z(z2)
insert_hole(strap_insert(type), counterbore);
}
}
}
}
//
//! * Place the insert into the hole and push home with a soldering iron with a tapered bit heated to 200&deg;C.

1221
readme.md

File diff suppressed because it is too large Load Diff

View File

@@ -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)

View File

@@ -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)

167
scripts/changelog.py Normal file
View File

@@ -0,0 +1,167 @@
#!/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):
comment = comment.replace('cnc_bit+_r', 'cnc_bit_r')
""" 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 chang.*log.*', 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())

View File

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

View File

@@ -28,7 +28,10 @@ from set_config import *
import time
import times
from deps import *
from tmpdir import *
import json
import shutil
from colorama import Fore, init
def bom_to_parts(bom_dir, part_type, assembly = None):
#
@@ -43,7 +46,7 @@ def bom_to_parts(bom_dir, part_type, assembly = None):
if words:
last_word = words[-1]
if last_word.endswith(suffix):
part_files.append(last_word[:-4] + '.' + part_type)
part_files.append(last_word[:-4] + '.' + part_type)
return part_files
def usage(t):
@@ -62,20 +65,29 @@ def make_parts(target, part_type, parts = None):
#
top_dir = set_config(target, lambda: usage(part_type))
target_dir = top_dir + part_type + 's'
deps_dir = top_dir + "deps"
deps_dir = target_dir + "/deps"
bom_dir = top_dir + "bom"
tmp_dir = mktmpdir(top_dir)
if not os.path.isdir(target_dir):
os.makedirs(target_dir)
if not os.path.isdir(deps_dir):
os.makedirs(deps_dir)
old_deps = top_dir + 'deps' #old location
if os.path.isdir(old_deps):
shutil.rmtree(old_deps)
times.read_times(target_dir)
#
# Decide which files to make
#
all_parts = bom_to_parts(bom_dir, part_type)
if parts:
targets = list(parts) #copy the list so we dont modify the list passed in
else:
targets = bom_to_parts(bom_dir, part_type)
targets = list(all_parts)
for file in os.listdir(target_dir):
if file.endswith('.' + part_type):
if not file in targets:
@@ -119,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)
@@ -144,10 +157,14 @@ def make_parts(target, part_type, parts = None):
with open(bounds_fname, 'w') as outfile:
json.dump(bounds_map, outfile, indent = 4)
#
# Remove tmp dir
#
rmtmpdir(tmp_dir)
#
# List the ones we didn't find
#
if targets:
for part in targets:
print("Could not find a module called", part[:-4] + module_suffix, "to make", part)
usage(part_type)
times.print_times()
times.print_times(all_parts)

View File

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

View File

@@ -25,19 +25,25 @@ from __future__ import print_function
import subprocess, sys
def run_list(args, silent = False, verbose = False):
cmd = ["openscad", "--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)

View File

@@ -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():

View File

@@ -26,8 +26,10 @@ import sys
import c14n_stl
from set_config import *
from deps import *
from shutil import copyfile
import shutil
import re
import time
import times
source_dirs = { "stl" : "platters", "dxf" : "panels" }
target_dirs = { "stl" : "printed", "dxf" : "routed" }
@@ -41,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,40 +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)
openscad.run("-D$bom=1", "-d", dname, "-o", part_file, src_file)
t = time.time()
openscad.run_list(["-D$bom=1"] + target_def + cwd_def + ["-d", dname, "-o", part_file, src_file])
if part_type == 'stl':
c14n_stl.canonicalise(part_file)
times.add_time(part, t)
log_name = 'openscad.log'
#
# Add the files on the BOM to the used list
#
with open(log_name) as file:
for line in file.readlines():
match = re.match(r'^ECHO: "~(.*?\.' + part_type + r').*"$', line)
if match:
used.append(match.group(1))
with open(uses_file, "wt") as file:
for part in used:
print(part, file = file)
else:
log_name = 'openscad.echo'
openscad.run_silent("-D$bom=1", "-o", log_name, src_file)
#
# Add the files on the BOM to the used list
#
with open(log_name) as file:
for line in file.readlines():
match = re.match(r'^ECHO: "~(.*?\.' + part_type + r').*"$', line)
if match:
used.append(match.group(1))
with open(uses_file, "rt") as file:
for line in file:
used.append(line[:-1])
all_used += used
copied = []
if all_sources:
#
# Copy files that are not included
#
for file in os.listdir(parts_dir):
if file.endswith('.' + part_type) and not file in used:
if file.endswith('.' + part_type) and not file in all_used:
src = parts_dir + '/' + file
dst = target_dir + '/' + file
if mtime(src) > mtime(dst):
print("Copying %s to %s" % (src, dst))
copyfile(src, dst)
shutil.copyfile(src, dst)
copied.append(file)
#
# Remove any cruft
@@ -109,3 +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)

View File

@@ -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. |

View File

@@ -30,6 +30,7 @@ from tests import do_cmd, update_image, colour_scheme, background
from deps import mtime
from colorama import init
import json
from tmpdir import *
def usage():
print("\nusage:\n\trender [target_config] - Render images of the stl and dxf files.");
@@ -40,6 +41,7 @@ def render(target, type):
# Make the target directory
#
top_dir = set_config(target, usage)
tmp_dir = mktmpdir(top_dir)
target_dir = top_dir + type + 's'
bom_dir = top_dir + 'bom'
if not os.path.isdir(target_dir):
@@ -80,7 +82,7 @@ def render(target, type):
# make a file to import the stl
#
if mtime(part_file) > mtime(png_name):
png_maker_name = "png.scad"
png_maker_name = tmp_dir + "/png.scad"
pp1 = [0, 146/255, 0]
colour = pp1
if part in colours:
@@ -88,15 +90,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()

View File

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

View File

@@ -34,6 +34,7 @@ import shutil
from deps import *
from blurb import *
from colorama import Fore
from tmpdir import *
w = 4096
h = w
@@ -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__':

View File

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

41
scripts/tmpdir.py Normal file
View 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)

View File

@@ -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,8 @@ 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):
for filename in os.listdir(dir):
@@ -182,33 +186,44 @@ def views(target, do_assemblies = None):
#
for ass in flat_bom:
if ass["name"] == real_name:
zoomed = ass['zoomed']
if not "blurb" in ass:
ass["blurb"] = blurb.scrape_module_blurb(lines[:line_no])
break
if not do_assemblies or real_name in do_assemblies:
#
# Run openscad on the created file
#
dname = deps_name(deps_dir, filename)
for explode in [0, 1]:
#
# Run openscad on the created file
# Generate png name
#
dname = deps_name(deps_dir, filename)
for explode in [0, 1]:
png_name = target_dir + '/' + real_name + '.png'
if not explode:
png_name = png_name.replace('_assembly', '_assembled')
png_name = target_dir + '/' + real_name + '.png'
if not explode:
png_name = png_name.replace('_assembly', '_assembled')
pngs.append(png_name)
if not do_assemblies or real_name in do_assemblies:
changed = check_deps(png_name, dname)
changed = times.check_have_time(changed, png_name)
changed = options.have_changed(changed, png_name)
tmp_name = 'tmp.png'
tmp_name = tmp_dir + '/' + real_name + '.png'
if changed:
print(changed)
#
# make a file to use the module
#
png_maker_name = 'png.scad'
png_maker_name = tmp_dir + '/png.scad'
with open(png_maker_name, "w") as f:
f.write("use <%s/%s>\n" % (dir, filename))
f.write("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_list(options.list() + ["-D$pose=1", "-D$explode=%d" % explode, colour_scheme, "--projection=p", "--imgsize=4096,4096", "--autocenter", "--viewall", "-d", dname, "-o", tmp_name, png_maker_name]);
target_def = ['-D$target="%s"' % target] if target else []
cwd_def = ['-D$cwd="%s"' % os.getcwd().replace('\\', '/')]
view_def = ['--viewall', '--autocenter'] if not (zoomed & (1 << explode)) else ['--camera=0,0,0,55,0,25,140']
openscad.run_list(["-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)
@@ -219,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
#
@@ -233,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):
@@ -403,16 +415,16 @@ def views(target, do_assemblies = None):
#
# Convert to HTML
#
html_name = 'readme.html'
html_name = top_dir + 'readme.html'
t = time.time()
with open(top_dir + html_name, "wt") as html_file:
with open(html_name, "wt") as html_file:
do_cmd(("python -m markdown -x tables -x sane_lists " + doc_name).split(), html_file)
times.add_time(top_dir + html_name, t)
times.print_times()
times.add_time(html_name, t)
times.print_times(pngs + [html_name])
#
# Make the printme.html by replacing empty spans that invisbly mark the page breaks by page break divs.
#
with open(top_dir + 'readme.html', 'rt') as src:
with open(html_name, 'rt') as src:
lines = src.readlines()
i = 0
@@ -430,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())

31
tests/7_segments.scad Normal file
View 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 <../utils/core/core.scad>
use <../utils/layout.scad>
include <../vitamins/7_segments.scad>
function digits(s) = 7_segment_digits(s) < 2 ? 2 : 1;
module 7_segments()
layout([for(s = 7_segments) 7_segment_size(s).x * digits(s)], 3) let(s = 7_segments[$i])
7_segment_digits(s, digits(s));
if($preview)
7_segments();

31
tests/BLDC_motors.scad Normal file
View 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();

View File

@@ -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;
@@ -43,31 +43,29 @@ module widget(thickness) {
}
}
module widgit_stl() {
stl("widget");
module widget_stl() {
stl("widget")
union() {
rounded_rectangle([30, 30, 3], 2, true);
union() {
rounded_rectangle([30, 30, 3], 2);
render() insert_boss(insert, height, 2.2);
}
render() insert_boss(insert, height, 2.2);
}
}
module widgit_dxf() {
dxf("widget");
module widget_dxf() {
dxf("widget")
difference() {
sheet_2D(sheet, 20, 20, 1);
difference() {
sheet_2D(sheet, 20, 20, 1);
drill(screw_clearance_radius(screw), 0);
}
drill(screw_clearance_radius(screw), 0);
}
}
//! * Push the insert into the base with a soldering iron heated to 200&deg;C
module widgit_base_assembly()
assembly("widgit_base") {
module widget_base_assembly()
assembly("widget_base") {
stl_colour(pp1_colour)
widgit_stl();
widget_stl();
translate_z(height)
insert(insert);
@@ -80,14 +78,14 @@ assembly("widget_top") {
widget(sheet_thickness(sheet));
render_2D_sheet(sheet) // Must be last because it is transparent
widgit_dxf();
widget_dxf();
}
//! * Screw the two assemblies together
module widgit_assembly()
assembly("wigdit") {
module widget_assembly()
assembly("widget") {
widgit_base_assembly(); // Note this is not exloded because it is sub-assembly
widget_base_assembly(); // Note this is not exloded because it is sub-assembly
translate_z(height) {
translate_z(sheet_thickness(sheet))
@@ -100,7 +98,7 @@ assembly("wigdit") {
}
module boms() {
widgit_assembly();
widget_assembly();
}
boms();

View File

@@ -16,7 +16,7 @@
// You should have received a copy of the GNU General Public License along with NopSCADlib.
// If not, see <https://www.gnu.org/licenses/>.
//
include <../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"]];

View File

@@ -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>

View File

@@ -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
[]

View File

@@ -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])

View File

@@ -16,20 +16,32 @@
// You should have received a copy of the GNU General Public License along with NopSCADlib.
// If not, see <https://www.gnu.org/licenses/>.
//
show_cutout = false;
include <../core.scad>
include <../vitamins/psus.scad>
use <../utils/layout.scad>
module psus()
layout([for(p = psus) psu_width(p)], 10) let(p = psus[$i])
layout([for(p = psus) atx_psu(p) ? psu_length(p) : psu_width(p)], 10) let(p = psus[$i])
rotate(atx_psu(p) ? 0 : 90) {
psu(p);
psu_screw_positions(p)
translate_z(3)
screw_and_washer(psu_screw(p), 8);
if(show_cutout && atx_psu(p))
#atx_psu_cutout(p);
}
if($preview)
if($preview) {
psus();
for(p = psus_not_shown)
hidden()
psu(p);
}

View File

@@ -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);

View File

@@ -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)

View File

@@ -16,7 +16,7 @@
// You should have received a copy of the GNU General Public License along with NopSCADlib.
// If not, see <https://www.gnu.org/licenses/>.
//
include <../core.scad>
include <../utils/core/core.scad>
include <../vitamins/ssrs.scad>
use <../utils/layout.scad>

View File

@@ -16,7 +16,7 @@
// You should have received a copy of the GNU General Public License along with NopSCADlib.
// If not, see <https://www.gnu.org/licenses/>.
//
include <../utils/core/core.scad>
use <../utils/layout.scad>
include <../vitamins/ball_bearings.scad>

View File

@@ -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>

View File

@@ -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)

View File

@@ -22,7 +22,7 @@ use <../utils/layout.scad>
include <../vitamins/blowers.scad>
module blowers()
layout([for(b = blowers) blower_width(b)], 10, true) let(b = blowers[$i]){
layout([for(b = blowers) blower_width(b)], 5, true) let(b = blowers[$i]){
screw = blower_screw(b);
h = blower_lug(b);

30
tests/box_sections.scad Normal file
View 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();

View File

@@ -16,7 +16,7 @@
// You should have received a copy of the GNU General Public License along with NopSCADlib.
// If not, see <https://www.gnu.org/licenses/>.
//
include <../core.scad>
include <../utils/core/core.scad>
use <../utils/layout.scad>
use <../printed/camera_housing.scad>

View File

@@ -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])

136
tests/core_xy.scad Normal file
View File

@@ -0,0 +1,136 @@
//
// 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);
pos = [100, 50];
coreXYPosBL = [0, 0, 0];
coreXYPosTR = [200, 150, 0];
separation = [0, coreXY_coincident_separation(coreXY_type).y, pulley_height(plain_idler) + washer_thickness(M3_washer)];
x_gap = 10;
plain_idler_offset = [10, 5];
upper_drive_pulley_offset = [40, 0];
lower_drive_pulley_offset = [0, 0];
coreXY_belts(coreXY_type,
pos,
coreXYPosBL,
coreXYPosTR,
separation,
x_gap,
plain_idler_offset,
upper_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) + plain_idler_offset)
translate([0, -upper_drive_pulley_offset.y, -pulley_offset(plain_idler)])
screw(M3_cap_screw, 20);
translate(coreXY_drive_toothed_idler_offset(coreXY_type))
translate([0, -upper_drive_pulley_offset.y, -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 + plain_idler_offset.y])
translate([0, -upper_drive_pulley_offset.y, -pulley_offset(plain_idler)])
screw(M3_cap_screw, 20);
translate([2*coreXY_drive_pulley_x_alignment(coreXY_type) + plain_idler_offset.x, coreXY_drive_toothed_idler_offset(coreXY_type).y])
translate([0, -upper_drive_pulley_offset.y, -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 - plain_idler_offset.x, coreXY_drive_plain_idler_offset(coreXY_type).y + plain_idler_offset.y])
translate([0, -lower_drive_pulley_offset.y, -pulley_offset(plain_idler)])
screw(M3_cap_screw, 20);
translate(coreXY_drive_toothed_idler_offset(coreXY_type))
translate([0, -lower_drive_pulley_offset.y, -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 + plain_idler_offset.y])
translate([0, -lower_drive_pulley_offset.y, -pulley_offset(plain_idler)])
screw(M3_cap_screw, 20);
translate([-2*coreXY_drive_pulley_x_alignment(coreXY_type) - plain_idler_offset.x, coreXY_drive_toothed_idler_offset(coreXY_type).y])
translate([0, -lower_drive_pulley_offset.y, -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 + (upper_drive_pulley_offset.x == 0 ? 0 : plain_idler_offset.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 - (lower_drive_pulley_offset.x == 0 ? 0 : plain_idler_offset.x), separation.y + coreXY_plain_idler_offset(coreXY_type).y, 0])
screw(M3_cap_screw, 20);
}
}
if ($preview)
coreXY_belts_test();

View File

@@ -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();

View File

@@ -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);

View File

@@ -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();

View File

@@ -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();

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