arctan查表法_arctan()函数的查表算法

arctan()函数的查表算法

2018-11-21

目标:实现反正切函数的查表算法,精度0.5°。分析:f(x) = arctan(x)函数单调但非线性,越接近原点处,斜率越大。90°比较特殊,其值为正无穷大,只要得到的正切值tana大于114.59(89.5度对应的正切值),就可以认为是90度。假如0-89.5°用一个查找表实现,索引为正切值,值为角度值。tan89.5为115,假如用N点uint16_t型查找表,需要保证arctan(115 / N) < 0.5°即 115 / N < 0.0087可选的最小值为13219,意味着至少要建立一张13K×16的表,占用26KB的Flash,对于一般的MCU来说不可接受。如果0-45°用一个查找表实现,由于tan45°=1,根据上面的计算公式,可以得出N的最小值为114,这个N值对一般的MCU均可以接受,甚至可以增加至256点来提高精度。对于45°以上的角度,可以根据两角和的三角公式来得到,推导过程如下:

如果测量的正切值K大于1,那么根据最后的公式,可以求出比45°大的那个角度a,再加上45°就是实际的角度。而a的计算可以由256点查找表来快速得到,这样就实现了用一个小容量查找表计算90度以内的反正切值。查找表涉及两个数值:表索引idx和表的角度值angle[idx]。索引值idx对应0-45°的正切值,由于这些值均小于1,采用整体扩大256倍的方法,将正切值就映射到了0-256的区间,从而索引idx的范围为0-255。角度值angle[]是uint16_t型的,而实际的范围为0-45,根据65536/45=1456,可以用Q12的表示方式来提高分辨率。查找表如下:static const uint16_t tb_atan[256] = {0, 229, 458, 687, 916, 1145, 1374, 1603,1832, 2061, 2290, 2519, 2748, 2976, 3205, 3433,3662, 3890, 4118, 4346, 4574, 4802, 5029, 5257,5484, 5711, 5938, 6165, 6391, 6618, 6844, 7070,7296, 7521, 7746, 7971, 8196, 8421, 8645, 8869,9093, 9317, 9540, 9763, 9986, 10208, 10431, 10652,10874, 11095, 11316, 11537, 11757, 11977, 12197, 12416,12635, 12853, 13071, 13289, 13507, 13724, 13940, 14157,14373, 14588, 14803, 15018, 15232, 15446, 15660, 15873,16085, 16297, 16509, 16720, 16931, 17142, 17352, 17561,17770, 17979, 18187, 18394, 18601, 18808, 19014, 19220,19425, 19630, 19834, 20038, 20241, 20444, 20646, 20848,21049, 21250, 21450, 21649, 21848, 22047, 22245, 22443,22640, 22836, 23032, 23227, 23422, 23616, 23810, 24003,24196, 24388, 24580, 24771, 24961, 25151, 25340, 25529,25717, 25905, 26092, 26278, 26464, 26649, 26834, 27018,27202, 27385, 27568, 27750, 27931, 28112, 28292, 28471,28650, 28829, 29007, 29184, 29361, 29537, 29712, 29887,30062, 30236, 30409, 30582, 30754, 30925, 31096, 31266,31436, 31605, 31774, 31942, 32109, 32276, 32442, 32608,32773, 32938, 33101, 33265, 33428, 33590, 33751, 33913,34073, 34233, 34392, 34551, 34709, 34867, 35024, 35180,35336, 35492, 35646, 35801, 35954, 36107, 36260, 36412,36563, 36714, 36864, 37014, 37163, 37312, 37460, 37607,37754, 37901, 38047, 38192, 38337, 38481, 38624, 38768,38910, 39052, 39194, 39335, 39475, 39615, 39754, 39893,40032, 40169, 40307, 40443, 40580, 40715, 40850, 40985,41119, 41253, 41386, 41519, 41651, 41782, 41913, 42044,42174, 42303, 42432, 42561, 42689, 42817, 42944, 43070,43196, 43322, 43447, 43572, 43696, 43819, 43943, 44065,44188, 44309, 44431, 44551, 44672, 44792, 44911, 45030,45148, 45266, 45384, 45501, 45618, 45734, 45849, 45965,};static int16_t calc_phase(int16_t real, int16_t imag){int16_tabs_real;int16_tabs_imag;int16_tphase;uint16_tzone;uint32_ttmp_tan;uint32_tdelta_tan;if (real< 0){abs_real = -real;zone = 1U;}else{abs_real = real;zone = 0U;}if (imag< 0){abs_imag = -imag;zone +=2U;}else{abs_imag = imag;zone =0U;}if (abs_imag<= abs_real){tmp_tan =(uint32_t)abs_imag<<8U;tmp_tan /= abs_real;phase =tb_atan[tmp_tan]>>3U;}else if((abs_imag>>7U) <=abs_real){delta_tan = ((uint32_t)(abs_imag -abs_real))<<15U;tmp_tan = (uint32_t)abs_imag + (uint32_t)abs_real;delta_tan /= tmp_tan;delta_tan >>= 7U;phase =tb_atan[delta_tan]>>3U;phase += 5760;}else{phase = 11520;}switch(zone){case 0U:{break;}case 1U:{phase = 23040 - phase;break;}case 2U:{phase = -phase;break;}case 3U:{phase = phase - 23040;break;}default:{break;}}return(phase);}辅助的python计算程序如下:#!/usr/bin/python# -*- coding: utf-8 -*-from math import sinfrom math import cosfrom math import tanfrom math import atanfrom math import pi"""#验证FFT和相角计算的程序wave = []Fai = 17.5 / 180 * 3.1415926for i in range(128):base =cos(3.1415926*2*i/128 + Fai)#    harm =0.07*cos(3.1415926*11*2*i/128)harm =0wave.append((int)(32768*(base+harm)))# 格式化输出print "static const int16_t vol[128] = {"for i in range(128):print "%d,"%wave[i],if i%8 ==7:printprint "};"#    print ",",round(cos(3.1415926*2*i/128),4)""""""for i in range(142,180):print i/2.0,tan(i * pi /360)"""val_tan = []num = 256for i in range(num):val_tan.append((atan(i * 1.0 / num) * 180 / pi) )# 格式化输出print "static const uint16_t arctan[%d] = {" % numfor i in range(num):print "%f,"%val_tan[i],if i%8 ==7:printprint "};"

免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。

http://www.pinlue.com/style/images/nopic.gif

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
单片机是一种微型计算机芯片,常常用于控制和处理各种电子设备。在单片机中使用查表求解arctan函数可以有效地减少计算量和提高运算速度。 要实现查表arctan函数,首先需要在单片机中存储一张arctan的查找表。这个查找表将包含一系列输入和对应的输出值。输入值可以是arctan函数的自变量,而输出值是对应的arctan函数函数值。具体的查找表内容可以根据需求和精确度进行设计。 在实际运算中,当需要计算某个角度的arctan值时,单片机可以通过查找表来快速获取该角度对应的arctan函数的值。只需要将输入角度作为查找表的索引,即可得到相应的arctan函数值。 通过查找表求解arctan函数可以大大减少计算量,因为在计算过程中只需要进行简单的查表操作,而不需要使用复杂的数学公式或算法。同时,也可以提高计算速度,因为单片机可以高效地访问和获取查找表中的数值。 当然,查找表也有一定的限制。首先,查找表的精确度取决于数据的存储和查找表的规模,如果查找表的规模太大,可能会导致内存占用过高。另外,查找表只适用于有限的输入范围内,如果需要计算超过查找表范围的角度值,就需要使用其他方来进行计算。 综上所述,单片机使用查表求解arctan函数可以简化计算过程,并提高计算速度,但需要根据需求和精确度进行查找表的设计。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值