preload-margin-tool/preload-margin.html

330 lines
11 KiB
HTML
Raw Normal View History

2026-07-19 05:36:38 +02:00
<!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>