Finite Impulse Response Filter Implementation on CanMV K230
Composite Signal Generation
To evaluate the filter, a mixed-frequency discrete signal is synthesized. Assuming a sampling rate of 1 kHz, 1000 data points yield a frequency resolution of 1 Hz per bin during Fast Fourier Transform (FFT) analysis. The signal combines 10 Hz, 100 Hz, and 400 Hz harmonics.
import math
from ulab import numpy as np
SAMPLE_RATE = 1000
NUM_POINTS = 1000
PI = 3.141592653589793
wave_data = []
def build_test_signal():
for idx in range(NUM_POINTS):
comp_10hz = 10 * math.cos(1 * 2 * PI * idx / 100) # 10 Hz component
comp_100hz = 10 * math.cos(10 * 2 * PI * idx / 100) # 100 Hz component
comp_400hz = 1 * math.cos(40 * 2 * PI * idx / 100) # 400 Hz component
wave_data.append(comp_10hz + comp_100hz + comp_400hz)
build_test_signal()
signal_array = np.array(wave_data, dtype=np.float)
print('Input Signal:', wave_data)
Filter Coefficient Extraction
Low-pass FIR filter coefficients can be derived using engineering software such as MATLAB, SciPy, or MWORKS.Syslab. The number of taps equals the filter order plus one. The coefficients used here represent a symmetric low-pass filter designed to attenuate higher frequencies.
fir_taps = [
0.002132348687167138,
0.03183860634245905,
0.12748116776405022,
0.26426444991339704,
0.33265892576487105,
0.26426444991339704,
0.12748116776405022,
0.03183860634245905,
0.002132348687167138
]
Convolution and Filtering
The FIR filtering process relies on the convolution of the input sequence with the impulse response. As the discrete signal shifts along the time axis, each window of samples is multiplied by the corresponding tap. Since this particular set of coefficients is symmetric, reversing the array for correlation is unnecessary; direct element-wise multiplication suffices for this static dataset.
filtered_output = []
window_size = len(fir_taps)
for n in range(NUM_POINTS - window_size):
# Extract a sliding window of input samples
sample_window = wave_data[n : n + window_size]
# Perform element-wise multiplication
products = [fir_taps[k] * sample_window[k] for k in range(window_size)]
# Sum the products to get the current output sample
filtered_output.append(sum(products))
print('Filtered Output:', filtered_output)
When executed on the K230, the FFT of the filtered signal (zero-padded) confirms the elimination of the 400 Hz component. The magnitude of the remaining lower frequencies aligns with the filter's frequency response. To isolate the 400 Hz harmonic, a high-pass filter would be required instead.