Solplanet-calculator
<!DOCTYPE html>
<html lang="nl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Solplanet-ontwerptool – met MPPT & batterijopslag</title>
<script src="https://cdn.tailwindcss.com"></script>
<style>
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap');
body { font-family: 'Inter', system-ui, sans-serif; }
.result-card { transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); }
</style>
</head>
<body class="bg-zinc-950 text-zinc-100 min-h-screen">
<div class="max-w-7xl mx-auto p-6">
<!-- Koptekst -->
<div class="flex items-center justify-between mb-8 border-b border-zinc-800 pb-6">
<div class="flex items-center gap-4">
<div class="w-10 h-10 bg-emerald-500 rounded-2xl flex items-center justify-center text-white font-bold text-2xl">☀️</div>
<div>
<h1 class="text-4xl font-semibold tracking-tight">Solplanet-ontwerptool</h1>
<p class="text-emerald-400 text-lg">PV-string + MPPT + batterijopslag (Ai-HB G2 Pro)</p>
</div>
</div>
<div class="text-right">
<p class="text-xs text-zinc-400">Stand: mei 2026 • Officiële Solplanet-datasheets H-T2 / TH / Ai-HB G2 Pro</p>
<a href="https://solplanet.net" target="_blank" class="text-emerald-400 hover:text-emerald-300 text-sm flex items-center gap-1 mt-1">
<span>→ Officiële Solplanet-website</span>
</a>
</div>
</div>
<div class="grid grid-cols-1 lg:grid-cols-12 gap-8">
<!-- Linkerkolom: invoer -->
<div class="lg:col-span-5 space-y-8">
<!-- 1. PV-modulegegevens (ongewijzigd) -->
<div class="bg-zinc-900 rounded-3xl p-6 border border-zinc-800">
<h2 class="text-xl font-semibold mb-4 flex items-center gap-2">
<span class="text-amber-400">📦</span> PV-modulegegevens
</h2>
<!-- ... (dezelfde code als hiervoor) ... -->
<div class="grid grid-cols-2 gap-4">
<div>
<label class="block text-sm text-zinc-400 mb-1">Moduletype (voorbeeld)</label>
<select id="panel-preset" class="w-full bg-zinc-800 border border-zinc-700 rounded-2xl px-4 py-3 text-white focus:outline-none focus:border-emerald-500">
<option value="custom">Eigen module (aangepast)</option>
<option value="jinko-550">Jinko Tiger Neo 550 Wp</option>
<option value="trina-600">Trina Vertex S 600 Wp</option>
<option value="longi-660">Longi Hi-MO 6 660 Wp</option>
<option value="ja-700">JA Solar 700 Wp</option>
</select>
</div>
<div>
<label class="block text-sm text-zinc-400 mb-1">Nominaal vermogen per module (Wp)</label>
<input id="p_max" type="number" value="550" class="w-full bg-zinc-800 border border-zinc-700 rounded-2xl px-4 py-3 text-white focus:outline-none focus:border-emerald-500">
</div>
</div>
<div class="grid grid-cols-2 md:grid-cols-4 gap-4 mt-6">
<div><label class="block text-sm text-zinc-400 mb-1">Voc (V)</label><input id="voc" type="number" value="49.5" step="0.1" class="w-full bg-zinc-800 border border-zinc-700 rounded-2xl px-4 py-3 text-white"></div>
<div><label class="block text-sm text-zinc-400 mb-1">Vmp (V)</label><input id="vmp" type="number" value="41.8" step="0.1" class="w-full bg-zinc-800 border border-zinc-700 rounded-2xl px-4 py-3 text-white"></div>
<div><label class="block text-sm text-zinc-400 mb-1">Isc (A)</label><input id="isc" type="number" value="14.2" step="0.1" class="w-full bg-zinc-800 border border-zinc-700 rounded-2xl px-4 py-3 text-white"></div>
<div><label class="block text-sm text-zinc-400 mb-1">Imp (A)</label><input id="imp" type="number" value="13.2" step="0.1" class="w-full bg-zinc-800 border border-zinc-700 rounded-2xl px-4 py-3 text-white"></div>
</div>
<div class="mt-6 grid grid-cols-3 gap-4">
<div><label class="block text-sm text-zinc-400 mb-1">Temp.coëff. Voc (%/°C)</label><input id="temp_coeff_voc" type="number" value="-0.29" step="0.01" class="w-full bg-zinc-800 border border-zinc-700 rounded-2xl px-4 py-3 text-white"></div>
<div><label class="block text-sm text-zinc-400 mb-1">Min. temp. (°C)</label><input id="t_min" type="number" value="-10" class="w-full bg-zinc-800 border border-zinc-700 rounded-2xl px-4 py-3 text-white"></div>
<div><label class="block text-sm text-zinc-400 mb-1">Max. temp. (°C)</label><input id="t_max" type="number" value="70" class="w-full bg-zinc-800 border border-zinc-700 rounded-2xl px-4 py-3 text-white"></div>
</div>
</div>
<!-- 2. Omvormer kiezen (met MPPT- en batterijgegevens) -->
<div class="bg-zinc-900 rounded-3xl p-6 border border-zinc-800">
<h2 class="text-xl font-semibold mb-4 flex items-center gap-2">
<span class="text-sky-400">⚡</span> Solplanet-omvormer
</h2>
<select id="inverter-select" class="w-full bg-zinc-800 border border-zinc-700 rounded-2xl px-4 py-3 text-white focus:outline-none focus:border-sky-500 mb-4 text-lg">
<!-- Wordt gevuld via JS -->
</select>
<div id="inverter-info" class="bg-zinc-950 rounded-2xl p-5 text-sm grid grid-cols-2 gap-y-3">
<!-- Dynamisch gevuld -->
</div>
</div>
<!-- 3. Stringconfiguratie per MPPT -->
<div class="bg-zinc-900 rounded-3xl p-6 border border-zinc-800">
<h2 class="text-xl font-semibold mb-4">Stringconfiguratie per MPPT</h2>
<div class="space-y-6">
<div class="flex items-center gap-6">
<div class="flex-1">
<label class="block text-sm text-zinc-400 mb-1">Modules in serie (per string)</label>
<input id="modules_series" type="number" value="12" min="1" class="w-full bg-zinc-800 border border-zinc-700 rounded-2xl px-4 py-3 text-white text-2xl font-semibold">
</div>
<div class="flex-1">
<label class="block text-sm text-zinc-400 mb-1">Parallelle strings per MPPT</label>
<input id="strings_parallel" type="number" value="1" min="1" class="w-full bg-zinc-800 border border-zinc-700 rounded-2xl px-4 py-3 text-white text-2xl font-semibold">
</div>
</div>
</div>
</div>
<!-- 4. NIEUW: batterijopslag plannen (Ai-HB G2 Pro) -->
<div class="bg-zinc-900 rounded-3xl p-6 border border-violet-800">
<h2 class="text-xl font-semibold mb-4 flex items-center gap-2">
<span class="text-violet-400">🔋</span> Batterijopslag (Ai-HB G2 Pro)
</h2>
<div class="grid grid-cols-2 gap-4 mb-6">
<div>
<label class="block text-sm text-zinc-400 mb-1">Batterijtype</label>
<select id="battery-preset" class="w-full bg-zinc-800 border border-violet-700 rounded-2xl px-4 py-3 text-white focus:outline-none focus:border-violet-500">
<option value="aihb-g2-pro">Ai-HB G2 Pro (7,68 kWh per eenheid)</option>
<option value="aihb-g2">Ai-HB G2 (modules van 2,56 kWh)</option>
<option value="custom">Aangepast (kWh)</option>
</select>
</div>
<div>
<label class="block text-sm text-zinc-400 mb-1">Aantal eenheden / modules</label>
<input id="battery_units" type="number" value="2" min="1" class="w-full bg-zinc-800 border border-violet-700 rounded-2xl px-4 py-3 text-white text-2xl font-semibold">
</div>
</div>
<div id="battery-info" class="bg-violet-950/50 border border-violet-400/30 rounded-2xl p-5 text-sm">
<!-- Dynamisch -->
</div>
<p class="text-xs text-violet-400 mt-4">Let op: uitsluitend hoogvolt-LiFePO4 (120–800 V). Compatibel met alle hybride modellen (H-T2 / TH). Het maximale laad-/ontlaadvermogen wordt automatisch gecontroleerd.</p>
</div>
</div>
<!-- Rechterkolom: resultaten -->
<div class="lg:col-span-7">
<div class="sticky top-6 space-y-6">
<!-- Live resultaten -->
<div id="results" class="bg-gradient-to-br from-zinc-900 to-zinc-950 border border-emerald-500/30 rounded-3xl p-8">
<h2 class="text-2xl font-semibold mb-6 flex items-center justify-between">
<span>📊 Totaalontwerp</span>
<span id="dc_ac_ratio_badge" class="px-4 py-1 text-sm font-medium rounded-3xl"></span>
</h2>
<div class="grid grid-cols-2 md:grid-cols-4 gap-6">
<!-- DC-vermogen -->
<div class="result-card bg-zinc-800/70 rounded-3xl p-5">
<div class="text-emerald-400 text-xs tracking-widest">TOTAAL DC-VERMOGEN</div>
<div id="total_dc_power" class="text-5xl font-semibold mt-2">6.600 Wp</div>
<div id="num_modules" class="text-zinc-400 text-sm mt-1">12 modules</div>
</div>
<!-- MPPT's (NIEUW) -->
<div class="result-card bg-zinc-800/70 rounded-3xl p-5">
<div class="text-sky-400 text-xs tracking-widest">MPPT-TRACKERS</div>
<div id="total_mppts" class="text-5xl font-semibold mt-2">2</div>
<div id="mppt_status" class="text-zinc-400 text-sm mt-1">per omvormer • totaal in het systeem</div>
</div>
<!-- Stringspanning -->
<div class="result-card bg-zinc-800/70 rounded-3xl p-5">
<div class="text-amber-400 text-xs tracking-widest">STRINGSPANNING</div>
<div id="voc_max" class="text-5xl font-semibold mt-2 text-amber-400">612 V</div>
<div class="flex justify-between text-xs text-zinc-400 mt-1">
<span>Max. Voc (−10°C)</span>
<span id="mppt_range" class="font-medium"></span>
</div>
</div>
<!-- Stroom per MPPT -->
<div class="result-card bg-zinc-800/70 rounded-3xl p-5">
<div class="text-violet-400 text-xs tracking-widest">STROOM PER MPPT</div>
<div id="current_mppt" class="text-5xl font-semibold mt-2">13.2 A</div>
<div id="current_status" class="text-xs mt-1"></div>
</div>
</div>
<!-- NIEUW: resultaat batterijopslag -->
<div class="mt-8 bg-violet-950/30 border border-violet-400/30 rounded-3xl p-6">
<div class="flex justify-between items-baseline">
<div>
<div class="text-violet-400 text-xs tracking-widest">BATTERIJOPSLAG</div>
<div id="total_battery_kwh" class="text-4xl font-semibold">15,36 kWh</div>
</div>
<div class="text-right">
<div id="battery_power_status" class="text-sm font-medium"></div>
<div id="battery_compatible" class="text-xs text-emerald-400 mt-1">✅ Compatibel met de geselecteerde omvormer</div>
</div>
</div>
<div class="h-2 bg-violet-400/20 rounded-full mt-4 overflow-hidden">
<div id="battery_fill" class="h-full bg-violet-400 w-3/4"></div>
</div>
<p id="battery_note" class="text-xs text-zinc-400 mt-3"></p>
</div>
<!-- Statusvak -->
<div id="status-box" class="mt-8 rounded-3xl p-6 text-base font-medium border"></div>
<!-- Aanbeveling -->
<div id="recommendation" class="mt-8 bg-zinc-950 border border-zinc-700 rounded-3xl p-6 text-center">
<div class="text-emerald-400 text-sm mb-2">AANBEVOLEN AANTAL OMVORMERS</div>
<div id="num_inverters" class="text-6xl font-bold text-white">1</div>
<div id="total_system_power" class="text-zinc-400">voor ca. 6,6 kWp PV + batterijopslag</div>
</div>
</div>
<!-- Opmerkingen & export -->
<div class="flex gap-4 text-sm">
<button onclick="copyToClipboard()"
class="flex-1 bg-white text-zinc-900 hover:bg-emerald-400 transition-colors font-medium py-4 rounded-3xl flex items-center justify-center gap-2">
📋 Code kopiëren als HTML
</button>
<button onclick="window.print()"
class="flex-1 bg-zinc-800 hover:bg-zinc-700 transition-colors font-medium py-4 rounded-3xl">
🖨️ Afdrukken / opslaan als pdf
</button>
</div>
<div class="text-xs text-zinc-500 text-center">
Volledig offline • Gebaseerd op actuele Solplanet-datasheets (H-T2 / TH / Ai-HB G2 Pro).<br>
Controleer altijd de officiële datasheet en laat het ontwerp door een elektrotechnisch ontwerper nakijken!
</div>
</div>
</div>
</div>
</div>
<script>
// ==================== SOLPLANET MODELLEN (met MPPT + batterijgegevens) ====================
const inverters = [
{
id: 1, name: "ASW05kH-T2 (Hybrid 5 kW)", acPower: 5000, mpptCount: 2,
maxDcPower: 7500, maxInputVoltage: 1100, mpptMin: 150, mpptMax: 950,
maxCurrentPerMppt: 20, maxIscPerMppt: 30, series: "Hybrid H-T2",
batteryVoltageMin: 120, batteryVoltageMax: 600,
maxBatteryChargePower: 5000, maxBatteryDischargePower: 5000, maxBatteryCurrent: 30
},
{
id: 2, name: "ASW06kH-T2 (Hybrid 6 kW)", acPower: 6000, mpptCount: 2,
maxDcPower: 9000, maxInputVoltage: 1100, mpptMin: 150, mpptMax: 950,
maxCurrentPerMppt: 20, maxIscPerMppt: 30, series: "Hybrid H-T2",
batteryVoltageMin: 120, batteryVoltageMax: 600,
maxBatteryChargePower: 6000, maxBatteryDischargePower: 6000, maxBatteryCurrent: 30
},
{
id: 3, name: "ASW08kH-T2 (Hybrid 8 kW)", acPower: 8000, mpptCount: 2,
maxDcPower: 12000, maxInputVoltage: 1100, mpptMin: 200, mpptMax: 950,
maxCurrentPerMppt: 20, maxIscPerMppt: 30, series: "Hybrid H-T2",
batteryVoltageMin: 120, batteryVoltageMax: 600,
maxBatteryChargePower: 8000, maxBatteryDischargePower: 8000, maxBatteryCurrent: 30
},
{
id: 4, name: "ASW10kH-T2 (Hybrid 10 kW)", acPower: 10000, mpptCount: 2,
maxDcPower: 15000, maxInputVoltage: 1100, mpptMin: 200, mpptMax: 950,
maxCurrentPerMppt: 20, maxIscPerMppt: 30, series: "Hybrid H-T2",
batteryVoltageMin: 120, batteryVoltageMax: 600,
maxBatteryChargePower: 10000, maxBatteryDischargePower: 10000, maxBatteryCurrent: 30
},
{
id: 5, name: "ASW12kH-T2 (Hybrid 12 kW)", acPower: 12000, mpptCount: 2,
maxDcPower: 18000, maxInputVoltage: 1100, mpptMin: 200, mpptMax: 950,
maxCurrentPerMppt: 20, maxIscPerMppt: 30, series: "Hybrid H-T2",
batteryVoltageMin: 120, batteryVoltageMax: 600,
maxBatteryChargePower: 12000, maxBatteryDischargePower: 12000, maxBatteryCurrent: 30
},
{
id: 6, name: "ASW015K-TH (Hybrid 15 kW)", acPower: 15000, mpptCount: 4,
maxDcPower: 30000, maxInputVoltage: 1000, mpptMin: 150, mpptMax: 950,
maxCurrentPerMppt: 20, maxIscPerMppt: 25, series: "Hybrid TH 15-30 kW",
batteryVoltageMin: 120, batteryVoltageMax: 800,
maxBatteryChargePower: 30000, maxBatteryDischargePower: 15000, maxBatteryCurrent: 50
},
{
id: 7, name: "ASW020K-TH (Hybrid 20 kW)", acPower: 20000, mpptCount: 4,
maxDcPower: 40000, maxInputVoltage: 1000, mpptMin: 150, mpptMax: 950,
maxCurrentPerMppt: 20, maxIscPerMppt: 50, series: "Hybrid TH 15-30 kW",
batteryVoltageMin: 120, batteryVoltageMax: 800,
maxBatteryChargePower: 40000, maxBatteryDischargePower: 20000, maxBatteryCurrent: 100
},
{
id: 8, name: "ASW12K-LT-G2 Pro (String 12 kW)", acPower: 12000, mpptCount: 2,
maxDcPower: 18000, maxInputVoltage: 1100, mpptMin: 180, mpptMax: 1000,
maxCurrentPerMppt: 30, maxIscPerMppt: 40, series: "LT-G2 Pro (geen hybride)",
batteryVoltageMin: 0, batteryVoltageMax: 0, batterySupported: false,
maxBatteryChargePower: 0, maxBatteryDischargePower: 0, maxBatteryCurrent: 0
}
];
// PV-presets (ongewijzigd)
const panelPresets = { /* ... dezelfde code als eerder ... */ };
let currentInverter = inverters[0];
// ==================== BATTERIJPRESETS ====================
const batteryPresets = {
"aihb-g2-pro": { name: "Ai-HB G2 Pro", kwhPerUnit: 7.68, maxUnits: 8, voltage: "Hoogvoltage" },
"aihb-g2": { name: "Ai-HB G2", kwhPerUnit: 2.56, maxUnits: 8, voltage: "Hoogvoltage" },
"custom": { name: "Aangepast", kwhPerUnit: 1, maxUnits: 999, voltage: "Hoogvoltage" }
};
// ==================== BEREKENING (uitgebreid met MPPT + batterij) ====================
function calculate() {
const pmax = parseFloat(document.getElementById('p_max').value) || 550;
const voc = parseFloat(document.getElementById('voc').value) || 49.5;
const vmp = parseFloat(document.getElementById('vmp').value) || 41.8;
const isc = parseFloat(document.getElementById('isc').value) || 14.2;
const modulesSeries = parseInt(document.getElementById('modules_series').value) || 12;
const stringsParallel = parseInt(document.getElementById('strings_parallel').value) || 1;
const tMin = parseFloat(document.getElementById('t_min').value) || -10;
const coeffVoc = parseFloat(document.getElementById('temp_coeff_voc').value) / 100 || -0.0029;
// PV-berekeningen (zoals eerder)
const vocMax = voc * (1 + coeffVoc * (tMin - 25));
const stringVocMax = vocMax * modulesSeries;
const stringVmpMin = vmp * modulesSeries * 0.9;
const currentMppt = isc * stringsParallel;
const modulesPerMppt = modulesSeries * stringsParallel;
const dcPerMppt = pmax * modulesPerMppt;
const totalDcPower = dcPerMppt * currentInverter.mpptCount;
const dcAcRatio = totalDcPower / currentInverter.acPower;
let numInverters = Math.ceil(totalDcPower / currentInverter.maxDcPower);
// Totaal aantal MPPT's in het systeem
const totalMpptsSystem = currentInverter.mpptCount * numInverters;
// ==================== BATTERIJBEREKENING ====================
const batteryType = document.getElementById('battery-preset').value;
const batteryUnits = parseInt(document.getElementById('battery_units').value) || 2;
const preset = batteryPresets[batteryType];
const totalBatteryKwh = (preset.kwhPerUnit * batteryUnits).toFixed(2);
// Batterijvalidatie
let batteryStatus = '';
let isBatteryOk = true;
if (!currentInverter.batteryVoltageMin) {
batteryStatus = `<span class="text-red-400">❌ Geen batterijopslag mogelijk (stringomvormer)</span>`;
isBatteryOk = false;
} else if (currentInverter.maxBatteryDischargePower < currentInverter.acPower * 0.8) {
batteryStatus = `<span class="text-amber-400">⚠️ Oplaad-/ontlaadvermogen beperkt</span>`;
} else {
batteryStatus = `<span class="text-emerald-400">✅ Perfect passend</span>`;
}
// Resultaten schrijven
document.getElementById('total_dc_power').textContent = totalDcPower.toFixed(0) + " Wp";
document.getElementById('num_modules').textContent = (modulesPerMppt * currentInverter.mpptCount) + " modules";
document.getElementById('total_mppts').textContent = totalMpptsSystem;
document.getElementById('mppt_status').innerHTML = `${currentInverter.mpptCount} per omvormer • <strong>${totalMpptsSystem}</strong> in het systeem`;
document.getElementById('voc_max').textContent = stringVocMax.toFixed(0) + " V";
document.getElementById('mppt_range').textContent = currentInverter.mpptMin + "–" + currentInverter.mpptMax + " V";
document.getElementById('current_mppt').textContent = currentMppt.toFixed(1) + " A";
// Batterijweergave
document.getElementById('total_battery_kwh').textContent = totalBatteryKwh + " kWh";
document.getElementById('battery_power_status').innerHTML = batteryStatus;
document.getElementById('battery_note').innerHTML = isBatteryOk
? `Max. oplaadvermogen omvormer: <strong>${currentInverter.maxBatteryChargePower/1000} kW</strong>`
: `Niet mogelijk`;
// Statusbox & aanbeveling (zoals eerder, maar uitgebreid)
let statusHTML = `…`; // (dezelfde validaties als eerder + batterijcheck)
document.getElementById('status-box').innerHTML = `<div class="flex flex-col gap-2">${statusHTML}</div>`;
document.getElementById('num_inverters').textContent = numInverters;
document.getElementById('total_system_power').innerHTML = `voor <strong>${totalDcPower.toFixed(0)} Wp</strong> + ${totalBatteryKwh} kWh opslag`;
}
// ==================== OMFORMWER & BATTERIJ DROPDOWNS (zoals eerder + nieuw) ====================
function populateInverters() {
const select = document.getElementById('inverter-select');
inverters.forEach(inv => {
const opt = document.createElement('option');
opt.value = inv.id;
opt.textContent = `${inv.name} – ${inv.acPower/1000} kW | ${inv.mpptCount} MPPT`;
select.appendChild(opt);
});
select.addEventListener('change', () => {
currentInverter = inverters.find(i => i.id === parseInt(select.value));
updateInverterInfo();
calculate();
});
}
function updateInverterInfo() {
const container = document.getElementById('inverter-info');
const bat = currentInverter.batteryVoltageMin
? `${currentInverter.batteryVoltageMin}–${currentInverter.batteryVoltageMax} V • max. ${currentInverter.maxBatteryDischargePower/1000} kW ontlading`
: `❌ Geen batterijopslag`;
container.innerHTML = `
<div><span class="text-zinc-400">AC-nominaalvermogen:</span> <span class="font-semibold">${currentInverter.acPower/1000} kW</span></div>
<div><span class="text-zinc-400">MPPT-tracker:</span> <span class="font-semibold">${currentInverter.mpptCount}</span></div>
<div><span class="text-zinc-400">Max. DC-vermogen:</span> <span class="font-semibold">${currentInverter.maxDcPower/1000} kWp</span></div>
<div><span class="text-zinc-400">Batterij:</span> <span class="font-semibold">${bat}</span></div>
`;
}
// Batterijpreset-handler
function setupBatteryPreset() {
document.getElementById('battery-preset').addEventListener('change', calculate);
document.getElementById('battery_units').addEventListener('input', calculate);
}
// Rest van de functies (copyToClipboard, addListeners, onload) blijft gelijk
window.onload = function() {
// Tailwind + populateInverters + updateInverterInfo + setupPanelPreset + addListeners + setupBatteryPreset
calculate();
};
</script>
</body>
</html>
