Files

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}")