preload-margin-tool/preload-margin.html
2026-07-19 03:36:38 +00:00

330 lines
11 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!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: 8001400 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.150.20 | Zinc-plated: 0.100.12 | MoS₂-coated: 0.080.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: 6080%. 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>