(原创)超声波/雷达信号处理仿真与FPGA加速
一、标准信号产生与接收
1、标准信号的产生与接收
1、要求首先使用10Mhz Sine波进行发送一次持续10个Sine周期的脉冲信号模拟超声波信号发送。在不发送的时候,就保持0。
2、假设物体距离探头的距离为10米,当前声速为1000m/s,请计算超声波碰到物体后弹回来的总时间作为延时。然后在发射的信号前增加这个延时作为模拟接收到的原始信号。
3、将发射和接受到的信号以图像的形式进行显示出来。
4、计算接收到的信号的FFT,频率范围为0到5倍信号原始频率(10Mhz)。
5、对接收到的信号与发射的信号脉冲进行互相关计算,然后找到最大值,计算发射和接收之间的延时。
import numpy as np
import matplotlib.pyplot as plt
from scipy.fft import fft, fftfreq
from scipy.signal import correlate
# Constants
f = 10e6 # Frequency of the sine wave (10 MHz)
distance = 10 # Distance to the object in meters
speed_of_sound = 1000 # Speed of sound in m/s
sampling_rate = 100e6 # Sampling rate (100 MHz)
# Time settings
pulse_duration = 10 / f # Duration of the pulse in seconds
pulse_samples = int(sampling_rate * pulse_duration) # Number of samples for the pulse
# Generate time array
T = 1 / sampling_rate
t = np.arange(0, 2 * pulse_duration + 0.1, T) # Time array for sending and receiving
# Generate transmitted signal (10 MHz sine wave)
transmitted_signal = np.zeros_like(t)
transmitted_signal[:pulse_samples] = np.sin(2 * np.pi * f * t[:pulse_samples])
# Calculate round trip time
round_trip_time = 2 * distance / speed_of_sound # Total time for the sound to travel to the object and back
# Simulate received signal with delay
received_signal = np.zeros_like(t)
received_delay_index = int(round_trip_time / T)
received_signal[received_delay_index:received_delay_index + pulse_samples] = transmitted_signal[:pulse_samples]
# Plot transmitted and received signals
plt.figure(figsize=(12, 6))
plt.subplot(2, 1, 1)
plt.title('Transmitted and Received Signals')
plt.plot(t, transmitted_signal, label='Transmitted Signal', color='blue')
plt.plot(t, received_signal, label='Received Signal', color='orange')
plt.xlabel('Time (s)')
plt.ylabel('Amplitude')
plt.legend()
# FFT of received signal
N = len(received_signal)
frequencies = fftfreq(N, T)[:N // 2]
received_signal_fft = fft(received_signal)
# Plot FFT
plt.subplot(2, 1, 2)
plt.title('FFT of Received Signal')
plt.plot(frequencies, 2.0/N * np.abs(received_signal_fft[:N // 2]), color='green')
plt.xlim(0, 5 * f) # Limit to 5 times the original frequency
plt.xlabel('Frequency (Hz)')
plt.ylabel('Amplitude')
plt.tight_layout()
plt.show()
# Cross-correlation
correlation = correlate(received_signal, transmitted_signal, mode='full')
lag = np.arange(-len(transmitted_signal) + 1, len(received_signal))
# Find the delay
max_corr_index = np.argmax(correlation)
max_delay = lag[max_corr_index] * T
print(f'Maximum correlation delay: {max_delay:.6f} seconds')运行结果:

二、添加干扰和直流偏置
1、发射信号的幅值为10V。
2、模拟的接收信号,添加随机噪声,以尽可能模拟真实情况。然后模拟的接收信号全部添加100V的直流偏置。
3、画出互相关的图像。
import numpy as np
import matplotlib.pyplot as plt
from scipy.fft import fft, fftfreq
from scipy.signal import correlate
# Constants
f = 10e6 # Frequency of the sine wave (10 MHz)
distance = 10 # Distance to the object in meters
speed_of_sound = 1000 # Speed of sound in m/s
sampling_rate = 100e6 # Sampling rate (100 MHz)
# Time settings
pulse_duration = 10 / f # Duration of the pulse in seconds
pulse_samples = int(sampling_rate * pulse_duration) # Number of samples for the pulse
# Generate time array
T = 1 / sampling_rate
t = np.arange(0, 2 * pulse_duration + 0.1, T) # Time array for sending and receiving
# Generate transmitted signal (10 MHz sine wave)
transmitted_signal = np.zeros_like(t)
transmitted_signal[:pulse_samples] = 10 * np.sin(2 * np.pi * f * t[:pulse_samples]) # Amplitude 10V
# Calculate round trip time
round_trip_time = 2 * distance / speed_of_sound # Total time for the sound to travel to the object and back
# Simulate received signal with delay
received_signal = np.zeros_like(t)
received_delay_index = int(round_trip_time / T)
received_signal[received_delay_index:received_delay_index + pulse_samples] = transmitted_signal[:pulse_samples]
# Add random noise to the received signal
noise = np.random.normal(0, 1, received_signal.shape) # Gaussian noise
received_signal += noise
# Add DC offset of 100V
received_signal += 100
# Plot transmitted and received signals
plt.figure(figsize=(12, 6))
plt.subplot(3, 1, 1)
plt.title('Transmitted and Received Signals')
plt.plot(t, transmitted_signal, label='Transmitted Signal', color='blue')
plt.plot(t, received_signal, label='Received Signal', color='orange')
plt.xlabel('Time (s)')
plt.ylabel('Amplitude')
plt.legend()
# FFT of received signal
N = len(received_signal)
frequencies = fftfreq(N, T)[:N // 2]
received_signal_fft = fft(received_signal)
# Plot FFT
plt.subplot(3, 1, 2)
plt.title('FFT of Received Signal')
plt.plot(frequencies, 2.0/N * np.abs(received_signal_fft[:N // 2]), color='green')
plt.xlim(0, 5 * f) # Limit to 5 times the original frequency
plt.xlabel('Frequency (Hz)')
plt.ylabel('Amplitude')
# Cross-correlation
correlation = correlate(received_signal, transmitted_signal, mode='full')
lag = np.arange(-len(transmitted_signal) + 1, len(received_signal))
# Plot cross-correlation
plt.subplot(3, 1, 3)
plt.title('Cross-Correlation')
plt.plot(lag * T, correlation, color='purple')
plt.xlabel('Lag (s)')
plt.ylabel('Correlation')
plt.tight_layout()
plt.show()
# Find the delay
max_corr_index = np.argmax(correlation)
max_delay = lag[max_corr_index] * T
print(f'Maximum correlation delay: {max_delay:.6f} seconds')运行结果:

三、滤波
1、接收到信号之后,使用切比雪夫I滤波器实现一个高通滤波器,滤除直流分量。
2、高通滤波器之后,进行低通滤波器,已知信号频率为10Mhz,设计合适的滤波器。
3、对滤波前和滤波后的接收信号进行显示,同时绘制FFT图像。
4、对滤波后的信号进行互相关计算和图像显示。
import numpy as np
import matplotlib.pyplot as plt
from scipy.fft import fft, fftfreq
from scipy.signal import correlate, cheby1, lfilter
# Constants
f = 10e6 # Frequency of the sine wave (10 MHz)
distance = 10 # Distance to the object in meters
speed_of_sound = 1000 # Speed of sound in m/s
sampling_rate = 100e6 # Sampling rate (100 MHz)
# Time settings
pulse_duration = 10 / f # Duration of the pulse in seconds
pulse_samples = int(sampling_rate * pulse_duration) # Number of samples for the pulse
# Generate time array
T = 1 / sampling_rate
t = np.arange(0, 2 * pulse_duration + 0.1, T) # Time array for sending and receiving
# Generate transmitted signal (10 MHz sine wave)
transmitted_signal = np.zeros_like(t)
transmitted_signal[:pulse_samples] = 10 * np.sin(2 * np.pi * f * t[:pulse_samples]) # Amplitude 10V
# Calculate round trip time
round_trip_time = 2 * distance / speed_of_sound # Total time for the sound to travel to the object and back
# Simulate received signal with delay
received_signal = np.zeros_like(t)
received_delay_index = int(round_trip_time / T)
received_signal[received_delay_index:received_delay_index + pulse_samples] = transmitted_signal[:pulse_samples]
# Add random noise to the received signal
noise = np.random.normal(0, 1, received_signal.shape) # Gaussian noise
received_signal += noise
# Add DC offset of 100V
received_signal += 100
# Design Chebyshev I high-pass filter to remove DC component
nyquist = 0.5 * sampling_rate
cutoff_high = 1e5 # High-pass cutoff frequency (100 kHz)
order = 1
b, a = cheby1(order, 0.5, cutoff_high / nyquist, btype='highpass')
filtered_signal_high = lfilter(b, a, received_signal)
# Design Chebyshev I low-pass filter to remove high-frequency noise
cutoff_low = 15e6 # Low-pass cutoff frequency (15 MHz)
b_low, a_low = cheby1(order, 0.5, cutoff_low / nyquist, btype='low')
filtered_signal_low = lfilter(b_low, a_low, filtered_signal_high)
# Plot received and filtered signals
plt.figure(figsize=(12, 8))
plt.subplot(4, 1, 1)
plt.title('Received Signal with Noise and DC Offset')
plt.plot(t, received_signal, label='Received Signal', color='orange')
plt.xlabel('Time (s)')
plt.ylabel('Amplitude')
plt.legend()
plt.subplot(4, 1, 2)
plt.title('Filtered Signal (High-Pass and Low-Pass)')
plt.plot(t, filtered_signal_low, label='Filtered Signal', color='green')
plt.xlabel('Time (s)')
plt.ylabel('Amplitude')
plt.legend()
# FFT of filtered signal
N = len(filtered_signal_low)
frequencies = fftfreq(N, T)[:N // 2]
filtered_signal_fft = fft(filtered_signal_low)
# Plot FFT of filtered signal
plt.subplot(4, 1, 3)
plt.title('FFT of Filtered Signal')
plt.plot(frequencies, 2.0/N * np.abs(filtered_signal_fft[:N // 2]), color='blue')
plt.xlim(0, 5 * f) # Limit to 5 times the original frequency
plt.xlabel('Frequency (Hz)')
plt.ylabel('Amplitude')
# Cross-correlation
correlation = correlate(filtered_signal_low, transmitted_signal, mode='full')
lag = np.arange(-len(transmitted_signal) + 1, len(filtered_signal_low))
# Plot cross-correlation
plt.subplot(4, 1, 4)
plt.title('Cross-Correlation of Filtered Signal')
plt.plot(lag * T, correlation, color='purple')
plt.xlabel('Lag (s)')
plt.ylabel('Correlation')
plt.tight_layout()
plt.show()
# Find the delay
max_corr_index = np.argmax(correlation)
max_delay = lag[max_corr_index] * T
print(f'Maximum correlation delay: {max_delay:.6f} seconds')
截止到目前,基本都功能已经实现了,但是我们仍然可以进行改进。
目前已知问题:
1、滤波后的波形在初始位置有个瞬态响应。
2、按理说滤波器会改变高频时的相位,滤波器的设计需要小心。
3、没有考虑到多普勒效应。
4、多目标的距离检测没有实现。
四、多点探测
在多点检测时,可能会发生混叠现象,解决方法是:1、更换脉冲形状,改为不定频脉冲,例如LFM脉冲。2、降低脉宽,但可能会带来信噪比的问题。
1、首先修改脉冲为LFM。
2、增加一个物体的模拟,即原先距离10米的物体不变,增加一个距离50米的物体。其他条件保持不变。
3、能够通过互相关识别到多个物体(超过最大峰值50%的峰均认为是有效的物体距离)。
import numpy as np
import matplotlib.pyplot as plt
from scipy.fft import fft, fftfreq
from scipy.signal import correlate, cheby1, lfilter
# Constants
f0 = 10e6 # Start frequency of the LFM pulse (10 MHz)
distance1 = 10 # Distance to the first object in meters
distance2 = 50 # Distance to the second object in meters
speed_of_sound = 1000 # Speed of sound in m/s
sampling_rate = 100e6 # Sampling rate (100 MHz)
# Time settings
pulse_duration = 10 / f0 # Duration of the pulse in seconds
pulse_samples = int(sampling_rate * pulse_duration) # Number of samples for the pulse
# Generate time array
T = 1 / sampling_rate
t = np.arange(0, 2 * pulse_duration + 0.1, T) # Time array for sending and receiving
# Generate LFM pulse
k = (1e10) # Chirp rate
lfm_pulse = np.zeros_like(t)
lfm_pulse[:pulse_samples] = np.sin(2 * np.pi * (f0 * t[:pulse_samples] + 0.5 * k * t[:pulse_samples]**2)) # LFM pulse
# Simulate received signals with delays
received_signal = np.zeros_like(t)
received_delay_index1 = int((2 * distance1) / speed_of_sound / T)
received_delay_index2 = int((2 * distance2) / speed_of_sound / T)
received_signal[received_delay_index1:received_delay_index1 + pulse_samples] = lfm_pulse[:pulse_samples]
received_signal[received_delay_index2:received_delay_index2 + pulse_samples] += lfm_pulse[:pulse_samples]
# Add random noise to the received signal (lower standard deviation for realistic simulation)
noise_std_dev = 0.1 # Standard deviation of noise
noise = np.random.normal(0, noise_std_dev, received_signal.shape) # Gaussian noise
received_signal += noise
# Add DC offset of 100V
received_signal += 100
# Design Chebyshev I high-pass filter to remove DC component
nyquist = 0.5 * sampling_rate
cutoff_high = 1e5 # High-pass cutoff frequency (100 kHz)
order = 1
b, a = cheby1(order, 0.5, cutoff_high / nyquist, btype='highpass')
filtered_signal_high = lfilter(b, a, received_signal)
# Design Chebyshev I low-pass filter to remove high-frequency noise
cutoff_low = 15e6 # Low-pass cutoff frequency (15 MHz)
b_low, a_low = cheby1(order, 0.5, cutoff_low / nyquist, btype='low')
filtered_signal_low = lfilter(b_low, a_low, filtered_signal_high)
# Plot received and filtered signals
plt.figure(figsize=(12, 8))
plt.subplot(4, 1, 1)
plt.title('Received Signal with Noise and DC Offset')
plt.plot(t, received_signal, label='Received Signal', color='orange')
plt.xlabel('Time (s)')
plt.ylabel('Amplitude')
plt.legend()
plt.subplot(4, 1, 2)
plt.title('Filtered Signal (High-Pass and Low-Pass)')
plt.plot(t, filtered_signal_low, label='Filtered Signal', color='green')
plt.xlabel('Time (s)')
plt.ylabel('Amplitude')
plt.legend()
# FFT of filtered signal
N = len(filtered_signal_low)
frequencies = fftfreq(N, T)[:N // 2]
filtered_signal_fft = fft(filtered_signal_low)
# Plot FFT of filtered signal
plt.subplot(4, 1, 3)
plt.title('FFT of Filtered Signal')
plt.plot(frequencies, 2.0/N * np.abs(filtered_signal_fft[:N // 2]), color='blue')
plt.xlim(0, 5 * f0) # Limit to 5 times the original frequency
plt.xlabel('Frequency (Hz)')
plt.ylabel('Amplitude')
# Cross-correlation
correlation = correlate(filtered_signal_low, lfm_pulse, mode='full')
lag = np.arange(-len(lfm_pulse) + 1, len(filtered_signal_low))
# Plot cross-correlation
plt.subplot(4, 1, 4)
plt.title('Cross-Correlation of Filtered Signal')
plt.plot(lag * T, correlation, color='purple')
plt.xlabel('Lag (s)')
plt.ylabel('Correlation')
plt.tight_layout()
plt.show()
# Identify peaks in cross-correlation
threshold = 0.5 * np.max(correlation) # 50% of the maximum peak
peaks = np.where(correlation > threshold)[0]
# Calculate distances for detected objects
detected_distances = []
for peak in peaks:
distance_detected = (peak - len(lfm_pulse) + 1) * T * speed_of_sound / 2
detected_distances.append(distance_detected)
print(f'Detected distances: {detected_distances}')运行结果:

但是算出来了很多点:
PS C:\Users\ChanRa1n> & C:/Users/ChanRa1n/AppData/Local/Programs/Python/Python37/python.exe c:/Users/ChanRa1n/Desktop/ultrasonic.py Detected distances: [-9.999999999999999e-05, -4.9999999999999996e-05, 0.0, 5e-06, 1e-05, 1.5000000000000002e-05, 2e-05, 2.4999999999999998e-05, 3.0000000000000004e-05, 3.5000000000000004e-05, 4e-05, 4.4999999999999996e-05, 4.9999999999999996e-05, 5.5e-05, 6.000000000000001e-05, 6.5e-05, 7.000000000000001e-05, 7.5e-05, 8e-05, 8.5e-05, 8.999999999999999e-05, 9.5e-05, 9.999999999999999e-05, 0.000105, 0.00011, 0.000115, 0.00012000000000000002, 0.000125, 0.00013, 0.000135, 0.00014000000000000001, 0.00014500000000000003, 0.00015, 0.000155, 0.00016, 0.000165, 0.00017, 0.000175, 0.00017999999999999998, 0.000185, 0.00019, 0.00019500000000000002, 0.00019999999999999998, 0.000205, 0.00021, 0.000215, 0.00022, 0.00022500000000000002, 0.00023, 0.000235, 0.00024000000000000003, 0.000245, 0.00025, 0.000255, 0.00026, 0.000265, 0.00027, 0.000275, 0.00028000000000000003, 0.00028500000000000004, 0.00029000000000000006, 0.00029499999999999996, 0.0003, 0.000305, 0.00031, 0.000315, 0.00032, 0.000325, 0.00033, 0.000335, 0.00034, 0.00034500000000000004, 0.00035, 0.00037, 0.000375, 0.00038, 0.00038500000000000003, 0.00039000000000000005, 0.000395, 0.00039999999999999996, 0.00042500000000000003, 0.00043, 0.000435, 0.00044, 0.00044500000000000003, 0.000485, 0.00049, 0.000495, 9.99975, 9.999755, 9.9998, 9.999805, 9.999849999999999, 9.999855, 9.999895, 9.9999, 9.999905, 9.999945, 9.99995, 9.999955, 9.999995, 10.0, 10.000005000000002, 10.00001, 10.000045, 10.00005, 10.000055000000001, 10.000095, 10.0001, 10.000105, 10.000150000000001, 10.000155, 10.000200000000001, 10.000205, 49.9998, 49.999805, 49.999849999999995, 49.999855000000004, 49.999895, 49.9999, 49.999905000000005, 49.999945000000004, 49.99995, 49.999955, 49.999995, 50.0, 50.000005, 50.00001, 50.000045, 50.00005, 50.000055, 50.000099999999996, 50.000105000000005, 50.00015, 50.00015500000001, 50.0002, 50.000205]
但是很明显存在问题,所以我修改了代码,首先找到所有极大值,然后在极大值中进行设定阈值,超过阈值的部分方可被认为是有效的。
import numpy as np
import matplotlib.pyplot as plt
from scipy.fft import fft, fftfreq
from scipy.signal import correlate, cheby1, lfilter, find_peaks
# Constants
f0 = 10e6 # Start frequency of the LFM pulse (10 MHz)
distance1 = 10 # Distance to the first object in meters
distance2 = 50 # Distance to the second object in meters
speed_of_sound = 1000 # Speed of sound in m/s
sampling_rate = 100e6 # Sampling rate (100 MHz)
# Time settings
pulse_duration = 10 / f0 # Duration of the pulse in seconds
pulse_samples = int(sampling_rate * pulse_duration) # Number of samples for the pulse
# Generate time array
T = 1 / sampling_rate
t = np.arange(0, 2 * pulse_duration + 0.1, T) # Time array for sending and receiving
# Generate LFM pulse
k = (1e10) # Chirp rate
lfm_pulse = np.zeros_like(t)
lfm_pulse[:pulse_samples] = np.sin(2 * np.pi * (f0 * t[:pulse_samples] + 0.5 * k * t[:pulse_samples]**2)) # LFM pulse
# Simulate received signals with delays
received_signal = np.zeros_like(t)
received_delay_index1 = int((2 * distance1) / speed_of_sound / T)
received_delay_index2 = int((2 * distance2) / speed_of_sound / T)
received_signal[received_delay_index1:received_delay_index1 + pulse_samples] = lfm_pulse[:pulse_samples]
received_signal[received_delay_index2:received_delay_index2 + pulse_samples] += lfm_pulse[:pulse_samples]
# Add random noise to the received signal (lower standard deviation for realistic simulation)
noise_std_dev = 0.1 # Standard deviation of noise
noise = np.random.normal(0, noise_std_dev, received_signal.shape) # Gaussian noise
received_signal += noise
# Add DC offset of 100V
received_signal += 100
# Design Chebyshev I high-pass filter to remove DC component
nyquist = 0.5 * sampling_rate
cutoff_high = 1e5 # High-pass cutoff frequency (100 kHz)
order = 1
b, a = cheby1(order, 0.5, cutoff_high / nyquist, btype='highpass')
filtered_signal_high = lfilter(b, a, received_signal)
# Design Chebyshev I low-pass filter to remove high-frequency noise
cutoff_low = 15e6 # Low-pass cutoff frequency (15 MHz)
b_low, a_low = cheby1(order, 0.5, cutoff_low / nyquist, btype='low')
filtered_signal_low = lfilter(b_low, a_low, filtered_signal_high)
# Plot received and filtered signals
plt.figure(figsize=(12, 8))
plt.subplot(4, 1, 1)
plt.title('Received Signal with Noise and DC Offset')
plt.plot(t, received_signal, label='Received Signal', color='orange')
plt.xlabel('Time (s)')
plt.ylabel('Amplitude')
plt.legend()
plt.subplot(4, 1, 2)
plt.title('Filtered Signal (High-Pass and Low-Pass)')
plt.plot(t, filtered_signal_low, label='Filtered Signal', color='green')
plt.xlabel('Time (s)')
plt.ylabel('Amplitude')
plt.legend()
# FFT of filtered signal
N = len(filtered_signal_low)
frequencies = fftfreq(N, T)[:N // 2]
filtered_signal_fft = fft(filtered_signal_low)
# Plot FFT of filtered signal
plt.subplot(4, 1, 3)
plt.title('FFT of Filtered Signal')
plt.plot(frequencies, 2.0/N * np.abs(filtered_signal_fft[:N // 2]), color='blue')
plt.xlim(0, 5 * f0) # Limit to 5 times the original frequency
plt.xlabel('Frequency (Hz)')
plt.ylabel('Amplitude')
# Cross-correlation
correlation = correlate(filtered_signal_low, lfm_pulse, mode='full')
lag = np.arange(-len(lfm_pulse) + 1, len(filtered_signal_low))
# Plot cross-correlation
plt.subplot(4, 1, 4)
plt.title('Cross-Correlation of Filtered Signal')
plt.plot(lag * T, correlation, color='purple')
plt.xlabel('Lag (s)')
plt.ylabel('Correlation')
plt.tight_layout()
plt.show()
# Identify peaks in cross-correlation
peaks, _ = find_peaks(correlation) # Find peaks in the correlation
threshold = 0.6 * np.max(correlation) # 60% of the maximum peak
valid_peaks = peaks[correlation[peaks] > threshold] # Filter peaks based on threshold
# Calculate distances for detected objects
detected_distances = []
for peak in valid_peaks:
distance_detected = (peak - len(lfm_pulse) + 1) * T * speed_of_sound / 2
detected_distances.append(distance_detected)
print(f'Detected distances: {detected_distances}')这个时候结果好了一点:
Detected distances: [-4.9999999999999996e-05, 0.0, 1e-05, 6.5e-05, 9.999849999999999, 9.9999, 9.99995, 10.0, 10.00005, 10.0001, 10.000150000000001, 49.999849999999995, 49.9999, 49.99995, 50.0, 50.00005, 50.000099999999996, 50.00015, 50.0002]
进一步优化:
import numpy as np
import matplotlib.pyplot as plt
from scipy.fft import fft, fftfreq
from scipy.signal import correlate, cheby1, lfilter, find_peaks
# Constants
f0 = 10e6 # Start frequency of the LFM pulse (10 MHz)
distance1 = 10 # Distance to the first object in meters
distance2 = 50 # Distance to the second object in meters
speed_of_sound = 1000 # Speed of sound in m/s
sampling_rate = 100e6 # Sampling rate (100 MHz)
# Time settings
pulse_duration = 10 / f0 # Duration of the pulse in seconds
pulse_samples = int(sampling_rate * pulse_duration) # Number of samples for the pulse
# Generate time array
T = 1 / sampling_rate
t = np.arange(0, 2 * pulse_duration + 0.1, T) # Time array for sending and receiving
# Generate LFM pulse
k = (1e10) # Chirp rate
lfm_pulse = np.zeros_like(t)
lfm_pulse[:pulse_samples] = np.sin(2 * np.pi * (f0 * t[:pulse_samples] + 0.5 * k * t[:pulse_samples]**2)) # LFM pulse
# Simulate received signals with delays
received_signal = np.zeros_like(t)
received_delay_index1 = int((2 * distance1) / speed_of_sound / T)
received_delay_index2 = int((2 * distance2) / speed_of_sound / T)
received_signal[received_delay_index1:received_delay_index1 + pulse_samples] = lfm_pulse[:pulse_samples]
received_signal[received_delay_index2:received_delay_index2 + pulse_samples] += lfm_pulse[:pulse_samples]
# Add random noise to the received signal (lower standard deviation for realistic simulation)
noise_std_dev = 0.1 # Standard deviation of noise
noise = np.random.normal(0, noise_std_dev, received_signal.shape) # Gaussian noise
received_signal += noise
# Add DC offset of 100V
received_signal += 100
# Design Chebyshev I high-pass filter to remove DC component
nyquist = 0.5 * sampling_rate
cutoff_high = 1e5 # High-pass cutoff frequency (100 kHz)
order = 1
b, a = cheby1(order, 0.5, cutoff_high / nyquist, btype='highpass')
filtered_signal_high = lfilter(b, a, received_signal)
# Design Chebyshev I low-pass filter to remove high-frequency noise
cutoff_low = 15e6 # Low-pass cutoff frequency (15 MHz)
b_low, a_low = cheby1(order, 0.5, cutoff_low / nyquist, btype='low')
filtered_signal_low = lfilter(b_low, a_low, filtered_signal_high)
# Plot received and filtered signals
plt.figure(figsize=(12, 8))
plt.subplot(4, 1, 1)
plt.title('Received Signal with Noise and DC Offset')
plt.plot(t, received_signal, label='Received Signal', color='orange')
plt.xlabel('Time (s)')
plt.ylabel('Amplitude')
plt.legend()
plt.subplot(4, 1, 2)
plt.title('Filtered Signal (High-Pass and Low-Pass)')
plt.plot(t, filtered_signal_low, label='Filtered Signal', color='green')
plt.xlabel('Time (s)')
plt.ylabel('Amplitude')
plt.legend()
# FFT of filtered signal
N = len(filtered_signal_low)
frequencies = fftfreq(N, T)[:N // 2]
filtered_signal_fft = fft(filtered_signal_low)
# Plot FFT of filtered signal
plt.subplot(4, 1, 3)
plt.title('FFT of Filtered Signal')
plt.plot(frequencies, 2.0/N * np.abs(filtered_signal_fft[:N // 2]), color='blue')
plt.xlim(0, 5 * f0) # Limit to 5 times the original frequency
plt.xlabel('Frequency (Hz)')
plt.ylabel('Amplitude')
# Cross-correlation
correlation = correlate(filtered_signal_low, lfm_pulse, mode='full')
lag = np.arange(-len(lfm_pulse) + 1, len(filtered_signal_low))
# Plot cross-correlation
plt.subplot(4, 1, 4)
plt.title('Cross-Correlation of Filtered Signal')
plt.plot(lag * T, correlation, color='purple')
plt.xlabel('Lag (s)')
plt.ylabel('Correlation')
plt.tight_layout()
plt.show()
# Identify peaks in cross-correlation
peaks, _ = find_peaks(correlation) # Find peaks in the correlation
threshold = 0.8 * np.max(correlation) # 80% of the maximum peak
valid_peaks = peaks[correlation[peaks] > threshold] # Filter peaks based on threshold
# Calculate distances for detected objects
detected_distances = []
tolerance = 0.01 # Tolerance for detecting unique distances
last_distance = None
for peak in valid_peaks:
distance_detected = abs((peak - len(lfm_pulse) + 1) * T * speed_of_sound / 2)
if last_distance is None or abs(distance_detected - last_distance) > tolerance:
detected_distances.append(distance_detected)
last_distance = distance_detected
print(f'Detected distances: {detected_distances}')此时的结果:
PS C:\Users\ChanRa1n> & C:/Users/ChanRa1n/AppData/Local/Programs/Python/Python37/python.exe c:/Users/ChanRa1n/Desktop/ultrasonic.py Detected distances: [9.9999, 49.9999]
和我们设计的10米和50米非常接近了。为了减少FFT计算的频谱泄露问题,添加汉明窗函数。
import numpy as np
import matplotlib.pyplot as plt
from scipy.fft import fft, fftfreq
from scipy.signal import correlate, cheby1, lfilter, find_peaks, hamming
# Constants
f0 = 10e6 # Start frequency of the LFM pulse (10 MHz)
distance1 = 10 # Distance to the first object in meters
distance2 = 50 # Distance to the second object in meters
speed_of_sound = 1000 # Speed of sound in m/s
sampling_rate = 100e6 # Sampling rate (100 MHz)
# Time settings
pulse_duration = 10 / f0 # Duration of the pulse in seconds
pulse_samples = int(sampling_rate * pulse_duration) # Number of samples for the pulse
# Generate time array
T = 1 / sampling_rate
t = np.arange(0, 2 * pulse_duration + 0.1, T) # Time array for sending and receiving
# Generate LFM pulse
k = (1e10) # Chirp rate
lfm_pulse = np.zeros_like(t)
lfm_pulse[:pulse_samples] = np.sin(2 * np.pi * (f0 * t[:pulse_samples] + 0.5 * k * t[:pulse_samples]**2)) # LFM pulse
# Simulate received signals with delays
received_signal = np.zeros_like(t)
received_delay_index1 = int((2 * distance1) / speed_of_sound / T)
received_delay_index2 = int((2 * distance2) / speed_of_sound / T)
received_signal[received_delay_index1:received_delay_index1 + pulse_samples] = lfm_pulse[:pulse_samples]
received_signal[received_delay_index2:received_delay_index2 + pulse_samples] += lfm_pulse[:pulse_samples]
# Add random noise to the received signal (lower standard deviation for realistic simulation)
noise_std_dev = 0.1 # Standard deviation of noise
noise = np.random.normal(0, noise_std_dev, received_signal.shape) # Gaussian noise
received_signal += noise
# Add DC offset of 100V
received_signal += 100
# Design Chebyshev I high-pass filter to remove DC component
nyquist = 0.5 * sampling_rate
cutoff_high = 1e5 # High-pass cutoff frequency (100 kHz)
order = 1
b, a = cheby1(order, 0.5, cutoff_high / nyquist, btype='highpass')
filtered_signal_high = lfilter(b, a, received_signal)
# Design Chebyshev I low-pass filter to remove high-frequency noise
cutoff_low = 15e6 # Low-pass cutoff frequency (15 MHz)
b_low, a_low = cheby1(order, 0.5, cutoff_low / nyquist, btype='low')
filtered_signal_low = lfilter(b_low, a_low, filtered_signal_high)
# Plot received and filtered signals
plt.figure(figsize=(12, 8))
plt.subplot(4, 1, 1)
plt.title('Received Signal with Noise and DC Offset')
plt.plot(t, received_signal, label='Received Signal', color='orange')
plt.xlabel('Time (s)')
plt.ylabel('Amplitude')
plt.legend()
plt.subplot(4, 1, 2)
plt.title('Filtered Signal (High-Pass and Low-Pass)')
plt.plot(t, filtered_signal_low, label='Filtered Signal', color='green')
plt.xlabel('Time (s)')
plt.ylabel('Amplitude')
plt.legend()
# Apply Hamming window to the filtered signal before FFT
window = hamming(len(filtered_signal_low))
windowed_signal = filtered_signal_low * window
# FFT of windowed signal
N = len(windowed_signal)
frequencies = fftfreq(N, T)[:N // 2]
filtered_signal_fft = fft(windowed_signal)
# Plot FFT of filtered signal
plt.subplot(4, 1, 3)
plt.title('FFT of Filtered Signal with Hamming Window')
plt.plot(frequencies, 2.0/N * np.abs(filtered_signal_fft[:N // 2]), color='blue')
plt.xlim(0, 5 * f0) # Limit to 5 times the original frequency
plt.xlabel('Frequency (Hz)')
plt.ylabel('Amplitude')
# Cross-correlation
correlation = correlate(filtered_signal_low, lfm_pulse, mode='full')
lag = np.arange(-len(lfm_pulse) + 1, len(filtered_signal_low))
# Plot cross-correlation
plt.subplot(4, 1, 4)
plt.title('Cross-Correlation of Filtered Signal')
plt.plot(lag * T, correlation, color='purple')
plt.xlabel('Lag (s)')
plt.ylabel('Correlation')
plt.tight_layout()
plt.show()
# Identify peaks in cross-correlation
peaks, _ = find_peaks(correlation) # Find peaks in the correlation
threshold = 0.8 * np.max(correlation) # 80% of the maximum peak
valid_peaks = peaks[correlation[peaks] > threshold] # Filter peaks based on threshold
# Calculate distances for detected objects
detected_distances = []
tolerance = 0.01 # Tolerance for detecting unique distances
last_distance = None
for peak in valid_peaks:
distance_detected = abs((peak - len(lfm_pulse) + 1) * T * speed_of_sound / 2)
if last_distance is None or abs(distance_detected - last_distance) > tolerance:
detected_distances.append(distance_detected)
last_distance = distance_detected
print(f'Detected distances: {detected_distances}')运行结果:

PS C:\Users\ChanRa1n> & C:/Users/ChanRa1n/AppData/Local/Programs/Python/Python37/python.exe c:/Users/ChanRa1n/Desktop/ultrasonic.py Detected distances: [9.9999, 49.99995]
之所以会有误差,主要是来自两方面:1、在计算过程中,浮点数的精度可能导致结果略微偏离理论值。2、滤波器会稍微改变信号的相位。
由于误差在可接受范围内,故此处不进行修正(后面要在FPGA上实现,高精度会大幅度增加面积)。
五、多阵元单目标探测
假设存在第二个阵元,与第一个阵元的直线距离为1米,在本次实验中始终仅进行接收。

import numpy as np
import matplotlib.pyplot as plt
from scipy.fft import fft, fftfreq
from scipy.signal import correlate, cheby1, lfilter
# Constants
f = 10e6 # Frequency of the sine wave (10 MHz)
distance_vertical = 10 # Vertical distance to the object in meters
distance_horizontal = 1 # Horizontal distance between array 1 and array 2 in meters
speed_of_sound = 1000 # Speed of sound in m/s
sampling_rate = 100e6 # Sampling rate (100 MHz)
# Calculate the actual distances to the object for each array
distance_1 = distance_vertical # Distance from array 1 to the object
distance_2 = np.sqrt(distance_vertical**2 + distance_horizontal**2) # Distance from array 2 to the object
# Time settings
pulse_duration = 10 / f # Duration of the pulse in seconds
pulse_samples = int(sampling_rate * pulse_duration) # Number of samples for the pulse
# Generate time array
T = 1 / sampling_rate
t = np.arange(0, 2 * pulse_duration + 0.1, T) # Time array for sending and receiving
# Generate transmitted signal (10 MHz sine wave)
transmitted_signal = np.zeros_like(t)
transmitted_signal[:pulse_samples] = 10 * np.sin(2 * np.pi * f * t[:pulse_samples]) # Amplitude 10V
# Calculate round trip time for array 1
round_trip_time_1 = 2 * distance_1 / speed_of_sound # Total time for the sound to travel to the object and back
# Simulate received signal for array 1 with delay
received_signal_1 = np.zeros_like(t)
received_delay_index_1 = int(round_trip_time_1 / T)
received_signal_1[received_delay_index_1:received_delay_index_1 + pulse_samples] = transmitted_signal[:pulse_samples]
# Add random noise to the received signal for array 1
noise_1 = np.random.normal(0, 1, received_signal_1.shape) # Gaussian noise
received_signal_1 += noise_1
# Add DC offset of 100V
received_signal_1 += 100
# Calculate round trip time for array 2
round_trip_time_2 = 2 * distance_2 / speed_of_sound # Total time for the sound to travel to the object and back
# Simulate received signal for array 2 with delay
received_signal_2 = np.zeros_like(t)
received_delay_index_2 = int(round_trip_time_2 / T)
received_signal_2[received_delay_index_2:received_delay_index_2 + pulse_samples] = transmitted_signal[:pulse_samples]
# Add random noise to the received signal for array 2
noise_2 = np.random.normal(0, 1, received_signal_2.shape) # Gaussian noise
received_signal_2 += noise_2
# Add DC offset of 100V
received_signal_2 += 100
# Design Chebyshev I high-pass filter to remove DC component
nyquist = 0.5 * sampling_rate
cutoff_high = 1e5 # High-pass cutoff frequency (100 kHz)
order = 1
b, a = cheby1(order, 0.5, cutoff_high / nyquist, btype='highpass')
filtered_signal_high_1 = lfilter(b, a, received_signal_1)
filtered_signal_high_2 = lfilter(b, a, received_signal_2)
# Design Chebyshev I low-pass filter to remove high-frequency noise
cutoff_low = 15e6 # Low-pass cutoff frequency (15 MHz)
b_low, a_low = cheby1(order, 0.5, cutoff_low / nyquist, btype='low')
filtered_signal_low_1 = lfilter(b_low, a_low, filtered_signal_high_1)
filtered_signal_low_2 = lfilter(b_low, a_low, filtered_signal_high_2)
# Plot received and filtered signals for both arrays
plt.figure(figsize=(12, 10))
plt.subplot(4, 1, 1)
plt.title('Received Signal Array 1 with Noise and DC Offset')
plt.plot(t, received_signal_1, label='Received Signal Array 1', color='orange')
plt.xlabel('Time (s)')
plt.ylabel('Amplitude')
plt.legend()
plt.subplot(4, 1, 2)
plt.title('Received Signal Array 2 with Noise and DC Offset')
plt.plot(t, received_signal_2, label='Received Signal Array 2', color='blue')
plt.xlabel('Time (s)')
plt.ylabel('Amplitude')
plt.legend()
plt.subplot(4, 1, 3)
plt.title('Filtered Signal Array 1 (High-Pass and Low-Pass)')
plt.plot(t, filtered_signal_low_1, label='Filtered Signal Array 1', color='green')
plt.xlabel('Time (s)')
plt.ylabel('Amplitude')
plt.legend()
plt.subplot(4, 1, 4)
plt.title('Filtered Signal Array 2 (High-Pass and Low-Pass)')
plt.plot(t, filtered_signal_low_2, label='Filtered Signal Array 2', color='red')
plt.xlabel('Time (s)')
plt.ylabel('Amplitude')
plt.legend()
plt.tight_layout()
plt.show()
# Cross-correlation for both arrays
correlation_1 = correlate(filtered_signal_low_1, transmitted_signal, mode='full')
correlation_2 = correlate(filtered_signal_low_2, transmitted_signal, mode='full')
lag = np.arange(-len(transmitted_signal) + 1, len(filtered_signal_low_1))
# Find the delays
max_corr_index_1 = np.argmax(correlation_1)
max_delay_1 = lag[max_corr_index_1] * T
max_corr_index_2 = np.argmax(correlation_2)
max_delay_2 = lag[max_corr_index_2] * T
# Calculate distances based on delays
calculated_distance_1 = max_delay_1 * speed_of_sound / 2 # Distance to object from array 1
calculated_distance_2 = max_delay_2 * speed_of_sound / 2 # Distance to object from array 2
print(f'Maximum correlation delay for Array 1: {max_delay_1:.6f} seconds, Calculated Distance: {calculated_distance_1:.2f} meters')
print(f'Maximum correlation delay for Array 2: {max_delay_2:.6f} seconds, Calculated Distance: {calculated_distance_2:.2f} meters')运行结果:

Maximum correlation delay for Array 1: 0.020000 seconds, Calculated Distance: 10.00 meters Maximum correlation delay for Array 2: 0.020100 seconds, Calculated Distance: 10.05 meters
六、【待优化】多阵元多目标探测(以2阵元2目标为例)
信号生成:生成线性调频(LFM)脉冲信号。
信号接收:模拟两个阵元接收两个目标的信号,计算每个阵元的延迟。
噪声和偏移:为接收到的信号添加高斯噪声和直流偏移。
滤波:使用切比雪夫高通和低通滤波器去除直流成分和高频噪声。
交叉相关:对过滤后的信号进行交叉相关,识别信号中的峰值。
距离计算:根据检测到的峰值计算目标的距离。
运行这个程序将会模拟两个阵元对两个目标的检测,并输出检测到的距离。调整参数可以模拟不同的场景。
import numpy as np
import matplotlib.pyplot as plt
from scipy.fft import fft, fftfreq
from scipy.signal import correlate, cheby1, lfilter, find_peaks
# Constants
f0 = 10e6 # Start frequency of the LFM pulse (10 MHz)
distance_vertical = 10 # Distance to the first object in meters
distance_horizontal = 50 # Distance to the second object in meters
speed_of_sound = 1000 # Speed of sound in m/s
sampling_rate = 100e6 # Sampling rate (100 MHz)
# Time settings
pulse_duration = 10 / f0 # Duration of the pulse in seconds
pulse_samples = int(sampling_rate * pulse_duration) # Number of samples for the pulse
# Generate time array
T = 1 / sampling_rate
t = np.arange(0, 2 * pulse_duration + 0.1, T) # Time array for sending and receiving
# Generate LFM pulse
k = (1e10) # Chirp rate
lfm_pulse = np.zeros_like(t)
lfm_pulse[:pulse_samples] = np.sin(2 * np.pi * (f0 * t[:pulse_samples] + 0.5 * k * t[:pulse_samples]**2)) # LFM pulse
# Simulate received signals with delays for two arrays
received_signal_1 = np.zeros_like(t)
received_signal_2 = np.zeros_like(t)
# Calculate delays for both objects for both arrays
received_delay_index1_array1 = int((2 * distance_vertical) / speed_of_sound / T)
received_delay_index2_array1 = int((2 * distance_horizontal) / speed_of_sound / T)
received_delay_index1_array2 = int((2 * distance_vertical) / speed_of_sound / T)
received_delay_index2_array2 = int((2 * distance_horizontal) / speed_of_sound / T)
# Simulate received signals
received_signal_1[received_delay_index1_array1:received_delay_index1_array1 + pulse_samples] = lfm_pulse[:pulse_samples]
received_signal_1[received_delay_index2_array1:received_delay_index2_array1 + pulse_samples] += lfm_pulse[:pulse_samples]
received_signal_2[received_delay_index1_array2:received_delay_index1_array2 + pulse_samples] = lfm_pulse[:pulse_samples]
received_signal_2[received_delay_index2_array2:received_delay_index2_array2 + pulse_samples] += lfm_pulse[:pulse_samples]
# Add random noise to the received signals (lower standard deviation for realistic simulation)
noise_std_dev = 0.1 # Standard deviation of noise
noise_1 = np.random.normal(0, noise_std_dev, received_signal_1.shape) # Gaussian noise
noise_2 = np.random.normal(0, noise_std_dev, received_signal_2.shape) # Gaussian noise
received_signal_1 += noise_1
received_signal_2 += noise_2
# Add DC offset of 100V
received_signal_1 += 100
received_signal_2 += 100
# Design Chebyshev I high-pass filter to remove DC component
nyquist = 0.5 * sampling_rate
cutoff_high = 1e5 # High-pass cutoff frequency (100 kHz)
order = 1
b, a = cheby1(order, 0.5, cutoff_high / nyquist, btype='highpass')
filtered_signal_high_1 = lfilter(b, a, received_signal_1)
filtered_signal_high_2 = lfilter(b, a, received_signal_2)
# Design Chebyshev I low-pass filter to remove high-frequency noise
cutoff_low = 15e6 # Low-pass cutoff frequency (15 MHz)
b_low, a_low = cheby1(order, 0.5, cutoff_low / nyquist, btype='low')
filtered_signal_low_1 = lfilter(b_low, a_low, filtered_signal_high_1)
filtered_signal_low_2 = lfilter(b_low, a_low, filtered_signal_high_2)
# Plot received and filtered signals
plt.figure(figsize=(12, 10))
plt.subplot(4, 1, 1)
plt.title('Received Signal Array 1 with Noise and DC Offset')
plt.plot(t, received_signal_1, label='Received Signal Array 1', color='orange')
plt.xlabel('Time (s)')
plt.ylabel('Amplitude')
plt.legend()
plt.subplot(4, 1, 2)
plt.title('Received Signal Array 2 with Noise and DC Offset')
plt.plot(t, received_signal_2, label='Received Signal Array 2', color='blue')
plt.xlabel('Time (s)')
plt.ylabel('Amplitude')
plt.legend()
plt.subplot(4, 1, 3)
plt.title('Filtered Signal Array 1 (High-Pass and Low-Pass)')
plt.plot(t, filtered_signal_low_1, label='Filtered Signal Array 1', color='green')
plt.xlabel('Time (s)')
plt.ylabel('Amplitude')
plt.legend()
plt.subplot(4, 1, 4)
plt.title('Filtered Signal Array 2 (High-Pass and Low-Pass)')
plt.plot(t, filtered_signal_low_2, label='Filtered Signal Array 2', color='red')
plt.xlabel('Time (s)')
plt.ylabel('Amplitude')
plt.legend()
plt.tight_layout()
plt.show()
# Cross-correlation for both arrays
correlation_1 = correlate(filtered_signal_low_1, lfm_pulse, mode='full')
correlation_2 = correlate(filtered_signal_low_2, lfm_pulse, mode='full')
lag = np.arange(-len(lfm_pulse) + 1, len(filtered_signal_low_1))
# Identify peaks in cross-correlation for both arrays
peaks_1, _ = find_peaks(correlation_1)
peaks_2, _ = find_peaks(correlation_2)
# Threshold for peak detection
threshold_1 = 0.8 * np.max(correlation_1)
threshold_2 = 0.8 * np.max(correlation_2)
valid_peaks_1 = peaks_1[correlation_1[peaks_1] > threshold_1]
valid_peaks_2 = peaks_2[correlation_2[peaks_2] > threshold_2]
# Calculate distances for detected objects
detected_distances_1 = []
detected_distances_2 = []
tolerance = 0.01 # Tolerance for detecting unique distances
last_distance_1 = None
last_distance_2 = None
for peak in valid_peaks_1:
distance_detected = abs((peak - len(lfm_pulse) + 1) * T * speed_of_sound / 2)
if last_distance_1 is None or abs(distance_detected - last_distance_1) > tolerance:
detected_distances_1.append(distance_detected)
last_distance_1 = distance_detected
for peak in valid_peaks_2:
distance_detected = abs((peak - len(lfm_pulse) + 1) * T * speed_of_sound / 2)
if last_distance_2 is None or abs(distance_detected - last_distance_2) > tolerance:
detected_distances_2.append(distance_detected)
last_distance_2 = distance_detected
print(f'Detected distances for Array 1: {detected_distances_1}')
print(f'Detected distances for Array 2: {detected_distances_2}')
计算结果:
Detected distances for Array 1: [9.9999, 49.9999] Detected distances for Array 2: [9.99995, 49.99995]
PS:其实对于干扰不是特别强烈的互相关计算来说,不进行低通滤波也是可以的,尤其是对于FPGA来说,这点很重要。
七、【待优化】单阵元单目标的FPGA实现(Xilinx HLS)
#include <hls_stream.h>
#include <ap_int.h>
#include <cmath>
#include <iostream>
#include <complex>
#include <cstdlib>
#define N 1024 // FFT Size
#define PULSE_SAMPLES 1000 // Number of samples for the pulse
#define SAMPLING_RATE 100e6
#define F 10e6
#define DISTANCE 10
#define SPEED_OF_SOUND 1000
typedef std::complex<float> complex_float;
// Function to generate transmitted signal
void generate_signal(float transmitted_signal[PULSE_SAMPLES]) {
for (int i = 0; i < PULSE_SAMPLES; i++) {
transmitted_signal[i] = 10 * sin(2 * M_PI * F * (i / SAMPLING_RATE));
}
}
// Function to simulate received signal with delay and noise
void simulate_received_signal(float transmitted_signal[PULSE_SAMPLES], float received_signal[N]) {
float round_trip_time = 2 * DISTANCE / SPEED_OF_SOUND;
int received_delay_index = static_cast<int>(round_trip_time * SAMPLING_RATE);
// Initialize received signal
for (int i = 0; i < N; i++) {
received_signal[i] = 0;
}
// Simulate received signal with delay
for (int i = 0; i < PULSE_SAMPLES; i++) {
if (i + received_delay_index < N) {
received_signal[i + received_delay_index] = transmitted_signal[i] + (rand() % 100) / 100.0; // Add noise
}
}
}
// Function to apply a simple high-pass filter
void high_pass_filter(float input[N], float output[N], float cutoff) {
float previous = 0;
float alpha = 1.0 / (1.0 + (SAMPLING_RATE / (2 * M_PI * cutoff))); // Simple RC filter
for (int i = 0; i < N; i++) {
output[i] = alpha * (input[i] - previous);
previous = input[i];
}
}
// Function to perform FFT (Cooley-Tukey)
void fft(complex_float input[N], complex_float output[N]) {
// Bit-reversal permutation
int n = N;
int j = 0;
for (int i = 0; i < n; i++) {
if (i < j) {
std::swap(input[i], input[j]);
}
int m = n / 2;
while (m >= 1 && j >= m) {
j -= m;
m /= 2;
}
j += m;
}
// FFT computation
for (int s = 1; s <= log2(n); s++) {
int m = 1 << s;
complex_float wm = std::exp(complex_float(0, -2 * M_PI / m));
for (int k = 0; k < n; k += m) {
complex_float w(1);
for (int j = 0; j < m / 2; j++) {
complex_float t = w * input[k + j + m / 2];
complex_float u = input[k + j];
input[k + j] = u + t;
input[k + j + m / 2] = u - t;
w *= wm;
}
}
}
for (int i = 0; i < n; i++) {
output[i] = input[i];
}
}
// Function to perform cross-correlation
void cross_correlation(float signal1[N], float signal2[PULSE_SAMPLES], float correlation[N]) {
for (int lag = -PULSE_SAMPLES + 1; lag < N; lag++) {
correlation[lag + PULSE_SAMPLES - 1] = 0;
for (int i = 0; i < PULSE_SAMPLES; i++) {
if (i + lag >= 0 && i + lag < N) {
correlation[lag + PULSE_SAMPLES - 1] += signal1[i + lag] * signal2[i];
}
}
}
}
// Top-level function
extern "C" void signal_processing(float transmitted_signal[PULSE_SAMPLES], float received_signal[N], float filtered_signal[N], float correlation[N]) {
// Step 1: Generate transmitted signal
generate_signal(transmitted_signal);
// Step 2: Simulate received signal
simulate_received_signal(transmitted_signal, received_signal);
// Step 3: High-pass filter
high_pass_filter(received_signal, filtered_signal, 1e5);
// Step 4: FFT
complex_float fft_input[N];
complex_float fft_output[N];
for (int i = 0; i < N; i++) {
fft_input[i] = filtered_signal[i];
}
fft(fft_input, fft_output);
// Step 5: Cross-correlation
cross_correlation(filtered_signal, transmitted_signal, correlation);
}


