Show code
colors = ({
navy: "#2C3E50",
teal: "#16A085",
orange: "#E67E22",
blue: "#3498DB",
gray: "#7F8C8D",
purple: "#9B59B6",
red: "#E74C3C",
green: "#27AE60"
})
// Input controls
viewof txPower = Inputs.range([0, 30], {
value: 14,
step: 1,
label: "TX Power (dBm):"
})
viewof txGain = Inputs.range([0, 10], {
value: 2,
step: 1,
label: "TX Antenna Gain (dBi):"
})
viewof rxGain = Inputs.range([0, 10], {
value: 3,
step: 1,
label: "RX Antenna Gain (dBi):"
})
viewof distance = Inputs.range([0.01, 100], {
value: 1,
step: 0.1,
label: "Distance (km):"
})
viewof frequency = Inputs.select(
[[868, "868 MHz (LoRa EU)"], [915, "915 MHz (LoRa US)"], [2400, "2.4 GHz (Wi-Fi/BLE)"], [5000, "5 GHz (Wi-Fi)"]],
{
value: 868,
label: "Frequency:",
format: ([freq, name]) => name
}
)
viewof pathLossExp = Inputs.range([2.0, 5.0], {
value: 2.0,
step: 0.1,
label: "Path Loss Exponent (n):"
})
viewof rxSensitivity = Inputs.range([-140, -60], {
value: -137,
step: 1,
label: "RX Sensitivity (dBm):"
})
viewof fadingMargin = Inputs.range([0, 30], {
value: 15,
step: 1,
label: "Fading Margin (dB):"
})
// Calculations
fspl = 20 * Math.log10(distance) + 20 * Math.log10(frequency) + 32.45
realPathLoss = fspl * (pathLossExp / 2.0)
rxPower = txPower + txGain + rxGain - realPathLoss
linkMargin = rxPower - rxSensitivity
availableMargin = linkMargin - fadingMargin
// Link status
linkStatus = availableMargin > 20 ? {text: "Excellent", color: colors.green} :
availableMargin > 10 ? {text: "Good", color: colors.teal} :
availableMargin > 0 ? {text: "Marginal", color: colors.orange} :
{text: "FAIL", color: colors.red}
// Environment description
envDescription = pathLossExp === 2.0 ? "Free space" :
pathLossExp < 2.5 ? "Rural open" :
pathLossExp < 3.0 ? "Suburban" :
pathLossExp < 3.5 ? "Indoor (open)" :
pathLossExp < 4.5 ? "Indoor (partitioned)" :
"Indoor (heavy obstruction)"
// Display results
html`
<div style="font-family: Arial, sans-serif; padding: 20px; background: linear-gradient(135deg, ${colors.navy}15, ${colors.teal}15); border-radius: 8px; margin-top: 20px;">
<h3 style="color: ${colors.navy}; margin-top: 0;">Link Budget Results</h3>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px; margin-bottom: 20px;">
<div style="background: white; padding: 15px; border-radius: 6px; border-left: 4px solid ${colors.teal};">
<div style="font-size: 12px; color: ${colors.gray}; text-transform: uppercase; margin-bottom: 5px;">Environment</div>
<div style="font-size: 18px; font-weight: bold; color: ${colors.navy};">${envDescription}</div>
<div style="font-size: 12px; color: ${colors.gray}; margin-top: 5px;">Path Loss Exponent: ${pathLossExp.toFixed(1)}</div>
</div>
<div style="background: white; padding: 15px; border-radius: 6px; border-left: 4px solid ${colors.orange};">
<div style="font-size: 12px; color: ${colors.gray}; text-transform: uppercase; margin-bottom: 5px;">Path Loss</div>
<div style="font-size: 18px; font-weight: bold; color: ${colors.navy};">${realPathLoss.toFixed(1)} dB</div>
<div style="font-size: 12px; color: ${colors.gray}; margin-top: 5px;">Free space: ${fspl.toFixed(1)} dB</div>
</div>
<div style="background: white; padding: 15px; border-radius: 6px; border-left: 4px solid ${colors.blue};">
<div style="font-size: 12px; color: ${colors.gray}; text-transform: uppercase; margin-bottom: 5px;">Received Power</div>
<div style="font-size: 18px; font-weight: bold; color: ${colors.navy};">${rxPower.toFixed(1)} dBm</div>
<div style="font-size: 12px; color: ${colors.gray}; margin-top: 5px;">Raw link margin: ${linkMargin.toFixed(1)} dB</div>
</div>
<div style="background: white; padding: 15px; border-radius: 6px; border-left: 4px solid ${linkStatus.color};">
<div style="font-size: 12px; color: ${colors.gray}; text-transform: uppercase; margin-bottom: 5px;">Link Status</div>
<div style="font-size: 24px; font-weight: bold; color: ${linkStatus.color};">${linkStatus.text}</div>
<div style="font-size: 12px; color: ${colors.gray}; margin-top: 5px;">Available margin: ${availableMargin.toFixed(1)} dB</div>
</div>
</div>
<div style="background: white; padding: 15px; border-radius: 6px; border: 2px solid ${colors.navy};">
<h4 style="margin-top: 0; color: ${colors.navy};">Calculation Breakdown</h4>
<table style="width: 100%; font-size: 14px;">
<tr style="border-bottom: 1px solid #eee;">
<td style="padding: 8px; color: ${colors.gray};">TX Power + TX Gain + RX Gain</td>
<td style="padding: 8px; text-align: right; font-weight: bold; color: ${colors.teal};">
${txPower} + ${txGain} + ${rxGain} = +${(txPower + txGain + rxGain).toFixed(1)} dBm
</td>
</tr>
<tr style="border-bottom: 1px solid #eee;">
<td style="padding: 8px; color: ${colors.gray};">Path Loss</td>
<td style="padding: 8px; text-align: right; font-weight: bold; color: ${colors.orange};">
-${realPathLoss.toFixed(1)} dB
</td>
</tr>
<tr style="border-bottom: 1px solid #eee;">
<td style="padding: 8px; color: ${colors.gray};">Received Power</td>
<td style="padding: 8px; text-align: right; font-weight: bold; color: ${colors.navy};">
${rxPower.toFixed(1)} dBm
</td>
</tr>
<tr style="border-bottom: 1px solid #eee;">
<td style="padding: 8px; color: ${colors.gray};">RX Sensitivity</td>
<td style="padding: 8px; text-align: right; font-weight: bold;">
${rxSensitivity} dBm
</td>
</tr>
<tr style="border-bottom: 1px solid #eee;">
<td style="padding: 8px; color: ${colors.gray};">Link Margin (before fading)</td>
<td style="padding: 8px; text-align: right; font-weight: bold; color: ${colors.teal};">
${linkMargin.toFixed(1)} dB
</td>
</tr>
<tr style="border-bottom: 1px solid #eee;">
<td style="padding: 8px; color: ${colors.gray};">Fading Margin</td>
<td style="padding: 8px; text-align: right; font-weight: bold; color: ${colors.orange};">
-${fadingMargin} dB
</td>
</tr>
<tr>
<td style="padding: 8px; color: ${colors.gray}; font-weight: bold;">Available Margin</td>
<td style="padding: 8px; text-align: right; font-weight: bold; font-size: 16px; color: ${linkStatus.color};">
${availableMargin.toFixed(1)} dB
</td>
</tr>
</table>
</div>
<div style="margin-top: 15px; padding: 12px; background: ${colors.blue}15; border-radius: 6px; border-left: 4px solid ${colors.blue};">
<strong style="color: ${colors.navy};">Design Guidelines:</strong>
<ul style="margin: 10px 0 0 0; padding-left: 20px; color: ${colors.gray};">
<li>Target > 20 dB available margin for reliable links</li>
<li>10-20 dB is acceptable for most applications</li>
<li>0-10 dB means unreliable, occasional dropouts</li>
<li>< 0 dB means the link will fail</li>
</ul>
</div>
</div>
`