Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit0c16a35

Browse files
committed
static waterfall example updated
1 parent8fc3a5c commit0c16a35

File tree

1 file changed

+172
-0
lines changed

1 file changed

+172
-0
lines changed
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
#! /usr/bin/python3
2+
##-------------------------------------------------------------------------------\
3+
# tinySA_python (tsapython)
4+
# './examples/plotting_waterfall_1.py'
5+
# A waterfall plot example using matplotlib to plot multiple SCAN data over time
6+
#
7+
# Last update: August 17, 2025
8+
##-------------------------------------------------------------------------------\
9+
10+
# import tinySA_python (tsapython) package
11+
fromtsapythonimporttinySA
12+
13+
# imports FOR THE EXAMPLE
14+
importcsv
15+
importnumpyasnp
16+
importmatplotlib.pyplotasplt
17+
importtime
18+
fromdatetimeimportdatetime
19+
20+
defconvert_data_to_arrays(start,stop,pts,data):
21+
# using the start and stop frequencies, and the number of points,
22+
freq_arr=np.linspace(start,stop,pts)# note that the decimals might go out to many places.
23+
# you can truncate this because its only used
24+
# for plotting in this example
25+
# As of the Jan. 2024 build in some data returned with SWEEP or SCAN calls there is error data.
26+
# https://groups.io/g/tinysa/topic/tinasa_ultra_sweep_command/104194367
27+
# this shows up as "-:.000000e+01".
28+
# TEMP fix - replace the colon character with a -10. This puts the 'filled in' points around the noise floor.
29+
# more advanced filtering should be applied for actual analysis.
30+
31+
data1=bytearray(data.replace(b"-:.0",b"-10.0"))
32+
33+
# get both values in each row returned (for reference)
34+
#data_arr = [list(map(float, line.split())) for line in data.decode('utf-8').split('\n') if line.strip()]
35+
36+
# get first value in each returned row
37+
data_arr= [float(line.split()[0])forlineindata1.decode('utf-8').split('\n')ifline.strip()]
38+
returnfreq_arr,data_arr
39+
40+
defcollect_waterfall_data(tsa,start,stop,pts,outmask,num_scans,scan_interval):
41+
42+
waterfall_data= []# 2D array of scan data (time x frequency)
43+
timestamps= []
44+
freq_arr=None
45+
46+
print(f"Collecting{num_scans} scans with{scan_interval}s intervals...")
47+
48+
foriinrange(num_scans):
49+
print(f"Scan{i+1}/{num_scans}")
50+
51+
# Perform scan
52+
data_bytes=tsa.scan(start,stop,pts,outmask)
53+
54+
# Convert to arrays
55+
iffreq_arrisNone:
56+
freq_arr,data_arr=convert_data_to_arrays(start,stop,pts,data_bytes)
57+
else:
58+
_,data_arr=convert_data_to_arrays(start,stop,pts,data_bytes)
59+
60+
# Store data and timestamp
61+
waterfall_data.append(data_arr)
62+
timestamps.append(datetime.now())
63+
64+
# Wait before next scan (except for last scan)
65+
ifi<num_scans-1:
66+
time.sleep(scan_interval)
67+
68+
returnfreq_arr,np.array(waterfall_data),timestamps
69+
70+
defplot_waterfall(freq_arr,waterfall_data,timestamps,start,stop):
71+
# Create figure with subplots
72+
fig, (ax1,ax2)=plt.subplots(2,1,figsize=(12,10))
73+
74+
# Waterfall plot (main plot)
75+
# Create time array for y-axis (scan number or elapsed time)
76+
time_arr=np.arange(len(timestamps))
77+
78+
# Create meshgrid for pcolormesh
79+
freq_mesh,time_mesh=np.meshgrid(freq_arr,time_arr)
80+
81+
# Plot waterfall
82+
im=ax1.pcolormesh(freq_mesh/1e9,time_mesh,waterfall_data,
83+
shading='nearest',cmap='viridis')
84+
85+
ax1.set_xlabel('Frequency (GHz)')
86+
ax1.set_ylabel('Scan Number')
87+
ax1.set_title(f'Waterfall Plot:{start/1e9:.1f} -{stop/1e9:.1f} GHz')
88+
89+
# Add colorbar
90+
cbar=plt.colorbar(im,ax=ax1)
91+
cbar.set_label('Signal Strength (dBm)')
92+
93+
# Latest scan plot (bottom subplot)
94+
ax2.plot(freq_arr/1e9,waterfall_data[-1])
95+
ax2.set_xlabel('Frequency (GHz)')
96+
ax2.set_ylabel('Signal Strength (dBm)')
97+
ax2.set_title('Latest Scan')
98+
ax2.grid(True,alpha=0.3)
99+
100+
plt.tight_layout()
101+
returnfig
102+
103+
# create a new tinySA object
104+
tsa=tinySA()
105+
# set the return message preferences
106+
tsa.set_verbose(True)#detailed messages
107+
tsa.set_error_byte_return(True)#get explicit b'ERROR' if error thrown
108+
109+
# attempt to autoconnect
110+
found_bool,connected_bool=tsa.autoconnect()
111+
112+
# if port closed, then return error message
113+
ifconnected_bool==False:
114+
print("ERROR: could not connect to port")
115+
else:# if port found and connected, then complete task(s) and disconnect
116+
try:
117+
# set scan values
118+
start=int(1e9)# 1 GHz
119+
stop=int(3e9)# 3 GHz
120+
pts=450# sample points
121+
outmask=2# get measured data (y axis)
122+
123+
# waterfall parameters
124+
num_scans=5# number of scans to collect
125+
scan_interval=0.5# seconds between scans
126+
127+
# collect waterfall data
128+
freq_arr,waterfall_data,timestamps=collect_waterfall_data(
129+
tsa,start,stop,pts,outmask,num_scans,scan_interval)
130+
131+
print("Data collection complete!")
132+
133+
# resume and disconnect
134+
tsa.resume()#resume so screen isn't still frozen
135+
tsa.disconnect()
136+
137+
# processing after disconnect
138+
print("Creating waterfall plot...")
139+
140+
# create waterfall plot
141+
fig=plot_waterfall(freq_arr,waterfall_data,timestamps,start,stop)
142+
143+
# Save data out to .csv
144+
filename="waterfall_1_sample.csv"
145+
146+
# Create CSV with frequency headers and time/scan data
147+
withopen(filename,'w',newline='')ascsvfile:
148+
writer=csv.writer(csvfile)
149+
150+
# Write header row with frequencies (in Hz)
151+
header= ['Scan_Number','Timestamp']+ [f'{freq:.0f}'forfreqinfreq_arr]
152+
writer.writerow(header)
153+
154+
# Write data rows
155+
fori, (scan_data,timestamp)inenumerate(zip(waterfall_data,timestamps)):
156+
row= [i+1,timestamp.strftime('%Y-%m-%d %H:%M:%S.%f')[:-3]]+scan_data.tolist()
157+
writer.writerow(row)
158+
159+
print(f"Data saved to{filename}")
160+
print(f"CSV contains{len(waterfall_data)} scans with{len(freq_arr)} frequency points each")
161+
162+
# show plot
163+
plt.show()
164+
165+
exceptKeyboardInterrupt:
166+
print("\nScan interrupted by user")
167+
tsa.resume()
168+
tsa.disconnect()
169+
exceptExceptionase:
170+
print(f"Error occurred:{e}")
171+
tsa.resume()
172+
tsa.disconnect()

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp