作为射频工程师的你,是不是对EVM的计算方法也感点兴趣?

原创 加油射频工程师 2023-11-22 11:39

来看看,你需不需要这门接收机设计课程吧(已更新七次)

如有需要,现在仍然可以报名。


(1)

在EVM是个什么东东喽?,有说过,EVM衡量的是星座图上理想点和实测点偏移量的大小。

虽说,有这样一个公式,但是光看公式,总是觉得云里雾里的。

最近,因为在琢磨用ADS进行系统仿真的事,然后一步一步下来,发现在ADS的AEL文件里,藏着很多宝藏。

昨天说过,在射频层面仿真EVM的时候,在ADS里面发现两种仿真计算的方法。

一种是在dds文件上,以constellation()函数为基础,一个一个写公式,然后出来EVM的计算结果。

另一种,是在dds文件上,直接调用const_evm()函数来计算EVM的值。

我大概过了一下两种方法的流程,大致差不多。

但是,昨天在仿真的时候,发现当我把Symbol_rate从24.3KHz调整到150KHz,并且输入功率设小的时候,两者仿真出来的结果差很多。

没办法,只能仔细地去看const_evm()函数里面的具体细节。

(2)

先把这个程序贴出来。

defun const_evm(vfund_ideal, vfund_dist, u_symbol_rate,     u_sample_delay, u_rotation, u_transient_duration, u_path_delay){
if ( vfund_ideal == NULL || vfund_dist == NULL ) return;
decl symbol_rate = u_symbol_rate == NULL ? 0 : u_symbol_rate; decl transient_duration = u_transient_duration == NULL ? 0 : u_transient_duration; decl tran_time = 0; if ( transient_duration ) // skip integer number of symbols tran_time = ceil(mag(transient_duration)*symbol_rate)/symbol_rate; decl sample_delay = u_sample_delay == NULL ? best_delay_1d(vfund_ideal,symbol_rate,tran_time) : u_sample_delay;
decl rotation = u_rotation == NULL ? 0 : u_rotation; decl Path_Delay_default = delay_path(vfund_ideal,vfund_dist); decl path_delay = u_path_delay == NULL ? Path_Delay_default[0] : u_path_delay; // This is a better default than 0.
vfund_ideal = vfund_ideal*exp(j*rotation); vfund_dist = vfund_dist*exp(j*rotation); decl vfund_ideal_real = real(vfund_ideal); decl vfund_ideal_imag = imag(vfund_ideal); decl vfund_dist_real = real(vfund_dist); decl vfund_dist_imag = imag(vfund_dist); decl time_values = indep(vfund_ideal); decl time_step = time_values[1]-time_values[0]; decl i; decl numPts_i=9; decl min_time_offset = -0.5*time_step; decl time_offset; decl best_evm_rms = 1000; // initialized as an arbitrary large number decl evm_rms_this_trial; decl evm_percent; decl best_mean_phase_delta; decl best_vfund_C_dist; decl best_evm;
// Ideal trajectory decl ideal_trajectory = vs(vfund_ideal_imag, vfund_ideal_real);
// set interpolation points decl start_time = sample_delay; // removed + tran_time; decl stop_time = max(indep(vfund_ideal)); decl incr = NULL; if (symbol_rate) incr = 1/symbol_rate;
// Ideal constellation decl vfund_C_ideal_real = interp(vfund_ideal_real, start_time, stop_time, incr); decl vfund_C_ideal_imag = interp(vfund_ideal_imag, start_time, stop_time, incr); decl vfund_C_ideal = vfund_C_ideal_real+j*vfund_C_ideal_imag; decl vfund_C_ideal_rms = sqrt(mean(mag(vfund_C_ideal)**2)); vfund_C_ideal = vfund_C_ideal/vfund_C_ideal_rms; decl ideal_constellation = vs(imag(vfund_C_ideal), real(vfund_C_ideal)); set_attr(ideal_constellation,"TraceType","Scatter");
for (i=0; i { time_offset = min_time_offset + i*time_step/8; decl vfund_C_dist_real = interp(vfund_dist_real, start_time+path_delay+time_offset, stop_time, incr); // this length may change with i. decl vfund_C_dist_imag = interp(vfund_dist_imag, start_time+path_delay+time_offset, stop_time, incr); // this length may change with i. decl vfund_C_dist = vfund_C_dist_real +j*vfund_C_dist_imag;
decl sn = min([sweep_size(vfund_C_dist_real), sweep_size(vfund_C_ideal_real)]);
// phase compensation decl mean_phase_delta = __phase_delta_calc(vfund_C_ideal[0::sn-1], vfund_C_dist[0::sn-1]); vfund_C_dist = (vfund_C_dist)*exp(-j*mean_phase_delta);
// scaling decl scaling = sqrt(mean(mag(vfund_C_dist[0::sn-1])**2)); // Previously divided this by RMS value of ideal constellation, but this is now 1. vfund_C_dist = vfund_C_dist/scaling;
// EVM decl evm = mag(vfund_C_dist[0::sn-1]-vfund_C_ideal[0::sn-1]);
// EVM_percent evm_rms_this_trial = sqrt(mean(evm**2)); // This could be divided by the RMS value of the ideal constellation, but this is now 1. if (evm_rms_this_trial < best_evm_rms) { best_evm = evm; best_evm_rms = evm_rms_this_trial; best_mean_phase_delta = mean_phase_delta; best_vfund_C_dist = vfund_C_dist*scaling; // undoing the scaling to generate the distorted constellation } evm_percent = 100*best_evm_rms; // has to be calculated inside the loop because sn could change from one iteration to the next. }
// distorted compensated trajectory (phase compensation only) vfund_dist=vfund_dist*exp(-j*best_mean_phase_delta); decl dist_trajectory = vs(imag(vfund_dist),real(vfund_dist));
decl distorted_constellation = vs(imag(best_vfund_C_dist), real(best_vfund_C_dist)); set_attr(distorted_constellation,"TraceType","Scatter");
return list(ideal_constellation, ideal_trajectory, distorted_constellation, dist_trajectory, best_evm, evm_percent);} //fun - const_evm

看上去很长也很难懂,对不对?我也是鼓足很大的勇气,才对着电脑开始研读的。

但是等看完了以后,发现,以后不能自己吓自己。这个程序看上去很长,但是其实只要懂点英文,然后有点数学基础,基本都能看懂。

对于我来说,这上面最大的不懂点,可能就是这条语句。但是现在有AI,分分钟给你解释的清清楚楚。

decl symbol_rate = u_symbol_rate == NULL ? 0 : u_symbol_rate;

比如说,上面这条语句,chatgpt是这样给我解释的。

简单理解,就是把u_symbol_rate的值,赋给symbol_rate。

接着,我们一条条看一下const_evm()中的语句哈!

(3)


if ( vfund_ideal == NULL || vfund_dist == NULL )   return;
decl symbol_rate = u_symbol_rate == NULL ? 0 : u_symbol_rate; decl transient_duration = u_transient_duration == NULL ? 0 : u_transient_duration; decl tran_time = 0; if ( transient_duration ) // skip integer number of symbols tran_time = ceil(mag(transient_duration)*symbol_rate)/symbol_rate; decl sample_delay = u_sample_delay == NULL ? best_delay_1d(vfund_ideal,symbol_rate,tran_time) : u_sample_delay;
decl rotation = u_rotation == NULL ? 0 : u_rotation; decl Path_Delay_default = delay_path(vfund_ideal,vfund_dist); decl path_delay = u_path_delay == NULL ? Path_Delay_default[0] : u_path_delay; // This is a better default than 0.

decl,从ADS的help文件可知,是define a variable的意思。

在dds文件中,使用const_evm的时候,会给参数,如下图所示。

所以,上面的语句,主要就是把用户给的参数传递给函数内部。

注意一下,这里有个delay_path()这个函数。为啥提醒注意呢?前面不是说,发现两种仿真计算下,结果有时候会不一样么?其中一个因素就是这个。
在const_evm中,计算失真信号的星座图的时候,把链路的延时考虑进去的;但是另一种计算过程中,则没有。

(4)
 vfund_ideal = vfund_ideal*exp(j*rotation); vfund_dist = vfund_dist*exp(j*rotation); decl vfund_ideal_real = real(vfund_ideal); decl vfund_ideal_imag = imag(vfund_ideal); decl vfund_dist_real = real(vfund_dist); decl vfund_dist_imag = imag(vfund_dist);

在const_evm()的参数中,第一个参数,是理想的信号;第二个参数,是经过射频链路后的信号,暂且把它称为失真信号。


上面的语句,主要是把理想信号(vfund_ideal)和失真信号(vfund_dist)都旋转一个角度,这个角度也是在const_evm()的参数中定义。然后取出旋转后信号的实部和虚部。


可以看到,这个旋转对理想信号和失真信号是同时有效的。所以,还没搞清楚,这个参数的主要的作用是啥。不过呢,这个参数主要是影响星座图的旋转角度,和EVM的值,倒是没啥关系。


(5)

  decl time_values = indep(vfund_ideal);  decl time_step = time_values[1]-time_values[0];    decl i;  decl numPts_i=9;  decl min_time_offset = -0.5*time_step;  decl time_offset;  decl best_evm_rms = 1000;  // initialized as an arbitrary large number  decl evm_rms_this_trial;  decl evm_percent;  decl best_mean_phase_delta;  decl best_vfund_C_dist;  decl best_evm;

因为仿真结果是基于envelope仿真器的,有Tstep设置。所以上面的第一和第二句,就是从信号中恢复出这个Tstep。

接下来的语句,是定义各种各样的变量。


(6)

    // Ideal trajectory    decl ideal_trajectory = vs(vfund_ideal_imag, vfund_ideal_real);

这个语句厉害了,没看到这个语句的时候,我觉得,把星座图画出来好难啊!等我看到这个语句的时候,一下子无言,就这么一句话!当然,这里还不是星座图,是符号变化的轨迹。不过离星座图就差一行代码!


不过,我个人觉得这里有个小bug。

因为仿真过程中发现,在dds文件上,想把理想信号的星座图和轨迹放在一张图上的话,轨迹变成一个很小的点。

从代码来看,应该是因为计算星座图的时候,归一化了,但是看计算轨迹的时候,则没有。

再说回上面的语句。

看help文件,vs()是这么解释的。

看上去不太直观哈,但是从最终绘制的结果来看,大概就是在二维矩形坐标上,画出dependent随independent变化的曲线。

(7)

 // set interpolation points    decl start_time = sample_delay;                                 // removed + tran_time;    decl stop_time = max(indep(vfund_ideal));    decl incr = NULL;    if (symbol_rate)    incr = 1/symbol_rate;
// Ideal constellation decl vfund_C_ideal_real = interp(vfund_ideal_real, start_time, stop_time, incr); decl vfund_C_ideal_imag = interp(vfund_ideal_imag, start_time, stop_time, incr); decl vfund_C_ideal = vfund_C_ideal_real+j*vfund_C_ideal_imag; decl vfund_C_ideal_rms = sqrt(mean(mag(vfund_C_ideal)**2)); vfund_C_ideal = vfund_C_ideal/vfund_C_ideal_rms; decl ideal_constellation = vs(imag(vfund_C_ideal), real(vfund_C_ideal)); set_attr(ideal_constellation,"TraceType","Scatter");


在help文件中,interp()的解释是这样的。

信号的时间间隔原来是Tstep,这个我在原理图中设置的是1/(4*symbolrate),在程序中,做了个线性插值,使得信号的时间间隔变为1/symbolrate。


然后对理想信号进行归一化,并用vs()画出在二维坐标系上,虚部和实部的关系。并且用set_attr()来设置图形的表现形式,让其以点状的形式显示,从而显示成星座图,而不是轨迹。


(8)

 for (i=0; i// Loop to find minimum EVM  {    time_offset = min_time_offset + i*time_step/8;    decl vfund_C_dist_real = interp(vfund_dist_real, start_time+path_delay+time_offset, stop_time, incr);    // this length may change with i.    decl vfund_C_dist_imag = interp(vfund_dist_imag, start_time+path_delay+time_offset, stop_time, incr);    // this length may change with i.    decl vfund_C_dist = vfund_C_dist_real +j*vfund_C_dist_imag;
decl sn = min([sweep_size(vfund_C_dist_real), sweep_size(vfund_C_ideal_real)]); // phase compensation decl mean_phase_delta = __phase_delta_calc(vfund_C_ideal[0::sn-1], vfund_C_dist[0::sn-1]); vfund_C_dist = (vfund_C_dist)*exp(-j*mean_phase_delta); // scaling decl scaling = sqrt(mean(mag(vfund_C_dist[0::sn-1])**2)); // Previously divided this by RMS value of ideal constellation, but this is now 1. vfund_C_dist = vfund_C_dist/scaling; // EVM decl evm = mag(vfund_C_dist[0::sn-1]-vfund_C_ideal[0::sn-1]);
// EVM_percent evm_rms_this_trial = sqrt(mean(evm**2)); // This could be divided by the RMS value of the ideal constellation, but this is now 1. if (evm_rms_this_trial < best_evm_rms) { best_evm = evm; best_evm_rms = evm_rms_this_trial; best_mean_phase_delta = mean_phase_delta; best_vfund_C_dist = vfund_C_dist*scaling; // undoing the scaling to generate the distorted constellation } evm_percent = 100*best_evm_rms; // has to be calculated inside the loop because sn could change from one iteration to the next. }

这个for语句,是代码里面做了一个循环,以time_step/8为步进,来找出最合适的采样点,使得EVM最小。


 // phase compensation    decl mean_phase_delta = __phase_delta_calc(vfund_C_ideal[0::sn-1], vfund_C_dist[0::sn-1]);    vfund_C_dist =  (vfund_C_dist)*exp(-j*mean_phase_delta);        // scaling    decl scaling = sqrt(mean(mag(vfund_C_dist[0::sn-1])**2));   // Previously divided this by RMS value of ideal constellation, but this is now 1.    vfund_C_dist = vfund_C_dist/scaling;

这四个语句,分别是进行相位补偿和幅度归一化。



// EVM decl evm = mag(vfund_C_dist[0::sn-1]-vfund_C_ideal[0::sn-1]);

这个呢,就是开始计算EVM呢,即理想矢量点和实测矢量点之间的误差的幅值。


(9)

    // distorted compensated trajectory (phase compensation only)    vfund_dist=vfund_dist*exp(-j*best_mean_phase_delta);    decl dist_trajectory = vs(imag(vfund_dist),real(vfund_dist));
decl distorted_constellation = vs(imag(best_vfund_C_dist), real(best_vfund_C_dist)); set_attr(distorted_constellation,"TraceType","Scatter"); return list(ideal_constellation, ideal_trajectory, distorted_constellation, dist_trajectory, best_evm, evm_percent);


最后,就是计算失真信号的星座图和变化轨迹啦!

(10)

终于讲完了!


如果想和我进一步交流的话,欢迎关注个人微信号,注明:公司(如方便的话)+工作性质(如研发,调试,销售等)。



评论
  • 根据环洋市场咨询(Global Info Research)项目团队最新调研,预计2030年全球无人机锂电池产值达到2457百万美元,2024-2030年期间年复合增长率CAGR为9.6%。 无人机锂电池是无人机动力系统中存储并释放能量的部分。无人机使用的动力电池,大多数是锂聚合物电池,相较其他电池,锂聚合物电池具有较高的能量密度,较长寿命,同时也具有良好的放电特性和安全性。 全球无人机锂电池核心厂商有宁德新能源科技、欣旺达、鹏辉能源、深圳格瑞普和EaglePicher等,前五大厂商占有全球
    GIRtina 2025-01-07 11:02 63浏览
  • 这篇内容主要讨论三个基本问题,硅电容是什么,为什么要使用硅电容,如何正确使用硅电容?1.  硅电容是什么首先我们需要了解电容是什么?物理学上电容的概念指的是给定电位差下自由电荷的储藏量,记为C,单位是F,指的是容纳电荷的能力,C=εS/d=ε0εrS/4πkd(真空)=Q/U。百度百科上电容器的概念指的是两个相互靠近的导体,中间夹一层不导电的绝缘介质。通过观察电容本身的定义公式中可以看到,在各个变量中比较能够改变的就是εr,S和d,也就是介质的介电常数,金属板有效相对面积以及距离。当前
    知白 2025-01-06 12:04 167浏览
  • 本文介绍Linux系统更换开机logo方法教程,通用RK3566、RK3568、RK3588、RK3576等开发板,触觉智能RK3562开发板演示,搭载4核A53处理器,主频高达2.0GHz;内置独立1Tops算力NPU,可应用于物联网网关、平板电脑、智能家居、教育电子、工业显示与控制等行业。制作图片开机logo图片制作注意事项(1)图片必须为bmp格式;(2)图片大小不能大于4MB;(3)BMP位深最大是32,建议设置为8;(4)图片名称为logo.bmp和logo_kernel.bmp;开机
    Industio_触觉智能 2025-01-06 10:43 87浏览
  • 彼得·德鲁克被誉为“现代管理学之父”,他的管理思想影响了无数企业和管理者。然而,关于他的书籍分类,一种流行的说法令人感到困惑:德鲁克一生写了39本书,其中15本是关于管理的,而其中“专门写工商企业或为企业管理者写的”只有两本——《为成果而管理》和《创新与企业家精神》。这样的表述广为流传,但深入探讨后却发现并不完全准确。让我们一起重新审视这一说法,解析其中的矛盾与根源,进而重新认识德鲁克的管理思想及其著作的真正价值。从《创新与企业家精神》看德鲁克的视角《创新与企业家精神》通常被认为是一本专为企业管
    优思学院 2025-01-06 12:03 113浏览
  • 村田是目前全球量产硅电容的领先企业,其在2016年收购了法国IPDiA头部硅电容器公司,并于2023年6月宣布投资约100亿日元将硅电容产能提升两倍。以下内容主要来自村田官网信息整理,村田高密度硅电容器采用半导体MOS工艺开发,并使用3D结构来大幅增加电极表面,因此在给定的占位面积内增加了静电容量。村田的硅技术以嵌入非结晶基板的单片结构为基础(单层MIM和多层MIM—MIM是指金属 / 绝缘体/ 金属) 村田硅电容采用先进3D拓扑结构在100um内,使开发的有效静电容量面积相当于80个
    知白 2025-01-07 15:02 66浏览
  • 在智能家居领域中,Wi-Fi、蓝牙、Zigbee、Thread与Z-Wave等无线通信协议是构建短距物联局域网的关键手段,它们常在实际应用中交叉运用,以满足智能家居生态系统多样化的功能需求。然而,这些协议之间并未遵循统一的互通标准,缺乏直接的互操作性,在进行组网时需要引入额外的网关作为“翻译桥梁”,极大地增加了系统的复杂性。 同时,Apple HomeKit、SamSung SmartThings、Amazon Alexa、Google Home等主流智能家居平台为了提升市占率与消费者
    华普微HOPERF 2025-01-06 17:23 141浏览
  • 根据Global Info Research项目团队最新调研,预计2030年全球封闭式电机产值达到1425百万美元,2024-2030年期间年复合增长率CAGR为3.4%。 封闭式电机是一种电动机,其外壳设计为密闭结构,通常用于要求较高的防护等级的应用场合。封闭式电机可以有效防止外部灰尘、水分和其他污染物进入内部,从而保护电机的内部组件,延长其使用寿命。 环洋市场咨询机构出版的调研分析报告【全球封闭式电机行业总体规模、主要厂商及IPO上市调研报告,2025-2031】研究全球封闭式电机总体规
    GIRtina 2025-01-06 11:10 103浏览
  • By Toradex 秦海1). 简介嵌入式平台设备基于Yocto Linux 在开发后期量产前期,为了安全以及提高启动速度等考虑,希望将 ARM 处理器平台的 Debug Console 输出关闭,本文就基于 NXP i.MX8MP ARM 处理器平台来演示相关流程。 本文所示例的平台来自于 Toradex Verdin i.MX8MP 嵌入式平台。  2. 准备a). Verdin i.MX8MP ARM核心版配合Dahlia载板并
    hai.qin_651820742 2025-01-07 14:52 40浏览
  • 每日可见的315MHz和433MHz遥控模块,你能分清楚吗?众所周知,一套遥控设备主要由发射部分和接收部分组成,发射器可以将控制者的控制按键经过编码,调制到射频信号上面,然后经天线发射出无线信号。而接收器是将天线接收到的无线信号进行解码,从而得到与控制按键相对应的信号,然后再去控制相应的设备工作。当前,常见的遥控设备主要分为红外遥控与无线电遥控两大类,其主要区别为所采用的载波频率及其应用场景不一致。红外遥控设备所采用的射频信号频率一般为38kHz,通常应用在电视、投影仪等设备中;而无线电遥控设备
    华普微HOPERF 2025-01-06 15:29 125浏览
  • PLC组态方式主要有三种,每种都有其独特的特点和适用场景。下面来简单说说: 1. 硬件组态   定义:硬件组态指的是选择适合的PLC型号、I/O模块、通信模块等硬件组件,并按照实际需求进行连接和配置。    灵活性:这种方式允许用户根据项目需求自由搭配硬件组件,具有较高的灵活性。    成本:可能需要额外的硬件购买成本,适用于对系统性能和扩展性有较高要求的场合。 2. 软件组态   定义:软件组态主要是通过PLC
    丙丁先生 2025-01-06 09:23 83浏览
  • 大模型的赋能是指利用大型机器学习模型(如深度学习模型)来增强或改进各种应用和服务。这种技术在许多领域都显示出了巨大的潜力,包括但不限于以下几个方面: 1. 企业服务:大模型可以用于构建智能客服系统、知识库问答系统等,提升企业的服务质量和运营效率。 2. 教育服务:在教育领域,大模型被应用于个性化学习、智能辅导、作业批改等,帮助教师减轻工作负担,提高教学质量。 3. 工业智能化:大模型有助于解决工业领域的复杂性和不确定性问题,尽管在认知能力方面尚未完全具备专家级的复杂决策能力。 4. 消费
    丙丁先生 2025-01-07 09:25 77浏览
我要评论
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦