Leveling & ARB

DUT RX 校准流程中的 Leveling & ARB 特性化

概述

本文档描述 RequestExternalStimuli RPC 中 步骤 2.5 Leveling步骤 2.6 ARB 特性化 的实现方案。

功率计底层驱动实现(NRPPowerMeter 类),本模块直接调用 pm.measure_power(freq_hz) 获取 dBm 值,专注于 Leveling 闭环算法和 ARB 特性化业务逻辑。


在 RequestExternalStimuli 中的位置

RequestExternalStimuli()
│
├── 步骤 2.1: 判断信号类型 (CW / 调制 / 多音)
├── 步骤 2.2: 分配硬件资源
├── 步骤 2.3: 加载波形 (仅调制/多音)          ← 已实现
├── 步骤 2.4: 配置信号发生器 (频率、功率、RF ON) ← 已实现
│
├── 步骤 2.5: Leveling (电平校准) ★
│       └── perform_leveling(sg, pm, ...)
│
├── 步骤 2.6: ARB 特性化 (仅多音) ★
│       └── arb_characterization(sg, pm, arb_uploader, ...)
│
└── 步骤 2.7: 计算端口偏移响应

提供的功率计驱动

代码位置: tx_output_power_cal_service/nrp_power_meter.py
类名: NRPPowerMeter
连接方式: VISA (USB/LAN)
支持型号: R&S NRP8S / NRP40S 系列

Leveling 和 ARB 特性化中实际调用的函数:

函数 功能 返回
pm.measure_power(frequency_hz, average_count=4) 设置频率+平均,测量功率 float (dBm) 或 None
pm.set_frequency(frequency_hz) 设置功率计校正频率
pm.read_power() 单次测量 (不改频率) float (dBm) 或 None
pm.connect() / pm.disconnect() 连接/断开 VISA
pm.reset() 复位到已知状态
pm.zero_calibration() 校零 (需断开 RF)

使用方式:

from nrp_power_meter import NRPPowerMeter

pm = NRPPowerMeter(visa_resource="USB0::0x0AAD::0x00E2::108020::INSTR")
pm.connect()
pm.reset()

步骤 2.5: Leveling

触发条件

情况 行为
开关网络不支持 Leveling 跳过,返回 0
信号输出未开启 跳过,返回 0
14天内缓存命中 用缓存值,不实测
以上都不满足 执行闭环校准

算法 (对应 C# PerformLevelingAsync)

wantedLevel = stimuliLevel + pathCompensation

迭代 (最多 10 次):
  1. sg.set_level(rfLevel)
  2. measured = pm.measure_power(freq_hz, average_count=4)
  3. deviation = measured - wantedLevel
  4. |deviation| < 0.1 dB → 收敛,完成
  5. 每 3 次迭代: adjustmentFactor *= 0.75
  6. adjustment = (wantedLevel - measured) * adjustmentFactor
  7. |累计调整| > 2.0 dB → 异常终止
  8. rfLevel += adjustment

调用方式

from service_client.leveling import perform_leveling

result = perform_leveling(
    sg=signal_generator,
    pm=power_meter,                    # NRPPowerMeter 实例
    stimuli_level_dbm=-30.0,
    frequency_hz=3.5e9,
    path_compensation_db=3.7,          # 路径衰减 (查表或默认 0)
    serial_number="1419.4501k02/110489",
    waveform="cw",
    leveling_cache=leveling_cache,     # 可选,14天缓存
)

# result.rf_level_dbm      → 信号源最终电平
# result.signal_deviation_db → 残余偏差
# result.converged          → 是否收敛
# result.from_cache         → 是否来自缓存

步骤 2.6: ARB 特性化

触发条件

情况 行为
不是多音信号 跳过
输出未开启 / 调制未开启 跳过
开关网络不支持 ARB 特性化 用波形元数据默认值
14天内缓存命中 用缓存
以上都不满足 执行逐音测量

流程 (对应 C# RFGeneratorCharacterization)

Step 1: ALC 功率搜索
  生成 +50kHz 单音 IQ → 上传 ARB → pm.measure_power() → 基准

Step 2: 逐音测量 (跳过中心音)
  FOR each tone:
    生成该音单音 IQ (sinusoidal_signal)
    上传 ARB → 播放
    pm.measure_power(tone_freq) → 记录

Step 3: 恢复原始多音波形

Step 4: rfLevel[tone] = measured - 10*log10(N+1)

Step 5: 中心音 = (相邻低音 + 相邻高音) / 2

Step 6: phase = hilbert_transform(rfLevel)

Step 7: 验证: 相邻差 < 0.5dB, 总差 < 1.5dB

Step 8: 保存缓存

调用方式

from service_client.leveling import arb_characterization

result = arb_characterization(
    sg=signal_generator,
    pm=power_meter,                    # NRPPowerMeter 实例
    arb_uploader=arb_uploader,
    tone_frequencies_hz=[3.497e9, 3.498e9, 3.499e9, 3.5e9, 3.501e9, 3.502e9, 3.503e9],
    carrier_freq_hz=3.5e9,
    sample_rate=122880000.0,
    no_tones=7,
    original_waveform="multitone.wf",
    serial_number="1419.4501k02/110489",
    wanted_level_dbm=-30.0,
    arb_cache=arb_cache,               # 可选,14天缓存
)

# result.rf_levels  → 每个音的补偿电平 (dBm)
# result.phases     → 每个音的相位 (rad)
# result.from_cache → 是否来自缓存

在 RFStimuliServicer 中的集成

from nrp_power_meter import NRPPowerMeter
from service_client.leveling import perform_leveling, arb_characterization
from service_client.leveling_cache import LevelingContainer, ArbCalibrationContainer

class RFStimuliServicer:

    def __init__(self, signal_generator, power_meter_resource, ...):
        self._sg = signal_generator
        self._pm = NRPPowerMeter(visa_resource=power_meter_resource)
        self._leveling_cache = LevelingContainer("leveling_cache.json")
        self._arb_cache = ArbCalibrationContainer("arb_calibration_cache.json")
        ...

    def RequestExternalStimuli(self, request, context):
        # ... 步骤 2.1 ~ 2.4 ...

        # 连接功率计
        self._pm.connect()
        self._pm.reset()

        for sig_config in request.configurations:
            for signal in sig_config.signals:
                self._configure_signal(signal)  # 步骤 2.4

                # 步骤 2.5: Leveling
                if self._leveling_support and self._sg.output_enabled:
                    lev_result = perform_leveling(
                        sg=self._sg,
                        pm=self._pm,
                        stimuli_level_dbm=stimuli_level,
                        frequency_hz=carrier_freq_hz,
                        path_compensation_db=path_compensation,
                        serial_number=sg_serial,
                        waveform=waveform_name,
                        leveling_cache=self._leveling_cache,
                    )
                    signal_deviation = lev_result.signal_deviation_db
                else:
                    signal_deviation = 0.0

                # 步骤 2.6: ARB 特性化 (仅多音)
                if is_multitone and self._arb_char_support:
                    arb_result = arb_characterization(
                        sg=self._sg,
                        pm=self._pm,
                        arb_uploader=self._arb_uploader,
                        tone_frequencies_hz=tone_freqs,
                        carrier_freq_hz=center_freq,
                        sample_rate=sample_rate,
                        no_tones=no_tones,
                        original_waveform=waveform_name,
                        serial_number=sg_serial,
                        wanted_level_dbm=stimuli_level,
                        arb_cache=self._arb_cache,
                    )
                    rf_gen_levels = arb_result.rf_levels
                    rf_gen_phases = arb_result.phases

                # 步骤 2.7: 计算端口偏移
                ...

        self._pm.disconnect()
        return ConfigurationResponse(...)

已实现的模块

文件 内容 对应 C#
service_client/leveling.py perform_leveling() + arb_characterization() ExternalSignalStimuli.PerformLevelingAsync() + RFGeneratorCharacterization
service_client/rf_stimuli_calculate.py sinusoidal_signal() + hilbert_transform() + validate_tone_consistency() RFStimuliCalculate.cs
service_client/leveling_cache.py LevelingContainer + ArbCalibrationContainer LevelingContainer.cs + ArbCalibrationContainer.cs
service_client/power_meter.py 接口说明

文件结构

test-interface-client/
├── service_client/
│   ├── leveling.py                 # ★ Leveling + ARB 特性化核心逻辑
│   ├── leveling_cache.py           # ★ 14天缓存 (JSON 文件读写)
│   ├── rf_stimuli_calculate.py     # ★ 计算辅助函数
│   ├── power_meter.py              # 接口说明 (实际用 NRPPowerMeter)
│   ├── rf_stimuli.py               # SignalGeneratorController + RFStimuliServicer
│   └── waveform_loader.py          # ARB 波形加载
├── test_case/
│   └── test_leveling_arb_characterization.py  # 端到端验证脚本
└── docs/
    ├── EXTERNAL_SIGNAL_STIMULI_WORKFLOW.md
    └── leveling_arb_characterization_workflow.md  ← 本文档

tx_output_power_cal_service/              # 功率计代码
├── nrp_power_meter.py                    # NRPPowerMeter 驱动类
└── tx_output_power_cal/
    ├── servicer.py                       # TxOutputPowerCalService gRPC 服务
    └── calibration_manager.py            # 脉冲 Leveling 业务逻辑
posted @ 2026-05-19 17:04  mo686  阅读(0)  评论(0)    收藏  举报