之前做FOC算法的时候,用到了TLV493D磁传感芯片通过两个相差90°的正弦曲线计算角度,所以需要计算arctan的值。这里就基于CORDIC(坐标旋转数字计算方法,Coordinate Rotation Digital Computer)理论,实现一种arctan的定点计算方法。

一、原理

坐标旋转

与FOC中的Park变换原理相同,CORDIC也是通过旋转坐标轴来求解反正切值的。

如果去掉cosθ,这样不会影响角度旋转的结果,只是x和y都被缩小了cosθ,这样能简化计算,这称为伪旋转。得到下式:

而CORDIC的核心则是令,此时得到下式:

(1) 为什么用呢?

因为在实际代码中,可以使用右移操作来完成,能加快计算速度。

(2)这个方法能计算的角度范围?

上表中列出了5个θ值,若为无穷个呢?由可得

所以可以看出用这个方法能求的角度范围在[-99.8829°,99.8829°]。而在大多数场合,我们的计算范围是在[-180°,180°]。四个象限内的arctan都可以相互转换,且arctan是个奇函数,所以我们只需要将其它角度都转到[0°,45°]范围内计算,得到结果后变换一下即可。

迭代

迭代求arctan的方法的原理就是:每次旋转上面表中计算出的角度,累加这个角度,使y趋近于0。

  • y趋近于0的意思,可以把旋转坐标系想象为Park变换。如图所示,坐标轴在以表中的角度旋转,假设此时要求点(1,1)相对x轴的角度,即θ = arctan(1/1) = 45°,坐标轴第一次旋转,则为表中最大的45°,此时在旋转坐标系(下图黑色)中,(1,1)点变为(,0)。当然在计算的过程中,x最后不会是,因为最开始我们为了方便计算将x和y都缩小了cosθ,但是一旦旋转到了我们期望的角度,y就是0。

因此,我们只需要不断让坐标轴旋转表中的角度,得到下式:

  • 坐标轴在逆时针旋转时,顺时针旋转时。其实就是因为,规定以逆时针旋转为正,顺时针旋转为负。

假设θ=30°,初始角度为0°。第一次逆时针旋转45°,。此时45°>30°,坐标轴要往回旋转26°,,此时角度为19°<30°,所以,就这样按表中的角度继续旋转,直到y趋近于0。

二、C语言实现

1、定义tan表格,即表示1、0.5、0.25.....的表格,采用Q15格式保存

#define DEPTH      16            //最大赋值为16
#define DEP_SHIFT (DEPTH-1)      //tan数组中的标幺值移位
static uint16_t _tan[DEPTH];
for(i=0; i<DEPTH; i++)
{_tan[i] = 1<<(DEPTH-i-1);    //减1,最大支持Q15表示
}
//如果DEPTH为16,则0号元素为32768,超过int16范围,后续会溢出,故最大元素减1
if(DEPTH == 16)_tan[0] -= 1;

2、定义angle表格

#include <math.h>#define DIVPI 57.295779513082    //即弧度转角度,180/pi
#define ANG_AMP        64        //角度放大的倍数,理论上来说越大精度越高,建议设为2的倍数
#define ANG_PRECICE    100       //计算出来的结果是小数点后几位的,100表示后两位
#define ANG_MUL        (ANG_AMP*ANG_PRECICE)
static uint32_t _angle[DEPTH];   //tanθ = 2^(-i)时对应的θ值double ang_tmp = 1;
for(i=0; i<DEPTH; i++)
{res = (int)(1.0 * atan(ang_tmp) * DIVPI * ANG_MUL);_angle[i] = res;ang_tmp /= 2;
}
  • 在确定好求解深度DEPTH后,上述表格都可以先求出来放在一个const数组中,而不用每次初始化中计算。

由于FOC中使用的是int16_t来表示0~360°,故将宏定义定义为如下:

#define ANG_AMP        182.5487465181058
#define ANG_PRECICE    32

最后的结果右移5位赋值给int16_t变量,即为FOC表示的电角度。

3、CORDIC算法

(1)预处理:所有角度都转为第一象限的[0°,45°]范围内处理
       ①保证x、y都大于0,即位于第一象限
       ②保证x>y,否则交换,结果根据arctan(y/x)+arctan(x/y)=π/2得出

if(x < 0)
{x = -x;flag |= 1<<0;
}
if(y < 0)
{y = -y;flag |= 1<<1;
}
if(y > x)
{tmp = y;y = x;x = tmp;flag |= 1<<2;
}

(2)防溢出处理

不能直接将x、y用于计算,否则后面的乘法过程可能会超出int32变量的范围。

/* 限制范围在uint16范围内,后续乘法不会超过uint32范围,防止溢出 */
_y = ((y << DEPTH)-1)/x;    //前面保证x>y,所以这里_y<65535
_x = (1<<DEPTH)-1;          //即为1

(3)CORDIC迭代计算

/* 迭代计算 */
int x_tan,y_tan,_y,_x;
uint16_t *ptan = (uint16_t *)&_tan;    //指针访问比数组访问快
uint32_t *pang = (uint32_t *)&_angle;
uint32_t res = 0;for(i=0; i<DEPTH ;i++)
{//由于x_tan和y_tan有正有负,设置为int类型,但最大值为31位,故前面的tan用Q15来表示x_tan = (_x * (*ptan)) >> DEP_SHIFT;   //Q15的tan * Q16的用户输入,计算后要右移Q15y_tan = (_y * (*ptan++)) >> DEP_SHIFT;if(_y > 0){_x += y_tan;_y -= x_tan;res += *pang++;}else{_x -= y_tan;_y += x_tan;res -= *pang++;}
}

(4)角度还原

前面把所有的角度都转化为[0°,45°]范围内,这里要转化回去,输出[0°,360°]范围的角度

if(flag & 0x04)
{switch(flag){case 7:res = 270 * ANG_MUL - res;break;case 4:res = 90 * ANG_MUL - res;break;case 5:res = 90 * ANG_MUL + res;break;case 6:res = 270 * ANG_MUL + res;break;}
}else
{switch(flag){case 0:break;case 1:res = 180 * ANG_MUL - res;break;case 2:res = 360 * ANG_MUL - res;break;case 3:res = 180 * ANG_MUL + res;break;}
}

最终的结果除以ANG_AMP,即为精度为ANG_PRECICE的角度值。

CORDIC算法 arctan反正切计算原理及C语言定点实现相关推荐

  1. cordic算法反正切c语言,Cordic 算法之 反正切

    在通信的算法中,常采用Cordic算法之一,知道角度产生正交的的正弦余弦, 或者知道正弦和余弦求角度,求反正切. 1. 求正弦和余弦值. 方法:旋转角度,得到正弦余弦值: 再旋转角度,到达下一个正弦余 ...

  2. verilog实现基于Cordic算法的双曲函数计算

    Cordic算法可以用FPGA硬件来实现三角函数,向量旋转,指数函数以及三角函数等数值计算,它是一种从一般的矢量旋转方程中推导得出.采用用不断的旋转求出对应的正弦余弦值,是一种近似求解法.旋转的角度很 ...

  3. 硬件中的三角函数计算 Cordic算法入门

    三角函数的计算是个复杂的主题,有计算机之前,人们通常通过查找三角函数表来计算任意角度的三角函数的值.这种表格在人们刚刚产生三角函数的概念的时候就已经有了,它们通常是通过从已知值(比如sin(π/2)= ...

  4. HLS / Chisel 实现CORDIC算法双曲系统

    CORDIC(坐标旋转数字算法)是一种计算三角.双曲和其他数学函数的有效方法.它是一种数字算法,每次运算均产生一次结果输出.这使我们能够根据应用需求调整算法精度:增加运算迭代次数可以得到更精确的结果. ...

  5. vivado中Cordic IP核使用——计算正余弦(sin/cos)

    目录 1.Cordic算法介绍 2.Cordic IP核介绍 3.仿真 4.存在的问题 5.参考 1.Cordic算法介绍 cordic算法将正余弦计算转换为简单的迭代过程(一系列的加减和移位操作), ...

  6. 2---理解正余弦、复数求模、反正切和乘除运算的CORDIC算法实现

    CORDIC(Coordinate Rotation Digital Computer)算法是J.Volder在1956在航空控制系统设计中构思的,但其实相似的算法在更早的1624年就已经被Henry ...

  7. CORDIC算法原理详解及其Verilog实现

    CORDIC算法原理详解及其Verilog实现 本文的verilog代码 链接:https://pan.baidu.com/s/1GGbRjxO5CxoIODQAg1l6Lw 提取码:jo0h *本文 ...

  8. CORDIC算法计算复数相位角(含verilog源码)

    前言   截止2022年2月15日,中国科学院大学<高等数字集成电路分析及设计>课程终于完结,所以我计划分享几个自己完成的实践作业,供大家交流学习. 设计收获 对cordic算法有了清晰的 ...

  9. 02、cordic算法原理及verilog实现

    发布时间:2021/11/25 发布版本:2021-02 一.cordic算法原理 cordic算法主要应用于三角函数计算,尽管现在随着大规模存储器的普及,设计人员可以将所需三角函数值全部存储在存储器 ...

  10. FPGA实现Cordic算法求解arctan和sqr(x*2 + y* 2)

    一. 简介 由于在项目中需要使用的MPU6050,进行姿态解算,计算中设计到**arctan 和 sqr(x2 + y 2),**这两部分的计算,在了解了一番之后,发现Cordic算法可以很方便的一次 ...

最新文章

  1. 大数据集合求交集_通达信北上资金+盘面分析sp版面,智能大数据集合,筹码占比指标...
  2. 对话推荐算法研究综述
  3. CentOS查看CPU、内存、网络流量和磁盘 I/O
  4. 反射机制(1)认识Class类
  5. python 函数参数前面两个星号_Python中参数前面一个星号两个星号(*参数,**参数)起什么作用呢?...
  6. vue中mixin的一点理解
  7. mysql首次安装后原始密码存放位置
  8. win10商店下载位置_Win10删应用商店下载记录|Win10删Microsoft Store下载记录
  9. SpringBoot——slf4j+logback日志处理及配置详解
  10. 开弹幕卡顿的原因_QQ飞车手游卡顿严重怎么解决,来看看这个安卓手游卡顿解决方法!...
  11. 高清电脑手机壁纸任你选,每天不重样!
  12. linux设置不同地址,ubuntu20.04设置静态ip地址(包括不同版本)
  13. 专注NLP、推荐等AI算法招聘群,慢者无,包括几乎所有公司最新信息
  14. 《剑指offer》面试题20——顺时针打印矩阵(C++)
  15. 将Win7中的IE11降级为IE8
  16. 广工Anyview数据结构习题
  17. 高中数学平面解析几何解题技巧-直线与圆锥曲线的位置关系-习题
  18. vector详解以及一些问题(C++)
  19. 网上书城—登录、书籍管理
  20. 【Linux】Centos安装mvn命令(maven)

热门文章

  1. 基于51单片机俄罗斯方块游戏电路设计
  2. HotPower超级CRC计算器与第三方CRC计算器名词解释与对照及操作
  3. Cracker学习——任务1
  4. html平行四边形标签,平行四边形
  5. Linux路由选择与策略路由
  6. NDB和InnoDB存储引擎比较
  7. 从今往后,我就是一名前端攻城狮
  8. 金蝶软件界面文字全部变为乱码解决办法
  9. java : mozilla rhino js引擎 使用教程
  10. SCIgen与野鸡期刊的梗