This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] CCS/LAUNCHXL-F28069M:ADC:如果频率发生变化、信号测量会振荡

Guru**** 2613355 points


请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/689770/ccs-launchxl-f28069m-adc-the-signal-measurements-oscillate-if-the-frequency-changes

器件型号:LAUNCHXL-F28069M

工具/软件:Code Composer Studio

大家好。

我是 Mike、感谢大家的支持。

我再次获取我留下的项目。 我现在遇到的问题是信号电压的测量。

我编码了一个真 RMS 电压表、因此误差为40mV、我认为这还不错

我的输入波形是一个60Hz 的相当正弦波、示波器中的测量值是3V。 同样、真正的 rms 测量的电压也相同

然后、如果更改频率、例如58.9Hz、我的测量值开始振荡 2.78V 至3.02V

当我绘制信号时、就像波形被削波一样。  

我认为这是有关 PWM 周期和比较的内容、但我不知道如何解决它。

此致

Mike

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    有人在那里吗?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Mike、
    当您说该图被削波时、您是说 ADC 的输出看起来已经饱和了吗? 如果是、它在0和4095处的物理饱和还是在固定输入电压波形峰值的非最小/最大代码处的感应饱和?

    最棒的
    Matt
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好、Matt
    我想我不能像我想的那样解释,我不是一个母语英语的 XD
    但不是、它不饱和、如果是饱和、则可以通过限制振幅输入来解决、但这不是问题。
    当我说"它被削波"时、我只想对失真的波形说些什么、就像频率变化改变了比较、信号开始失真一样。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    有人在那里吗?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Mike、
    是否可以提供有关如何对输入交流电压采样的更多背景信息? 由于您在移动频率时看到一些失真、我认为您可能是根据对交流电压周期的某种估算来控制 ADC 采样? 如果有足够的 BW、我们可以提高 ADC 的采样率、以免"错过"波峰/波谷。

    如果您愿意分享一些示例代码、请随时附上。

    最棒的
    Matthew
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    你好、Matthew

    这里是代码。

    #include "F2806x_Device.h"
    #include "F2806x_examples.h"
    #include "DSP28x_Project.h"
    #include 
    #include 
    #include 
    #include 
    #include "IQmathLib.h"
    
    extern UINT16 RamfuncsLoadStart;
    extern UINT16 RamfuncsLoadEnd;
    extern UINT16 RamfuncsRunStart;
    __interrupt void ADC_ISR (void);
    
    
    // Declaración de 变量 Globales*/uint16
    
    ADC_Buffer[154];
    uint32 ADC_buer2
    
    
    ;_Iq 缓冲区4;_bufferf_Iq
    uint32 adc_BufferVDC;
    _IQ adc_buff_VDC2;
    _IQ RMS;
    _IQ 直流;
    uint16 conv;
    uint16 cont;
    uint16 i;
    
    
    void main (void)
    {
    
    
    memcpy (&RamfuncsRunStart、&RamfuncsLoadStart、(size_t)&RamfuncsLoadEnd);// manipulación de bloque de memia:El contenido de RamfuncsLoadStart
    // se copia en RamfuncsRunStart,la rostadad de bytes copiados lo define
    // el tamaño de RamfuncsLoadEnd。 estas acciones las reiza el enlazador (F28069M.cmd)
    InitFlash();//初始化 las funciones para copiar el programa la memoria Flash
    InitSysCtrl();//初始化 el Sistema de Control:PLL、WD、外设时钟。
    Dint; //对 CPU 进行断路
    InitPieCtrl();// Iniciza los registros de control del Puerto de Interrupciones Expandido a sus Estado predeterminado
    IER = 0x0000;// Deshabiita las interruptiones del CPU
    IFR = 0x0000;// Limpia las Bandas de interrupción del CPU
    InitPieVectTable();//Iniciza la tabla de arreglos de interrupción ó n, las interruciones utilizadas son remapeadas en esta función ó n
    EALLOW; // Habilitia la emulación ó n de registros
    PieVectTable.ADCINT1 =&ADC_ISR;// El contenido del subprograma de interrupción "ADC_ISR" es copiado por el subprograma de interrupción "ADCINT1" contenido en la tabla.
    EDIS; // Deshabilita la emulación ó n de registros
    InitAdc(); //初始化 el módulo del ADC
    AdcOffsetSelfCal(); // Ajuste de offset del ADC debido a su construcción
    PieCtrlRegs.PIEIER1.bit.INTx1 = 1;// Habilitia la Interrupción 1.1 en el Puerto de expansión è re de interruciones
    IER |= M_INT1; // Habitila la interrupción 1 del CPU
    EINT; // Habitilia las interruciones globales
    ERTM; //使用 tiempo Real 的 Habilitia las interruciones
    conv=0; //可变附加定义、临时、长整型 del Buffer
    EALLOW; // Habilitia la emulación ó n de registros
    AdcRegs.ADCCTL2.bit.ADCNONOVERLAP = 1;// Habilit性 el moto de sobre apamiento de muestras
    AdcRegs.ADCCTL1.bit.INTPULSEPOS = 1;// Control de Pulso generador de interrupción -> 0 = inicio de conversión ó n、1 = UN ciclo POR resultado
    AdcRegs.INTSEL1N2.bit.INT1E = 1; // Habilit性 ADCINT1
    AdcRegs.INTSEL1N2.bit.INT1CONT = 0;// Mdo de interruptiones continuas desrabilitado -> 0= Pulso generado si la Bandera es limpiada por SW、1=Pulso generado cada EOC
    AdcRegs.INTSEL1N2.bit.INT1SEL = 1; //最终转换1 (EOC 1)对 ADCINT1进行贬低(触发)
    AdcRegs.ADCSOC1CTL.bit.CHSEL = 1; // inicio de conversión 0 (SOC) para el canal ADCIN1 (引脚29)
    AdcRegs.ADCSOC1CTL.bit.TRIGSEL = 5;// ePWM 1 es el madio para SOC1
    AdcRegs.ADCSOC1CTL.bit.ACQPS = 6; // Ventana de Sample/Holding a 7 ciclos del reloj del ADC
    EPwm1Regs.ETSEL.bit.SOCAEN = 1; // selección ó n de registros para Eventos de dimpo -> dimulos en SOC a habilitados
    EPwm1Regs.ETSEL.bit.SOCASEL = 4; // selección ó n de SOC en la comparación ó n del contador ascente de A
    EPwm1Regs.ETPS.bit.SOCAPRD = 1; // Generación de SOC al primer evento
    EPwm1Regs.CMPA.half.CMPA = 0xE647; // Valor 十进制 POR 默认值:29220。 参数 un Duty Cycle en modo de conteo ascendente del 99%-> CMPA =(100%-占空比)*(TBPRD + 1)- 1.
    EPwm1Regs.TBPRD = 0xFFDE; // Valor 十进制 POR 默认值:29220。 在莫多岛上的可里多
    EPwm1Regs.TBCTL.bit.CTRMODE = 0; //模式控制
    GpioCtrlRegs.GPBMUX1.bit.GPIO39 = 0;// MUX -> GPIO
    GpioDataRegs.GPBCLEAR.bit.GPIO39 = 1;// Salida en Estado bajo antes de configurar el pin como Salida、Mdo Drenador (SINK)。 咨询 spruh18g.pdf (pág 120)
    GpioCtrlRegs.GPBDIR.bit.GPIO39 = 1;// GPIO39 como salida
    EDIS; // Deshabilita la emulación ó n de registros
    对于(i=0;i<154;i++) // Ciclo 用于参数化 ADC_Buffer con un arreglo de 0
    {
    ADC_Buffer[I]=0; // Ciclo for para inicializar ADC_Buffer con un arreglo de 0
    }
    对于(i=0;i<154;i++) // Ciclo for para inicializar ADC_Buffer2 con un arreglo de 0
    {
    ADC_Buffer2[i]= 0;
    }
    for (;;)
    {// inicio de for
    EALLOW; // Habilitia la emulación ó n de registros
    GpioDataRegs.GPBSET.BIO39 = 1;//引脚 Modo Fuente (来源)ó Alto
    DELAY_US (100000); // intervero de tiempo de 0.1 s
    GpioDataRegs.GPBCLEAR.bit.GPIO39 = 1;//引脚 MODO Sumidero (SINK)ó 低电平
    DELAY_US (100000); // intervero de tiempo de 0.1 s
    EDIS; // desrabilita la emulación ó n de registros
    }// Fin de for
    
    }// Fin de programa principal
    
    __interrupt void
    ADC_ISR (void)// inicio del programa de interrupción
    ó n{
    
    ADC_Buffer[conv]= AdcResult.ADCRESULT1; // cada espacio o localidad del arreglo es llenado con el resultado del registro AdcResult 1.
    ADC_Buffer2[conv]= pow (ADC_Buffer[conv]、2);// VRMS se Eleva al Cuadrado cada Dato ingresado en el buffer *
    ADC_BufferVDC += ADC_Buffer[conv]; /* vdc se hace una suma de toos los datos ingados en el buffer*/
    ADC_buf_sum += ADC_Buffer2[conv]; /* VRMS se hace una suma de toos datos elevados al Cuadrado que ingresaron al buffer*/
    
    
    如果(conv ==153) // Si la variable conv si es igual a la longitud del buffer menos uno reiza los algoritmos de VDC y VRMS y despues se reicia
    {
    ADC_Buffer3 = ADC_buf_Sum/conv+1; /* VRMS La suma de los datos evelados al cuadro del ADC es sedr分 之一 la longitud del buffer */
    ADC_buff_VDC2 = ADC_BufferVDC/conv+1;/* VDC La suma de los datos del ADC 对一个入口的长度 del buffer 进行分段*
    DC=(3.3*ADC_buff VDC2)/4096; /* VDC se multiplica el promedio de los datos por un factor de conversión y se tiene el valor DC de la señal muestreada */
    ADC_Buffer4 = sqrt (ADC_Buffer3); /* VRMS se obtiene la raíz ó n cuadrada de la división ó n (Sumarita/longitud_Buffer)*/
    RMS=ADC_Buffer4*(3.3/4096); /* VRMS se multiplica el resultado de la raíz ó n cuadrada por el factor de conversión ó n y se obtiene el valor RMS de la señal ó n muestreada *
    CONV = 0; /* El contador auxiliar del buffer se reinicia */
    ADC_BufferVDC=0; /* El contenido de la suma de todos los datos del buffer se Iguala a cero,con el fin de evitar sobre apamiento de datos *
    ADC_buf_Sum = 0; /* El contenido de la suma del Cuadrado de todos los datos del buffer se Iguala a cero,con el fin de evitar sobre apamiento de datos */
    }
    
    其他 // Si la 变量 conv no es igual a la longitud del buffer menos uno entones incumenta en uno
    {
    conv++;
    }
    AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; // Limpia la Bandera de interrupción ó n del ADC
    PieCtrlRegs.PIEACK.ALL = PIEACK_Group1;// El bloque de expansido de interrupción ó n de perifericos reconoce una interrupción en el grupo 1.
    返回;
    
    } 

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    有人??

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Mike、
    我错过了您的回复、今天下午我将查看并回复。

    Matt
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Mike、
    感谢您提供的代码、假设您以最大速度运行 F28069、我相信您已设置 PWM、以根据60Hz 输入每728us 触发一次 ADC 采样、因此我们大约有23倍过采样。 然后、您将获取其中的153个样本以获得 RMS 电压。

    关于错误、可以尝试一些方法来看看我们是否可以使结果更加稳定:

    1)提高 ADC 的采样速度、使正弦波沿线的点更多
    2)增加用于生成 RMS 的样本数、以确保无论频率如何、我们都能检测到满量级
    3)浮点或定点数学;通过此操作、我想验证您是否在此器件上使用浮点单元(使用-f 编译选项)与定点或 IQmath。 物理数学可能会在某些输入频率下导致错误。

    Matt
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Matt、很抱歉回答太晚了。 我一直在处理其他项目。

    1) 1)提高 ADC 的采样速度、以便沿正弦波获取更多点

    如何实现这一点? 我认为这是超过153点。 或者您是否在谈论样片窗口? 寄存器  AdcRegs.ADCSOC1CTL.bit.ACQPS 中的最小窗口= 6;

    2)增加用于生成 RMS 的样本数、以确保无论频率如何、我们都能检测到满量级

    我放置了153个样本、取奈奎斯特定理的值。 因此、我认为如果我放置更多样本、检测 o 采样将会很慢。 我将放置1000个采样点。 你怎么看?

    3)浮点或定点数学;通过此操作、我想验证您是否在此器件上使用浮点单元(使用-f 编译选项)与定点或 IQmath。 物理数学可能会在某些输入频率下导致错误。

    我正在使用浮点单元。

     

    此致  

    Mike。

     

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Mike、
    我意识到我的第一点不清楚、当您为 ADC 使用最小的采样窗口时、您可以通过降低触发 ADC 的 CMPA 的比较/匹配值来提高采样率。

    我们还可以尝试将 ADC 结果从 uint32重新转换为浮点值、然后再将其在代码中使用。

    Matt