Skip to content

Commit a9e28c3

Browse files
committed
feat: add Energy Sweep app with region-based scan range
1 parent 7a06f21 commit a9e28c3

File tree

9 files changed

+2217
-14
lines changed

9 files changed

+2217
-14
lines changed
1.55 MB
Loading

docs/EnergySweep/function.md

Lines changed: 375 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,375 @@
1+
它实现了什么功能?
2+
3+
## 1️⃣ 实时频段能量扫描(Energy Sweep)
4+
5+
左侧柱状图表示:
6+
7+
* X 轴:频率区间(例如 433.050 → 434.790 MHz)
8+
* Y 轴:RSSI 强度
9+
* 每根柱:一个步进频点的瞬时/平均功率
10+
11+
它的意义是:
12+
13+
* 快速查看该频段是否拥挤
14+
* 判断是否存在强干扰
15+
* 观察噪声底(Noise Floor)
16+
* 找出峰值位置
17+
18+
这不是 SDR 级 FFT,而是 **工程级信道占用判断工具**
19+
20+
---
21+
22+
## 2️⃣ 精确频点分析(Cursor 模式)
23+
24+
右侧 CURSOR 区域实现:
25+
26+
* 当前指向频点(433.550 MHz)
27+
* 该频点 RSSI
28+
* 当前噪声水平
29+
30+
这让它从“观察”变成“测量”。
31+
32+
你不只是看到一堆柱子,而是可以:
33+
34+
* 精确读取某个频点的功率
35+
* 判断是否可用
36+
* 判断是否存在连续干扰
37+
38+
---
39+
40+
## 3️⃣ 自动最优信道选择(Best Channel Detection)
41+
42+
BEST 区域实现:
43+
44+
* 计算“最干净”的频点
45+
* 显示推荐频率
46+
* 显示 SNR
47+
48+
这一步非常关键,它实现了:
49+
50+
> 从频谱数据 → 可行动建议
51+
52+
它不只是显示世界,而是**给出决策结果**
53+
54+
---
55+
56+
## 4️⃣ 扫描进度管理
57+
58+
72% 进度条说明:
59+
60+
* 扫描是区间遍历
61+
* 用户知道系统状态
62+
* 避免“卡住”误解
63+
64+
这提升了工程可用性。
65+
66+
---
67+
68+
## 5️⃣ 扫描控制(STOP / AUTO)
69+
70+
* STOP:终止扫描
71+
* AUTO:自动选择最佳信道
72+
73+
这意味着:
74+
75+
这个页面已经从“只读显示器”
76+
变成了
77+
“频段管理工具”。
78+
79+
---
80+
81+
# 二、这个界面在系统层面的意义
82+
83+
在 Trail-Mate 架构里,这个页面完成的是:
84+
85+
### 🛰 频谱态势感知(RF Situational Awareness)
86+
87+
它回答:
88+
89+
* 现在这个频段干净吗?
90+
* 是否有强占用?
91+
* 我的 LoRa 该选哪个频点?
92+
* 是否存在持续干扰源?
93+
94+
它是一个“战术前侦查页面”。
95+
96+
---
97+
98+
# 三、它属于什么级别的功能?
99+
100+
不是:
101+
102+
* ❌ 频谱仪
103+
* ❌ SDR 分析工具
104+
105+
而是:
106+
107+
* ✅ 信道规划工具
108+
* ✅ 干扰检测工具
109+
* ✅ 频段健康监测器
110+
* ✅ 自动选频前置模块
111+
112+
---
113+
114+
# 四、从用户视角来看
115+
116+
这个界面完成的是:
117+
118+
> “在野外部署前,快速检查当前 Sub-GHz 频段是否适合通信。”
119+
120+
这对于:
121+
122+
* LoRa mesh
123+
* FSK 语音
124+
* APRS
125+
* 临时战术部署
126+
127+
都非常实用。
128+
129+
---
130+
131+
# 五、它的核心能力总结
132+
133+
这个 UI 实现了:
134+
135+
| 能力 | 是否实现 |
136+
| ------------- | ---- |
137+
| 频段扫描 ||
138+
| 功率可视化 ||
139+
| 精确频点读取 ||
140+
| 最佳信道推荐 ||
141+
| 扫描控制 ||
142+
| LoRa CAD 状态展示 ||
143+
144+
下面按“你这个界面对应的能力”把**算法 + 功能实现方案**讲清楚,目标是:用 SX1262 在 MCU 上做一个**可用的能量扫描/信道选择器**(不是 FFT 频谱仪)。
145+
146+
---
147+
148+
## 1) 总体架构
149+
150+
**输入**:频段范围(f_start, f_end)、步进(step)、每点采样时长(dwell)、采样次数(N)
151+
**输出**:每个频点的能量值(RSSI/ED)、噪声底(noise floor)、最佳频点(best channel)、峰值/干扰标记、扫描进度
152+
153+
数据流:
154+
155+
1. 扫频采样 → 得到 `rssi[f_i]`
156+
2. 估计噪声底 → 得到 `noise_floor`
157+
3. 计算评分/选优 → 得到 `best_freq`
158+
4. UI 渲染:柱状图、cursor、RSSI/NOISE/BEST、进度
159+
160+
---
161+
162+
## 2) 扫频采样算法(核心)
163+
164+
### 2.1 频点序列
165+
166+
把频率离散化:
167+
168+
* `bins = floor((f_end - f_start)/step) + 1`
169+
* `f_i = f_start + i * step`
170+
171+
**步进怎么选(工程上)**
172+
173+
* 想“看干扰哪里高”:`step = 25 kHz``50 kHz` 足够
174+
* 想“粗扫很快”:`step = 100 kHz`
175+
* 如果你 LoRa 频道带宽是 125 kHz,你用 25 kHz 扫描能更精细地看占用“峰”的位置(但更慢)
176+
177+
### 2.2 每个频点怎么测“能量”
178+
179+
SX1262 拿不到 IQ,所以只能用“能量指标”。最常见是 **Instant RSSI** 或类似 ED 指标(取决于你用的库/驱动暴露的命令)。
180+
181+
每个频点做:
182+
183+
1. `SetRfFrequency(f_i)`
184+
2. 进入 RX(可以是 LoRa RX 或 FSK RX,关键是能读到 RSSI)
185+
3. 等待 **settle**(本振/AGC 稳定):`t_settle ≈ 1~3 ms`
186+
4. 采样 N 次瞬时 RSSI:每次间隔 `t_gap ≈ 1~2 ms`
187+
5. 得到该频点值 `P_i`
188+
189+
**P_i 不要直接用平均值(会被突发信号骗)**
190+
推荐三种稳健聚合方式:
191+
192+
* **median(中位数)**:抗突发、抗偶发尖峰(推荐默认)
193+
* **trimmed mean(去头去尾均值)**:丢掉最高/最低各 10~20%
194+
* **EMA(指数滑动均值)**:适合连续扫描实时更新
195+
196+
> 我建议默认:`P_i = median(rssi_samples)`
197+
198+
### 2.3 扫描速度估算(让 UI 不卡)
199+
200+
总时间大约:
201+
202+
`T ≈ bins * (t_settle + N*(t_gap + t_read))`
203+
204+
例如:
205+
206+
* 频段宽 1.74 MHz(433.050–434.790)
207+
* step=25 kHz → bins≈70
208+
* t_settle=2ms, N=6, t_gap=1ms
209+
→ 单 bin ~ 2 + 6*(1+读寄存器开销) ≈ 10ms
210+
→ 总计 ~ 700ms(很好用)
211+
212+
---
213+
214+
## 3) 噪声底(NOISE)如何估计
215+
216+
你界面右侧有 `NOISE -104 dBm`,这不是芯片“真噪声”,而是你对扫描数据的统计估计。
217+
218+
### 3.1 推荐方法:分位数/中位数 + 偏置
219+
220+
因为频段里可能有很多峰,直接平均会被抬高。
221+
222+
* `noise_floor = percentile(P, 20%)``median(P)`
223+
* 然后再做一个轻微平滑:`noise = 0.7*noise + 0.3*noise_floor`(跨帧稳定)
224+
225+
### 3.2 为什么用 20% 分位数
226+
227+
* 频段里如果有少数强信号,它们只占少量 bins
228+
* 20% 分位数更接近“底噪水平”
229+
* 你要的是“哪里比底噪高”,不是绝对精密测量
230+
231+
---
232+
233+
## 4) 峰值/干扰标记(柱子变红)
234+
235+
UI 中红柱代表“干扰/占用较强”。规则建议:
236+
237+
* `threshold = noise + margin`
238+
* margin 典型:`6 dB ~ 12 dB`(看你希望多敏感)
239+
*`P_i > threshold` → 标红(Warn)
240+
*`P_i > threshold + 10 dB` → 可以加一个“尖峰标记”(小三角)
241+
242+
为了避免抖动,给红柱加**滞回**
243+
244+
* 进入红色:`P_i > noise + 10 dB`
245+
* 退出红色:`P_i < noise + 7 dB`
246+
247+
---
248+
249+
## 5) CURSOR(指针)怎么实现
250+
251+
Cursor 有两种交互模式:
252+
253+
### 5.1 自动跟随(扫描中)
254+
255+
* cursor_index = 当前正在采样的 bin
256+
* UI 每采完一个 bin,就移动光标竖线
257+
258+
### 5.2 手动浏览(扫描结束/暂停)
259+
260+
* 按键左右移动 cursor_index
261+
* 右侧显示 `freq[cursor]``P_cursor``noise`
262+
263+
光标竖线 + 底部小三角只是渲染层,数据来自数组即可。
264+
265+
---
266+
267+
## 6) BEST(最佳信道)如何选
268+
269+
你要的是“最干净、最适合通信”的频点。简单选最小 RSSI 不够,因为:
270+
271+
* 单点最低可能是偶然低谷
272+
* LoRa/FSK 发射占带宽,不是一个点
273+
274+
### 6.1 “带宽窗口”评分(推荐)
275+
276+
设通信带宽 `BW`(例如 125k),换算成需要覆盖的 bin 数:
277+
278+
* `k = ceil(BW / step)`
279+
* 对每个中心 bin i,计算窗口内的“最坏情况”:
280+
281+
* `score_i = max(P[i - k/2 ... i + k/2])`
282+
* 选择 score 最小的 i 作为 best
283+
284+
这会避免选到“旁边有大峰”的位置。
285+
286+
### 6.2 加上保护间隔(guard)
287+
288+
LoRa 频偏/温漂/邻道干扰都存在,可以再加 guard,例如 ±1~2 个 bin 也纳入窗口。
289+
290+
---
291+
292+
## 7) SNR +12 怎么来?
293+
294+
在你这个“能量扫描”场景里,SNR 是**估算值**
295+
296+
* `snr_est = noise - P_best` (注意 dBm 越小越弱,所以符号要小心)
297+
更直观写法:
298+
* `snr_est = (P_best - noise)`,如果 P_best 比 noise 高就是负数;但你 UI 里显示 +12,代表你希望“越干净越大”。
299+
300+
所以建议定义为:
301+
302+
* `cleanliness = noise - P_best`(越大越干净)
303+
* 显示:`SNR +cleanliness`
304+
305+
例如:noise=-104, best=-116 → cleanliness=12 → `SNR +12`(符合 UI)
306+
307+
---
308+
309+
## 8) CAD(LoRa preamble 检测)怎么融合
310+
311+
CAD 不是全频谱扫描,它是“在某个频点上检测是否存在 LoRa 前导码”。
312+
313+
你 UI 顶部的 `CAD` 可以这样实现:
314+
315+
* 当用户开启 CAD:
316+
317+
* 每次扫描到某个 bin,如果你关心该点是否有 LoRa,执行一次 CAD
318+
* 得到 `cad_detected`(布尔)
319+
* 如果 detected:给该 bin 做一个“蓝色小点/标记”,或者让状态灯闪一下
320+
321+
但要注意:**CAD 会增加耗时**,所以策略上可以:
322+
323+
* 只对“疑似忙碌”的 bins(P_i > noise+X)做 CAD
324+
* 或者扫描完成后,对 best 候选点做 CAD 复核
325+
326+
---
327+
328+
## 9) 进度条与 STOP/AUTO 行为
329+
330+
### 9.1 进度条
331+
332+
* `progress = scanned_bins / bins`
333+
* UI 每完成一个 bin 更新一次(不要每次采样更新,UI 会抖)
334+
335+
### 9.2 STOP
336+
337+
* 设置一个 `scan_abort` 标志
338+
* 每个 bin 结束检查一次,立即退出
339+
* UI 状态切换到“冻结显示 + 可移动 cursor”
340+
341+
### 9.3 AUTO
342+
343+
* 触发 best 计算
344+
* 并把无线模块的工作频点切换到 best
345+
* (可选)保存到配置:让下一次上电沿用
346+
347+
---
348+
349+
## 10) 如果你要更“专业”的两点增强
350+
351+
### A) 动态中心频率校准(你之前提过)
352+
353+
如果你担心频偏/温漂导致“峰”位置漂:
354+
355+
* 在每个 bin 的 dwell 中,取前 2ms 的样本作为快速估计
356+
* 用它对后续样本做轻微校正(本质是稳定统计,不是真频偏补偿)
357+
更实际的做法:**只做 UI 平滑**,别做“频率校准”的强承诺。
358+
359+
### B) 多帧叠加(历史底噪)
360+
361+
维护 `P_i_hist` 的 EMA:
362+
363+
* `P_i = 0.6*P_i + 0.4*P_i_prev`
364+
这样界面更稳,像“仪表”而不是“闪动的噪声”。
365+
366+
---
367+
368+
## 11) 你最终会得到什么?
369+
370+
* 一个频段扫描器(几十~几百 ms 出结果)
371+
* 可视化占用峰(红柱)
372+
* 可读的底噪估计(NOISE)
373+
* 可行动的推荐频点(BEST + 清洁度)
374+
* 可选的 LoRa CAD 复核
375+
* 并能一键 AUTO 切换工作信道

0 commit comments

Comments
 (0)