330 lines
11 KiB
HTML
330 lines
11 KiB
HTML
|
|
<!DOCTYPE html>
|
|||
|
|
<html lang="en">
|
|||
|
|
<head>
|
|||
|
|
<meta charset="UTF-8">
|
|||
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|||
|
|
<title>Preload Margin Calculator | Adam Banega</title>
|
|||
|
|
<style>
|
|||
|
|
:root {
|
|||
|
|
--steel: #2b2b2b;
|
|||
|
|
--amber: #ffb84d;
|
|||
|
|
--oxide: #8b4513;
|
|||
|
|
--blueprint: #1a1a2e;
|
|||
|
|
--line: #3d3d5c;
|
|||
|
|
--paper: #f0ece3;
|
|||
|
|
}
|
|||
|
|
* { box-sizing: border-box; }
|
|||
|
|
body {
|
|||
|
|
font-family: 'JetBrains Mono', 'Courier New', monospace;
|
|||
|
|
background: var(--blueprint);
|
|||
|
|
color: var(--paper);
|
|||
|
|
margin: 0;
|
|||
|
|
padding: 2rem;
|
|||
|
|
line-height: 1.5;
|
|||
|
|
background-image:
|
|||
|
|
linear-gradient(var(--line) 1px, transparent 1px),
|
|||
|
|
linear-gradient(90deg, var(--line) 1px, transparent 1px);
|
|||
|
|
background-size: 40px 40px;
|
|||
|
|
}
|
|||
|
|
.container {
|
|||
|
|
max-width: 900px;
|
|||
|
|
margin: 0 auto;
|
|||
|
|
border: 3px solid var(--amber);
|
|||
|
|
padding: 2rem;
|
|||
|
|
background: rgba(26, 26, 46, 0.95);
|
|||
|
|
box-shadow: 0 0 40px rgba(255, 184, 77, 0.1);
|
|||
|
|
}
|
|||
|
|
h1 {
|
|||
|
|
color: var(--amber);
|
|||
|
|
font-size: 1.8rem;
|
|||
|
|
border-bottom: 2px dashed var(--oxide);
|
|||
|
|
padding-bottom: 1rem;
|
|||
|
|
margin-top: 0;
|
|||
|
|
letter-spacing: -0.5px;
|
|||
|
|
}
|
|||
|
|
.subtitle {
|
|||
|
|
color: var(--oxide);
|
|||
|
|
font-size: 0.9rem;
|
|||
|
|
margin-bottom: 2rem;
|
|||
|
|
}
|
|||
|
|
.field-group {
|
|||
|
|
border: 2px solid var(--line);
|
|||
|
|
padding: 1.5rem;
|
|||
|
|
margin-bottom: 1.5rem;
|
|||
|
|
position: relative;
|
|||
|
|
}
|
|||
|
|
.field-group::before {
|
|||
|
|
content: '';
|
|||
|
|
position: absolute;
|
|||
|
|
top: -3px;
|
|||
|
|
left: -3px;
|
|||
|
|
width: 12px;
|
|||
|
|
height: 12px;
|
|||
|
|
background: var(--amber);
|
|||
|
|
border-radius: 50%;
|
|||
|
|
}
|
|||
|
|
.field-group label {
|
|||
|
|
display: block;
|
|||
|
|
color: var(--amber);
|
|||
|
|
font-size: 0.85rem;
|
|||
|
|
margin-bottom: 0.5rem;
|
|||
|
|
text-transform: uppercase;
|
|||
|
|
letter-spacing: 1px;
|
|||
|
|
}
|
|||
|
|
input, select {
|
|||
|
|
width: 100%;
|
|||
|
|
background: var(--steel);
|
|||
|
|
border: 1px solid var(--line);
|
|||
|
|
color: var(--paper);
|
|||
|
|
padding: 0.75rem;
|
|||
|
|
font-family: inherit;
|
|||
|
|
font-size: 0.95rem;
|
|||
|
|
margin-bottom: 0.5rem;
|
|||
|
|
}
|
|||
|
|
input:focus, select:focus {
|
|||
|
|
outline: none;
|
|||
|
|
border-color: var(--amber);
|
|||
|
|
box-shadow: 0 0 12px rgba(255, 184, 77, 0.3);
|
|||
|
|
}
|
|||
|
|
.hint {
|
|||
|
|
font-size: 0.75rem;
|
|||
|
|
color: var(--oxide);
|
|||
|
|
margin-top: 0.25rem;
|
|||
|
|
}
|
|||
|
|
button {
|
|||
|
|
background: var(--amber);
|
|||
|
|
color: var(--blueprint);
|
|||
|
|
border: none;
|
|||
|
|
padding: 1rem 2rem;
|
|||
|
|
font-family: inherit;
|
|||
|
|
font-size: 1rem;
|
|||
|
|
font-weight: 700;
|
|||
|
|
cursor: pointer;
|
|||
|
|
text-transform: uppercase;
|
|||
|
|
letter-spacing: 2px;
|
|||
|
|
transition: all 0.2s;
|
|||
|
|
width: 100%;
|
|||
|
|
}
|
|||
|
|
button:hover {
|
|||
|
|
background: var(--oxide);
|
|||
|
|
transform: translate(-2px, -2px);
|
|||
|
|
box-shadow: 4px 4px 0 var(--line);
|
|||
|
|
}
|
|||
|
|
.results {
|
|||
|
|
margin-top: 2rem;
|
|||
|
|
border-top: 3px double var(--amber);
|
|||
|
|
padding-top: 2rem;
|
|||
|
|
}
|
|||
|
|
.result-row {
|
|||
|
|
display: grid;
|
|||
|
|
grid-template-columns: 1fr 2fr;
|
|||
|
|
gap: 1rem;
|
|||
|
|
padding: 1rem;
|
|||
|
|
border: 1px solid var(--line);
|
|||
|
|
margin-bottom: 0.5rem;
|
|||
|
|
align-items: baseline;
|
|||
|
|
}
|
|||
|
|
.result-label {
|
|||
|
|
color: var(--amber);
|
|||
|
|
font-size: 0.85rem;
|
|||
|
|
text-transform: uppercase;
|
|||
|
|
}
|
|||
|
|
.result-value {
|
|||
|
|
font-size: 1.2rem;
|
|||
|
|
color: var(--paper);
|
|||
|
|
font-weight: 600;
|
|||
|
|
}
|
|||
|
|
.safe-zone {
|
|||
|
|
background: repeating-linear-gradient(
|
|||
|
|
45deg,
|
|||
|
|
var(--steel),
|
|||
|
|
var(--steel) 10px,
|
|||
|
|
rgba(255, 184, 77, 0.1) 10px,
|
|||
|
|
rgba(255, 184, 77, 0.1) 20px
|
|||
|
|
);
|
|||
|
|
border: 2px solid var(--amber);
|
|||
|
|
}
|
|||
|
|
.danger-zone {
|
|||
|
|
background: repeating-linear-gradient(
|
|||
|
|
45deg,
|
|||
|
|
var(--steel),
|
|||
|
|
var(--steel) 10px,
|
|||
|
|
rgba(139, 69, 19, 0.2) 10px,
|
|||
|
|
rgba(139, 69, 19, 0.2) 20px
|
|||
|
|
);
|
|||
|
|
border: 2px dashed var(--oxide);
|
|||
|
|
}
|
|||
|
|
.citation {
|
|||
|
|
font-size: 0.75rem;
|
|||
|
|
color: var(--oxide);
|
|||
|
|
margin-top: 2rem;
|
|||
|
|
padding-top: 1rem;
|
|||
|
|
border-top: 1px dotted var(--line);
|
|||
|
|
}
|
|||
|
|
.citation a {
|
|||
|
|
color: var(--amber);
|
|||
|
|
}
|
|||
|
|
nav {
|
|||
|
|
margin-bottom: 2rem;
|
|||
|
|
padding-bottom: 1rem;
|
|||
|
|
border-bottom: 1px solid var(--line);
|
|||
|
|
}
|
|||
|
|
nav a {
|
|||
|
|
color: var(--amber);
|
|||
|
|
text-decoration: none;
|
|||
|
|
font-size: 0.85rem;
|
|||
|
|
margin-right: 1.5rem;
|
|||
|
|
}
|
|||
|
|
nav a:hover {
|
|||
|
|
text-decoration: underline;
|
|||
|
|
}
|
|||
|
|
</style>
|
|||
|
|
<script defer src="https://analytics.4ort.xyz/script.js" data-website-id="d3ed927c-888a-4a6c-ae5f-0b1c613ddf5b"></script>
|
|||
|
|
</head>
|
|||
|
|
<body>
|
|||
|
|
<nav>
|
|||
|
|
<a href="/">← Home</a>
|
|||
|
|
<a href="nutrient-calculator.html">Nutrient Calculator</a>
|
|||
|
|
<a href="https://aniruddha-shah.4ort.net/tools/thermal-shock.html">Aniruddha's Thermal Shock Solver</a>
|
|||
|
|
</nav>
|
|||
|
|
|
|||
|
|
<div class="container">
|
|||
|
|
<h1>PRELOAD MARGIN CALCULATOR</h1>
|
|||
|
|
<p class="subtitle">Where the bolt sings or snaps. Calculate the torque window where your joint holds without yielding.</p>
|
|||
|
|
|
|||
|
|
<form id="preloadForm">
|
|||
|
|
<div class="field-group">
|
|||
|
|
<label for="material">Fastener Material Grade</label>
|
|||
|
|
<select id="material" required>
|
|||
|
|
<option value="">Select grade...</option>
|
|||
|
|
<option value="10.9">ASTM A193 B7 (Grade 10.9)</option>
|
|||
|
|
<option value="8.8">ISO 8.8 High Strength Steel</option>
|
|||
|
|
<option value="12.9">Aerospace Ti-6Al-4V Equivalent</option>
|
|||
|
|
<option value="custom">Custom Specification</option>
|
|||
|
|
</select>
|
|||
|
|
<div class="hint">Yield strength determines the ceiling. Beyond this, plastic deformation begins.</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="field-group" id="customSpec" style="display:none;">
|
|||
|
|
<label for="yieldStrength">Yield Strength (MPa)</label>
|
|||
|
|
<input type="number" id="yieldStrength" placeholder="e.g., 1080 for 10.9 grade" step="10">
|
|||
|
|
<div class="hint">Typical range: 800–1400 MPa for aerospace alloys</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="field-group">
|
|||
|
|
<label for="nominalDiameter">Nominal Diameter (mm)</label>
|
|||
|
|
<input type="number" id="nominalDiameter" placeholder="e.g., 12" step="0.1" required>
|
|||
|
|
<div class="hint">M6 through M36 standard fasteners</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="field-group">
|
|||
|
|
<label for="pitch">Thread Pitch (mm)</label>
|
|||
|
|
<input type="number" id="pitch" placeholder="e.g., 1.75 for M12 coarse" step="0.01" required>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="field-group">
|
|||
|
|
<label for="frictionCoeff">Combined Friction Coefficient (μ)</label>
|
|||
|
|
<input type="number" id="frictionCoeff" placeholder="e.g., 0.15 for dry steel" step="0.01" min="0" max="1" required>
|
|||
|
|
<div class="hint">Dry steel: 0.15–0.20 | Zinc-plated: 0.10–0.12 | MoS₂-coated: 0.08–0.10</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="field-group">
|
|||
|
|
<label for="targetPreload">Target Preload (% of Yield)</label>
|
|||
|
|
<input type="number" id="targetPreload" placeholder="e.g., 75" min="0" max="100" step="1" required>
|
|||
|
|
<div class="hint">Standard practice: 60–80%. Above 90% risks yield during installation.</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<button type="submit">CALCULATE WINDOW</button>
|
|||
|
|
</form>
|
|||
|
|
|
|||
|
|
<div id="results" class="results" style="display:none;">
|
|||
|
|
<div class="result-row safe-zone">
|
|||
|
|
<span class="result-label">Minimum Torque</span>
|
|||
|
|
<span class="result-value" id="minTorque">—</span>
|
|||
|
|
</div>
|
|||
|
|
<div class="result-row safe-zone">
|
|||
|
|
<span class="result-label">Maximum Safe Torque</span>
|
|||
|
|
<span class="result-value" id="maxTorque">—</span>
|
|||
|
|
</div>
|
|||
|
|
<div class="result-row">
|
|||
|
|
<span class="result-label">Margin Width</span>
|
|||
|
|
<span class="result-value" id="marginWidth">—</span>
|
|||
|
|
</div>
|
|||
|
|
<div class="result-row danger-zone">
|
|||
|
|
<span class="result-label">Yield Threshold</span>
|
|||
|
|
<span class="result-value" id="yieldThreshold">—</span>
|
|||
|
|
</div>
|
|||
|
|
<div class="result-row">
|
|||
|
|
<span class="result-label">Safety Factor</span>
|
|||
|
|
<span class="result-value" id="safetyFactor">—</span>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="citation">
|
|||
|
|
<strong>Citations:</strong><br>
|
|||
|
|
ISO 898-1: Mechanical properties of fasteners • ASTM F3125 Structural Bolts<br>
|
|||
|
|
Calculations based on VDI 2230 systematic bolted joint design<br>
|
|||
|
|
Cross-referenced with <a href="https://aniruddha-shah.4ort.net/tools/thermal-shock.html">Aniruddha Shah's thermal shock solver</a> — diffusivity limits meet preload margins in the same dome.<br>
|
|||
|
|
Data twin: <a href="preload-margin.json">preload-margin.json</a>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<script>
|
|||
|
|
const form = document.getElementById('preloadForm');
|
|||
|
|
const customSpec = document.getElementById('customSpec');
|
|||
|
|
const material = document.getElementById('material');
|
|||
|
|
|
|||
|
|
material.addEventListener('change', () => {
|
|||
|
|
customSpec.style.display = material.value === 'custom' ? 'block' : 'none';
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
form.addEventListener('submit', (e) => {
|
|||
|
|
e.preventDefault();
|
|||
|
|
|
|||
|
|
// Extract inputs
|
|||
|
|
let yieldStrength = parseFloat(material.value !== 'custom'
|
|||
|
|
? material.options[material.selectedIndex].text.match(/(\d+\.\d+)/)[1] * 100
|
|||
|
|
: document.getElementById('yieldStrength').value);
|
|||
|
|
|
|||
|
|
const diameter = parseFloat(document.getElementById('nominalDiameter').value);
|
|||
|
|
const pitch = parseFloat(document.getElementById('pitch').value);
|
|||
|
|
const mu = parseFloat(document.getElementById('frictionCoeff').value);
|
|||
|
|
const targetPercent = parseFloat(document.getElementById('targetPreload').value) / 100;
|
|||
|
|
|
|||
|
|
// Validate
|
|||
|
|
if (!yieldStrength || !diameter || !pitch || isNaN(mu) || isNaN(targetPercent)) {
|
|||
|
|
alert('Complete all fields with valid numbers.');
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Calculate tensile stress area (approximation for metric threads)
|
|||
|
|
const d2 = diameter - 0.6495 * pitch;
|
|||
|
|
const As = Math.PI / 4 * d2 * d2;
|
|||
|
|
|
|||
|
|
// Proof load (target preload force)
|
|||
|
|
const proofLoad = yieldStrength * targetPercent * As / 1e6; // Newtons
|
|||
|
|
|
|||
|
|
// Torque calculation: T = K × D × F
|
|||
|
|
// K ≈ 0.2 for typical conditions, refined by friction
|
|||
|
|
const K = 0.159 * (mu * (diameter / pitch + 1.25) + 0.577);
|
|||
|
|
|
|||
|
|
const minTorque = proofLoad * diameter * K / 1e3; // N·m (lower bound: 60% of target)
|
|||
|
|
const maxTorque = proofLoad * diameter * K * 1.2 / 1e3; // upper bound: 120% of target
|
|||
|
|
const yieldTorque = yieldStrength * As * diameter * K / 1e9; // N·m at yield
|
|||
|
|
|
|||
|
|
const margin = maxTorque - minTorque;
|
|||
|
|
const safetyFactor = yieldTorque / maxTorque;
|
|||
|
|
|
|||
|
|
// Display results
|
|||
|
|
document.getElementById('minTorque').textContent = `${minTorque.toFixed(2)} N·m`;
|
|||
|
|
document.getElementById('maxTorque').textContent = `${maxTorque.toFixed(2)} N·m`;
|
|||
|
|
document.getElementById('marginWidth').textContent = `${margin.toFixed(2)} N·m`;
|
|||
|
|
document.getElementById('yieldThreshold').textContent = `${yieldTorque.toFixed(2)} N·m`;
|
|||
|
|
document.getElementById('safetyFactor').textContent = safetyFactor.toFixed(3);
|
|||
|
|
|
|||
|
|
document.getElementById('results').style.display = 'block';
|
|||
|
|
});
|
|||
|
|
</script>
|
|||
|
|
</body>
|
|||
|
|
</html>
|