ExpressLRS开源之基本调试数据含义
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 volatilecrsfLinkStatistics_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 logschar 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, bothif(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)
目前,天线配置方面有以下几种工作模式:
- Basic:一根天线
- Antenna Diversity:两根天线,其中一根天线接收信号
- True Diversity:两根天线,同时接收信号
- 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
注:关于跳频方面的设置,详见FHSSrandomiseFHSSsequence和FHSSgetNextFreq。
- 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) | Antenna | RSSI(dBm) | LQ | SNR | PWR | FHSS | TimingOffset |
|---|---|---|---|---|---|---|---|
| 报文ID | 天线编号 | 信号强度 | 信号质量 | 信噪比 | 发射功率 | 跳频频率 | 中断时延 |
| 单、双 | 双 | 单、双 | 单、双 | 单、双 | 单、双 | 单、双 | 单、双 |
| IRQ_CNT | RSSI_AVE | SNR_AVE | SNV_MAX | TELEM_CNT | FAIL_CNT |
|---|---|---|---|---|---|
| 中断数量 | 平均信号强度 | 平均信噪比 | 最大信噪比 | 发送报文数量 | 报文缺失次数 |
| 单、双 | 单、双 | 单、双 | 单、双 | 单、双 | 双 |
,
5. 参考资料
【1】ExpressLRS开源之RC链路性能测试
【2】ExpressLRS开源之接收机固件编译烧录步骤
【3】High-performance Open Source Radio Control Link
相关文章:
ExpressLRS开源之基本调试数据含义
ExpressLRS开源之基本调试数据含义 1. 源由2. 代码2.1 debugRcvrLinkstats2.2 debugRcvrSignalStats 3. 含义解释3.1 ID(packetCounter),Antenna,RSSI(dBm),LQ,SNR,PWR,FHSS,TimingOffset3.2 IRQ_CNT,RSSI_AVE,SNR_AVE,SNV_MAX,TELEM_CNT,FAIL_CNT 4. 总结5. 参考资料 1. 源由 …...
DOM 简介 | 深入了解DOM
目录 一、DOM是什么 二、DOM的访问 三、DOM节点类型 四、DOM的分级 今天我们将了解WEB编程中一个重要的概念DOM(Document Object Model)文档对象模型,它帮助我们使用JavaScript(或其他编程语言)操纵文档。 一、DO…...
机器学习丨2. 线性回归(Linear Regression)
Author:AXYZdong 硕士在读 工科男 有一点思考,有一点想法,有一点理性! 定个小小目标,努力成为习惯!在最美的年华遇见更好的自己! CSDNAXYZdong,CSDN首发,AXYZdong原创 唯…...
python+django企业员工考勤打卡信息管理系统66lgr
本员工信息管理系统以Django作为框架,Python语言,B/S模式以及MySql作为后台运行的数据库。本系统主要包括以下功能模块:员工、部门、员工合同、考勤信息、打卡信息、员工工资等模块。 本文着重阐述了员工信息管理系统的分析、设计与实现&…...
【Java Web】论坛帖子添加评论
数据层 增加评论数据;修改帖子评论数量; 业务层 处理添加评论的业务;先增加评论、在更新帖子的评论数量; 表现层 处理添加评论数据的请求;设置添加评论的表单。 一、数据层 1.1 CommentMapper.java package com.no…...
如何建设一个安全运营中心(SOC)?
然信息安全管理问题主要是个从上而下的问题,不能指望通过某一种工具来解决,但良好的安全技术基础架构能有效的推动和保障信息安全管理。随着国内行业IT应用度和信息安全管理水平的不断提高,企业对于安全管理的配套设施如安全运营中心…...
如何以Base64形式存储、返回图片数据
在Java中,可以使用Base64类来将图片转换为Base64编码。下面是一个示例代码: Java代码直接处理: import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.Base64; public class ImageToBase64…...
【大模型】自动化问答生成:使用GPT-3.5将文档转化为问答对
自动化问答生成:使用GPT-3.5将文档转化为问答对 正文步骤1:准备工作步骤2:编写Python脚本 总结 当我们需要将大段文档转化为问答对时,OpenAI的GPT-3.5模型提供了一个强大的工具。这个教程将向您展示如何编写一个Python脚本&#x…...
普通平衡树 Splay
Splay 简介 Splay(伸展树),又叫做分裂树,是一种自调整形式的二叉查找树,满足二叉查找树的性质:一个节点左子树的所有节点的权值,均小于这个节点的权值。且其右子树所有节点的权值,均…...
复旦-华盛顿EMBA:走近亿咖通科技,探寻汽车智能化的科创“密码”
6月20日,应复旦大学-华盛顿大学EMBA项目18班校友周靖的邀请,项目校友参访了科创企业ECARX亿咖通科技。作为该公司资深副总裁、中国首席财务官,周靖带领大家通过产品演示、实车驾驶和交流对话探寻汽车智能化的科创“密码”,近距离感…...
学习心得07:C#
之前也没有看过C#的书,C#的程序倒是搞了一些。好在项目不大,我又会套路。 C#很象是JAVA。好像就是JAVA出来之后,微软抄的。好东西就要学习,这不丢脸。 我倒是想,有没有办法把JAVA和C#进行映射,然后直接编译…...
importlib的使用、9个视图子类、视图集、drf之路由、drf之请求响应回顾、GenericViewSet相关流程图
一 drf之请求响应回顾 # 1 drf请求-请求对象:data,query_params,其他跟之前一样,FILES-默认:支持三种编码-局部配置:视图类中-from rest_framework.parsers import JSONParser, FormParser, MultiPartPars…...
国际站阿里云服务器远程桌面密码错误怎么办?苹果手机如何远程登录?
阿里云服务器是云计算领域的一种重要服务,它可以帮助用户在云端部署和管理自己的应用程序和网站。但是,有时候用户可能会遇到远程桌面密码错误的问题,导致无法登录到服务器。本文将介绍一些解决办法,以及如何使用苹果手机远程登录…...
CRMEB多端多语言系统文件上传0Day代审历程
Git仓库: https://github.com/crmeb/CRMEB简介: 两天攻防中,某政局子公司官网后台采用的CRMEB开源商城CMS,挺奇葩,别问怎么总让我碰到这种东西,我也不知道,主打的就是一个魔幻、抽象。最后通过…...
孙哥Spring源码第18集
第18集 refresh()-invokeBeanFactoryPostProcessor-二-ConfigurationClassPostProcessor的处理逻辑 【视频来源于:B站up主孙帅suns Spring源码视频】【微信号:suns45】 1、为什么PropertySource先处理? 因为Conponent A在处理的过程中 要把…...
【STM32】文件系统FATFS与Flash的初步使用
文件系统简介 简介可以不看,直接看移植步骤 文件系统是介于应用层和底层间的模糊层。底层提供API,比如说使用SDIO或者SPI等读写一个字节。文件系统把这些API组合包装起来,并且提供一些列函数,我们可以使用这些函数进行更进一步的…...
Android Glide in RecyclerView,only load visible item when page return,Kotlin
Android Glide in RecyclerView,only load visible item when page return,Kotlin base on this article: Android Glide preload RecyclerView切入后台不可见再切换可见只加载当前视野可见区域item图片,Kotlin_zhangphil的博客…...
【SCI征稿】3个月左右录用!计算机信息技术等领域均可,如机器学习、遥感技术、人工智能、物联网、人工神经网络、数据挖掘、图像处理
计算机技术类SCIE&EI 【期刊简介】IF:1.0-2.0,JCR4区,中科院4区 【检索情况】SCIE&EI 双检,正刊 【参考周期】期刊部系统内提交,录用周期3个月左右,走完期刊部流程上线 【征稿领域】计算机信息…...
Golang 中的 crypto/ecdh 包详解
什么是 ECDH 算法? ECDH(Elliptic Curve Diffie-Hellman)算法是一种基于椭圆曲线的密钥交换协议,用于安全地协商共享密钥(Secret Key),步骤如下: 1. 选择椭圆曲线:ECDH…...
系统学习live555
文章目录 系统学习live555系统学习LIVE555的步骤:1.了解基本概念:2.**查看官方文档:**3.**下载和编译库:**4.**阅读示例代码:**5.**了解库结构:**6.**创建简单项目:**7.**阅读更多文档ÿ…...
STM32F4基本定时器使用和原理详解
STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...
工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配
AI3D视觉的工业赋能者 迁移科技成立于2017年,作为行业领先的3D工业相机及视觉系统供应商,累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成,通过稳定、易用、高回报的AI3D视觉系统,为汽车、新能源、金属制造等行…...
Unit 1 深度强化学习简介
Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库,例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体,比如 SnowballFight、Huggy the Do…...
【论文阅读28】-CNN-BiLSTM-Attention-(2024)
本文把滑坡位移序列拆开、筛优质因子,再用 CNN-BiLSTM-Attention 来动态预测每个子序列,最后重构出总位移,预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵(S…...
大学生职业发展与就业创业指导教学评价
这里是引用 作为软工2203/2204班的学生,我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要,而您认真负责的教学态度,让课程的每一部分都充满了实用价值。 尤其让我…...
Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)
目录 一、👋🏻前言 二、😈sinx波动的基本原理 三、😈波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、🌊波动优化…...
AI+无人机如何守护濒危物种?YOLOv8实现95%精准识别
【导读】 野生动物监测在理解和保护生态系统中发挥着至关重要的作用。然而,传统的野生动物观察方法往往耗时耗力、成本高昂且范围有限。无人机的出现为野生动物监测提供了有前景的替代方案,能够实现大范围覆盖并远程采集数据。尽管具备这些优势…...
DingDing机器人群消息推送
文章目录 1 新建机器人2 API文档说明3 代码编写 1 新建机器人 点击群设置 下滑到群管理的机器人,点击进入 添加机器人 选择自定义Webhook服务 点击添加 设置安全设置,详见说明文档 成功后,记录Webhook 2 API文档说明 点击设置说明 查看自…...
Linux nano命令的基本使用
参考资料 GNU nanoを使いこなすnano基础 目录 一. 简介二. 文件打开2.1 普通方式打开文件2.2 只读方式打开文件 三. 文件查看3.1 打开文件时,显示行号3.2 翻页查看 四. 文件编辑4.1 Ctrl K 复制 和 Ctrl U 粘贴4.2 Alt/Esc U 撤回 五. 文件保存与退出5.1 Ctrl …...
Razor编程中@Html的方法使用大全
文章目录 1. 基础HTML辅助方法1.1 Html.ActionLink()1.2 Html.RouteLink()1.3 Html.Display() / Html.DisplayFor()1.4 Html.Editor() / Html.EditorFor()1.5 Html.Label() / Html.LabelFor()1.6 Html.TextBox() / Html.TextBoxFor() 2. 表单相关辅助方法2.1 Html.BeginForm() …...
