Rád bych si pořídil na střechu rodinného domu solární elektrárnu (FVE), po prostudování nabídek různých prodejců jsem dospěl k názoru, že si musím udělat vlastní analýzu návratnosti.
Data prezentovaná dodavateli jsou obvykle založena na měsíční výrobě a měsíční spotřebě. To osobně považuju za velmi špinavý trik, který vůbec nezohledňuje soudobost spotřeby a výroby, zejména ve spojitosti s baterií.
Následující text obsahuje analýzu založenou na denní výrobě a denní spotřebě. Vstupní data získáme z PVWatts calculatoru.
Jako nástroj pro analýzu volím R.
Úvodní předpoklady pro moji analýzu jsou
Moje analýza je velmi pesimistická. Uvažuji pouze dnešní ceny energie a zároveň vůbec neuvažuji vlastní spotřebu domácností (pračka, myčka). Reálně tedy bude návratnost FVE pravděpodobně rychlejší než mnou uvažovaná.
Variant jsem analyzoval mnoho, zde prezentované výsledky se týkají 3f elektrárny o výkonu 4.5 kWp, téměř čistý jih, bez stínění, sklon 42°.
Data z PVwatts jsou super, ale pro rozumnou práci si je musíme trochu přechroustat…
df <- read.csv("pvwatts_hourly_4.5kW.csv", skip=17) #Odstraneni posledni radky s celkovym souctem df <- head(df, -1)
Vyzobání pouze hodinových výkonů a teplot a sloučení sloupců s dny a měsíci do „normálního“ datumu.
df_day <- df[,c("AC.System.Output..W.", "Ambient.Temperature..C.")] df_day$Date <- ISOdate(year=2020, month=df$Month, day=df$Day)
Původní data obsahují hodinové výkony, to je pro moje potřeby příliš jemné, takže je pomocí funkce aggregate převedu na součty výkonu po dnech a denní průměry teplot.
df_sumP_day <- aggregate(AC.System.Output..W. ~ Date, data=df_day, sum) df_mean_temp_day <- aggregate(Ambient.Temperature..C. ~ Date, data=df_day, mean)
Abych nemusel pořád generovat csv soubory, pro různé velikosti elektrárny (počet FV panelů), dovolím si výkon lehce přenásobit.
Přenásobení 1.15 dělám i z toho důvodu, že data z PVWats jsou v porovnání s analýzou z SolarGIS lehce pesimistická. Rozdíl není příliš zásadní.
df_sumP_day$AC.System.Output..W. <- df_sumP_day$AC.System.Output..W. * 1.15
Průměrné denní teploty a součet denního výkonu (neboli energie vyrobené za den) spojíme do jednoho dataframe. Tím, že se „Date“ jmenuje v obou spojovaných dataframe stejně, funkce merge si se spojováním poradí bez pomoci.
df_day <- merge(df_sumP_day, df_mean_temp_day)
Tím máme předchroustání hotové. V dataframe df_day máme pro každý den v roce vyrobenou energii a průměrnou teplotu. Můžeme se tedy vrhnout na analýzu dat.
V následujícím textu se podíváme na to, kolik energie jsem schopný nacpat do boileru, kolik do topení, do baterie a kolik jí zbude.
Boiler je v mém případě primárním úložištěm pro přebytky vyrobené energie. Do boileru o objemu 150l můžu při ohřevu o 60°C uložit pěkných 10kWh.
boiler_objem <- 150 #l boiler_delta_T <- 60 #K; rozdil teplot vstupni voda/vystupni boiler_akumulace <- boiler_objem * boiler_delta_T * 1.163 #kolik bolier muze naakumulovat [Wh]
Zdroj tzb-info.cz
Tolik teplé vody ale naše rodina nezvládne bohužel (nebo spíš bohudík) vyplácat. Můj odhad (nepodložený měřením) je, že denně spotřebujeme z boileru nejméně 4.5kW. Z toho je 1kWh vlastní ztráta boileru.
boiler_spotreba <- 4500 #Wh
Na začátku roku předpokládám boiler úplně studený.
boiler_stav <- 0 #okamzita hodnota energie ulozene v boileru
Pro analýzu si připravím dva sloupce. Spotreba_boiler je určen pro energii uloženou do boileru (spotřebovanou z FV panelů). Stav_boiler obsahuje aktuální energii uloženou v boileru pro daný den.
df_day$spotreba_boiler <- NULL df_day$stav_boiler <- NULL
Následně spotreba_boiler a stav_boiler spočítáme ve for cyklu
for (i in (1:nrow(df_day))) { chybi <- boiler_akumulace - boiler_stav increment <- df_day$"AC.System.Output..W."[i] if (increment > chybi) { increment <- chybi } boiler_stav <- boiler_stav + increment - boiler_spotreba if (boiler_stav < 0) { boiler_stav <- 0 } df_day[i, "spotreba_boiler"] <- increment df_day[i, "boiler_stav"] <- boiler_stav }
Celkový součet energie spotřebované boilerem a výpis do konzole
sum_spotreba_boiler <- sum(df_day$spotreba_boiler) / 1000 cat(paste("Boiler spotrebuje", round(sum_spotreba_boiler), "kWh", ", v cene", round(sum_spotreba_boiler*cena_nakup), "Kc\n"))
Boiler spotrebuje 1501 kWh , v cene 4803 Kc
V mém případě je boiler super úložiště, zvládne uložit velké množství energie (zhruba 33% vyrobené) za relativné málo peněz. Vzhledem k tomu, že už boiler vlastním, investice se omezí pouze na wattrouter a v mém případě ještě na třífázové topné těleso. Větší boiler by byl asi lepší, ale dokud funguje, měnit ho nebudu.
Až současný boiler doslouží, rád bych koupil 200l boiler se dvěma tělesy jedno ve spodní částí natápěné energií z FV na 80C, druhé uprostřed natápěné ze sítě na 50C.
Elektrické topení je sekundární úložiště přebytků. Nahřívání vody v akumulační nádrži přijde na řadu po nahřátí boileru. Pochopitelně pouze v topné sezóně. Pro energii ukládanou do topení (topná patrona v akumulační nádrži 500l) nenastavuju žádný limit. Jinými slovy předpokládám, že topení sežere neomezené množství energie.
Bohužel si nevedu žádné statistiky od kdy do kdy topím, takže topnou sezónu pouze odhadnu z toho, že průměrná denní teplota (za tři dny) poklesne pod 10°C.
df_day$TopSez <- filter(df_day$Ambient.Temperature..C., c(1/3,1/3,1/3), circular=T) < 10 cat(paste("Delka dopne sezony",sum(df_day$TopSez),"dni\n"))
Na základě topné sezóny a spotřeby boileru můžeme snadno dopočítat kolik energie zbyde na topení.
df_day$spotreba_tuv <- (df_day$AC.System.Output..W. - df_day$spotreba_boiler) * df_day$TopSez df_day$spotreba_tuv[df_day$spotreba_tuv < 0] <- 0
a následná statistika
sum_spotreba_tuv <- sum(df_day$spotreba_tuv)/1000 cat(paste("Topeni spotrebuje", round(sum_spotreba_tuv), "kWh", ", v cene", round(sum_spotreba_tuv*cena_nakup), "Kc\n"))
Topeni spotrebuje 879 kWh , v cene 2812 Kc
Je vidět, že do topení se příliš energie neuloží, zhruba 20%. Reálně bude toto číslo ještě nižší, protože zanedbávám vlastní spotřebu domácnosti. Nicméně vzhledem k nízké pořizovací ceně se zdá, že návratnost přidání druhé topné patrony do akumulační nádrže je celkem krátká.
Baterie jsou v současné době poměrně štědře dotované a pravděpodobně z tohoto důvodu jsou jednotlivými prodejci poměrně silně tlačené do hlav zákazníků. Pojďme se podívat, jak to vychází v mém případě.
Do baterie bych ukládal přebytky, které se nepodaří uložit do boileru a topení. Pro LiFePo technologii platí, že ji není rozumně možné vybít pod 30% kapacity. Pro jmenovitou kapacitu tedy platí
kapacita_baterky <- 7100 max_vybiti_baterky <- 0.3
Pro jednoduchost nebudu uvažovat účinnost nabíjení baterií, jejich samovybíjení, ani to, že během pracovního týdne baterii nebudu schopný plně vybít. Jedná se tedy o extrémně optimistický odhad.
df_day$baterka <- (df_day$AC.System.Output..W. - df_day$spotreba_boiler - df_day$spotreba_tuv) df_day$baterka[df_day$baterka < 0] <- 0 df_day$baterka[df_day$baterka > kapacita_baterky*(1-max_vybiti_baterky)] <- kapacita_baterky*(1-max_vybiti_baterky)
A následná statistika
cat(paste("Dodano do baterie", round(sum_baterka), "kWh", ", v cene", round(sum_baterka*cena_nakup), "Kc\n")) cat(paste("Pocet dni kdy baterka udela alespon 20% cyklus", sum(df_day$baterka > kapacita_baterky*(1-max_vybiti_baterky)*0.2),"\n"))
Pocet dni kdy baterka udela alespon 20% cyklus 153 Dodano do baterie 718 kWh , v cene 2299 Kc
Výsledek je neradostný, přes astronomickou pořizovací cenu baterie i ve velmi optimistickém odhadu, zvládne uložit energii v ceně 2300 Kč ročně. Návratnost je v mém případě daleko za životností baterie. Reálně nikdy. Je lepší přebytečnou energii prodat za 0.8 Kč a následně za 3.2 Kč nakoupit.
Někdo by mohl namítnout, že baterii můžu použit jako primární úložiště přebytků místo boileru. To ale nedává při cca 6% rozdílu ceny kWh v nízkém a vysokém tarifu smysl. Navíc bych pak z baterie nahříval vodu v boileru, případně topení a to bych si připadal opravdu jako blbec… :)
Další argument pro baterii je, že může sloužit jako záloha sítě. Pokud má ale baterie sloužit jako opravdová záloha sítě, tak ji nesmím vybíjet prakticky vůbec, protože ji potřebuju při výpadku sítě nabitou.
Baterii v dalších výpočtech neuvažuji (kapacitu baterie nastavuji na nulu).
Pro jednoduchost uvažuji, že vše co nebylo uloženo do boileru, topení nebo baterií prodám zpět do sítě. Jak už zaznělo v úvodu – je to značně pesimistické, ale pokud bude tento pesimistický odhad dávat ekonomicky smysl, stavbě elektrárny nic nebrání.
df_day$dodano_do_site <- df_day$AC.System.Output..W. - df_day$spotreba_boiler - df_day$spotreba_tuv - df_day$baterka
A opět statistika
sum_dodano_do_site <- sum(df_day$dodano_do_site)/1000 cat(paste("Dodano do site", round(sum_dodano_do_site), "kWh", ", v cene", round(sum_dodano_do_site*cena_prodej), "Kc\n"))
Dodano do site 2095 kWh , v cene 1676 Kc
V mém odhadu dodáme do sítě zhruba 45% vyrobené energie (zanedbávám vlastní spotřebu domácnosti).
Zbývá závěrečná statistika a výpočet návratnosti. Dále pro jistotu kontrolní součet, jestli se mi nějaká energie při výpočtu neztrácí.
celkovy_zisk <- sum_dodano_do_site*cena_prodej + sum_spotreba_tuv*cena_nakup + sum_spotreba_boiler*cena_nakup + sum_baterka*cena_nakup cat(paste("Celkovy soucet", round(sum_dodano_do_site+sum_spotreba_tuv+sum_spotreba_boiler + sum_baterka), "kWh", ", v cene", round(celkovy_zisk), "Kc\n")) cat(paste("Navratost", round((naklady) / celkovy_zisk,1), "let\n"))
Celkovy soucet 4475 kWh , v cene 9292 Kc Navratost 14 let
Je vidět, že i přes velmi pesimistické odhady je návratnost vstupní investice v době plánovaného života elektrárny. Reálně bude pravděpodobně ještě kratší.
Návratnost by se dala značně zkrátit realizací pouze jednofázového řešení. To se mi ale technicky nelíbí.
Na úplný závěr ještě graf, Modrá – boiler, Zelená – topení, Černá – prodáno do sítě, Obálka – celková výroba.
plot(df_day$Date, df_day$AC.System.Output..W., type="l", xlab="Date", ylab="E [Wh]") lines(df_day$Date, df_day$spotreba_tuv + df_day$spotreba_boiler + df_day$baterka, type="l", col="red") lines(df_day$Date, df_day$spotreba_tuv + df_day$spotreba_boiler, type="l", col="green") lines(df_day$Date, df_day$spotreba_boiler, type="l", col="blue")
#cena za 1kWh v Kc
cena_nakup <- 3.2
cena_prodej <- 0.8
kapacita_baterky <- 0 #7100
max_vybiti_baterky <- 0.3
naklady <- 130000
boiler_objem <- 150 #l
boiler_delta_T <- 60 #K; rozdil teplot vstupni voda/vystupni
boiler_akumulace <- boiler_objem * boiler_delta_T * 1.163 #kolik bolier muze naakumulovat [Wh]
boiler_spotreba <- 4500 #Wh
boiler_stav <- 0 #okamzita hodnota energie ulozene v boileru
#################### Nacteni vstupnich dat ####################
df <- read.csv("pvwatts_hourly_4.5kW.csv", skip=17)
#Odstraneni posledni radky s celkovym souctem
df <- head(df, -1)
df_day <- df[,c("AC.System.Output..W.", "Ambient.Temperature..C.")]
df_day$Date <- ISOdate(year=2020, month=df$Month, day=df$Day)
#denni soucet vykonu
df_sumP_day <- aggregate(AC.System.Output..W. ~ Date, data=df_day, sum)
df_sumP_day$AC.System.Output..W. <- df_sumP_day$AC.System.Output..W. * 1.15
#denni prumer teploty
df_mean_temp_day <- aggregate(Ambient.Temperature..C. ~ Date, data=df_day, mean)
#spojeni ramcu
df_day <- merge(df_sumP_day, df_mean_temp_day)
df_day$Ambient.Temperature..C. <- round(df_day$Ambient.Temperature..C., 2)
#################### Bioler ####################
df_day$spotreba_boiler <- NULL
df_day$stav_boiler <- NULL
for (i in (1:nrow(df_day)))
{
#tohle bych potreboval nahrat
chybi <- boiler_akumulace - boiler_stav
increment <- df_day$"AC.System.Output..W."[i]
if (increment > chybi)
{
increment <- chybi
}
boiler_stav <- boiler_stav + increment - boiler_spotreba
if (boiler_stav < 0)
{
boiler_stav <- 0
}
df_day[i, "spotreba_boiler"] <- increment
df_day[i, "boiler_stav"] <- boiler_stav
}
#celkova spotreba bioler v kWh
sum_spotreba_boiler <- sum(df_day$spotreba_boiler) / 1000
cat(paste("Boiler spotrebuje", round(sum_spotreba_boiler), "kWh", ", v cene", round(sum_spotreba_boiler*cena_nakup), "Kc\n"))
#################### Topeni ####################
#energie spotrebovana do topeni, neni omezena
#jenom ohrati 500l vody z 20 na 80C spotrebuje 35kWh.
#topna sezona
df_day$TopSez <- filter(df_day$Ambient.Temperature..C., c(1/3,1/3,1/3), circular=T) < 10
cat(paste("Delka dopne sezony",sum(df_day$TopSez),"dni\n"))
#plot(x=df_day$Date, y=df_day$Ambient.Temperature..C.)
#points(x=df_day$Date, y=df_day$TopSez, col="red", pch=".")
#plot(x=df_day$Date, y=df_day$AC.System.Output..W., type="l")
#points(x=df_day$Date, y=df_day$TopSez*1000, col="red", pch=".")
df_day$spotreba_tuv <- (df_day$AC.System.Output..W. - df_day$spotreba_boiler) * df_day$TopSez
df_day$spotreba_tuv[df_day$spotreba_tuv < 0] <- 0
#celkova energie spotrebovana topenim
sum_spotreba_tuv <- sum(df_day$spotreba_tuv)/1000
cat(paste("Topeni spotrebuje", round(sum_spotreba_tuv), "kWh", ", v cene", round(sum_spotreba_tuv*cena_nakup), "Kc\n"))
#################### Baterky ####################
#Jako hruby odhad co nenacpu do vody nacpu do baterek
#pocitam ze co do ni jeden den ulozim druhy den spotrebuju
df_day$baterka <- (df_day$AC.System.Output..W. - df_day$spotreba_boiler - df_day$spotreba_tuv)
df_day$baterka[df_day$baterka < 0] <- 0
df_day$baterka[df_day$baterka > kapacita_baterky*(1-max_vybiti_baterky)] <- kapacita_baterky*(1-max_vybiti_baterky) #lze vyuzit pouze 70 az 80% kapacity
sum_baterka <- sum(df_day$baterka)/1000
cat(paste("Dodano do baterie", round(sum_baterka), "kWh", ", v cene", round(sum_baterka*cena_nakup), "Kc\n"))
cat(paste("Pocet dni kdy baterka udela alespon 20% cyklus", sum(df_day$baterka > kapacita_baterky*(1-max_vybiti_baterky)*0.2),"\n"))
#################### dodano do site ####################
df_day$dodano_do_site <- df_day$AC.System.Output..W. - df_day$spotreba_boiler - df_day$spotreba_tuv - df_day$baterka
sum_dodano_do_site <- sum(df_day$dodano_do_site)/1000
cat(paste("Dodano do site", round(sum_dodano_do_site), "kWh", ", v cene", round(sum_dodano_do_site*cena_prodej), "Kc\n"))
celkovy_zisk <- sum_dodano_do_site*cena_prodej + sum_spotreba_tuv*cena_nakup + sum_spotreba_boiler*cena_nakup + sum_baterka*cena_nakup
#celkovy soucet
cat(paste("Celkovy soucet", round(sum_dodano_do_site+sum_spotreba_tuv+sum_spotreba_boiler + sum_baterka), "kWh", ", v cene", round(celkovy_zisk), "Kc\n"))
cat(paste("Navratost", round((naklady) / celkovy_zisk,1), "let\n"))
plot(df_day$Date, df_day$AC.System.Output..W., type="l", xlab="Date", ylab="E [Wh]")
lines(df_day$Date, df_day$spotreba_tuv + df_day$spotreba_boiler + df_day$baterka, type="l", col="red")
lines(df_day$Date, df_day$spotreba_tuv + df_day$spotreba_boiler, type="l", col="green")
lines(df_day$Date, df_day$spotreba_boiler, type="l", col="blue")
write.csv(df_day, "df_day.csv")
"PVWatts: Hourly PV Performance Data" "Requested Location:","..." "Location:","PRAGUE, CZECH REPUBLIC" "Lat (deg N):","50.1" "Long (deg E):","14.28" "Elev (m):","366" "DC System Size (kW):","4.5" "Module Type:","Standard" "Array Type:","Fixed (roof mount)" "Array Tilt (deg):","42" "Array Azimuth (deg):","180" "System Losses:","11.42" "Invert Efficiency:","96" "DC to AC Size Ratio:","1.2" "Average Cost of Electricity Purchased from Utility ($/kWh):","No utility data available" "Capacity Factor (%)","9.9" "Month","Day","Hour","Beam Irradiance (W/m^2)","Diffuse Irradiance (W/m^2)","Ambient Temperature (C)","Wind Speed (m/s)","Plane of Array Irradiance (W/m^2)","Cell Temperature (C)","DC Array Output (W)","AC System Output (W)" "1","1","0","0","0","2.8","9","0","2.8","0","0" "1","1","1","0","0","2.8","10","0","2.8","0","0" "1","1","2","0","0","2.6","11","0","2.6","0","0" "1","1","3","0","0","2.3","10","0","2.3","0","0" "1","1","4","0","0","2","9.3","0","2","0","0" "1","1","5","0","0","1.8","8.7","0","1.8","0","0" "1","1","6","0","0","1.1","8","0","1.1","0","0" "1","1","7","0","0","1.5","7.5","0","1.5","0","0" "1","1","8","0","12","2","7","10.447","0.796","46.379","22.577" "1","1","9","0","38","1.4","7","33.544","0.64","149.017","123.286" "1","1","10","5","89","1.7","7","96.195","2.145","424.525","393.187" "1","1","11","54","122","2.1","7","194.629","4.48","850.065","808.833" "1","1","12","105","131","2.4","7","269.154","6.325","1166.036","1116.49" "1","1","13","66","108","3","7","185.749","5.492","807.138","766.972" "1","1","14","4","68","2","7","75.222","2.296","331.664","302.286" "1","1","15","0","16","-0.2","7","13.943","-1.229","62.429","38.332" "1","1","16","0","0","-0.2","7.7","0","-0.2","0","0" "1","1","17","0","0","-0.3","8.3","0","-0.3","0","0" "1","1","18","0","0","-0.3","9","0","-0.3","0","0" "1","1","19","0","0","-0.2","8.5","0","-0.2","0","0" "1","1","20","0","0","0","8","0","0","0","0" "1","1","21","0","0","-0.4","10","0","-0.4","0","0" "1","1","22","0","0","-0.9","10.3","0","-0.9","0","0" "1","1","23","0","0","-1.3","10.7","0","-1.3","0","0" "1","2","0","0","0","-1.8","11","0","-1.8","0","0" "1","2","1","0","0","-1.7","12.7","0","-1.7","0","0" "1","2","2","0","0","-1.6","14.3","0","-1.6","0","0" "1","2","3","0","0","-1.5","16","0","-1.5","0","0" "1","2","4","0","0","-1.5","14.7","0","-1.5","0","0" "1","2","5","0","0","-1.6","13.3","0","-1.6","0","0" "1","2","6","0","0","-1.6","12","0","-1.6","0","0" "1","2","7","0","0","-1.3","12","0","-1.3","0","0" "1","2","8","0","9","-1","12","7.822","-1.862","35.114","11.519" "1","2","9","0","38","-0.4","11","33.508","-0.954","149.857","124.111" "1","2","10","0","70","-0.4","12","66.722","-0.466","297.791","269.111" "1","2","11","0","90","-0.3","13","87.839","-0.077","391.402","360.772" "1","2","12","0","92","-0.3","14","89.928","-0.051","400.669","369.841" "1","2","13","0","87","-0.7","12.3","87.362","-0.459","389.903","359.305" "1","2","14","0","59","-1.2","10.7","58.822","-1.34","263.496","235.512" "1","2","15","0","17","-1.6","9","14.819","-2.484","66.701","42.525" "1","2","16","0","0","-1.7","8","0","-1.7","0","0" "1","2","17","0","0","-1.9","7","0","-1.9","0","0" ... ... ... "12","31","8","0","18","1","1","15.782","-1.714","70.807","46.554" "12","31","9","43","81","1","1","141.427","3.4","618.691","583.024" "12","31","10","108","106","2","1","228.34","8.782","977.326","932.844" "12","31","11","16","111","2","2.1","127.074","4.71","554.665","520.46" "12","31","12","0","46","1.9","1","38.947","1.192","172.62","146.434" "12","31","13","0","38","2","1","32.141","0.259","143.013","117.398" "12","31","14","0","23","2","1","19.409","-0.309","86.569","62.023" "12","31","15","0","6","1.9","1","5.042","-1.093","22.564","0" "12","31","16","0","0","2","0","0","2","0","0" "12","31","17","0","0","2","1","0","2","0","0" "12","31","18","0","0","2.4","1","0","2.4","0","0" "12","31","19","0","0","2.4","2.1","0","2.4","0","0" "12","31","20","0","0","2.4","1","0","2.4","0","0" "12","31","21","0","0","2.5","1","0","2.5","0","0" "12","31","22","0","0","2.6","1","0","2.6","0","0" "12","31","23","0","0","2.8","1","0","2.8","0","0" "Totals", , ,"548990","639125","70832.4","35457","1042862.04","92150.127","4096890.72","3891512.84"
Kazdy to asi vidi jinak, pro me by delat tohle v excelu bylo utrpeni.
S tema senzorama a obecne merenim souhas. Pokud colvek nema data o spotrebe, tak se navratnost odhaduje blbe. A vubec by to nemuselo byt drahe, merit jako douho sviti kontrolka na boileru, nebo topi siprala pro topeni by bylo trivialni. Dopocitat z toho vykon/spotrebovanou energii (s dostacujici presnosti) by nebyl problem.