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

news2024/11/29 20:33:44

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

  • 1. 源由
  • 2. 代码
    • 2.1 debugRcvrLinkstats
    • 2.2 debugRcvrSignalStats
  • 3. 含义解释
    • 3.1 ID(packetCounter),Antenna,RSSI(dBm),LQ,SNR,PWR,FHSS,TimingOffset
    • 3.2 IRQ_CNT,RSSI_AVE,SNR_AVE,SNV_MAX,TELEM_CNT,FAIL_CNT
  • 4. 总结
  • 5. 参考资料

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/951634.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

详解 ElasticSearch Kibana 配置部署

默认安装部署所在机器允许外网 SSH工具 Putty 链接&#xff1a;https://pan.baidu.com/s/1b6gumtsjL_L64rEsOdhd4A 提取码&#xff1a;lxs9 Winscp 链接&#xff1a;https://pan.baidu.com/s/1tD8_2knvv0EJ5OYvXP6VTg 提取码&#xff1a;lxs9 WinSCP安装直接下一步到完成…

UE 5 GAS 在项目中通过数据初始化

近期&#xff0c;在制作多角色&#xff0c;考虑到角色和角色之间有很多共用的内容&#xff0c;正常项目中的实现的话&#xff0c;会通过数据的方式去实现角色初始化&#xff0c;接下来介绍一下&#xff0c;我的实现方式。 以上是我设置的相应的数据&#xff0c;上面最简单的名…

设计模式行为模式-命令模式

文章目录 前言定义结构工作原理优点适用场景消息队列模式Demo实现分写业务总结 前言 定义 命令模式&#xff08;Command Pattern&#xff09;是一种行为型设计模式&#xff0c;用于将请求封装为对象&#xff0c;从而使你可以使用不同的请求、队列或者日志请求来参数化其他对象…

服务器端污染属性反射提升权限

污染属性反射检测服务器端原型污染 通过服务器端原型污染提升权限 Lab: Privilege escalation via server-side prototype pollution 必要知识点 开发人员很容易陷入的一个陷阱是忘记或忽略 JavaScript 循环迭代对象的所有可枚举属性这一事实&#xff0c;包括它通过原型链继…

医学案例|线性回归

一、案例介绍 某医师预研究糖尿病患者的总胆固醇和甘油三酯对空腹血糖的影响&#xff0c;某研究者调查40名糖尿病患者的总胆固醇、甘油三酯和空腹血糖的测量值如下&#xff0c;试根据上述研究问题作统计分析。 二、问题分析 本案例想要研究一些变量&#xff08;总胆固醇和甘油…

PocketMiner:基于深度学习发现蛋白的隐式口袋

文章目录 1. 文章简介2. 前言3. 方法3.1 模型框架 4. 结果4.1 已知隐式口袋在分子动力学模拟分析迅速打开4.2 图神经网络模型能够准确预测模拟中口袋的动态变化4.3 隐式口袋数据集数据集揭示了新的隐式口袋形成的模式4.4 PocketMiner能够从无配体的蛋白结构中精准预测预测口袋4…

2007-2022年上市公司污染排放数据/2007-2022年上市公司污染排放水平、污染排放量数据

2007-2022年上市公司污染排放数据/2007-2022年上市公司污染排放水平、污染排放量数据 1、时间&#xff1a;2007-2022年 2、指标&#xff1a;证券代码、year、化学需氧量、氨氮排放量、总氮、总磷、水体综合污染当量对数、二氧化硫、氮氧化物、烟尘、空气综合污染当量对数、总…

小游戏分发平台如何以技术拓流?

2023年&#xff0c;小游戏的发展将受到多方面的影响&#xff0c;例如新技术的引入、参与小游戏的新玩家以及游戏市场的激烈竞争等。首先&#xff0c;新技术如虚拟现实&#xff08;VR&#xff09;、增强现实&#xff08;AR&#xff09;和机器人技术都可以带来新颖的游戏体验。其…

滑动窗口实例1(长度最小的子数组)

题目&#xff1a; 给定一个含有 n 个正整数的数组和一个正整数 target 。 找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl1, ..., numsr-1, numsr] &#xff0c;并返回其长度。如果不存在符合条件的子数组&#xff0c;返回 0 。 示例 1&#xff1a; …

VC++使用Microsoft Speech SDK进行文字TTS朗读

Microsoft Speech SDK下载地址 https://www.microsoft.com/en-us/download/details.aspx?id=10121 需要msttss22L.exe、SpeechSDK51.exe、SpeechSDK51LangPack.exe三个,下载后全部安装 使用VS2005建立一个win32控制台项目 朗读"hello word"、中文“你好”的程序 …

百科有不需要的信息怎么删除?

百科词条的权威性众所周知&#xff0c;所以百度百科的内容审核也非常严格&#xff0c;百科营销成为目前网络营销工作中一个难点&#xff0c;很多企业无法得到自己完全满意的百度百科词条 &#xff0c;这其实也是合理的。小马识途营销顾问分析&#xff0c;百科词条内容是提供给广…

10、【WebGIS实战】图层篇——通用服务图层加载全流程(适用于全部图层)

大家好,我是X北辰北。本文是「WebGIS实战」系列,关注这个标签,阅读所有文章,成为WebGIS开发高手。 图层可以理解为添加到地图上面的数据,比如我们要在地图上展示成都市所有大型公园的位置,那么当前地图中除了初始化地图时添加的底图之外,在底图的上面我们还叠加了一份关…

HuggingFace中的 Files and versions 如何优雅下载到本地?(Python requests,tqdm)

前言 在使用huggingface把玩各种大模型时&#xff0c;如果选择从远程加载模型&#xff0c;这个过程可能因为网络问题而非常耗时甚至直接失败&#xff0c;所以把模型、分词器等相关文件下载到本地&#xff0c;再直接从本地加载就成了不可回避的流程。 在进入具体版本的模型后&…

新版Mongodb(6.0以上)找不到mongo.exe

安装目录下/bin目录中&#xff0c;没有mongo.exe文件&#xff0c;只有mongod和mongos&#xff0c;以及一个powershell命令脚本。 原因在于&#xff0c;mongodb6.0以后做出了重大改变&#xff0c;mongodb已经不再默认为你安装shell工具&#xff0c;因此需要安装一个额外的shell…

二十二、迭代器模式

一、什么是迭代器模式 迭代器&#xff08;Iterator&#xff09;模式的定义&#xff1a;迭代器模式是一种对象行为型模式&#xff0c;它提供一个对象来顺序访问聚合对象中的一系列数据&#xff0c;而不暴露聚合对象的内部表示。   迭代器模式包含以下主要角色: 抽象聚合&…

字符串匹配的Rabin–Karp算法

leetcode-28 实现strStr() 更熟悉的字符串匹配算法可能是KMP算法, 但在Golang中,使用的是Rabin–Karp算法 一般中文译作 拉宾-卡普算法,由迈克尔拉宾与理查德卡普于1987年提出 “ 要在一段文本中找出单个模式串的一个匹配&#xff0c;此算法具有线性时间的平均复杂度&#xff0…

【XAMPP】启动数据库Error: MySQL shutdown unexpectedly.

问题&#xff1a; 启动MySQL时报错如下&#xff1a; Error: MySQL shutdown unexpectedly. This may be due to a blocked port, missing dependencies, improper privileges, a crash, or a shutdown by another method. Press the Logs button to view error logs and check…

SQL-子查询

SQL 子查询 是指将一个SELECT查询&#xff08;子查询&#xff09;的结果用括号括起来作为另一个SQL语句的数据来源或者判断条件

RK3399平台开发系列讲解(入门篇)内核模块详细加载/卸载过程

🚀返回专栏总目录 文章目录 一、 ko文件的文件格式二、内核模块加载过程三、内核模块卸载过程沉淀、分享、成长,让自己和他人都能有所收获!😄 📢 本篇将介绍内核模块详细加载/卸载过程。 一、 ko文件的文件格式 “KO” 文件通常是指 Linux 内核模块文件,这些文件包含…

现货黄金走势图中的止盈点

对平仓时机的把握能力&#xff0c;是衡量现货黄金投资者水平的重要标志&#xff0c;止盈点设置得是否合理&#xff0c;在行情兑现的时候能否及时地离场&#xff0c;是事关投资者账户浮盈最终能否落袋为安的“头等大事”&#xff0c;要在现货黄金走势图中把握止盈点&#xff0c;…