ExpressLRS开源之基本调试数据含义

1. 源由

基于ExpressLRS开源代码对基本调试验证数据进行详细的研读理解,以期望更深入的理解相关数据的实际含义。

ID(packetCounter),Antenna,RSSI(dBm),LQ,SNR,PWR,FHSS,TimingOffset
IRQ_CNT,RSSI_AVE,SNR_AVE,SNV_MAX,TELEM_CNT,FAIL_CNT

2. 代码

2.1 debugRcvrLinkstats

static void debugRcvrLinkstats()
{
#if defined(DEBUG_RCVR_LINKSTATS)
    if (debugRcvrLinkstatsPending)
    {
        debugRcvrLinkstatsPending = false;

        // Copy the data out of the ISR-updating bits ASAP
        // While YOLOing (const void *) away the volatile
        crsfLinkStatistics_t ls = *(crsfLinkStatistics_t *)((const void *)&CRSF::LinkStatistics);
        uint32_t packetCounter = debugRcvrLinkstatsPacketId;
        uint8_t fhss = debugRcvrLinkstatsFhssIdx;
        // actually the previous packet's offset since the update happens in tick, and this will
        // fire right after packet reception (a little before tock)
        int32_t pfd = PfdPrevRawOffset;

        // Use serial instead of DBG() because do not necessarily want all the debug in our logs
        char buf[50];
        snprintf(buf, sizeof(buf), "%u,%u,-%u,%u,%d,%u,%u,%d\r\n",
            packetCounter, ls.active_antenna,
            ls.active_antenna ? ls.uplink_RSSI_2 : ls.uplink_RSSI_1,
            ls.uplink_Link_quality, ls.uplink_SNR,
            ls.uplink_TX_Power, fhss, pfd);
        Serial.write(buf);
    }
#endif
}

2.2 debugRcvrSignalStats

static void debugRcvrSignalStats(uint32_t now)
{
#if defined(DEBUG_RCVR_SIGNAL_STATS)
    static uint32_t lastReport = 0;

    // log column header:  cnt1, rssi1, snr1, snr1_max, telem1, fail1, cnt2, rssi2, snr2, snr2_max, telem2, fail2, or, both
    if(now - lastReport >= 1000 && connectionState == connected)
    {
        for (int i = 0 ; i < (isDualRadio()?2:1) ; i++)
        {
            DBG("%d\t%f\t%f\t%f\t%d\t%d\t",
                Radio.rxSignalStats[i].irq_count,
                (Radio.rxSignalStats[i].irq_count==0) ? 0 : double(Radio.rxSignalStats[i].rssi_sum)/Radio.rxSignalStats[i].irq_count,
                (Radio.rxSignalStats[i].irq_count==0) ? 0 : double(Radio.rxSignalStats[i].snr_sum)/Radio.rxSignalStats[i].irq_count/RADIO_SNR_SCALE,
                float(Radio.rxSignalStats[i].snr_max)/RADIO_SNR_SCALE,
                Radio.rxSignalStats[i].telem_count,
                Radio.rxSignalStats[i].fail_count);

                Radio.rxSignalStats[i].irq_count = 0;
                Radio.rxSignalStats[i].snr_sum = 0;
                Radio.rxSignalStats[i].rssi_sum = 0;
                Radio.rxSignalStats[i].snr_max = INT8_MIN;
                Radio.rxSignalStats[i].telem_count = 0;
                Radio.rxSignalStats[i].fail_count = 0;
        }
        if (isDualRadio())
        {
            DBGLN("%d\t%d", Radio.irq_count_or, Radio.irq_count_both);
        }
        else
        {
            DBGLN("");
        }
        Radio.irq_count_or = 0;
        Radio.irq_count_both = 0;

        lastReport = now;
    }
#endif
}

3. 含义解释

对于debug给出参数含义解释,有助于理解性能测试结果。

ID(packetCounter),Antenna,RSSI(dBm),LQ,SNR,PWR,FHSS,TimingOffset
IRQ_CNT,RSSI_AVE,SNR_AVE,SNV_MAX,TELEM_CNT,FAIL_CNT

3.1 ID(packetCounter),Antenna,RSSI(dBm),LQ,SNR,PWR,FHSS,TimingOffset

  • ID(packetCounter):报文ID(递增,需打开Tx发射端DEBUG_RCVR_LINKSTATS)

报文ID是在发射机发射信号是递增,接收机解析报文是获取ID信息的。

//接收机
OtaUpdateSerializers
 ├──> UnpackChannelDataHybridSwitch8/UnpackChannelDataHybridWide
 │   └──> UnpackChannelDataHybridCommon - ota4->dbg_linkstats.packetNum
 │       └──> debugRcvrLinkstatsPacketId
 │           └──> packetCounter
 └──> UnpackChannelData8ch - ota8->dbg_linkstats.packetNum
     └──> debugRcvrLinkstatsPacketId
         └──> packetCounter

//发射机
OtaUpdateSerializers
 └──> GenerateChannelData8ch/GenerateChannelData12ch
     └──> GenerateChannelData8ch12ch
         └──> <DEBUG_RCVR_LINKSTATS> ota8->dbg_linkstats.packetNum = packetCnt++
  • Antenna:天线编号(0或1)

目前,天线配置方面有以下几种工作模式:

  1. Basic:一根天线
  2. Antenna Diversity:两根天线,其中一根天线接收信号
  3. True Diversity:两根天线,同时接收信号
  4. Gemini:两根天线,同时接收信号,并且工作在两个不同的频点。
    在这里插入图片描述
  • RSSI(dBm):信号强度,单位dBm

分贝毫瓦简写为dBm或dBmW,是一个表示绝对功率的量。

uplink_RSSI_1/uplink_RSSI_2
 └──> rssiDBM
     └──> LastPacketRSSI
         └──> GetLastPacketRSSI/GetLastPacketStats
             └──> readRegister(SX127X_REG_PKT_RSSI_VALUE)/ReadCommand(SX1280_RADIO_GET_PACKETSTATUS)
  • LQ(Link Quality):链路质量

链路接收到数据包与预期数据包的百分比,表示信号中丢包的概率。

uplink_Link_quality
 └──> uplinkLQ
     └──> LQCalc.getLQ()/LQCalcDVDA.getLQ()
  • SNR(Signal-to-noise ratio):信噪比

信号与干扰加噪声比 (Signal to Interference plus Noise Ratio)是指接收到的有用信号的强度与接收到的干扰信号(噪声和干扰)的强度的比值。

uplink_SNR
 └──> LastPacketSNRRaw
     └──> GetLastPacketSNRRaw/GetLastPacketStats
         └──> readRegister(SX127X_REG_PKT_SNR_VALUE)/ReadCommand(SX1280_RADIO_GET_PACKETSTATUS)
  • PWR(Power):功率

发射机工作时的发射功率。

RX::uplink_TX_Power
 └──> RX::UnpackChannelData8ch/UnpackChannelDataHybridWide
     └──> TX::GenerateChannelDataHybridWide/GenerateChannelData8ch12ch
         └──> TX::CurrentPower
             └──> TX::decPower/incPower
                 └──> TX::DynamicPower_Update
                     └──> TX::loop

其对应输出数值与功率之间的对应关系。

uint8_t powerToCrsfPower(PowerLevels_e Power)
{
    // Crossfire's power levels as defined in opentx:radio/src/telemetry/crossfire.cpp
    //static const int32_t power_values[] = { 0, 10, 25, 100, 500, 1000, 2000, 250, 50 };
    switch (Power)
    {
    case PWR_10mW: return 1;
    case PWR_25mW: return 2;
    case PWR_50mW: return 8;
    case PWR_100mW: return 3;
    case PWR_250mW: return 7;
    case PWR_500mW: return 4;
    case PWR_1000mW: return 5;
    case PWR_2000mW: return 6;
    default:
        return 0;
    }
}
  • FHSS(Frequency-hopping spread spectrum):跳频频率

FHSS,跳频技术 (Frequency-Hopping Spread Spectrum)在同步、且同时的情况下,接受两端以特定型式的窄频载波来传送讯号,对于一个非特定的接受器,FHSS所产生的跳动讯号对它而言,也只算是脉冲噪声。FHSS所展开的讯号可依特别设计来规避噪声或One-to-Many的非重复的频道,并且这些跳频讯号必须遵守要求。

debugRcvrLinkstatsFhssIdx
 └──> getRFlinkInfo
     └──> ProcessRFPacket
         └──> RXdoneISR
             └──> setupRadio
                 └──> setup

注:关于跳频方面的设置,详见FHSSrandomiseFHSSsequenceFHSSgetNextFreq

  • TimingOffset

这里的时间差是指HWtimerCallbackTock调用到ProcessRFPacket报文开始处理的时间差。

PfdPrevRawOffset
 └──> PFDloop.calcResult() = PFDloop.intEvent(HWtimerCallbackTock) - PFDloop.extEvent(ProcessRFPacket)
     └──> updatePhaseLock
         └──> HWtimerCallbackTick
             └──> setup

3.2 IRQ_CNT,RSSI_AVE,SNR_AVE,SNV_MAX,TELEM_CNT,FAIL_CNT

  • IRQ_CNT

接收机收到RF芯片中断的数量。

setup
 └──> setupRadio
     └──> RXdoneISR
         └──> ProcessRFPacket
             └──> GetLastPacketStats
                 └──> instance->rxSignalStats[i].irq_count++
  • RSSI_AVE

接收机平均RSSI信号强度。

double(Radio.rxSignalStats[i].rssi_sum)/Radio.rxSignalStats[i].irq_count
  • SNR_AVE

接收机平均SNR信号强度。

double(Radio.rxSignalStats[i].snr_sum)/Radio.rxSignalStats[i].irq_count/RADIO_SNR_SCALE
  • SNV_MAX

接收机最大SNR信号强度。

float(Radio.rxSignalStats[i].snr_max)/RADIO_SNR_SCALE
  • TELEM_CNT

接收机发送报文数量。

setup
 └──> HWtimerCallbackTock
     └──> HandleSendTelemetryResponse
         └──> TXnb
             └──> telem_count++
  • FAIL_CNT

判断双天线是否第二根天线受到同样的报文,如果没有收到则fail++。

setup
 └──> setupRadio
     └──> RXdoneISR
         └──> ProcessRFPacket
             └──> GetLastPacketStats
                 └──> fail_count++

4. 总结

通过对上面调试参数含义的分析,在对单/双天线模块配置下:

可以根据以下表格内容进行可选择性的分析比对,详细比对方法请见:
【1】ExpressLRS开源之RC链路性能测试
【2】ExpressLRS开源之接收机固件编译烧录步骤

ID(packetCounter)AntennaRSSI(dBm)LQSNRPWRFHSSTimingOffset
报文ID天线编号信号强度信号质量信噪比发射功率跳频频率中断时延
单、双单、双单、双单、双单、双单、双单、双
IRQ_CNTRSSI_AVESNR_AVESNV_MAXTELEM_CNTFAIL_CNT
中断数量平均信号强度平均信噪比最大信噪比发送报文数量报文缺失次数
单、双单、双单、双单、双单、双

,

5. 参考资料

【1】ExpressLRS开源之RC链路性能测试
【2】ExpressLRS开源之接收机固件编译烧录步骤
【3】High-performance Open Source Radio Control Link

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 很多时候,我们在进行开发、测试或调试过程中会遇到很多问题,而网络调试助手则是一个非常有用的工具。相信很多程序员都有用过网络调试助手这个工具,而目前市面上也有很多网络调试助手的选择。 其中,通过开源的网络调试助手,我们可以获得很多好处。首先,开源软件具有较高的可信度和可靠性。开源软件的代码公开、透明,可以随时查看、修改和改进,相比较闭源软件,开源软件更容易获取他人的信任,无需像其他商业软件一样需要付费或担心其他隐私问题。 其次,开源的网络调试助手也可以满足不同的需求。通过对源代码的修改和衍生,可以满足不同用户的需求。如果没有满足你的需求,你也可以自己修改和定制,获得更加适合自己的版本。 最后,通过开源的网络调试助手,可以促进开源社区的发展和壮大。很多人可以在开源项目中为其做出贡献,包括代码开发、Bug报告、推广等,都可以帮助网络调试助手变得更加完善。同时,通过不断的更新和完善,也可以让更多人受益于开源项目。 总之,开源的网络调试助手具有很多优势,让我们获得更加安全、可靠和适用的工具,同时也激发了我们的创造力和思考能力,为整个开源社区的发展做出贡献。 ### 回答2: 网络调试助手是一款优秀的开源C语言工具,它可以帮助程序员快速定位和调试网络通信问题,提升开发效率。该工具具有开源、跨平台、易上手等诸多优势,得到了广泛的应用和赞誉。 通过网络调试助手,程序员可以实现多种网络通信方式的调试,例如TCP/IP、UDP、HTTP等,还能对网络数据进行分析、转换、加密等操作,支持实时监控和交互式调试,同时提供多种通信协议支持和通用API接口,方便快速开发和测试。 网络调试助手的开源性质,也为其赢得了更多开发者的支持和贡献。这意味着程序员可以自由地修改、扩展工具的功能,增加新的插件和模块,也可以与其他工具和环境进行集成,以满足不同需求和场景。此外,网络调试助手还提供文档和社区支持,方便用户学习和交流。 在今天的互联网时代,网络通信已经成为程序开发的必要组成部分。网络调试助手开源C工具的出现,提升了网络通信的调试和开发效率,为程序员们带来了更多方便和选择,也将为网络通信技术的发展和应用带来新的推动力。 ### 回答3: 网络调试助手是一款开源的工具,它可以帮助开发人员快速定位和解决网络调试问题。该工具提供了多种常见的网络调试功能,例如发送 HTTP 请求、WebSocket 连接等。通过网络调试助手,开发人员可以快速测试网络接口,并通过实时的数据反馈获得调试结果。 该工具使用 C 语言实现,可运行于多个平台和设备上,例如 Windows、Mac、Linux 和移动端设备等。这使得开发人员可以在不同的环境中使用网络调试助手,无需额外安装或配置软件,提高了工作效率和便利性。 网络调试助手不仅提供了简单易用的命令行界面,还可以通过 GUI 界面进行操作。这使得开发人员能够更加方便地进行调试和交互,同时也提高了用户友好性。另外,网络调试助手还提供了丰富的插件机制,可以通过插件扩展功能,满足不同用户的需求。 总之,网络调试助手是一款非常实用的工具,它能够帮助开发人员快速解决网络调试问题,提高开发效率和质量。同时,该工具的开源性也使得它具有更高的可扩展性和可定制性,能够满足不同用户的个性化需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值