{"id":10262,"date":"2026-08-15T00:53:12","date_gmt":"2026-08-14T22:53:12","guid":{"rendered":"https:\/\/www.lukaswojcik.com\/blog\/toolbox\/pv-surplus-battery-charging-calculator\/"},"modified":"2026-08-15T00:53:12","modified_gmt":"2026-08-14T22:53:12","slug":"pv-surplus-battery-charging-calculator","status":"publish","type":"page","link":"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/pv-surplus-battery-charging-calculator\/","title":{"rendered":"PV Surplus &#038; Battery Charging Calculator"},"content":{"rendered":"<div class=\"gtm-analyser-container\" style=\"background: var(--bg-panel, #1e1e24); padding: 25px; border-radius: 8px; border: 1px solid var(--border, #2a2a35);\">\n<p style=\"color: var(--text-secondary, #a0a0b0); margin-bottom: 20px;\">Surplus charging fails on the details: the battery takes the power first, the load falls just short of its minimum, and the relay starts chattering. This calculator splits the surplus the way the automation would and hands over usable thresholds.<\/p>\n<div style=\"display: flex; gap: 12px; flex-wrap: wrap;\">\n<div style=\"flex: 1; min-width: 160px;\">\n            <label for=\"pv-erzeugung\" style=\"color: var(--text-secondary, #a0a0b0); display: block; font-size: 0.85rem; margin-bottom: 5px;\">PV output now (W)<\/label><br \/>\n            <input type=\"text\" id=\"pv-erzeugung\" class=\"form-control\" style=\"width: 100%; padding: 10px; background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); color: var(--text-primary, #e8e8ee); border-radius: 6px; font-family: monospace; box-sizing: border-box;\" value=\"5200\">\n        <\/div>\n<div style=\"flex: 1; min-width: 160px;\">\n            <label for=\"pv-grundlast\" style=\"color: var(--text-secondary, #a0a0b0); display: block; font-size: 0.85rem; margin-bottom: 5px;\">House base load (W)<\/label><br \/>\n            <input type=\"text\" id=\"pv-grundlast\" class=\"form-control\" style=\"width: 100%; padding: 10px; background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); color: var(--text-primary, #e8e8ee); border-radius: 6px; font-family: monospace; box-sizing: border-box;\" value=\"600\">\n        <\/div>\n<div style=\"flex: 1; min-width: 160px;\">\n            <label for=\"pv-kapazitaet\" style=\"color: var(--text-secondary, #a0a0b0); display: block; font-size: 0.85rem; margin-bottom: 5px;\">Battery capacity (kWh)<\/label><br \/>\n            <input type=\"text\" id=\"pv-kapazitaet\" class=\"form-control\" style=\"width: 100%; padding: 10px; background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); color: var(--text-primary, #e8e8ee); border-radius: 6px; font-family: monospace; box-sizing: border-box;\" value=\"10\">\n        <\/div>\n<div style=\"flex: 1; min-width: 160px;\">\n            <label for=\"pv-ladestand\" style=\"color: var(--text-secondary, #a0a0b0); display: block; font-size: 0.85rem; margin-bottom: 5px;\">State of charge (%)<\/label><br \/>\n            <input type=\"text\" id=\"pv-ladestand\" class=\"form-control\" style=\"width: 100%; padding: 10px; background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); color: var(--text-primary, #e8e8ee); border-radius: 6px; font-family: monospace; box-sizing: border-box;\" value=\"45\">\n        <\/div>\n<\/p><\/div>\n<div style=\"display: flex; gap: 12px; flex-wrap: wrap; margin-top: 12px;\">\n<div style=\"flex: 1; min-width: 160px;\">\n            <label for=\"pv-ladeleistung\" style=\"color: var(--text-secondary, #a0a0b0); display: block; font-size: 0.85rem; margin-bottom: 5px;\">Maximum charge power (W)<\/label><br \/>\n            <input type=\"text\" id=\"pv-ladeleistung\" class=\"form-control\" style=\"width: 100%; padding: 10px; background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); color: var(--text-primary, #e8e8ee); border-radius: 6px; font-family: monospace; box-sizing: border-box;\" value=\"3000\">\n        <\/div>\n<div style=\"flex: 1; min-width: 160px;\">\n            <label for=\"pv-wirkungsgrad\" style=\"color: var(--text-secondary, #a0a0b0); display: block; font-size: 0.85rem; margin-bottom: 5px;\">Charging efficiency (%)<\/label><br \/>\n            <input type=\"text\" id=\"pv-wirkungsgrad\" class=\"form-control\" style=\"width: 100%; padding: 10px; background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); color: var(--text-primary, #e8e8ee); border-radius: 6px; font-family: monospace; box-sizing: border-box;\" value=\"92\">\n        <\/div>\n<div style=\"flex: 1; min-width: 160px;\">\n            <label for=\"pv-verbraucher\" style=\"color: var(--text-secondary, #a0a0b0); display: block; font-size: 0.85rem; margin-bottom: 5px;\">Minimum power of the switchable load (W)<\/label><br \/>\n            <input type=\"text\" id=\"pv-verbraucher\" class=\"form-control\" style=\"width: 100%; padding: 10px; background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); color: var(--text-primary, #e8e8ee); border-radius: 6px; font-family: monospace; box-sizing: border-box;\" value=\"1380\">\n        <\/div>\n<div style=\"flex: 1; min-width: 160px;\">\n            <label for=\"pv-vorrang\" style=\"color: var(--text-secondary, #a0a0b0); display: block; font-size: 0.85rem; margin-bottom: 5px;\">Priority<\/label><br \/>\n            <select id=\"pv-vorrang\" class=\"form-control\" style=\"width: 100%; padding: 10px; background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); color: var(--text-primary, #e8e8ee); border-radius: 6px; font-family: monospace; box-sizing: border-box;\"><option value=\"speicher\">battery first<\/option><option value=\"verbraucher\">load first<\/option><\/select>\n        <\/div>\n<\/p><\/div>\n<div style=\"display: flex; gap: 12px; flex-wrap: wrap; margin-top: 12px;\">\n<div style=\"flex: 1; min-width: 160px;\">\n            <label for=\"pv-strompreis\" style=\"color: var(--text-secondary, #a0a0b0); display: block; font-size: 0.85rem; margin-bottom: 5px;\">Electricity price (cent per kWh)<\/label><br \/>\n            <input type=\"text\" id=\"pv-strompreis\" class=\"form-control\" style=\"width: 100%; padding: 10px; background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); color: var(--text-primary, #e8e8ee); border-radius: 6px; font-family: monospace; box-sizing: border-box;\" value=\"32\">\n        <\/div>\n<div style=\"flex: 1; min-width: 160px;\">\n            <label for=\"pv-verguetung\" style=\"color: var(--text-secondary, #a0a0b0); display: block; font-size: 0.85rem; margin-bottom: 5px;\">Feed-in tariff (cent per kWh)<\/label><br \/>\n            <input type=\"text\" id=\"pv-verguetung\" class=\"form-control\" style=\"width: 100%; padding: 10px; background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); color: var(--text-primary, #e8e8ee); border-radius: 6px; font-family: monospace; box-sizing: border-box;\" value=\"8\">\n        <\/div>\n<\/p><\/div>\n<div style=\"display: flex; gap: 10px; flex-wrap: wrap; margin: 18px 0 0;\">\n        <button id=\"pv-btn\" class=\"button\" style=\"background: var(--accent, #7ee787); color: #0b1114; border: none; padding: 12px 24px; border-radius: 6px; font-weight: 700; cursor: pointer;\">Work it out<\/button>\n    <\/div>\n<div id=\"pv-ergebnis\" style=\"margin-top: 22px;\"><\/div>\n<\/div>\n<p><script>\n(function () {\n    'use strict';<\/p>\n<p>    const T = {\"einleitung\":\"Surplus charging fails on the details: the battery takes the power first, the load falls just short of its minimum, and the relay starts chattering. This calculator splits the surplus the way the automation would and hands over usable thresholds.\",\"label_erzeugung\":\"PV output now (W)\",\"label_grundlast\":\"House base load (W)\",\"label_kapazitaet\":\"Battery capacity (kWh)\",\"label_ladestand\":\"State of charge (%)\",\"label_ladeleistung\":\"Maximum charge power (W)\",\"label_wirkungsgrad\":\"Charging efficiency (%)\",\"label_verbraucher\":\"Minimum power of the switchable load (W)\",\"label_vorrang\":\"Priority\",\"vorrang_speicher\":\"battery first\",\"vorrang_verbraucher\":\"load first\",\"label_strompreis\":\"Electricity price (cent per kWh)\",\"label_verguetung\":\"Feed-in tariff (cent per kWh)\",\"knopf\":\"Work it out\",\"fehler_erzeugung\":\"The PV output has to be a number of 0 or more.\",\"fehler_grundlast\":\"The base load has to be a number of 0 or more.\",\"fehler_kapazitaet\":\"The battery capacity has to be a number of 0 or more.\",\"fehler_ladestand\":\"The state of charge has to lie between 0 and 100.\",\"fehler_ladeleistung\":\"The charge power has to be a number of 0 or more.\",\"fehler_wirkungsgrad\":\"The efficiency has to lie between 0 and 100.\",\"fehler_verbraucher\":\"The minimum power has to be a number of 0 or more.\",\"fehler_preis\":\"Price and tariff have to be numbers of 0 or more.\",\"h_verteilung\":\"Where the power goes\",\"h_schwellen\":\"Thresholds for the automation\",\"h_befunde\":\"Findings\",\"z_ueberschuss\":\"Surplus after the base load\",\"z_speicher\":\"Into the battery\",\"z_speicher_netto\":\"Of that, actually stored\",\"z_verbraucher\":\"To the switchable load\",\"z_einspeisung\":\"Fed into the grid\",\"z_netzbezug\":\"Drawn from the grid\",\"z_fehlend\":\"Missing to a full battery\",\"z_dauer\":\"Time to full at this rate\",\"z_ein\":\"Switch on above\",\"z_aus\":\"Switch off below\",\"schwellen_erklaerung\":\"The thresholds include the base load and keep ten percent of headroom on each side. A delay of three to five minutes on both edges keeps a passing cloud from switching the load.\",\"b_kein_ueberschuss\":\"There is no surplus, the house draws %s W from the grid. Nothing can be charged from the sun right now.\",\"b_verbraucher_reicht_nicht\":\"The load needs %s W and only %r W remain, so it stays off. Anything else would mean drawing the difference from the grid.\",\"b_speicher_zuerst\":\"The battery takes the power first and the load waits, although the surplus would be enough for it. Priority for the load fills the battery later but consumes on the spot.\",\"b_speicher_voll\":\"The battery is full, the whole surplus is available for loads or goes to the grid.\",\"b_teillast\":\"Only %s W of the possible %m W flow into the battery, because the surplus does not carry more.\",\"b_takten\":\"Surplus and load power are almost identical. Without a delay and a wide hysteresis the relay will chatter.\",\"b_einspeisen_lohnt\":\"The feed-in tariff is at least as high as the electricity price. Under that arrangement feeding in beats self-consumption.\",\"b_ersparnis\":\"Every kilowatt hour used instead of exported is worth %s cent.\",\"b_wirkungsgrad\":\"Charging losses eat %s W, which is heat and not storage.\"};<\/p>\n<p>    \/\/ --- reine Rechenlogik ---<\/p>\n<p>    function zahl(wert) {\n        const roh = String(wert === undefined || wert === null ? '' : wert).trim().replace(',', '.');\n        if (roh === '') { return NaN; }\n        if (!\/^-?[0-9]+(\\.[0-9]+)?$\/.test(roh)) { return NaN; }\n        return parseFloat(roh);\n    }<\/p>\n<p>    function runde(wert, stellen) {\n        const faktor = Math.pow(10, stellen === undefined ? 0 : stellen);\n        return Math.round(wert * faktor) \/ faktor;\n    }<\/p>\n<p>    function rechnen(e) {\n        const ergebnis = { ok: false, fehler: '', befunde: [] };\n        const eingabe = e || {};<\/p>\n<p>        const erzeugung = zahl(eingabe.erzeugung);\n        const grundlast = zahl(eingabe.grundlast);\n        const kapazitaet = zahl(eingabe.kapazitaet);\n        const ladestand = zahl(eingabe.ladestand);\n        const ladeleistung = zahl(eingabe.ladeleistung);\n        const wirkungsgrad = zahl(eingabe.wirkungsgrad);\n        const verbraucher = zahl(eingabe.verbraucher);\n        const strompreis = zahl(eingabe.strompreis);\n        const verguetung = zahl(eingabe.verguetung);<\/p>\n<p>        if (!isFinite(erzeugung) || erzeugung < 0) { ergebnis.fehler = T.fehler_erzeugung; return ergebnis; }\n        if (!isFinite(grundlast) || grundlast < 0) { ergebnis.fehler = T.fehler_grundlast; return ergebnis; }\n        if (!isFinite(kapazitaet) || kapazitaet < 0) { ergebnis.fehler = T.fehler_kapazitaet; return ergebnis; }\n        if (!isFinite(ladestand) || ladestand < 0 || ladestand > 100) { ergebnis.fehler = T.fehler_ladestand; return ergebnis; }\n        if (!isFinite(ladeleistung) || ladeleistung < 0) { ergebnis.fehler = T.fehler_ladeleistung; return ergebnis; }\n        if (!isFinite(wirkungsgrad) || wirkungsgrad <= 0 || wirkungsgrad > 100) { ergebnis.fehler = T.fehler_wirkungsgrad; return ergebnis; }\n        if (!isFinite(verbraucher) || verbraucher < 0) { ergebnis.fehler = T.fehler_verbraucher; return ergebnis; }\n        if (!isFinite(strompreis) || strompreis < 0) { ergebnis.fehler = T.fehler_preis; return ergebnis; }\n        if (!isFinite(verguetung) || verguetung < 0) { ergebnis.fehler = T.fehler_preis; return ergebnis; }\n\n        const ueberschuss = erzeugung - grundlast;\n        const fehlend = kapazitaet * (100 - ladestand) \/ 100;   \/\/ kWh, die noch hineinpassen\n        const vorrang = eingabe.vorrang === 'verbraucher' ? 'verbraucher' : 'speicher';\n\n        let anSpeicher = 0;\n        let anVerbraucher = 0;\n        let rest = Math.max(0, ueberschuss);\n\n        if (vorrang === 'speicher') {\n            anSpeicher = fehlend > 0 ? Math.min(rest, ladeleistung) : 0;\n            rest -= anSpeicher;\n            anVerbraucher = rest >= verbraucher ? verbraucher : 0;\n            rest -= anVerbraucher;\n        } else {\n            anVerbraucher = rest >= verbraucher ? verbraucher : 0;\n            rest -= anVerbraucher;\n            anSpeicher = fehlend > 0 ? Math.min(rest, ladeleistung) : 0;\n            rest -= anSpeicher;\n        }<\/p>\n<p>        \/\/ Der Wirkungsgrad frisst einen Teil dessen, was in den Speicher geht.\n        const imSpeicher = anSpeicher * (wirkungsgrad \/ 100);\n        const stunden = imSpeicher > 0 ? (fehlend * 1000) \/ imSpeicher : 0;<\/p>\n<p>        \/\/ Schwellen fuer die Schaltung, mit Abstand nach oben und unten.\n        const einschalten = Math.ceil((verbraucher * 1.1 + grundlast) \/ 50) * 50;\n        const ausschalten = Math.floor((verbraucher * 0.9 + grundlast) \/ 50) * 50;<\/p>\n<p>        ergebnis.ok = true;\n        ergebnis.ueberschuss = runde(ueberschuss);\n        ergebnis.anSpeicher = runde(anSpeicher);\n        ergebnis.imSpeicher = runde(imSpeicher);\n        ergebnis.anVerbraucher = runde(anVerbraucher);\n        ergebnis.einspeisung = runde(Math.max(0, rest));\n        ergebnis.netzbezug = runde(Math.max(0, -ueberschuss));\n        ergebnis.fehlend = runde(fehlend, 2);\n        ergebnis.stunden = runde(stunden, 2);\n        ergebnis.einschalten = einschalten;\n        ergebnis.ausschalten = ausschalten;\n        ergebnis.vorrang = vorrang;\n        ergebnis.ersparnis = runde(strompreis - verguetung, 2);\n        ergebnis.wertEigenverbrauch = runde((anVerbraucher \/ 1000) * (strompreis - verguetung), 2);<\/p>\n<p>        \/\/ --- Befunde ---\n        if (ueberschuss <= 0) {\n            ergebnis.befunde.push({ schwer: true, text: T.b_kein_ueberschuss.replace('%s', String(ergebnis.netzbezug)) });\n        }\n        if (ueberschuss > 0 && anVerbraucher === 0 && verbraucher > 0) {\n            ergebnis.befunde.push({ schwer: true, text: T.b_verbraucher_reicht_nicht.replace('%s', String(verbraucher)).replace('%r', String(runde(Math.max(0, ueberschuss - anSpeicher)))) });\n        }\n        if (vorrang === 'speicher' && anVerbraucher === 0 && ueberschuss >= verbraucher && fehlend > 0) {\n            ergebnis.befunde.push({ schwer: false, text: T.b_speicher_zuerst });\n        }\n        if (fehlend <= 0) {\n            ergebnis.befunde.push({ schwer: false, text: T.b_speicher_voll });\n        }\n        if (anSpeicher > 0 && anSpeicher < ladeleistung &#038;&#038; fehlend > 0) {\n            ergebnis.befunde.push({ schwer: false, text: T.b_teillast.replace('%s', String(ergebnis.anSpeicher)).replace('%m', String(ladeleistung)) });\n        }\n        if (ueberschuss > 0 && Math.abs(ueberschuss - verbraucher) < verbraucher * 0.15) {\n            ergebnis.befunde.push({ schwer: true, text: T.b_takten });\n        }\n        if (ergebnis.ersparnis <= 0) {\n            ergebnis.befunde.push({ schwer: true, text: T.b_einspeisen_lohnt });\n        } else {\n            ergebnis.befunde.push({ schwer: false, text: T.b_ersparnis.replace('%s', String(ergebnis.ersparnis)) });\n        }\n        if (wirkungsgrad < 100) {\n            ergebnis.befunde.push({ schwer: false, text: T.b_wirkungsgrad.replace('%s', String(runde(anSpeicher - imSpeicher))) });\n        }\n\n        return ergebnis;\n    }\n\n    if (typeof window !== 'undefined') {\n        window.LW_TEST = window.LW_TEST || {};\n        window.LW_TEST.PV = { rechnen: rechnen, zahl: zahl };\n    }\n\n    \/\/ --- Anbindung an das Dokument ---\n\n    const btn = document.getElementById('pv-btn');\n    const out = document.getElementById('pv-ergebnis');\n    if (!btn || !out) { return; }\n\n    const KASTEN = 'background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); border-radius: 6px; padding: 14px; margin-bottom: 18px;';\n    const UEBERSCHRIFT = 'color: var(--text-primary, #e8e8ee); font-weight: 700; margin-bottom: 8px;';\n\n    function el(tag, css, inhalt) {\n        const knoten = document.createElement(tag);\n        if (css) { knoten.setAttribute('style', css); }\n        if (inhalt !== undefined &#038;&#038; inhalt !== null) { knoten.textContent = inhalt; }\n        return knoten;\n    }\n\n    function wert(id) {\n        const knoten = document.getElementById(id);\n        return knoten ? knoten.value : '';\n    }\n\n    function zeile(kasten, name, inhalt, hervor) {\n        const z = el('div', 'display: flex; justify-content: space-between; gap: 14px; flex-wrap: wrap; padding: 5px 0;');\n        z.appendChild(el('span', 'color: var(--text-secondary, #a0a0b0);', name));\n        z.appendChild(el('span', 'color: ' + (hervor ? 'var(--accent, #7ee787)' : 'var(--text-primary, #e8e8ee)') + '; font-family: monospace;', inhalt));\n        kasten.appendChild(z);\n    }\n\n    btn.addEventListener('click', function () {\n        const erg = rechnen({\n            erzeugung: wert('pv-erzeugung'),\n            grundlast: wert('pv-grundlast'),\n            kapazitaet: wert('pv-kapazitaet'),\n            ladestand: wert('pv-ladestand'),\n            ladeleistung: wert('pv-ladeleistung'),\n            wirkungsgrad: wert('pv-wirkungsgrad'),\n            verbraucher: wert('pv-verbraucher'),\n            vorrang: wert('pv-vorrang'),\n            strompreis: wert('pv-strompreis'),\n            verguetung: wert('pv-verguetung')\n        });\n\n        out.textContent = '';\n        if (!erg.ok) {\n            out.appendChild(el('div', 'background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); border-left: 3px solid #ffb86c; color: var(--text-secondary, #a0a0b0); padding: 14px; border-radius: 6px;', erg.fehler));\n            return;\n        }\n\n        out.appendChild(el('div', UEBERSCHRIFT, T.h_verteilung));\n        const kasten = el('div', KASTEN);\n        zeile(kasten, T.z_ueberschuss, erg.ueberschuss + ' W', erg.ueberschuss > 0);\n        zeile(kasten, T.z_speicher, erg.anSpeicher + ' W');\n        zeile(kasten, T.z_speicher_netto, erg.imSpeicher + ' W');\n        zeile(kasten, T.z_verbraucher, erg.anVerbraucher + ' W', erg.anVerbraucher > 0);\n        zeile(kasten, T.z_einspeisung, erg.einspeisung + ' W');\n        if (erg.netzbezug > 0) { zeile(kasten, T.z_netzbezug, erg.netzbezug + ' W'); }\n        zeile(kasten, T.z_fehlend, erg.fehlend + ' kWh');\n        zeile(kasten, T.z_dauer, erg.stunden > 0 ? erg.stunden + ' h' : '-');\n        out.appendChild(kasten);<\/p>\n<p>        out.appendChild(el('div', UEBERSCHRIFT, T.h_schwellen));\n        const schwellen = el('div', KASTEN);\n        zeile(schwellen, T.z_ein, erg.einschalten + ' W', true);\n        zeile(schwellen, T.z_aus, erg.ausschalten + ' W');\n        schwellen.appendChild(el('div', 'color: var(--text-secondary, #a0a0b0); font-size: 0.85rem; line-height: 1.6; padding-top: 8px;', T.schwellen_erklaerung));\n        out.appendChild(schwellen);<\/p>\n<p>        out.appendChild(el('div', UEBERSCHRIFT, T.h_befunde));\n        const befunde = el('div', KASTEN);\n        erg.befunde.forEach(function (b) {\n            const z = el('div', 'display: flex; gap: 10px; padding: 5px 0;');\n            z.appendChild(el('span', 'color: ' + (b.schwer ? '#ffb86c' : 'var(--text-secondary, #a0a0b0)') + '; font-family: monospace;', b.schwer ? '!' : '-'));\n            z.appendChild(el('span', 'color: var(--text-secondary, #a0a0b0); font-size: 0.9rem; line-height: 1.5;', b.text));\n            befunde.appendChild(z);\n        });\n        out.appendChild(befunde);\n    });\n})();\n<\/script><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Splits the current surplus between battery and a switchable load, works out how long the battery needs, and derives the switching thresholds for a surplus automation.<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":38,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"template-tool-base.php","meta":{"footnotes":""},"tags":[91371,91362,91626],"class_list":["post-10262","page","type-page","status-publish","hentry","tag-energy-management","tag-photovoltaics","tag-smart-home-de"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>PV Surplus &amp; Battery Charging Calculator - Lukas Wojcik - Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/pv-surplus-battery-charging-calculator\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"PV Surplus &amp; Battery Charging Calculator - Lukas Wojcik - Blog\" \/>\n<meta property=\"og:description\" content=\"Splits the current surplus between battery and a switchable load, works out how long the battery needs, and derives the switching thresholds for a surplus automation.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/pv-surplus-battery-charging-calculator\/\" \/>\n<meta property=\"og:site_name\" content=\"Lukas Wojcik - Blog\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/08\/og-default.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"630\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/toolbox\\\/pv-surplus-battery-charging-calculator\\\/\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/toolbox\\\/pv-surplus-battery-charging-calculator\\\/\",\"name\":\"PV Surplus & Battery Charging Calculator - Lukas Wojcik - Blog\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#website\"},\"datePublished\":\"2026-08-14T22:53:12+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/toolbox\\\/pv-surplus-battery-charging-calculator\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/toolbox\\\/pv-surplus-battery-charging-calculator\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/toolbox\\\/pv-surplus-battery-charging-calculator\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Toolbox\",\"item\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/toolbox\\\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"PV Surplus &#038; Battery Charging Calculator\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/\",\"name\":\"Lukas Wojcik - Blog\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\",\"name\":\"luky\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"contentUrl\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"width\":424,\"height\":636,\"caption\":\"luky\"},\"logo\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\"},\"sameAs\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"PV Surplus & Battery Charging Calculator - Lukas Wojcik - Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/pv-surplus-battery-charging-calculator\/","og_locale":"en_US","og_type":"article","og_title":"PV Surplus & Battery Charging Calculator - Lukas Wojcik - Blog","og_description":"Splits the current surplus between battery and a switchable load, works out how long the battery needs, and derives the switching thresholds for a surplus automation.","og_url":"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/pv-surplus-battery-charging-calculator\/","og_site_name":"Lukas Wojcik - Blog","og_image":[{"width":1200,"height":630,"url":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/08\/og-default.jpg","type":"image\/jpeg"}],"twitter_card":"summary_large_image","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/pv-surplus-battery-charging-calculator\/","url":"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/pv-surplus-battery-charging-calculator\/","name":"PV Surplus & Battery Charging Calculator - Lukas Wojcik - Blog","isPartOf":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#website"},"datePublished":"2026-08-14T22:53:12+00:00","breadcrumb":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/pv-surplus-battery-charging-calculator\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/pv-surplus-battery-charging-calculator\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/pv-surplus-battery-charging-calculator\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.lukaswojcik.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Toolbox","item":"https:\/\/www.lukaswojcik.com\/blog\/en\/toolbox\/"},{"@type":"ListItem","position":3,"name":"PV Surplus &#038; Battery Charging Calculator"}]},{"@type":"WebSite","@id":"https:\/\/www.lukaswojcik.com\/blog\/#website","url":"https:\/\/www.lukaswojcik.com\/blog\/","name":"Lukas Wojcik - Blog","description":"","publisher":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.lukaswojcik.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9","name":"luky","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","url":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","contentUrl":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","width":424,"height":636,"caption":"luky"},"logo":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg"},"sameAs":["https:\/\/www.lukaswojcik.com\/blog"]}]}},"_links":{"self":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages\/10262","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/comments?post=10262"}],"version-history":[{"count":0,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages\/10262\/revisions"}],"up":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages\/38"}],"wp:attachment":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/media?parent=10262"}],"wp:term":[{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/tags?post=10262"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}