Poprawki do testera - konwersja jednostek i obsługa przekładni

- Poprawiono obliczanie impedancji dla danych pierwotnych
- Dodano parametry PRZEKLADNIA i PRZEKLADNIA_NAPIECIA
- Dane są teraz konwertowane do wartości wtórnych przed obliczeniami
- Test na danych MOR-MIL: zwarcie wykryte prawidłowo

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-19 00:18:39 +01:00
parent a928855904
commit bdde63a8d8
6 changed files with 1170 additions and 86 deletions

View File

@@ -30,6 +30,23 @@ else:
print(f"=== Używany algorytm: {ALGORITHM_DESC} ===")
# ============================================================
# Przekładnia prądowa (domyślna) - zmień tę wartość dla swoich danych
# Dla rejestracji MOR-MIL: przekładnia 1000/5 = 200
# Dane z rejestracji są w wartościach PIERWOTNYCH
# Algorytm oczekuje wartości WTÓRNYCH
# Konwersja: dane_wtórne = dane_pierwotne / PRZEKLADNIA
PRZEKLADNIA = 200.0 # <-- zmień tę wartość (np. 200 dla przekładni 1000/5)
PRZEKLADNIA_NAPIECIA = 1100.0 # 110kV/100V = 1100
# Przekładnia efektywna dla Z = U/I
# Z_wt = (U_pierw/n_U) / (I_pierw/n_I) = Z_pierw * n_I/n_U
# Z_wt = Z_pierw / (PRZEKLADNIA_NAPIECIA / PRZEKLADNIA)
PRZEKLADNIA_EFF = PRZEKLADNIA_NAPIECIA / PRZEKLADNIA # = 1100/200 = 5.5
# Kierunek zabezpieczenia:
# Kierunek zabezpieczenia: 0=bez, 1=do linii, 2=do szyn
KIERUNEK = 0 # <-- zmień tę wartość (0=bez, 1=do linii, 2=do szyn)
# Obsluga argumentow wiersza polecen
if len(sys.argv) > 1:
base_name = sys.argv[1] # Nazwa pliku bez rozszerzenia
@@ -44,7 +61,7 @@ print(f"Wczytywanie rejestracji: {cfg_file}")
rec = Comtrade()
# Probuj rozne kodowania dla plikow CFG
encodings = ['utf-8', 'cp1250', 'cp1252', 'latin-1', 'iso-8859-1']
encodings = ['utf-8', 'cp1250', 'cp1252', 'latin-1', 'iso-8859-1', 'cp1251', 'cp1253']
loaded = False
for encoding in encodings:
@@ -83,13 +100,25 @@ print(f" Liczba probek na okres: {N}")
max_analog = min(6, num_analog)
# Pobierz tyle ile mamy
# Indeksy dla standardowych rejestracji (6 kanałów):
# 0:I_L1, 1:I_L2, 2:I_L3, 3:U_L1, 4:U_L2, 5:U_L3
# Dla MOR-MIL (22 kanały):
# 0:I_L1, 1:I_L2, 2:I_L3, 3:3Io, 4:U_L1, 5:U_L2, 6:U_L3
i1_raw = np.array(rec.analog[0])
i2_raw = np.array(rec.analog[1]) # Kanał 1: I_L2
i3_raw = np.array(rec.analog[2]) # Kanał 2: I_L3
u1_raw = np.array(rec.analog[3]) # Kanał 3: U_L1
u2_raw = np.array(rec.analog[4]) # Kanał 4: U_L2
u3_raw = np.array(rec.analog[5]) # Kanał 5: U_L3
# (musisz dopasować indeksy analog[] do swojego pliku .cfg)
i2_raw = np.array(rec.analog[1])
i3_raw = np.array(rec.analog[2])
# Wykryj typ rejestracji na podstawie liczby kanałów
if num_analog >= 7:
# Rejestracja z 7+ kanałami - użyj indeksów dla U_L1, U_L2, U_L3
u1_raw = np.array(rec.analog[4])
u2_raw = np.array(rec.analog[5])
u3_raw = np.array(rec.analog[6])
else:
# Standardowa rejestracja 6 kanałowa
u1_raw = np.array(rec.analog[3])
u2_raw = np.array(rec.analog[4])
u3_raw = np.array(rec.analog[5])
# === ANALIZA DANYCH - wyznaczenie impedancji przed zwarciem ===
print(f" Czestotliwosc probkowania: {Fs} Hz")
@@ -121,6 +150,12 @@ def calculate_impedance_from_raw(u_raw, i_raw, idx):
i_mag_sq = i_re**2 + i_im**2
if i_mag_sq < 1e-9:
return 0, 0
# Z_wt = Z_pierw / (n_U / n_I) = Z_pierw / PRZEKLADNIA_EFF
i_re = i_re / PRZEKLADNIA
i_im = i_im / PRZEKLADNIA
u_re = u_re / PRZEKLADNIA_NAPIECIA
u_im = u_im / PRZEKLADNIA_NAPIECIA
i_mag_sq = i_re**2 + i_im**2
z_re = (u_re * i_re + u_im * i_im) / i_mag_sq
z_x = (u_im * i_re - u_re * i_im) / i_mag_sq
return z_re, z_x
@@ -161,7 +196,7 @@ else:
print("Nie mozna wyznaczyc impedancji linii, uzywam wartosci domyslnych")
# Utworzenie relay z automatycznie dobranymi nastawami
relay = DistanceRelay(Z_line_R=Z_line_R, Z_line_X=Z_line_X, line_angle=line_angle)
relay = DistanceRelay(Z_line_R=Z_line_R, Z_line_X=Z_line_X, line_angle=line_angle, kierunek=KIERUNEK)
# Macierz operatora obrotu dla składowych symetrycznych
a = complex(-0.5, np.sqrt(3)/2)
@@ -185,6 +220,10 @@ z3_x_history = []
def calculate_impedance(u_cpx, i_cpx):
"""Oblicza impedancję Z = U/I jako liczbę zespoloną"""
# Konwersja do wartości wtórnych
i_cpx = complex(i_cpx.real / PRZEKLADNIA, i_cpx.imag / PRZEKLADNIA)
u_cpx = complex(u_cpx.real / PRZEKLADNIA_NAPIECIA, u_cpx.imag / PRZEKLADNIA_NAPIECIA)
i_mag_sq = i_cpx.real**2 + i_cpx.imag**2
if i_mag_sq < 1e-9: # Zabezpieczenie przed dzieleniem przez zero
return 0.0, 0.0
@@ -210,6 +249,8 @@ for i in range(N, len(t)):
u2_re, u2_im = fcdft(window_u2)
u3_re, u3_im = fcdft(window_u3)
# Konwersja do wartości wtórnych (dla calculate_impedance_from_raw)
# Tworzenie liczb zespolonych dla łatwiejszej matematyki symetrycznej
I1_cpx = complex(i1_re, i1_im)
I2_cpx = complex(i2_re, i2_im)