Files
trail-mate/docs/EnergySweep/function.md
T

376 lines
9.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
它实现了什么功能?
## 1️⃣ 实时频段能量扫描(Energy Sweep
左侧柱状图表示:
* X 轴:频率区间(例如 433.050 → 434.790 MHz
* Y 轴:RSSI 强度
* 每根柱:一个步进频点的瞬时/平均功率
它的意义是:
* 快速查看该频段是否拥挤
* 判断是否存在强干扰
* 观察噪声底(Noise Floor
* 找出峰值位置
这不是 SDR 级 FFT,而是 **工程级信道占用判断工具**
---
## 2️⃣ 精确频点分析(Cursor 模式)
右侧 CURSOR 区域实现:
* 当前指向频点(433.550 MHz
* 该频点 RSSI
* 当前噪声水平
这让它从“观察”变成“测量”。
你不只是看到一堆柱子,而是可以:
* 精确读取某个频点的功率
* 判断是否可用
* 判断是否存在连续干扰
---
## 3️⃣ 自动最优信道选择(Best Channel Detection
BEST 区域实现:
* 计算“最干净”的频点
* 显示推荐频率
* 显示 SNR
这一步非常关键,它实现了:
> 从频谱数据 → 可行动建议
它不只是显示世界,而是**给出决策结果**。
---
## 4️⃣ 扫描进度管理
72% 进度条说明:
* 扫描是区间遍历
* 用户知道系统状态
* 避免“卡住”误解
这提升了工程可用性。
---
## 5️⃣ 扫描控制(STOP / AUTO
* STOP:终止扫描
* AUTO:自动选择最佳信道
这意味着:
这个页面已经从“只读显示器”
变成了
“频段管理工具”。
---
# 二、这个界面在系统层面的意义
在 Trail-Mate 架构里,这个页面完成的是:
### 🛰 频谱态势感知(RF Situational Awareness
它回答:
* 现在这个频段干净吗?
* 是否有强占用?
* 我的 LoRa 该选哪个频点?
* 是否存在持续干扰源?
它是一个“战术前侦查页面”。
---
# 三、它属于什么级别的功能?
不是:
* ❌ 频谱仪
* ❌ SDR 分析工具
而是:
* ✅ 信道规划工具
* ✅ 干扰检测工具
* ✅ 频段健康监测器
* ✅ 自动选频前置模块
---
# 四、从用户视角来看
这个界面完成的是:
> “在野外部署前,快速检查当前 Sub-GHz 频段是否适合通信。”
这对于:
* LoRa mesh
* FSK 语音
* APRS
* 临时战术部署
都非常实用。
---
# 五、它的核心能力总结
这个 UI 实现了:
| 能力 | 是否实现 |
| ------------- | ---- |
| 频段扫描 | ✅ |
| 功率可视化 | ✅ |
| 精确频点读取 | ✅ |
| 最佳信道推荐 | ✅ |
| 扫描控制 | ✅ |
| LoRa CAD 状态展示 | ✅ |
下面按“你这个界面对应的能力”把**算法 + 功能实现方案**讲清楚,目标是:用 SX1262 在 MCU 上做一个**可用的能量扫描/信道选择器**(不是 FFT 频谱仪)。
---
## 1) 总体架构
**输入**:频段范围(f_start, f_end)、步进(step)、每点采样时长(dwell)、采样次数(N)
**输出**:每个频点的能量值(RSSI/ED)、噪声底(noise floor)、最佳频点(best channel)、峰值/干扰标记、扫描进度
数据流:
1. 扫频采样 → 得到 `rssi[f_i]`
2. 估计噪声底 → 得到 `noise_floor`
3. 计算评分/选优 → 得到 `best_freq`
4. UI 渲染:柱状图、cursor、RSSI/NOISE/BEST、进度
---
## 2) 扫频采样算法(核心)
### 2.1 频点序列
把频率离散化:
* `bins = floor((f_end - f_start)/step) + 1`
* `f_i = f_start + i * step`
**步进怎么选(工程上)**
* 想“看干扰哪里高”:`step = 25 kHz``50 kHz` 足够
* 想“粗扫很快”:`step = 100 kHz`
* 如果你 LoRa 频道带宽是 125 kHz,你用 25 kHz 扫描能更精细地看占用“峰”的位置(但更慢)
### 2.2 每个频点怎么测“能量”
SX1262 拿不到 IQ,所以只能用“能量指标”。最常见是 **Instant RSSI** 或类似 ED 指标(取决于你用的库/驱动暴露的命令)。
每个频点做:
1. `SetRfFrequency(f_i)`
2. 进入 RX(可以是 LoRa RX 或 FSK RX,关键是能读到 RSSI
3. 等待 **settle**(本振/AGC 稳定):`t_settle ≈ 1~3 ms`
4. 采样 N 次瞬时 RSSI:每次间隔 `t_gap ≈ 1~2 ms`
5. 得到该频点值 `P_i`
**P_i 不要直接用平均值(会被突发信号骗)**
推荐三种稳健聚合方式:
* **median(中位数)**:抗突发、抗偶发尖峰(推荐默认)
* **trimmed mean(去头去尾均值)**:丢掉最高/最低各 10~20%
* **EMA(指数滑动均值)**:适合连续扫描实时更新
> 我建议默认:`P_i = median(rssi_samples)`
### 2.3 扫描速度估算(让 UI 不卡)
总时间大约:
`T ≈ bins * (t_settle + N*(t_gap + t_read))`
例如:
* 频段宽 1.74 MHz433.050434.790
* step=25 kHz → bins≈70
* t_settle=2ms, N=6, t_gap=1ms
→ 单 bin ~ 2 + 6*(1+读寄存器开销) ≈ 10ms
→ 总计 ~ 700ms(很好用)
---
## 3) 噪声底(NOISE)如何估计
你界面右侧有 `NOISE -104 dBm`,这不是芯片“真噪声”,而是你对扫描数据的统计估计。
### 3.1 推荐方法:分位数/中位数 + 偏置
因为频段里可能有很多峰,直接平均会被抬高。
* `noise_floor = percentile(P, 20%)``median(P)`
* 然后再做一个轻微平滑:`noise = 0.7*noise + 0.3*noise_floor`(跨帧稳定)
### 3.2 为什么用 20% 分位数
* 频段里如果有少数强信号,它们只占少量 bins
* 20% 分位数更接近“底噪水平”
* 你要的是“哪里比底噪高”,不是绝对精密测量
---
## 4) 峰值/干扰标记(柱子变红)
UI 中红柱代表“干扰/占用较强”。规则建议:
* `threshold = noise + margin`
* margin 典型:`6 dB ~ 12 dB`(看你希望多敏感)
*`P_i > threshold` → 标红(Warn
*`P_i > threshold + 10 dB` → 可以加一个“尖峰标记”(小三角)
为了避免抖动,给红柱加**滞回**
* 进入红色:`P_i > noise + 10 dB`
* 退出红色:`P_i < noise + 7 dB`
---
## 5) CURSOR(指针)怎么实现
Cursor 有两种交互模式:
### 5.1 自动跟随(扫描中)
* cursor_index = 当前正在采样的 bin
* UI 每采完一个 bin,就移动光标竖线
### 5.2 手动浏览(扫描结束/暂停)
* 按键左右移动 cursor_index
* 右侧显示 `freq[cursor]``P_cursor``noise`
光标竖线 + 底部小三角只是渲染层,数据来自数组即可。
---
## 6) BEST(最佳信道)如何选
你要的是“最干净、最适合通信”的频点。简单选最小 RSSI 不够,因为:
* 单点最低可能是偶然低谷
* LoRa/FSK 发射占带宽,不是一个点
### 6.1 “带宽窗口”评分(推荐)
设通信带宽 `BW`(例如 125k),换算成需要覆盖的 bin 数:
* `k = ceil(BW / step)`
* 对每个中心 bin i,计算窗口内的“最坏情况”:
* `score_i = max(P[i - k/2 ... i + k/2])`
* 选择 score 最小的 i 作为 best
这会避免选到“旁边有大峰”的位置。
### 6.2 加上保护间隔(guard
LoRa 频偏/温漂/邻道干扰都存在,可以再加 guard,例如 ±1~2 个 bin 也纳入窗口。
---
## 7) SNR +12 怎么来?
在你这个“能量扫描”场景里,SNR 是**估算值**:
* `snr_est = noise - P_best` (注意 dBm 越小越弱,所以符号要小心)
更直观写法:
* `snr_est = (P_best - noise)`,如果 P_best 比 noise 高就是负数;但你 UI 里显示 +12,代表你希望“越干净越大”。
所以建议定义为:
* `cleanliness = noise - P_best`(越大越干净)
* 显示:`SNR +cleanliness`
例如:noise=-104, best=-116 → cleanliness=12 → `SNR +12`(符合 UI
---
## 8) CADLoRa preamble 检测)怎么融合
CAD 不是全频谱扫描,它是“在某个频点上检测是否存在 LoRa 前导码”。
你 UI 顶部的 `CAD` 可以这样实现:
* 当用户开启 CAD
* 每次扫描到某个 bin,如果你关心该点是否有 LoRa,执行一次 CAD
* 得到 `cad_detected`(布尔)
* 如果 detected:给该 bin 做一个“蓝色小点/标记”,或者让状态灯闪一下
但要注意:**CAD 会增加耗时**,所以策略上可以:
* 只对“疑似忙碌”的 binsP_i > noise+X)做 CAD
* 或者扫描完成后,对 best 候选点做 CAD 复核
---
## 9) 进度条与 STOP/AUTO 行为
### 9.1 进度条
* `progress = scanned_bins / bins`
* UI 每完成一个 bin 更新一次(不要每次采样更新,UI 会抖)
### 9.2 STOP
* 设置一个 `scan_abort` 标志
* 每个 bin 结束检查一次,立即退出
* UI 状态切换到“冻结显示 + 可移动 cursor”
### 9.3 AUTO
* 触发 best 计算
* 并把无线模块的工作频点切换到 best
* (可选)保存到配置:让下一次上电沿用
---
## 10) 如果你要更“专业”的两点增强
### A) 动态中心频率校准(你之前提过)
如果你担心频偏/温漂导致“峰”位置漂:
* 在每个 bin 的 dwell 中,取前 2ms 的样本作为快速估计
* 用它对后续样本做轻微校正(本质是稳定统计,不是真频偏补偿)
更实际的做法:**只做 UI 平滑**,别做“频率校准”的强承诺。
### B) 多帧叠加(历史底噪)
维护 `P_i_hist` 的 EMA
* `P_i = 0.6*P_i + 0.4*P_i_prev`
这样界面更稳,像“仪表”而不是“闪动的噪声”。
---
## 11) 你最终会得到什么?
* 一个频段扫描器(几十~几百 ms 出结果)
* 可视化占用峰(红柱)
* 可读的底噪估计(NOISE
* 可行动的推荐频点(BEST + 清洁度)
* 可选的 LoRa CAD 复核
* 并能一键 AUTO 切换工作信道