Add files via upload
This commit is contained in:
@@ -0,0 +1,188 @@
|
|||||||
|
import numpy as np
|
||||||
|
import pandas as pd
|
||||||
|
import math
|
||||||
|
|
||||||
|
def generate_radar_csv(filename="pulse_compression_output.csv"):
|
||||||
|
"""
|
||||||
|
Generate realistic radar CSV data for testing the Python GUI
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Radar parameters matching your testbench
|
||||||
|
num_long_chirps = 16
|
||||||
|
num_short_chirps = 16
|
||||||
|
samples_per_chirp = 512 # Reduced for manageable file size
|
||||||
|
fs_adc = 400e6 # 400 MHz ADC
|
||||||
|
timestamp_ns = 0
|
||||||
|
|
||||||
|
# Target parameters
|
||||||
|
targets = [
|
||||||
|
{'range': 3000, 'velocity': 25, 'snr': 30, 'azimuth': 10, 'elevation': 5}, # Fast moving target
|
||||||
|
{'range': 5000, 'velocity': -15, 'snr': 25, 'azimuth': 20, 'elevation': 2}, # Approaching target
|
||||||
|
{'range': 8000, 'velocity': 5, 'snr': 20, 'azimuth': 30, 'elevation': 8}, # Slow moving target
|
||||||
|
{'range': 12000, 'velocity': -8, 'snr': 18, 'azimuth': 45, 'elevation': 3}, # Distant target
|
||||||
|
]
|
||||||
|
|
||||||
|
# Noise parameters
|
||||||
|
noise_std = 5
|
||||||
|
clutter_std = 10
|
||||||
|
|
||||||
|
data = []
|
||||||
|
chirp_number = 0
|
||||||
|
|
||||||
|
# Generate Long Chirps (30µs duration equivalent)
|
||||||
|
print("Generating Long Chirps...")
|
||||||
|
for chirp in range(num_long_chirps):
|
||||||
|
for sample in range(samples_per_chirp):
|
||||||
|
# Base noise
|
||||||
|
i_val = np.random.normal(0, noise_std)
|
||||||
|
q_val = np.random.normal(0, noise_std)
|
||||||
|
|
||||||
|
# Add clutter (stationary targets)
|
||||||
|
clutter_range = 2000 # Fixed clutter at 2km
|
||||||
|
if sample < 100: # Simulate clutter in first 100 samples
|
||||||
|
i_val += np.random.normal(0, clutter_std)
|
||||||
|
q_val += np.random.normal(0, clutter_std)
|
||||||
|
|
||||||
|
# Add moving targets with Doppler shift
|
||||||
|
for target in targets:
|
||||||
|
# Calculate range bin (simplified)
|
||||||
|
range_bin = int(target['range'] / 20) # ~20m per bin
|
||||||
|
doppler_phase = 2 * math.pi * target['velocity'] * chirp / 100 # Doppler phase shift
|
||||||
|
|
||||||
|
# Target appears around its range bin with some spread
|
||||||
|
if abs(sample - range_bin) < 10:
|
||||||
|
# Signal amplitude decreases with range
|
||||||
|
amplitude = target['snr'] * (10000 / target['range'])
|
||||||
|
phase = 2 * math.pi * sample / 50 + doppler_phase
|
||||||
|
|
||||||
|
i_val += amplitude * math.cos(phase)
|
||||||
|
q_val += amplitude * math.sin(phase)
|
||||||
|
|
||||||
|
# Calculate derived values
|
||||||
|
magnitude_squared = i_val**2 + q_val**2
|
||||||
|
|
||||||
|
data.append({
|
||||||
|
'timestamp_ns': timestamp_ns,
|
||||||
|
'chirp_number': chirp_number,
|
||||||
|
'chirp_type': 'LONG',
|
||||||
|
'sample_index': sample,
|
||||||
|
'I_value': int(i_val),
|
||||||
|
'Q_value': int(q_val),
|
||||||
|
'magnitude_squared': int(magnitude_squared)
|
||||||
|
})
|
||||||
|
|
||||||
|
timestamp_ns += int(1e9 / fs_adc) # 2.5ns per sample at 400MHz
|
||||||
|
|
||||||
|
chirp_number += 1
|
||||||
|
timestamp_ns += 137000 # Add listening period (137µs)
|
||||||
|
|
||||||
|
# Guard time between long and short chirps
|
||||||
|
timestamp_ns += 175400 # 175.4µs guard time
|
||||||
|
|
||||||
|
# Generate Short Chirps (0.5µs duration equivalent)
|
||||||
|
print("Generating Short Chirps...")
|
||||||
|
for chirp in range(num_short_chirps):
|
||||||
|
for sample in range(samples_per_chirp):
|
||||||
|
# Base noise
|
||||||
|
i_val = np.random.normal(0, noise_std)
|
||||||
|
q_val = np.random.normal(0, noise_std)
|
||||||
|
|
||||||
|
# Add clutter (different characteristics for short chirps)
|
||||||
|
if sample < 50: # Less clutter for short chirps
|
||||||
|
i_val += np.random.normal(0, clutter_std/2)
|
||||||
|
q_val += np.random.normal(0, clutter_std/2)
|
||||||
|
|
||||||
|
# Add moving targets with different Doppler for short chirps
|
||||||
|
for target in targets:
|
||||||
|
# Range bin calculation (different for short chirps)
|
||||||
|
range_bin = int(target['range'] / 40) # Different range resolution
|
||||||
|
doppler_phase = 2 * math.pi * target['velocity'] * (chirp + 5) / 80 # Different Doppler
|
||||||
|
|
||||||
|
# Target appears around its range bin
|
||||||
|
if abs(sample - range_bin) < 8:
|
||||||
|
# Different amplitude characteristics for short chirps
|
||||||
|
amplitude = target['snr'] * 0.7 * (8000 / target['range']) # 70% amplitude
|
||||||
|
phase = 2 * math.pi * sample / 30 + doppler_phase
|
||||||
|
|
||||||
|
i_val += amplitude * math.cos(phase)
|
||||||
|
q_val += amplitude * math.sin(phase)
|
||||||
|
|
||||||
|
# Calculate derived values
|
||||||
|
magnitude_squared = i_val**2 + q_val**2
|
||||||
|
|
||||||
|
data.append({
|
||||||
|
'timestamp_ns': timestamp_ns,
|
||||||
|
'chirp_number': chirp_number,
|
||||||
|
'chirp_type': 'SHORT',
|
||||||
|
'sample_index': sample,
|
||||||
|
'I_value': int(i_val),
|
||||||
|
'Q_value': int(q_val),
|
||||||
|
'magnitude_squared': int(magnitude_squared)
|
||||||
|
})
|
||||||
|
|
||||||
|
timestamp_ns += int(1e9 / fs_adc) # 2.5ns per sample
|
||||||
|
|
||||||
|
chirp_number += 1
|
||||||
|
timestamp_ns += 174500 # Add listening period (174.5µs)
|
||||||
|
|
||||||
|
# Create DataFrame
|
||||||
|
df = pd.DataFrame(data)
|
||||||
|
|
||||||
|
# Save to CSV
|
||||||
|
df.to_csv(filename, index=False)
|
||||||
|
print(f"Generated CSV file: {filename}")
|
||||||
|
print(f"Total samples: {len(df)}")
|
||||||
|
print(f"Long chirps: {num_long_chirps}, Short chirps: {num_short_chirps}")
|
||||||
|
print(f"Samples per chirp: {samples_per_chirp}")
|
||||||
|
print(f"File size: {len(df) // 1000}K samples")
|
||||||
|
|
||||||
|
return df
|
||||||
|
|
||||||
|
def analyze_generated_data(df):
|
||||||
|
"""
|
||||||
|
Analyze the generated data to verify target detection
|
||||||
|
"""
|
||||||
|
print("\n=== Data Analysis ===")
|
||||||
|
|
||||||
|
# Basic statistics
|
||||||
|
long_chirps = df[df['chirp_type'] == 'LONG']
|
||||||
|
short_chirps = df[df['chirp_type'] == 'SHORT']
|
||||||
|
|
||||||
|
print(f"Long chirp samples: {len(long_chirps)}")
|
||||||
|
print(f"Short chirp samples: {len(short_chirps)}")
|
||||||
|
print(f"Unique chirp numbers: {df['chirp_number'].nunique()}")
|
||||||
|
|
||||||
|
# Calculate actual magnitude and phase for analysis
|
||||||
|
df['magnitude'] = np.sqrt(df['I_value']**2 + df['Q_value']**2)
|
||||||
|
df['phase_rad'] = np.arctan2(df['Q_value'], df['I_value'])
|
||||||
|
|
||||||
|
# Find high-magnitude samples (potential targets)
|
||||||
|
high_mag_threshold = df['magnitude'].quantile(0.95) # Top 5%
|
||||||
|
targets_detected = df[df['magnitude'] > high_mag_threshold]
|
||||||
|
|
||||||
|
print(f"\nTarget detection threshold: {high_mag_threshold:.2f}")
|
||||||
|
print(f"High magnitude samples: {len(targets_detected)}")
|
||||||
|
|
||||||
|
# Group by chirp type
|
||||||
|
long_targets = targets_detected[targets_detected['chirp_type'] == 'LONG']
|
||||||
|
short_targets = targets_detected[targets_detected['chirp_type'] == 'SHORT']
|
||||||
|
|
||||||
|
print(f"Targets in long chirps: {len(long_targets)}")
|
||||||
|
print(f"Targets in short chirps: {len(short_targets)}")
|
||||||
|
|
||||||
|
return df
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# Generate the CSV file
|
||||||
|
df = generate_radar_csv("test_radar_data.csv")
|
||||||
|
|
||||||
|
# Analyze the generated data
|
||||||
|
analyze_generated_data(df)
|
||||||
|
|
||||||
|
print("\n=== CSV File Ready ===")
|
||||||
|
print("You can now test the Python GUI with this CSV file!")
|
||||||
|
print("The file contains:")
|
||||||
|
print("- 16 Long chirps + 16 Short chirps")
|
||||||
|
print("- 4 simulated targets at different ranges and velocities")
|
||||||
|
print("- Realistic noise and clutter")
|
||||||
|
print("- Proper I/Q data for Doppler processing")
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
import numpy as np
|
||||||
|
import pandas as pd
|
||||||
|
import math
|
||||||
|
|
||||||
|
def generate_small_radar_csv(filename="small_test_radar_data.csv"):
|
||||||
|
"""
|
||||||
|
Generate a smaller, faster-to-process radar CSV
|
||||||
|
"""
|
||||||
|
# Reduced parameters for faster processing
|
||||||
|
num_long_chirps = 8 # Reduced from 16
|
||||||
|
num_short_chirps = 8 # Reduced from 16
|
||||||
|
samples_per_chirp = 128 # Reduced from 512
|
||||||
|
fs_adc = 400e6
|
||||||
|
|
||||||
|
targets = [
|
||||||
|
{'range': 3000, 'velocity': 25, 'snr': 40},
|
||||||
|
{'range': 5000, 'velocity': -15, 'snr': 35},
|
||||||
|
]
|
||||||
|
|
||||||
|
data = []
|
||||||
|
chirp_number = 0
|
||||||
|
timestamp_ns = 0
|
||||||
|
|
||||||
|
# Generate Long Chirps
|
||||||
|
for chirp in range(num_long_chirps):
|
||||||
|
for sample in range(samples_per_chirp):
|
||||||
|
i_val = np.random.normal(0, 3)
|
||||||
|
q_val = np.random.normal(0, 3)
|
||||||
|
|
||||||
|
# Add targets
|
||||||
|
for target in targets:
|
||||||
|
range_bin = int(target['range'] / 40)
|
||||||
|
doppler_phase = 2 * math.pi * target['velocity'] * chirp / 50
|
||||||
|
|
||||||
|
if abs(sample - range_bin) < 5:
|
||||||
|
amplitude = target['snr'] * (8000 / target['range'])
|
||||||
|
phase = 2 * math.pi * sample / 30 + doppler_phase
|
||||||
|
i_val += amplitude * math.cos(phase)
|
||||||
|
q_val += amplitude * math.sin(phase)
|
||||||
|
|
||||||
|
magnitude_squared = i_val**2 + q_val**2
|
||||||
|
|
||||||
|
data.append({
|
||||||
|
'timestamp_ns': timestamp_ns,
|
||||||
|
'chirp_number': chirp_number,
|
||||||
|
'chirp_type': 'LONG',
|
||||||
|
'sample_index': sample,
|
||||||
|
'I_value': int(i_val),
|
||||||
|
'Q_value': int(q_val),
|
||||||
|
'magnitude_squared': int(magnitude_squared)
|
||||||
|
})
|
||||||
|
|
||||||
|
timestamp_ns += int(1e9 / fs_adc)
|
||||||
|
|
||||||
|
chirp_number += 1
|
||||||
|
timestamp_ns += 137000
|
||||||
|
|
||||||
|
# Generate Short Chirps
|
||||||
|
for chirp in range(num_short_chirps):
|
||||||
|
for sample in range(samples_per_chirp):
|
||||||
|
i_val = np.random.normal(0, 3)
|
||||||
|
q_val = np.random.normal(0, 3)
|
||||||
|
|
||||||
|
for target in targets:
|
||||||
|
range_bin = int(target['range'] / 60)
|
||||||
|
doppler_phase = 2 * math.pi * target['velocity'] * (chirp + 2) / 40
|
||||||
|
|
||||||
|
if abs(sample - range_bin) < 4:
|
||||||
|
amplitude = target['snr'] * 0.6 * (6000 / target['range'])
|
||||||
|
phase = 2 * math.pi * sample / 25 + doppler_phase
|
||||||
|
i_val += amplitude * math.cos(phase)
|
||||||
|
q_val += amplitude * math.sin(phase)
|
||||||
|
|
||||||
|
magnitude_squared = i_val**2 + q_val**2
|
||||||
|
|
||||||
|
data.append({
|
||||||
|
'timestamp_ns': timestamp_ns,
|
||||||
|
'chirp_number': chirp_number,
|
||||||
|
'chirp_type': 'SHORT',
|
||||||
|
'sample_index': sample,
|
||||||
|
'I_value': int(i_val),
|
||||||
|
'Q_value': int(q_val),
|
||||||
|
'magnitude_squared': int(magnitude_squared)
|
||||||
|
})
|
||||||
|
|
||||||
|
timestamp_ns += int(1e9 / fs_adc)
|
||||||
|
|
||||||
|
chirp_number += 1
|
||||||
|
timestamp_ns += 174500
|
||||||
|
|
||||||
|
df = pd.DataFrame(data)
|
||||||
|
df.to_csv(filename, index=False)
|
||||||
|
print(f"Generated small CSV: {filename}")
|
||||||
|
print(f"Total samples: {len(df)}")
|
||||||
|
return df
|
||||||
|
|
||||||
|
generate_small_radar_csv()
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
import numpy as np
|
||||||
|
from numpy.fft import fft, ifft
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
|
||||||
|
n = np.arange(0, 61, 1)
|
||||||
|
Fs=125e6
|
||||||
|
Ts = 1.0 / Fs
|
||||||
|
Tb=1e-6
|
||||||
|
y = 1 + np.sin(2*np.pi*(29e6*(n**2)*(Ts**2)/(2.0*Tb)+1e6*n*Ts))
|
||||||
|
|
||||||
|
t = Ts*np.arange(0,61,1)
|
||||||
|
Y = fft(y)
|
||||||
|
M =len(Y)
|
||||||
|
m = np.arange(M)
|
||||||
|
T = M*Ts
|
||||||
|
freq = m/T
|
||||||
|
|
||||||
|
|
||||||
|
plt.figure(figsize = (12, 6))
|
||||||
|
plt.subplot(121)
|
||||||
|
plt.stem(freq, np.abs(Y), 'b', \
|
||||||
|
markerfmt=" ", basefmt="-b")
|
||||||
|
plt.xlabel('Freq (Hz)')
|
||||||
|
plt.ylabel('FFT Amplitude |Y(freq)|')
|
||||||
|
plt.xlim(0, 40*pow(10,6))
|
||||||
|
plt.ylim(0, 20)
|
||||||
|
|
||||||
|
plt.subplot(122)
|
||||||
|
plt.plot(t, ifft(Y), 'r')
|
||||||
|
plt.xlabel('Time (s)')
|
||||||
|
plt.ylabel('Amplitude')
|
||||||
|
plt.tight_layout()
|
||||||
|
|
||||||
|
plt.show()
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
import numpy as np
|
||||||
|
from numpy.fft import fft, ifft
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
|
||||||
|
|
||||||
|
fs=125*pow(10,6) #sampling frequency
|
||||||
|
Ts=1/fs # sampling time
|
||||||
|
Tb=0.25*pow(10,-6) # burst time
|
||||||
|
Tau=1.5*pow(10,-6) # pulse repetition time
|
||||||
|
fmax=32*pow(10,6) # maximum frequency on ramp
|
||||||
|
fmin=1*pow(10,6) # minimum frequency on ramp
|
||||||
|
n=int(Tb/Ts) # number of samples per ramp
|
||||||
|
N = np.arange(0, n, 1)
|
||||||
|
theta_n= 2*np.pi*(pow(N,2)*pow(Ts,2)*(fmax-fmin)/(2*Tb)+fmin*N*Ts) # instantaneous phase
|
||||||
|
y = 1 + np.sin(theta_n) # ramp signal in time domain
|
||||||
|
|
||||||
|
M = np.arange(n, 2*n, 1)
|
||||||
|
theta_m= 2*np.pi*(pow(M,2)*pow(Ts,2)*(-fmax+fmin)/(2*Tb)+(-fmin+2*fmax)*M*Ts)-2*np.pi*((fmin-fmax)*Tb/2+(2*fmax-fmin)*Tb) # instantaneous phase
|
||||||
|
z = 1 + np.sin(theta_m) # ramp signal in time domain
|
||||||
|
|
||||||
|
x = np.concatenate((y, z))
|
||||||
|
|
||||||
|
t = Ts*np.arange(0,2*n,1)
|
||||||
|
X = fft(x)
|
||||||
|
L =len(X)
|
||||||
|
l = np.arange(L)
|
||||||
|
T = L*Ts
|
||||||
|
freq = l/T
|
||||||
|
|
||||||
|
|
||||||
|
plt.figure(figsize = (12, 6))
|
||||||
|
plt.subplot(121)
|
||||||
|
plt.stem(freq, np.abs(X), 'b', \
|
||||||
|
markerfmt=" ", basefmt="-b")
|
||||||
|
plt.xlabel('Freq (Hz)')
|
||||||
|
plt.ylabel('FFT Amplitude |Y(freq)|')
|
||||||
|
plt.xlim(0, (fmax+fmax/10))
|
||||||
|
plt.ylim(0, 20)
|
||||||
|
|
||||||
|
plt.subplot(122)
|
||||||
|
plt.plot(2*n, y)
|
||||||
|
plt.xlabel('Time (s)')
|
||||||
|
plt.ylabel('Amplitude')
|
||||||
|
plt.tight_layout()
|
||||||
|
|
||||||
|
plt.show()
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
import numpy as np
|
||||||
|
from numpy.fft import fft, ifft
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
|
||||||
|
|
||||||
|
fs=125*pow(10,6) #sampling frequency
|
||||||
|
Ts=1/fs # sampling time
|
||||||
|
Tb=0.5*pow(10,-6) # burst time
|
||||||
|
Tau=900*pow(10,-6) # pulse repetition time
|
||||||
|
fmax=30*pow(10,6) # maximum frequency on ramp
|
||||||
|
fmin=10*pow(10,6) # minimum frequency on ramp
|
||||||
|
n=int(Tb/Ts) # number of samples per ramp
|
||||||
|
N = np.arange(0, n, 1)
|
||||||
|
theta_n= 2*np.pi*(pow(N,2)*pow(Ts,2)*(fmax-fmin)/(2*Tb)+fmin*N*Ts) # instantaneous phase
|
||||||
|
|
||||||
|
y = 1 + np.sin(theta_n) # ramp signal in time domain
|
||||||
|
|
||||||
|
t = Ts*np.arange(0,n,1)
|
||||||
|
Y = fft(y)
|
||||||
|
M =len(Y)
|
||||||
|
m = np.arange(M)
|
||||||
|
T = M*Ts
|
||||||
|
freq = m/T
|
||||||
|
|
||||||
|
|
||||||
|
plt.figure(figsize = (12, 6))
|
||||||
|
plt.subplot(121)
|
||||||
|
plt.stem(freq, np.abs(Y), 'b', \
|
||||||
|
markerfmt=" ", basefmt="-b")
|
||||||
|
plt.xlabel('Freq (Hz)')
|
||||||
|
plt.ylabel('FFT Amplitude |Y(freq)|')
|
||||||
|
plt.xlim(0, (1.3*fmax))
|
||||||
|
plt.ylim(0, 60)
|
||||||
|
|
||||||
|
plt.subplot(122)
|
||||||
|
plt.plot(t, ifft(Y), 'r')
|
||||||
|
plt.xlabel('Time (s)')
|
||||||
|
plt.ylabel('Amplitude')
|
||||||
|
plt.tight_layout()
|
||||||
|
|
||||||
|
plt.show()
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
import numpy as np
|
||||||
|
from numpy.fft import fft, ifft
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
|
||||||
|
|
||||||
|
fs=125*pow(10,6) #sampling frequency
|
||||||
|
Ts=1/fs # sampling time
|
||||||
|
Tb=0.25*pow(10,-6) # burst time
|
||||||
|
Tau=1.5*pow(10,-6) # pulse repetition time
|
||||||
|
fmax=32*pow(10,6) # maximum frequency on ramp
|
||||||
|
fmin=1*pow(10,6) # minimum frequency on ramp
|
||||||
|
n=int(Tb/Ts) # number of samples per ramp
|
||||||
|
N = np.arange(0, n, 1)
|
||||||
|
theta_n= 2*np.pi*(pow(N,2)*pow(Ts,2)*(fmax-fmin)/(2*Tb)+fmin*N*Ts) # instantaneous phase
|
||||||
|
y = 1 + np.sin(theta_n) # ramp signal in time domain
|
||||||
|
|
||||||
|
M = np.arange(n, 2*n, 1)
|
||||||
|
theta_m= 2*np.pi*(pow(M,2)*pow(Ts,2)*(-fmax+fmin)/(2*Tb)+(-fmin+2*fmax)*M*Ts)-2*np.pi*((fmin-fmax)*Tb/2+(2*fmax-fmin)*Tb) # instantaneous phase
|
||||||
|
z = 1 + np.sin(theta_m) # ramp signal in time domain
|
||||||
|
|
||||||
|
x = np.concatenate((y, z))
|
||||||
|
|
||||||
|
t = Ts*np.arange(0,2*n,1)
|
||||||
|
plt.plot(t, x)
|
||||||
|
X = fft(x)
|
||||||
|
L =len(X)
|
||||||
|
l = np.arange(L)
|
||||||
|
T = L*Ts
|
||||||
|
freq = l/T
|
||||||
|
|
||||||
|
print("The Array is: ", x) #printing the array
|
||||||
|
|
||||||
|
plt.figure(figsize = (12, 6))
|
||||||
|
plt.subplot(121)
|
||||||
|
plt.stem(freq, np.abs(X), 'b', \
|
||||||
|
markerfmt=" ", basefmt="-b")
|
||||||
|
plt.xlabel('Freq (Hz)')
|
||||||
|
plt.ylabel('FFT Amplitude |Y(freq)|')
|
||||||
|
plt.xlim(0, (fmax+fmax/10))
|
||||||
|
plt.ylim(0, 20)
|
||||||
|
|
||||||
|
plt.subplot(122)
|
||||||
|
plt.plot(t, ifft(X), 'r')
|
||||||
|
plt.xlabel('Time (s)')
|
||||||
|
plt.ylabel('Amplitude')
|
||||||
|
plt.tight_layout()
|
||||||
|
|
||||||
|
plt.show()
|
||||||
|
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import numpy as np
|
||||||
|
|
||||||
|
# Define parameters
|
||||||
|
fs = 120e6 # Sampling frequency
|
||||||
|
Ts = 1 / fs # Sampling time
|
||||||
|
Tb = 1e-6 # Burst time
|
||||||
|
Tau = 30e-6 # Pulse repetition time
|
||||||
|
fmax = 15e6 # Maximum frequency on ramp
|
||||||
|
fmin = 1e6 # Minimum frequency on ramp
|
||||||
|
|
||||||
|
# Compute number of samples per ramp
|
||||||
|
n = int(Tb / Ts)
|
||||||
|
N = np.arange(0, n, 1)
|
||||||
|
|
||||||
|
# Compute instantaneous phase
|
||||||
|
theta_n = 2 * np.pi * ((N**2 * Ts**2 * (fmax - fmin) / (2 * Tb)) + fmin * N * Ts)
|
||||||
|
|
||||||
|
# Generate waveform and scale it to 8-bit unsigned values (0 to 255)
|
||||||
|
y = 1 + np.sin(theta_n) # Normalize from 0 to 2
|
||||||
|
y_scaled = np.round(y * 127.5).astype(int) # Scale to 8-bit range (0-255)
|
||||||
|
|
||||||
|
# Print values in Verilog-friendly format
|
||||||
|
for i in range(n):
|
||||||
|
print(f"waveform_LUT[{i}] = 8'h{y_scaled[i]:02X};")
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import numpy as np
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
n = np.arange(0, 61, 1)
|
||||||
|
Ts=8*pow(10,-9)
|
||||||
|
y = 1 + np.sin(2*np.pi*(-16*pow(10,12)*pow(n,2)*pow(Ts,2)+16*pow(10,6)*n*Ts))
|
||||||
|
plt.plot(n, y)
|
||||||
|
plt.show()
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
import numpy as np
|
||||||
|
|
||||||
|
def calculate_patch_antenna_parameters(frequency, epsilon_r, h_sub, h_cu, array):
|
||||||
|
# Constants
|
||||||
|
c = 3e8 # Speed of light in m/s
|
||||||
|
|
||||||
|
# Convert height from mm to meters
|
||||||
|
h_sub_m = h_sub * 1e-3
|
||||||
|
h_cu_m = h_cu * 1e-3
|
||||||
|
|
||||||
|
# Calculate Lambda
|
||||||
|
lamb = c /(frequency * 1e9)
|
||||||
|
|
||||||
|
# Calculate the effective dielectric constant
|
||||||
|
epsilon_eff = (epsilon_r + 1) / 2 + (epsilon_r - 1) / 2 * (1 + 12 * h_sub_m / (array[1] * h_cu_m)) ** (-0.5)
|
||||||
|
|
||||||
|
# Calculate the width of the patch
|
||||||
|
W = c / (2 * frequency * 1e9) * np.sqrt(2 / (epsilon_r + 1))
|
||||||
|
|
||||||
|
# Calculate the effective length
|
||||||
|
delta_L = 0.412 * h_sub_m * (epsilon_eff + 0.3) * (W / h_sub_m + 0.264) / ((epsilon_eff - 0.258) * (W / h_sub_m + 0.8))
|
||||||
|
|
||||||
|
# Calculate the length of the patch
|
||||||
|
L = c / (2 * frequency * 1e9 * np.sqrt(epsilon_eff)) - 2 * delta_L
|
||||||
|
|
||||||
|
# Calculate the separation distance in the horizontal axis (dx)
|
||||||
|
dx = lamb/2 # Typically 1.5 times the width of the patch
|
||||||
|
|
||||||
|
# Calculate the separation distance in the vertical axis (dy)
|
||||||
|
dy = lamb/2 # Typically 1.5 times the length of the patch
|
||||||
|
|
||||||
|
# Calculate the feeding line width (W_feed)
|
||||||
|
Z0 = 50 # Characteristic impedance of the feeding line (typically 50 ohms)
|
||||||
|
A = Z0 / 60 * np.sqrt((epsilon_r + 1) / 2) + (epsilon_r - 1) / (epsilon_r + 1) * (0.23 + 0.11 / epsilon_r)
|
||||||
|
W_feed = 8 * h_sub_m / np.exp(A) - 2 * h_cu_m
|
||||||
|
|
||||||
|
# Convert results back to mm
|
||||||
|
W_mm = W * 1e3
|
||||||
|
L_mm = L * 1e3
|
||||||
|
dx_mm = dx * 1e3
|
||||||
|
dy_mm = dy * 1e3
|
||||||
|
W_feed_mm = W_feed * 1e3
|
||||||
|
|
||||||
|
return W_mm, L_mm, dx_mm, dy_mm, W_feed_mm
|
||||||
|
|
||||||
|
# Example usage
|
||||||
|
frequency = 10.5 # Frequency in GHz
|
||||||
|
epsilon_r = 3.48 # Relative permittivity of the substrate
|
||||||
|
h_sub = 0.102 # Height of substrate in mm
|
||||||
|
h_cu = 0.07 # Height of copper in mm
|
||||||
|
array = [2, 2] # 2x2 array
|
||||||
|
|
||||||
|
W_mm, L_mm, dx_mm, dy_mm, W_feed_mm = calculate_patch_antenna_parameters(frequency, epsilon_r, h_sub, h_cu, array)
|
||||||
|
|
||||||
|
print(f"Width of the patch: {W_mm:.4f} mm")
|
||||||
|
print(f"Length of the patch: {L_mm:.4f} mm")
|
||||||
|
print(f"Separation distance in horizontal axis: {dx_mm:.4f} mm")
|
||||||
|
print(f"Separation distance in vertical axis: {dy_mm:.4f} mm")
|
||||||
|
print(f"Feeding line width: {W_feed_mm:.2f} mm")
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user