当前位置:首页 > FPGA > 正文内容

(原创)超声波/雷达信号处理仿真与FPGA加速

chanra1n3个月前 (08-24)FPGA580

一、标准信号产生与接收

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')

运行结果:

image.png

二、添加干扰和直流偏置

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')

运行结果:

image.png

三、滤波

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')

image.png

截止到目前,基本都功能已经实现了,但是我们仍然可以进行改进。

目前已知问题:

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

运行结果:

image.png

但是算出来了很多点:

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

运行结果:

image.png

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米,在本次实验中始终仅进行接收。

image.png

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')

运行结果:

image.png

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

image.png

计算结果:

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



扫描二维码推送至手机访问。

版权声明:本文由我的FPGA发布,如需转载请注明出处。

本文链接:https://world.myfpga.cn/index.php/post/427.html

分享给朋友:

“(原创)超声波/雷达信号处理仿真与FPGA加速” 的相关文章

ALGO C4MB V11引脚参照表(持续更新)

ALGO C4MB V11引脚参照表(持续更新)

功能:常用引脚CLKPIN_E1LED0PIN_G15LED1PIN_F16LED2PIN_F15LED3PIN_D16KEY1PIN_E15KEY2PIN_E16KEY3PIN_M15KEY4PIN_M16RXDPIN_M2TXDPIN_G1功能:VGA引脚VGA_BLUE[0]PIN_C15VG...

Verilog实现时钟分频(奇数分频,偶数分频)二分频 三分频 四分频 五分频

Verilog实现时钟分频(奇数分频,偶数分频)二分频 三分频 四分频 五分频

完整工程文件:clkdiv.zip//------------------------------------------------------// File Name        : clkdiv.v// Author     &nb...

CDC 单脉冲信号处理

CDC 单脉冲信号处理

代码中的Sys_clk其实是没有用到的,项目文件:cdc_single.zip//------------------------------------------------------// File Name        : cdc.v// Autho...

点亮LED灯实验

点亮LED灯实验

设计流程:设计规划 -> 波形绘制 -> 代码编写 -> 代码编译 -> 逻辑仿真 -> 波形对比 -> 绑定管脚 -> 分析综合布局布线 -> 上板验证新建项目文件夹(led):Doc:放置文档资料(数据手册、波形图、文档、项目日志)Pri:放置工程...

多路选择器

多路选择器

多路选择器:在多路数据传送过程中,能够根据需要将其中任意一路选出来的电路。二选一多路选择器 --- 模块框图in_1:输入信号in_2:输入信号sel:控制选择信号out:输出信号二选一多路选择器 --- 波形图in_1、in_2、sel 的波形是随机的。out 的波形根据控制选通信号而定。当 se...