144 lines
5.4 KiB
Python
144 lines
5.4 KiB
Python
import re
|
|
import matplotlib.pyplot as plt
|
|
import numpy as np
|
|
import pandas as pd
|
|
|
|
|
|
def parse_wit_log(file_path):
|
|
"""Parsea el archivo de log del WiT-CPV y extrae lecturas temporales."""
|
|
pattern = re.compile(
|
|
r"\[(?P<time>\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\] "
|
|
r"X:(?P<X>-?\d+),Y:(?P<Y>-?\d+),C:(?P<C>\d+),V:(?P<V>\d+),P:(?P<P>\d+),S:(?P<S>\d+)"
|
|
)
|
|
|
|
data = []
|
|
with open(file_path, "r", encoding="utf-8") as f:
|
|
for line in f:
|
|
match = pattern.search(line)
|
|
if match:
|
|
entry = match.groupdict()
|
|
data.append(
|
|
{
|
|
"timestamp": pd.to_datetime(entry["time"]),
|
|
"X_steps": int(entry["X"]),
|
|
"Y_steps": int(entry["Y"]),
|
|
"C_raw": int(entry["C"]), # Isc raw ADC counts
|
|
"V_raw": int(entry["V"]), # Voc raw ADC counts
|
|
"P_raw": int(entry["P"]), # Irradiance raw ADC counts
|
|
"S_elapsed": int(entry["S"]),
|
|
}
|
|
)
|
|
|
|
df = pd.DataFrame(data)
|
|
if df.empty:
|
|
raise ValueError("No se encontraron registros de mediciones en el archivo de log.")
|
|
|
|
# -------------------------------------------------------------------------
|
|
# Conversiones a Unidades Físicas (ADS122C04: 24-bit, Vref = 2.048V)
|
|
# -------------------------------------------------------------------------
|
|
ADC_MAX = 8388607.0 # 2^23 - 1
|
|
VREF_MV = 2048.0 # mV
|
|
|
|
# 1. Irradiancia Global en el Plano del Arreglo (G_POA in W/m2)
|
|
# Pira V2: (raw / ADC_MAX) * VREF_MV / 2.0
|
|
df["G_POA"] = (df["P_raw"] / ADC_MAX) * (VREF_MV / 2.0)
|
|
|
|
# 2. Voltaje de Circuito Abierto (Voc in Volts)
|
|
# Divisor 10k/10k (factor x2) -> (raw / ADC_MAX) * 2.048V * 2.0
|
|
df["Voc"] = (df["V_raw"] / ADC_MAX) * 2.048 * 2.0
|
|
|
|
# 3. Corriente de Cortocircuito (Isc in Amperes)
|
|
# V_shunt (mV) = (raw / ADC_MAX) * VREF_MV / Gain_AD8418 (20x)
|
|
# Isc (A) = V_shunt / R_shunt (75 mOhm = 0.075 Ohm)
|
|
df["V_shunt_mV"] = (df["C_raw"] / ADC_MAX) * (VREF_MV / 20.0)
|
|
df["Isc"] = (df["V_shunt_mV"] / 1000.0) / 0.075
|
|
|
|
# 4. Potencia Eléctrica Generada Estimada (P_CPV in Watts)
|
|
df["P_CPV"] = df["Voc"] * df["Isc"] * 0.82 #FILL FACTOR AL FINAL DE 0.82
|
|
|
|
# Diferencial de tiempo en horas (dt)
|
|
df["dt_hours"] = df["timestamp"].diff().dt.total_seconds() / 3600.0
|
|
df["dt_hours"] = df["dt_hours"].fillna(0)
|
|
|
|
return df
|
|
|
|
|
|
def calculate_energy_yield_metrics(df):
|
|
"""Calcula las métricas de Aprovechamiento Energético (E, H, E_1kWh/m2)."""
|
|
# Integración Trapezoidal para mayor precisión
|
|
# E: Energía Eléctrica Producida (Wh)
|
|
E_Wh = np.trapz(df["P_CPV"], x=df["timestamp"].astype("int64") / 1e9) / 3600.0
|
|
|
|
# H: Recurso Solar Recibido en el Plano (Wh/m2)
|
|
H_Wh_m2 = np.trapz(df["G_POA"], x=df["timestamp"].astype("int64") / 1e9) / 3600.0
|
|
|
|
# H convertido a kWh/m2
|
|
H_kWh_m2 = H_Wh_m2 / 1000.0
|
|
|
|
# E_1kWh/m2: Energía producida normalizada por cada 1 kWh/m2 de recurso solar
|
|
E_normalized = E_Wh / H_kWh_m2 if H_kWh_m2 > 0 else 0.0
|
|
|
|
metrics = {
|
|
"E_generada_Wh": E_Wh,
|
|
"H_irradiacion_Wh_m2": H_Wh_m2,
|
|
"H_irradiacion_kWh_m2": H_kWh_m2,
|
|
"E_normalizada_Wh_per_kWh_m2": E_normalized,
|
|
}
|
|
|
|
return metrics
|
|
|
|
|
|
def plot_energy_profile(df):
|
|
"""Genera las gráficas de potencia e irradiancia temporal."""
|
|
fig, ax1 = plt.subplots(figsize=(10, 5))
|
|
|
|
color = "tab:red"
|
|
ax1.set_xlabel("Hora del Día")
|
|
ax1.set_ylabel("Potencia CPV (W)", color=color)
|
|
ax1.plot(df["timestamp"], df["P_CPV"], color=color, linewidth=1.5, label="P_CPV (W)")
|
|
ax1.tick_params(axis="y", labelcolor=color)
|
|
ax1.grid(True, linestyle="--", alpha=0.6)
|
|
|
|
ax2 = ax1.twinx()
|
|
color = "tab:orange"
|
|
ax2.set_ylabel("Irradiancia G_POA (W/m²)", color=color)
|
|
ax2.plot(
|
|
df["timestamp"],
|
|
df["G_POA"],
|
|
color=color,
|
|
linestyle=":",
|
|
linewidth=1.5,
|
|
label="G_POA (W/m²)",
|
|
)
|
|
ax2.tick_params(axis="y", labelcolor=color)
|
|
|
|
plt.title("Perfil de Potencia Generada e Irradiancia Incidente")
|
|
fig.tight_layout()
|
|
plt.show()
|
|
|
|
|
|
# =============================================================================
|
|
# EJECUCIÓN DEL SCRIPT
|
|
# =============================================================================
|
|
if __name__ == "__main__":
|
|
file_path = "23092025.txt" # Ruta a tu archivo de log
|
|
|
|
try:
|
|
df_log = parse_wit_log(file_path)
|
|
metrics = calculate_energy_yield_metrics(df_log)
|
|
|
|
print("==================================================")
|
|
print(" MÉTRICAS DE APROVECHAMIENTO ENERGÉTICO ")
|
|
print("==================================================")
|
|
print(f"Energía Generada (E): {metrics['E_generada_Wh']:.4f} Wh")
|
|
print(f"Recurso Solar Incidente (H): {metrics['H_irradiacion_kWh_m2']:.4f} kWh/m²")
|
|
print(
|
|
f"Aprovechamiento (E_1kWh/m²): {metrics['E_normalizada_Wh_per_kWh_m2']:.4f} Wh / (kWh/m²)"
|
|
)
|
|
print("==================================================")
|
|
|
|
# Opcional: Graficar el perfil
|
|
plot_energy_profile(df_log)
|
|
|
|
except Exception as e:
|
|
print(f"Error procesando el archivo: {e}") |