Powerwall: Es rentable instalar una bateria en una instalación solar?
Powerwall: Es rentable instalar una batería en una instalación solar?
En el capítulo de hoy te enseñamos a calcular los ahorros producidos al instalar una batería o powerwall. Con el siguiente script vas a poder simular el uso de una batería sobre tus datos históricos y poder calcular tus ahorros..
A continuación el panel de Grafana:
{ "annotations": { "list": [ { "builtIn": 1, "datasource": "-- Grafana --", "enable": true, "hide": true, "iconColor": "rgba(0, 211, 255, 1)", "name": "Annotations & Alerts", "type": "dashboard" } ] }, "editable": true, "gnetId": null, "graphTooltip": 0, "id": 25, "links": [], "panels": [ { "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, "datasource": "InfluxDB", "fieldConfig": { "defaults": { "custom": {} }, "overrides": [] }, "fill": 1, "fillGradient": 0, "gridPos": { "h": 14, "w": 12, "x": 0, "y": 0 }, "hiddenSeries": false, "id": 2, "legend": { "avg": false, "current": false, "max": false, "min": false, "show": true, "total": false, "values": false }, "lines": true, "linewidth": 1, "nullPointMode": "null", "options": { "alertThreshold": true }, "percentage": false, "pluginVersion": "7.4.2", "pointradius": 2, "points": false, "renderer": "flot", "seriesOverrides": [ { "$$hashKey": "object:233", "alias": "porcentajebateria", "yaxis": 2 }, { "$$hashKey": "object:545", "alias": "porecentajebateria10kwh", "yaxis": 2 } ], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "alias": "", "groupBy": [ { "params": [ "$__interval" ], "type": "time" }, { "params": [ "null" ], "type": "fill" } ], "hide": false, "measurement": "iota_lineaDistribuidora", "orderByTime": "ASC", "policy": "default", "query": "SELECT mean(\"value\") FROM /^$Variable$/ WHERE $timeFilter GROUP BY time($__interval) fill(null)", "rawQuery": false, "refId": "A", "resultFormat": "time_series", "select": [ [ { "params": [ "value" ], "type": "field" }, { "params": [], "type": "mean" } ] ], "tags": [] }, { "groupBy": [ { "params": [ "$__interval" ], "type": "time" }, { "params": [ "null" ], "type": "fill" } ], "hide": false, "measurement": "battery_3kwh", "orderByTime": "ASC", "policy": "default", "refId": "B", "resultFormat": "time_series", "select": [ [ { "params": [ "net" ], "type": "field" }, { "params": [], "type": "mean" } ] ], "tags": [] }, { "alias": "net_delivery_3kw", "groupBy": [ { "params": [ "$__interval" ], "type": "time" }, { "params": [ "null" ], "type": "fill" } ], "hide": false, "measurement": "battery_3kwh", "orderByTime": "ASC", "policy": "default", "refId": "C", "resultFormat": "time_series", "select": [ [ { "params": [ "net_delivery" ], "type": "field" }, { "params": [], "type": "mean" } ] ], "tags": [] }, { "alias": "net_usage_3kw", "groupBy": [ { "params": [ "$__interval" ], "type": "time" }, { "params": [ "null" ], "type": "fill" } ], "hide": false, "measurement": "battery_3kwh", "orderByTime": "ASC", "policy": "default", "refId": "D", "resultFormat": "time_series", "select": [ [ { "params": [ "net_usage" ], "type": "field" }, { "params": [], "type": "mean" } ] ], "tags": [] } ], "thresholds": [], "timeFrom": null, "timeRegions": [], "timeShift": null, "title": "Panel Title", "tooltip": { "shared": true, "sort": 0, "value_type": "individual" }, "type": "graph", "xaxis": { "buckets": null, "mode": "time", "name": null, "show": true, "values": [] }, "yaxes": [ { "$$hashKey": "object:277", "format": "short", "label": null, "logBase": 1, "max": null, "min": null, "show": true }, { "$$hashKey": "object:278", "format": "short", "label": null, "logBase": 1, "max": "102", "min": "0", "show": true } ], "yaxis": { "align": false, "alignLevel": null } }, { "datasource": "InfluxDB", "fieldConfig": { "defaults": { "custom": {}, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "red", "value": null } ] }, "unit": "watth" }, "overrides": [] }, "gridPos": { "h": 3, "w": 9, "x": 12, "y": 0 }, "id": 4, "options": { "colorMode": "value", "graphMode": "none", "justifyMode": "auto", "orientation": "auto", "reduceOptions": { "calcs": [ "mean" ], "fields": "", "values": false }, "text": {}, "textMode": "auto" }, "pluginVersion": "7.4.2", "targets": [ { "alias": "Importada TOTAL", "groupBy": [ { "params": [ "$__interval" ], "type": "time" }, { "params": [ "null" ], "type": "fill" } ], "measurement": "energia_total", "orderByTime": "ASC", "policy": "default", "query": "SELECT integral(\"iota_importada\",1h) FROM \"energia_total\" WHERE $timeFilter ", "rawQuery": true, "refId": "D", "resultFormat": "time_series", "select": [ [ { "params": [ "iota_importada" ], "type": "field" }, { "params": [], "type": "integral" } ] ], "tags": [] }, { "alias": "Importada P1", "groupBy": [ { "params": [ "$__interval" ], "type": "time" }, { "params": [ "null" ], "type": "fill" } ], "hide": false, "orderByTime": "ASC", "policy": "default", "query": "SELECT integral(\"iota_importada_p1\",1h) FROM \"energia_total\" WHERE $timeFilter ", "rawQuery": true, "refId": "A", "resultFormat": "time_series", "select": [ [ { "params": [ "value" ], "type": "field" }, { "params": [], "type": "mean" } ] ], "tags": [] }, { "alias": "Importada P2", "groupBy": [ { "params": [ "$__interval" ], "type": "time" }, { "params": [ "null" ], "type": "fill" } ], "hide": false, "orderByTime": "ASC", "policy": "default", "query": "SELECT integral(\"iota_importada_p2\",1h) FROM \"energia_total\" WHERE $timeFilter ", "rawQuery": true, "refId": "B", "resultFormat": "time_series", "select": [ [ { "params": [ "value" ], "type": "field" }, { "params": [], "type": "mean" } ] ], "tags": [] } ], "timeFrom": null, "timeShift": null, "title": "IMPORTADA", "type": "stat" }, { "datasource": "InfluxDB", "fieldConfig": { "defaults": { "custom": {}, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null } ] }, "unit": "watth" }, "overrides": [] }, "gridPos": { "h": 4, "w": 9, "x": 12, "y": 3 }, "id": 5, "options": { "colorMode": "value", "graphMode": "none", "justifyMode": "auto", "orientation": "auto", "reduceOptions": { "calcs": [ "mean" ], "fields": "", "values": false }, "text": {}, "textMode": "auto" }, "pluginVersion": "7.4.2", "targets": [ { "alias": "TOTAL", "groupBy": [ { "params": [ "$__interval" ], "type": "time" }, { "params": [ "null" ], "type": "fill" } ], "measurement": "energia_total", "orderByTime": "ASC", "policy": "default", "query": "SELECT integral(\"iota_excedente\",1h) FROM \"energia_total\" WHERE $timeFilter", "rawQuery": true, "refId": "D", "resultFormat": "time_series", "select": [ [ { "params": [ "iota_excedente" ], "type": "field" }, { "params": [], "type": "integral" } ] ], "tags": [] }, { "alias": "Exportada P1", "groupBy": [ { "params": [ "$__interval" ], "type": "time" }, { "params": [ "null" ], "type": "fill" } ], "hide": false, "orderByTime": "ASC", "policy": "default", "query": "SELECT integral(\"iota_excedente_p1\",1h) FROM \"energia_total\" WHERE $timeFilter ", "rawQuery": true, "refId": "A", "resultFormat": "time_series", "select": [ [ { "params": [ "value" ], "type": "field" }, { "params": [], "type": "mean" } ] ], "tags": [] }, { "alias": "Exportada P2", "groupBy": [ { "params": [ "$__interval" ], "type": "time" }, { "params": [ "null" ], "type": "fill" } ], "hide": false, "orderByTime": "ASC", "policy": "default", "query": "SELECT integral(\"iota_excedente_p2\",1h) FROM \"energia_total\" WHERE $timeFilter ", "rawQuery": true, "refId": "B", "resultFormat": "time_series", "select": [ [ { "params": [ "value" ], "type": "field" }, { "params": [], "type": "mean" } ] ], "tags": [] } ], "timeFrom": null, "timeShift": null, "title": "EXCEDENTE", "type": "stat" }, { "datasource": "InfluxDB", "fieldConfig": { "defaults": { "custom": {}, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "red", "value": null } ] }, "unit": "watth" }, "overrides": [] }, "gridPos": { "h": 3, "w": 9, "x": 12, "y": 7 }, "id": 6, "options": { "colorMode": "value", "graphMode": "none", "justifyMode": "auto", "orientation": "auto", "reduceOptions": { "calcs": [ "mean" ], "fields": "", "values": false }, "text": {}, "textMode": "auto" }, "pluginVersion": "7.4.2", "targets": [ { "alias": "Importada TOTAL", "groupBy": [ { "params": [ "$__interval" ], "type": "time" }, { "params": [ "null" ], "type": "fill" } ], "measurement": "battery_3kwh", "orderByTime": "ASC", "policy": "default", "query": "SELECT integral(\"net_usage\",1h) FROM \"battery_5kwh\" WHERE $timeFilter", "rawQuery": true, "refId": "D", "resultFormat": "time_series", "select": [ [ { "params": [ "net_usage" ], "type": "field" }, { "params": [], "type": "integral" } ] ], "tags": [] }, { "alias": "Importada P1", "groupBy": [ { "params": [ "$__interval" ], "type": "time" }, { "params": [ "null" ], "type": "fill" } ], "hide": false, "orderByTime": "ASC", "policy": "default", "query": "SELECT integral(\"net_usage_p2\",1h) FROM \"battery_5kwh\" WHERE $timeFilter", "rawQuery": true, "refId": "A", "resultFormat": "time_series", "select": [ [ { "params": [ "value" ], "type": "field" }, { "params": [], "type": "mean" } ] ], "tags": [] }, { "alias": "Importada P2", "groupBy": [ { "params": [ "$__interval" ], "type": "time" }, { "params": [ "null" ], "type": "fill" } ], "hide": false, "orderByTime": "ASC", "policy": "default", "query": "SELECT integral(\"net_usage_p1\",1h) FROM \"battery_5kwh\" WHERE $timeFilter", "rawQuery": true, "refId": "B", "resultFormat": "time_series", "select": [ [ { "params": [ "value" ], "type": "field" }, { "params": [], "type": "mean" } ] ], "tags": [] } ], "timeFrom": null, "timeShift": null, "title": "IMPORTADA 5KWH", "type": "stat" }, { "datasource": "InfluxDB", "fieldConfig": { "defaults": { "custom": {}, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null } ] }, "unit": "watth" }, "overrides": [] }, "gridPos": { "h": 4, "w": 9, "x": 12, "y": 10 }, "id": 7, "options": { "colorMode": "value", "graphMode": "none", "justifyMode": "auto", "orientation": "auto", "reduceOptions": { "calcs": [ "mean" ], "fields": "", "values": false }, "text": {}, "textMode": "auto" }, "pluginVersion": "7.4.2", "targets": [ { "alias": "TOTAL", "groupBy": [ { "params": [ "$__interval" ], "type": "time" }, { "params": [ "null" ], "type": "fill" } ], "measurement": "battery_3kwh", "orderByTime": "ASC", "policy": "default", "query": "SELECT integral(\"net_delivery\",1h) FROM \"battery_5kwh\" WHERE $timeFilter ", "rawQuery": true, "refId": "D", "resultFormat": "time_series", "select": [ [ { "params": [ "net_delivery" ], "type": "field" }, { "params": [], "type": "integral" } ] ], "tags": [] }, { "alias": "Exportada P1", "groupBy": [ { "params": [ "$__interval" ], "type": "time" }, { "params": [ "null" ], "type": "fill" } ], "hide": false, "orderByTime": "ASC", "policy": "default", "query": "SELECT integral(\"net_delivery_p2\",1h) FROM \"battery_5kwh\" WHERE $timeFilter ", "rawQuery": true, "refId": "A", "resultFormat": "time_series", "select": [ [ { "params": [ "value" ], "type": "field" }, { "params": [], "type": "mean" } ] ], "tags": [] }, { "alias": "Exportada P2", "groupBy": [ { "params": [ "$__interval" ], "type": "time" }, { "params": [ "null" ], "type": "fill" } ], "hide": false, "orderByTime": "ASC", "policy": "default", "query": "SELECT integral(\"net_delivery_p1\",1h) FROM \"battery_5kwh\" WHERE $timeFilter ", "rawQuery": true, "refId": "B", "resultFormat": "time_series", "select": [ [ { "params": [ "value" ], "type": "field" }, { "params": [], "type": "mean" } ] ], "tags": [] } ], "timeFrom": null, "timeShift": null, "title": "EXCEDENTE 5KWH", "type": "stat" }, { "datasource": "InfluxDB", "fieldConfig": { "defaults": { "custom": {}, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "red", "value": null } ] }, "unit": "watth" }, "overrides": [] }, "gridPos": { "h": 3, "w": 9, "x": 12, "y": 14 }, "id": 8, "options": { "colorMode": "value", "graphMode": "none", "justifyMode": "auto", "orientation": "auto", "reduceOptions": { "calcs": [ "mean" ], "fields": "", "values": false }, "text": {}, "textMode": "auto" }, "pluginVersion": "7.4.2", "targets": [ { "alias": "Importada TOTAL", "groupBy": [ { "params": [ "$__interval" ], "type": "time" }, { "params": [ "null" ], "type": "fill" } ], "measurement": "battery_3kwh", "orderByTime": "ASC", "policy": "default", "query": "SELECT integral(\"net_usage\",1h) FROM \"battery_20kwh\" WHERE $timeFilter", "rawQuery": true, "refId": "D", "resultFormat": "time_series", "select": [ [ { "params": [ "net_usage" ], "type": "field" }, { "params": [], "type": "integral" } ] ], "tags": [] }, { "alias": "Importada P1", "groupBy": [ { "params": [ "$__interval" ], "type": "time" }, { "params": [ "null" ], "type": "fill" } ], "hide": false, "orderByTime": "ASC", "policy": "default", "query": "SELECT integral(\"net_usage_p2\",1h) FROM \"battery_20kwh\" WHERE $timeFilter", "rawQuery": true, "refId": "A", "resultFormat": "time_series", "select": [ [ { "params": [ "value" ], "type": "field" }, { "params": [], "type": "mean" } ] ], "tags": [] }, { "alias": "Importada P2", "groupBy": [ { "params": [ "$__interval" ], "type": "time" }, { "params": [ "null" ], "type": "fill" } ], "hide": false, "orderByTime": "ASC", "policy": "default", "query": "SELECT integral(\"net_usage_p1\",1h) FROM \"battery_20kwh\" WHERE $timeFilter", "rawQuery": true, "refId": "B", "resultFormat": "time_series", "select": [ [ { "params": [ "value" ], "type": "field" }, { "params": [], "type": "mean" } ] ], "tags": [] } ], "timeFrom": null, "timeShift": null, "title": "IMPORTADA 20KWH", "type": "stat" }, { "datasource": "InfluxDB", "fieldConfig": { "defaults": { "custom": {}, "mappings": [], "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null } ] }, "unit": "watth" }, "overrides": [] }, "gridPos": { "h": 4, "w": 9, "x": 12, "y": 17 }, "id": 9, "options": { "colorMode": "value", "graphMode": "none", "justifyMode": "auto", "orientation": "auto", "reduceOptions": { "calcs": [ "mean" ], "fields": "", "values": false }, "text": {}, "textMode": "auto" }, "pluginVersion": "7.4.2", "targets": [ { "alias": "TOTAL", "groupBy": [ { "params": [ "$__interval" ], "type": "time" }, { "params": [ "null" ], "type": "fill" } ], "measurement": "battery_3kwh", "orderByTime": "ASC", "policy": "default", "query": "SELECT integral(\"net_delivery\",1h) FROM \"battery_20kwh\" WHERE $timeFilter ", "rawQuery": true, "refId": "D", "resultFormat": "time_series", "select": [ [ { "params": [ "net_delivery" ], "type": "field" }, { "params": [], "type": "integral" } ] ], "tags": [] }, { "alias": "Exportada P1", "groupBy": [ { "params": [ "$__interval" ], "type": "time" }, { "params": [ "null" ], "type": "fill" } ], "hide": false, "orderByTime": "ASC", "policy": "default", "query": "SELECT integral(\"net_delivery_p2\",1h) FROM \"battery_20kwh\" WHERE $timeFilter ", "rawQuery": true, "refId": "A", "resultFormat": "time_series", "select": [ [ { "params": [ "value" ], "type": "field" }, { "params": [], "type": "mean" } ] ], "tags": [] }, { "alias": "Exportada P2", "groupBy": [ { "params": [ "$__interval" ], "type": "time" }, { "params": [ "null" ], "type": "fill" } ], "hide": false, "orderByTime": "ASC", "policy": "default", "query": "SELECT integral(\"net_delivery_p1\",1h) FROM \"battery_20kwh\" WHERE $timeFilter ", "rawQuery": true, "refId": "B", "resultFormat": "time_series", "select": [ [ { "params": [ "value" ], "type": "field" }, { "params": [], "type": "mean" } ] ], "tags": [] } ], "timeFrom": null, "timeShift": null, "title": "EXCEDENTE 20KWH", "type": "stat" } ], "refresh": false, "schemaVersion": 27, "style": "dark", "tags": [], "templating": { "list": [] }, "time": { "from": "2020-07-27T22:00:00.000Z", "to": "2020-07-30T21:59:59.000Z" }, "timepicker": {}, "timezone": "", "title": "Rentabilidad Bateria", "uid": "V2iNr2-Gz", "version": 6 }
El script de Python ‘calcula_tu_Bateria.py’:
#!/usr/bin/env python3 # by Luis Gonzalez https://domotica.solar from influxdb import InfluxDBClient import datetime import time import re import pytz #CONFIGURE DATABASE ACCESS influx_client = InfluxDBClient('influxdb.local', 8086, 'USER', 'PASSWORD', 'casaluis') def influx(measurements): try: influx_client.write_points(measurements) except Exception as e: print('Failed to write to influxdb: ', e) def charge(battery, power_line): if power_line > 0: #getting power from company. Check ammount battery. If discharging apply efficiency of charge/discharge battery if (battery['level'] * battery['power_sample_rate']) - (power_line / battery['efficiency']) < (battery['min'] * battery['power_sample_rate']): #not enough battery, getting power from net remaining_battery = battery['level'] - battery['min'] battery['level'] = battery['min'] battery['net_usage'] = (power_line - (remaining_battery * battery['efficiency'] * battery['power_sample_rate'])) else: # enough battery. Getting power only from battery battery['level'] = battery['level'] - (power_line / battery['efficiency'] / battery['power_sample_rate']) battery['net_delivery'] = 0 else: #reverse powerline power_line=-1*power_line #exporting energy. Check if there is enough space in battery. if (battery['level'] + (power_line / battery['power_sample_rate']) > battery['max']): #not enough space on battery, delivering to net remaining_battery = battery['max'] - battery['level'] battery['level'] = battery['max'] battery['net_delivery'] = power_line - (remaining_battery / battery['power_sample_rate']) else: #enough space on battery, charging battery battery['level'] = battery['level'] + power_line / battery['power_sample_rate'] battery['net_usage'] = 0 battery['level_percentage']=battery['level']/battery['max']*100 return battery def main(): prev_point = None measurements = [] #in UTC=0 starttime = '2020-01-01 00:00:00' endtime = '2020-12-31 23:59:59' ##baterry configuration battery = { "level": 0, "level_percentage": 0, "net_usage": 0, "net_delivery": 0, "min": 0, #MINIMO "max": 20000, #CAPACIDAD "label": "_20kwh", "efficiency": 0.9, "power_sample_rate": 3600, #power samples per hour "influx_meassurement": "iota_lineaDistribuidora", } cache_size=1000; #delete serie if exists result = influx_client.query('delete from "battery' + battery['label'] + '"') query = "select * from " + battery['influx_meassurement'] + " where time >= '" + format(starttime) + "' and time < '" + format(endtime) + "' order by time;"; print(query) result = influx_client.query(query) points = result.get_points() i=0 for point in points: for key in ['value']: # full timestamp with milliseconds match = re.match(r"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+Z", point['time']) if match: fecha=datetime.datetime.strptime(point['time'], "%Y-%m-%dT%H:%M:%S.%fZ") # timestamp missing milliseconds match = re.match(r"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z", point['time']) if match: fecha=datetime.datetime.strptime(point['time'], "%Y-%m-%dT%H:%M:%SZ") #hora=point['time'].hour #print(fecha.hour) charge(battery,point['value']) # if point['value']>=0: # iota_excedente=0 # iota_importada=point['value'] # else: # iota_importada=0 # iota_excedente=-1*point['value'] if fecha.hour>=11 and fecha.hour<21: net_delivery_p2=0 net_delivery_p1=battery['net_delivery'] net_usage_p2=0 net_usage_p1=battery['net_usage'] tramo=2 else: net_delivery_p1=0 net_delivery_p2=battery['net_delivery'] net_usage_p1=0 net_usage_p2=battery['net_usage'] tramo=1 i=i+1 battery['net']=battery['net_usage']-battery['net_delivery'] if i==cache_size: print("Punto=>" + format(point['time']) + " Tramo=" + format(tramo) + " " + format(point['value']) + "W Bateria=" + '{:04.1f}%'.format(battery['level_percentage'])) i=0 measurements.append({ "measurement": "battery" + battery['label'], "time": point['time'], "fields": { "net_usage": float(battery['net_usage']), "net_delivery": float(battery['net_delivery']), "level_percentage": float(battery['level_percentage']), "net_delivery_p1": float(net_delivery_p1), "net_delivery_p2": float(net_delivery_p2), "net_usage_p1": float(net_usage_p1), "net_usage_p2": float(net_usage_p2), "net": float(battery['net']), "tramo": float(tramo), }, }) if len(measurements) > cache_size: influx(measurements) print(".") measurements = [] influx(measurements) #print(tramo) if __name__ == "__main__": main()
y por último el fichero de excel:
Aquí tenéis la lista de los componentes necesarios para montar tu propia instalación:
¡También te pueden interesar estos otros vídeos!
Instala el software en la raspberry
Una introducción a NodeRed
Hola soy Diego.
Has probado a calcular que batería sería necesaria para desconectarte.
Me encantan tus vídeos.
Genial! te han salido buenos numeros?
Hola Luis
He intentado usar el script de Python, pero al menos a mi me da problemas en las líneas 23, 68 y 75 con los comentarios, que se han introducido entre medias y ha perdido las indentaciones¿Podrías volver a pegarlo?
Gracias
Gracias