Initial
This commit is contained in:
23
IIR_filter.py
Normal file
23
IIR_filter.py
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import numpy as np
|
||||||
|
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
import fft
|
||||||
|
|
||||||
|
class IIR_1_Order_LP(object):
|
||||||
|
"""docstring for fft_meas"""
|
||||||
|
def __init__(self, fs, fc=200):
|
||||||
|
self.fs = fs
|
||||||
|
self.fc = fc
|
||||||
|
self.dt = 1/self.fs
|
||||||
|
self.RC = 1 / (2*np.pi*self.fc)
|
||||||
|
self.alpha = self.dt / (self.RC + self.dt)
|
||||||
|
|
||||||
|
self.y = 0
|
||||||
|
|
||||||
|
def step(self, x):
|
||||||
|
self.y = self.y + self.alpha * (x - self.y)
|
||||||
|
return self.y
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
BIN
__pycache__/IIR_filter.cpython-312.pyc
Normal file
BIN
__pycache__/IIR_filter.cpython-312.pyc
Normal file
Binary file not shown.
BIN
__pycache__/fft.cpython-312.pyc
Normal file
BIN
__pycache__/fft.cpython-312.pyc
Normal file
Binary file not shown.
BIN
__pycache__/fft_meas.cpython-312.pyc
Normal file
BIN
__pycache__/fft_meas.cpython-312.pyc
Normal file
Binary file not shown.
BIN
__pycache__/ftt.cpython-312.pyc
Normal file
BIN
__pycache__/ftt.cpython-312.pyc
Normal file
Binary file not shown.
BIN
__pycache__/ftt_meas.cpython-312.pyc
Normal file
BIN
__pycache__/ftt_meas.cpython-312.pyc
Normal file
Binary file not shown.
BIN
__pycache__/zerocross_meas.cpython-312.pyc
Normal file
BIN
__pycache__/zerocross_meas.cpython-312.pyc
Normal file
Binary file not shown.
58
fft.py
Normal file
58
fft.py
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
import numpy as np
|
||||||
|
|
||||||
|
|
||||||
|
def fft(x, fs, X_nom=None, epsilon=None):
|
||||||
|
|
||||||
|
# Implementation from IEC 61000-4-7:2002/AMD1:2008
|
||||||
|
|
||||||
|
|
||||||
|
# Data length
|
||||||
|
N = len(x)
|
||||||
|
# Number of positive-frequency bins
|
||||||
|
K = int(np.floor(N/2))
|
||||||
|
# Frequency axis (0 .. fs/2)
|
||||||
|
#freq = np.linspace(start=0, stop=fs/2, num=K+1, endpoint=True)
|
||||||
|
freq = np.arange(K + 1) * fs / N
|
||||||
|
|
||||||
|
# allocate
|
||||||
|
a = np.zeros(K + 1)
|
||||||
|
b = np.zeros(K + 1)
|
||||||
|
c = np.zeros(K + 1)
|
||||||
|
Y_C = np.zeros(K + 1)
|
||||||
|
phi = np.zeros(K + 1)
|
||||||
|
|
||||||
|
n = np.arange(N)
|
||||||
|
|
||||||
|
# DC
|
||||||
|
c[0] = np.mean(x) # c0 per IEC
|
||||||
|
a[0] = 2 * c[0] # not really used; just for completeness
|
||||||
|
b[0] = 0.0
|
||||||
|
|
||||||
|
# k = 1..K
|
||||||
|
for k in range(1, K+1):
|
||||||
|
angle = 2 * np.pi * k * n / N
|
||||||
|
a[k] = (2/N) * np.sum(x * np.cos(angle))
|
||||||
|
b[k] = (2/N) * np.sum(x * np.sin(angle))
|
||||||
|
|
||||||
|
# Nyquist (if N even): do NOT apply the 2/N doubling
|
||||||
|
if (N % 2 == 0) and (k == K):
|
||||||
|
a[k] *= 0.5
|
||||||
|
b[k] *= 0.5
|
||||||
|
c[k] = np.sqrt(a[k]*a[k] + b[k]*b[k])
|
||||||
|
|
||||||
|
# RMS value calculated in Eq.2.
|
||||||
|
Y_C[k] = c[k] / np.sqrt(2)
|
||||||
|
|
||||||
|
|
||||||
|
# Phase: apply dead-band if provided, else always compute
|
||||||
|
if (X_nom is not None) and (epsilon is not None):
|
||||||
|
if (np.abs(a[k]) <= epsilon * X_nom) and (np.abs(b[k]) <= epsilon * X_nom):
|
||||||
|
phi[k] = 0.0
|
||||||
|
continue
|
||||||
|
|
||||||
|
# IEC quadrant handling (equivalent to the piecewise definition)
|
||||||
|
phi[k] = np.arctan2(a[k], b[k])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return freq, a, b, c, Y_C, phi
|
||||||
49
fft_meas.py
Normal file
49
fft_meas.py
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
import numpy as np
|
||||||
|
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
import fft
|
||||||
|
|
||||||
|
class fft_meas(object):
|
||||||
|
"""docstring for fft_meas"""
|
||||||
|
def __init__(self, fs=50e3, tn=0.2):
|
||||||
|
self.fs = fs
|
||||||
|
self.ts = 1/fs
|
||||||
|
self.tn = tn
|
||||||
|
self.N = int(int(fs*tn))
|
||||||
|
self.data = np.zeros(self.N)
|
||||||
|
self.idx = -1
|
||||||
|
self.time = 0
|
||||||
|
|
||||||
|
self.freq = 0
|
||||||
|
self.a = 0
|
||||||
|
self.b = 0
|
||||||
|
self.c = 0
|
||||||
|
self.Y_C = 0
|
||||||
|
self.phi = 0
|
||||||
|
|
||||||
|
def step(self, data, time, f_H1, unit):
|
||||||
|
|
||||||
|
if time - self.time > self.ts:
|
||||||
|
self.time = time
|
||||||
|
self.idx += 1
|
||||||
|
|
||||||
|
self.data[self.idx] = data
|
||||||
|
|
||||||
|
if self.idx == self.N-1:
|
||||||
|
|
||||||
|
|
||||||
|
self.freq , self.a, self.b , self.c, self.Y_C, self.phi = fft.fft(x=self.data, fs=self.fs)
|
||||||
|
|
||||||
|
self.idx = -1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def plot(self):
|
||||||
|
#fs, a, b, c, YC, phi = ftt.fft(Ph1, sample_freq)
|
||||||
|
|
||||||
|
plt.plot(self.freq, self.c)
|
||||||
|
plt.xlabel("x")
|
||||||
|
plt.ylabel("y")
|
||||||
|
plt.title("Simple plot")
|
||||||
|
plt.show()
|
||||||
|
|
||||||
46
main.py
Normal file
46
main.py
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
|
||||||
|
import numpy as np
|
||||||
|
import fft_meas
|
||||||
|
import zerocross_meas
|
||||||
|
|
||||||
|
|
||||||
|
# to do
|
||||||
|
# Need a zero-cross algorithem to comply with 61000-4-30
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
time = 0
|
||||||
|
delta_t = 1e-6
|
||||||
|
t_stop = 1.1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
amplitude = 1
|
||||||
|
base_freq = 50
|
||||||
|
|
||||||
|
|
||||||
|
fft_measurements = fft_meas.fft_meas(fs=50e3, tn=0.2)
|
||||||
|
zerocross = zerocross_meas.zerocross_meas(fs=50e3, tn=1)
|
||||||
|
|
||||||
|
for i in range(0, int(t_stop/delta_t)+1):
|
||||||
|
Ph1 = np.sin(2*np.pi*time*base_freq)
|
||||||
|
|
||||||
|
|
||||||
|
zerocross.step(x=Ph1, time=time)
|
||||||
|
|
||||||
|
fft_measurements.step(data=Ph1, time=time, f_H1=zerocross.freq, unit="I")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
time += delta_t
|
||||||
|
|
||||||
|
|
||||||
|
zerocross.print()
|
||||||
|
#fft_measurements.plot()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
41
zerocross_meas.py
Normal file
41
zerocross_meas.py
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
import numpy as np
|
||||||
|
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
import fft
|
||||||
|
import IIR_filter
|
||||||
|
|
||||||
|
class zerocross_meas(object):
|
||||||
|
"""docstring for fft_meas"""
|
||||||
|
def __init__(self, fs=50e3, tn=1):
|
||||||
|
self.fs = fs
|
||||||
|
self.ts = 1/self.fs
|
||||||
|
self.tn = tn
|
||||||
|
self.time = 0
|
||||||
|
self.freq = 0
|
||||||
|
self.freq_ts = 0
|
||||||
|
self.y = 0
|
||||||
|
self.y_old = 0
|
||||||
|
self.idx = 0
|
||||||
|
self.LPfilter = IIR_filter.IIR_1_Order_LP(fs=self.fs, fc=200)
|
||||||
|
|
||||||
|
def step(self, x, time):
|
||||||
|
|
||||||
|
if time - self.time > self.ts:
|
||||||
|
self.time = time
|
||||||
|
self.y = self.LPfilter.step(x)
|
||||||
|
|
||||||
|
if self.y_old < 0 and self.y > 0:
|
||||||
|
self.idx += 1
|
||||||
|
|
||||||
|
|
||||||
|
if time - self.freq_ts > self.tn:
|
||||||
|
self.freq = self.idx / self.tn
|
||||||
|
self.freq_ts = time
|
||||||
|
self.idx = 0
|
||||||
|
|
||||||
|
|
||||||
|
self.y_old = self.y
|
||||||
|
|
||||||
|
|
||||||
|
def print(self):
|
||||||
|
print(self.freq)
|
||||||
Reference in New Issue
Block a user