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.

[参考译文] RM48L952:Cortex-R4 CMSIS DSP 库中的错误

Guru**** 2476665 points
Other Parts Discussed in Thread: MOTORWARE

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/685112/rm48l952-error-in-cortex-r4-cmsis-dsp-lib

器件型号:RM48L952
主题中讨论的其他器件:MOTORWARE

您好!

数学库中包含的 ARM_SIN_COS_F32 ()函数中存在错误。

如果您使用该代码、则可以在迭代121、131、141、151和3591..3600时检查 ARM_SIN_F32 ()和 ARM_SIN_COS_F32 ()之间的错误约为9%。 FPU 中的错误是个问题:有时指令  i =(uint32_t)(theta - x1); 在 arm_sin_cos_F32 ()中、由于在减法中失去 FPU 分辨率、函数在访问正弦表时会导致无效索引。

静态空 showSin()
{
for (float angle_deg = 0.0F;angle_deg < 360.0F;angle_deg+=0.1f){
const float angle_rad = angle_deg * 2.0F *π/360.0F;
float vsin;
浮点 VCO;
float vsin2;
float vcos2;
arm_sin cos_F32 (-(angle_deg - 180.0F)、&vsin2、&vcos2);//由于 CMSIS Cortex R DSP 库正弦/余弦表访问方法而导致的相位变化*/
vcos2 =-vcos2;/*由于 CMSIS Cortex R DSP 库余弦表访问方法而反转*
Vsin = arm_sin F32 (angle_rad);
VCO = ARM_COS_F32 (ANGAL_rad);
showOneLine (angle_deg、vsin、VCO、vsin2、vcos2);
}
} 

我该怎么做?

由于性能原因、ARM_SIN_COS_F32 ()对于电机控制而言比 ARM_SIN_F32 ()和 ARM_COS_F32 ()更具有可预测性。

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

    正弦和余弦表的大小为360。 我不熟悉此功能。 您能在-179度至+181度范围内尝试 θ。

    arm_sin cos_F32 (-(angle_deg - 181.0F)、_vsin2、&vcos2);
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    大家好、QJ Wang。

    您的假设不正确、如果我更改了行上方、问题将无法解决。

    以下是 TI Hercules Cortex-R4 DSP 数学库中 ARM_SIN_COS_F32 ()的源代码:

    void arm_sin cos_F32 (
    float32_t theta、
    float32_t * pSinVal、
    float32_t * pCosVal)
    {
    uint32_t i; /*用于读取近端输出值的索引*/
    float32_t x1 =-179.0f; /*初始输入值*/
    float32_t ysin0、ysin1; /*最近的输出值*/
    float32_t ycos0、ycos1; /*最近的输出值*/
    float32_t FRAact; /*输入的小数部分*/
    float32_t ftheta =(float32_t)((int32_t) theta);
    
    
    /*用于读取最近输出值的索引计算*/
    I =(uint32_t)(θ- x1);
    
    /*小数部分的计算*/
    IF (θ> 0.0f)
    {
    FRAact = theta - ftheta;
    }
    其他
    {
    FRAact =(theta - ftheta)+ 1.0f;
    }
    
    /*读取最近的正弦输出值*/
    ysin0 = sincTable[i];
    ysin1 = sinTable[I + 1U];
    
    /*读取最近的余弦输出值*/
    ycos0 = cosTable[i];
    ycos1 = cosTable[I + 1U];
    
    /*最接近正弦输出值的差异*/
    ysin1 = ysin1 - ysin0;
    
    /*最近余弦输出值的差异*/
    ycos1 = ycos1 - ycos0;
    
    /*正弦值的计算*/
    *pSinVal = ysin0 +(Fract * ysin1);
    
    /*计算余弦值*/
    *pCosVal = ycos0+(Fract * ycos1);
    
    }
    

    以下是第  I 行的汇编列表=(uint32_t)(theta - x1); 使用 GCC 编译时、-O0:

    /*用于读取最近输出值的索引计算*/
    I =(uint32_t)(θ- x1);
    0800 BB52 VLDR.32 S14、[R7、#0x0C]
    0800 BB56 VLDR.32 S15、[R7、#0x28]
    0800 BB5A VSUB.F32 S15、S14、S15
    0800 BB5E VCVT.U32.F32 S15、S15
    0800 BB62 VMOV R3、S15
    0800 BB66 STR R3、[R7、#0x20] 

     如果输入  theta 167.99847412109375 (它是迭代#121)、变量 I 是什么?

    VLDR.32 S14、[R7、#0x0C]将该值(167.99847412109375)加载  S14

    VLDR.32 S15、[R7、#0x28]将值-179.0加载 S15

    请注意!  VSUB.F32 S15、S14和 S15使 S15=347.0!! 由于浮点精度损失的舍入、该值不能以浮点格式表示、而不是小于347 (167.99847412109375+179=346.99847412109375、该值不能以浮点格式表示)。 因此、索引  I 无效(347而不是346)、算法的下一部分使用无效点。

    将输入值  θ 舍入到0.1度分辨率不起作用、需要更正算法的其他部分才能使其正常工作。

    如果我将 arm_sin cos_F32 ()更改为使用  double 而不 是 float、那么它将是完全正确的、但最有可能的问题没有得到解决(双精度的丢失导致了同一个问题)。 对于(359、360)之间的角度、余弦误差保持较大。

    void arm_sin cos_F32 (float32_t theta、float32_t * pSinVal、float32_t * pCosVal)
    {
    uint32_t i;//读取
    
    最近的输出值的索引*/ float64_t x1 =-179.0cosF;// float64_t y0*
    、
    *、float64_t 输出值*/* /*输入的小数部分*/
    float64_t ftheta =(float64_t)((int32_t) theta);
    
    
    //读取最近的输出值的指数计算*/
    i =(uint32_t)(theta - x1);
    //小数部分的计算*
    / if (theta > 0.0f){
    FRAact = theta - ftheta;
    }否则{
    Fract =(theta - ftheta)+ 1.0;
    }
    
    //读取最近的正弦输出值*/
    ysin0 = sinTable[i];
    ysin1 = sinTable[I + 1U];
    
    //读取最近的余弦输出值*/
    ycos0 = cosTable[i];
    ycos1 = cosTable[I + 1U];
    
    /*最接近正弦输出值的差异*/
    ysin1 = ysin1 - ysin0;
    
    /*最接近的余弦输出值的差异*/
    ycos1 = ycos1 - ycos0;
    
    /*正弦值的计算*/
    *pSinVal = ysin0 +(Fract * ysin1);
    
    /*计算余弦值*/
    *pCosVal = ycos0+(Fract * ycos1);
    } 

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

    因此、我决定编写我自己的函数。

    以下是:

    /*
    *输入角度必须在[0、360]范围内
    */
    MATH_vec2 SIN_COS_F32 (常量浮点角度)
    {
    const size_t i = static_cast (角度);
    const float ysin_low = sinTable[i];
    const float ysin_high = sinTable[i+1];
    const float ycos_low = cosTable[i];
    const float ycos_high = cosTable[i+1];
    const float x_delta =角度- static_cast ㈠;
    常量浮点 sin 值= x_delta *(ysin_high - ysin_low)+ ysin_low;
    const float cos_value = x_delta *(ycos_high - ycos_low)+ ycos_low;
    返回{cos_value、sin _value};
    } 

    正弦和余弦的表大小为362。 从0到360:sinTable[i]= sin (i * 2 * Pi / 360);cosTable[i]= cos (i * 2 * Pi / 360);sinTable[361]= 0.0;cosTable[361]= 1.0F。 正弦和余弦表由电子表格程序生成。

    它正常工作。 更好地工作(更快、错误更少)。

    此线程可能会关闭、因为"无需执行任何操作、在 Cortex-R4 DSP 库和 Hercules Motorware 中保留原样"。