-
Notifications
You must be signed in to change notification settings - Fork 78
New content #7267
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
New content #7267
Changes from all commits
962609e
ec19b9b
5911df4
402de8c
fd3125e
2ddd546
4390788
bc6a8cc
a831dce
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
// Cable Gland | ||
// A cable gland is a mechanical fitting used to attach and secure the end of an electrical cable to equipment or an enclosure. It provides strain relief, sealing against environmental factors like dust and moisture, and can ensure earth continuity if required. | ||
|
||
// Set units | ||
@settings(defaultLengthUnit = mm) | ||
|
||
// Define parameters | ||
width = 40 | ||
length = 40 | ||
trim = 39 | ||
cableDiameter = 14 | ||
|
||
// Model a starting hexagon with a center securement hole for the cable diameter | ||
core = startSketchOn(XY) | ||
|> polygon(radius = width / 2, numSides = 6, center = [0, 0]) | ||
|> subtract2d(tool = circle(center = [0, 0], diameter = cableDiameter)) | ||
|> extrude(length) | ||
|
||
// Cut around the exterior to form the cable gland shape | ||
revolveCut = startSketchOn(YZ) | ||
|> startProfile(at = [cableDiameter / 2 + 5, -0.01]) | ||
|> angledLine(angle = 15, endAbsoluteX = trim / 2) | ||
|> yLine(length = length / 6) | ||
|> angledLine(angle = -15, endAbsoluteX = profileStartX(%)) | ||
|> yLine(length = length / 9) | ||
|> xLine(length = -0.9) | ||
|> yLine(length = length / 8) | ||
|> angledLine(angle = 15, endAbsoluteX = trim / 2) | ||
|> yLine(length = length / 6) | ||
|> angledLine(angle = -5, endAbsoluteX = cableDiameter / 2 + 2) | ||
|> yLine(endAbsolute = length + 0.1) | ||
|> xLine(endAbsolute = width / 1.75) | ||
|> yLine(endAbsolute = 0) | ||
|> line(endAbsolute = profileStart()) | ||
|> close() | ||
|> revolve(axis = Y) | ||
subtract([core], tools = [revolveCut]) | ||
// Assigning a material property to represent brass | ||
|> appearance(color = "#f2671c", metalness = 70, roughness = 30) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,165 @@ | ||
// Camshaft | ||
// A camshaft is a shaft with cams attached, used to convert rotational motion into reciprocating motion. In internal combustion engines, it's crucial for controlling the opening and closing of intake and exhaust valves at precise moments, ensuring proper timing for combustion. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess this is for some unfamiliar variety of American engine, but I can't make sense of this thing. Would it be for a pushrod V4? A nice way of parameterising firing order or even just crank journal layout is probably useful too There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
||
// Set units | ||
@settings(defaultLengthUnit = in) | ||
|
||
// Define shaft parameters | ||
valvesPerCylinder = 4 | ||
cylinderCount = 4 | ||
shaftDiameter = 0.97 | ||
supportBearingWidth = 0.45 | ||
|
||
// Define cam lobe parameters | ||
baseCircle = 1.34 | ||
lobeSeperation = 112 | ||
intakeCenterline = 108 | ||
intakeLift = 0.235 | ||
exhaustLift = 0.235 | ||
intakeDuration = 242 | ||
exhaustDuration = 246 | ||
camHeight = 0.522 | ||
camSpacing = 0.50 | ||
|
||
// Write a function to sketch a cam lobe profile given the specified parameters | ||
fn lobe(duration, lift) { | ||
camProfile = startSketchOn(offsetPlane(XY, offset = supportBearingWidth * 2)) | ||
|> startProfile(at = polar(angle = 90 + duration / 4, length = baseCircle / 2)) | ||
|> arc(interiorAbsolute = [0, -baseCircle / 2], endAbsolute = polar(angle = 90 - (duration / 4), length = baseCircle / 2), tag = $seg02) | ||
|> angledLine(angle = tangentToEnd(seg02), endAbsoluteY = baseCircle / 2 + lift, tag = $seg04) | ||
|> xLine(endAbsolute = 0, tag = $seg03) | ||
|> xLine(length = -segLen(seg03)) | ||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)], tag = $seg05) | ||
|> close() | ||
|> extrude(length = camHeight) | ||
|> fillet( | ||
radius = min([segLen(seg03), segLen(seg04)]) * 0.99, | ||
tags = [ | ||
getCommonEdge(faces = [seg04, seg03]), | ||
getCommonEdge(faces = [seg03, seg05]) | ||
], | ||
) | ||
|> rotate(yaw = intakeCenterline) | ||
|
||
return camProfile | ||
} | ||
|
||
// Create an intake and exhaust cam pair | ||
intake = lobe(duration = intakeDuration, lift = intakeLift) | ||
exhaust = lobe(duration = exhaustDuration, lift = exhaustLift) | ||
|> translate(z = camHeight + camSpacing) | ||
|> rotate(yaw = lobeSeperation) | ||
|
||
// Pattern the cam pair to represent the number of valves. Round odd number valves to the next highest even number | ||
fn valveCount(@i) { | ||
return { | ||
translate = [0, 0, i * (camHeight + camSpacing) * 2], | ||
rotation = { | ||
angle = lobeSeperation + 30 * i, | ||
// Rotate around the overall scene's origin. | ||
origin = 'global' | ||
} | ||
} | ||
} | ||
|
||
// Pattern the cam instances by the number of cylinders. Rotate each group to reflect the relative position of each piston | ||
fn cylinderPattern(@i) { | ||
return { | ||
translate = [ | ||
0, | ||
0, | ||
i * (2 * (camHeight + camSpacing) * round(valvesPerCylinder / 2) + supportBearingWidth) | ||
], | ||
rotation = { | ||
angle = 360 / cylinderCount * i, | ||
// Rotate around the overall scene's origin. | ||
origin = 'global' | ||
} | ||
} | ||
} | ||
|
||
// Call each pattern function in turn | ||
[intake, exhaust] | ||
|> patternTransform(instances = round(valvesPerCylinder / 2), transform = valveCount) | ||
|> patternTransform(instances = cylinderCount, transform = cylinderPattern) | ||
|
||
// Extrude a center connecting cylinder shaft through each cam position | ||
length = (2 * (camHeight + camSpacing) * round(valvesPerCylinder / 2) + supportBearingWidth) * cylinderCount + supportBearingWidth | ||
centerShaft = startSketchOn(XY) | ||
|> circle(center = [0, 0], diameter = shaftDiameter) | ||
|> extrude(length) | ||
|
||
// Attach a helical timing gear to the base of the camshaft | ||
fn helicalGear(nTeeth, module, pressureAngle, helixAngle, gearHeight) { | ||
// Calculate gear parameters | ||
pitchDiameter = module * nTeeth | ||
addendum = module | ||
deddendum = 1.25 * module | ||
baseDiameter = pitchDiameter * cos(pressureAngle) | ||
tipDiameter = pitchDiameter + 2 * module | ||
|
||
// Define a function to create a rotated gear sketch on an offset plane | ||
fn helicalGearSketch(@offsetHeight) { | ||
// Calculate the amount to rotate each planar sketch of the gear given the gear helix angle and total gear height | ||
helixCalc = acos(offsetHeight * tan(helixAngle) / (tipDiameter / 2)) | ||
|
||
// Using the gear parameters, sketch an involute tooth spanning from the base diameter to the tip diameter | ||
helicalGearSketch = startSketchOn(offsetPlane(XY, offset = offsetHeight)) | ||
|> startProfile(at = polar(angle = helixCalc, length = baseDiameter / 2)) | ||
|> involuteCircular( | ||
startRadius = baseDiameter / 2, | ||
endRadius = tipDiameter / 2, | ||
angle = helixCalc, | ||
tag = $seg01, | ||
) | ||
|> line(endAbsolute = polar(angle = 160 / nTeeth + helixCalc, length = tipDiameter / 2)) | ||
|> involuteCircular( | ||
startRadius = baseDiameter / 2, | ||
endRadius = tipDiameter / 2, | ||
angle = -(4 * atan(segEndY(seg01) / segEndX(seg01)) - (3 * helixCalc)), | ||
reverse = true, | ||
) | ||
|
||
// Position the end line of the sketch at the start of the next tooth | ||
|> line(endAbsolute = polar(angle = 360 / nTeeth + helixCalc, length = baseDiameter / 2)) | ||
|
||
// Pattern the sketch about the center by the specified number of teeth, then close the sketch | ||
|> patternCircular2d( | ||
%, | ||
instances = nTeeth, | ||
center = [0, 0], | ||
arcDegrees = 360, | ||
rotateDuplicates = true, | ||
) | ||
|> close() | ||
|> subtract2d(tool = circle(center = [0, 0], diameter = shaftDiameter)) | ||
return helicalGearSketch | ||
} | ||
|
||
// Draw a gear sketch on the base plane | ||
gearcamProfile = helicalGearSketch(0) | ||
|
||
// Draw a rotated gear sketch on a middle interstitial plane | ||
gearcenterShaft = helicalGearSketch(gearHeight / 2) | ||
|
||
// Draw a rotated gear sketch at the gear height offset plane | ||
gearSketch003 = helicalGearSketch(gearHeight) | ||
|
||
// Loft each rotated gear sketch together to form a helical gear | ||
helicalGear = loft([ | ||
gearcamProfile, | ||
gearcenterShaft, | ||
gearSketch003 | ||
]) | ||
|
||
return helicalGear | ||
} | ||
|
||
// Call the timing gear function | ||
helicalGear( | ||
nTeeth = 15, | ||
module = .15, | ||
pressureAngle = 20, | ||
helixAngle = 55, | ||
gearHeight = supportBearingWidth, | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is probably the most realistic looking part I've seen yet. The like turned profile into the hex cut out looks legit—though part of me thinks a cable gland is really an assembly of like 2-5 parts: