简体   繁体   English

嵌入式系统上的三角函数

[英]Trigonometric functions on embedded system

sin and cos functions are slow and need a lot of resources to run on embedded systems. sincos函数很慢,需要大量资源才能在嵌入式系统上运行。 How does one calculate sin and cos functions in a more resource-saving and faster way? 如何以更节省资源和更快速的方式计算sincos函数?

To calculate a Taylor or Fourier series is always going to be time-consuming. 计算泰勒傅里叶级数总是很费时间。

In an embedded system, you should think about lookup tables . 在嵌入式系统中,您应该考虑查找表

There might also be interesting information on the 'Net about how Hewlett-Packard optimised such calculations in their early scientific calculators. 关于惠普如何在早期科学计算器中优化此类计算的网络上可能还有一些有趣的信息。

I recall seeing such stuff at the time 我记得当时看到过这样的东西

A lookup table with interpolation would without doubt be the most efficient solution. 毫无疑问,带插值的查找表是最有效的解决方案。 If you want to use less memory however, CORDIC is a pretty efficient algorithm for calculating values of trig functions, and is commonly implemented in handheld calculators. 但是,如果您想使用更少的内存, CORDIC是一种非常有效的计算三角函数值的算法,通常在手持式计算器中实现。

As a side point, it doesn't make any sense to represent these functions using fourier series, since you're just creating a circular problem of how you then evaluate the sin/cos terms of series. 作为一个侧面点,使用傅立叶级数表示这些函数没有任何意义,因为您只是创建了一个循环问题,即如何评估系列的sin / cos项。 A Taylor series is a well-known approximation method, but the error turns out to be unacceptably large in many cases. 泰勒级数是一种众所周知的近似方法,但在许多情况下,误差大得令人无法接受。

You may also want to check out this question and its answers , regarding fast trigonometric functions for Java (thus the code could be ported easily). 您可能还想查看这个问题及其答案 ,关于Java的快速三角函数(因此代码可以轻松移植)。 It mentions both the CORDIC and Chebyshev approximations, among others. 它提到了CORDIC和Chebyshev近似等。 One of them will undoubtedly suit your needs. 其中一个无疑将满足您的需求。

Depends on what you need it for. 取决于你需要它。 If you are not very fussed about your angle accuracy (eg if to the nearest degree is OK) then just use a lookup table of values. 如果您对角度精度不太满意(例如,如果最接近的度数可以),那么只需使用值查找表。 If you don't have an FPU, work in fixed-point . 如果您没有FPU,请在定点工作。

One simple way to calculate sin/cos functions is with Taylor series (as shown under Trigonometric Functions here ). 一个简单的方法来计算正弦/余弦函数与泰勒级数(三角函数下,如图所示这里 )。 The fewer terms you use, the less accurate the values but the faster the calculations. 您使用的术语越少,值越不准确,但计算越快。

Fourier series calculations require some sin/cos values to be known. 傅里叶级数计算需要知道一些正弦/余弦值。 If you store things in the frequency domain most of the time, though, you can potentially save on calculations - depending on what it is you are doing. 但是,如果您在大多数情况下将事物存储在频域中 ,则可以节省计算 - 取决于您正在做什么。

Dobb博士的文章: 使用定点算法优化数学密集型应用程序对CORDIC算法有很好的解释,并为本文中讨论的库提供了完整的源代码。

  1. Lookup-tables 查找表
  2. Taylor series , like you say 泰勒系列 ,就像你说的那样

Note that with lookup-tables, you can often optimize things by limiting the domain, eg represent the angle as an unsigned char, giving you only 256 steps around the circle but also a very compact table. 请注意,对于查找表,您通常可以通过限制域来优化事物,例如将角度表示为无符号字符,在圆周围只有256步,但也是一个非常紧凑的表。 Similar things can be done to the value, like using fixed-point. 可以对值进行类似的操作,例如使用定点。

See the Stack Overflow question How do Trigonometric functions work? 请参阅Stack Overflow问题Trigonometric函数如何工作? The accepted answer there explains some details of how to do range reduction, then use CORDIC, then do some further optimizations. 那里接受的答案解释了如何进行范围缩减的一些细节,然后使用CORDIC,然后进行一些进一步的优化。

这可能是一些帮助/灵感: Quake III中神奇的平方根

You can take a look at this arbitrary fixed point library for 8-bit AVR microcontrollers: https://community.atmel.com/projects/afp-arbitrary-fixed-point-lib 您可以查看这个用于8位AVR微控制器的任意定点库: https//community.atmel.com/projects/afp-arbitrary-fixed-point-lib

EDIT: link updated 编辑:链接已更新

There seems to be an nice pseudocode example here and explicit code here . 似乎是一个很好的例子的伪代码这里和明确的代码在这里

However, as @unwind suggested, you might want to try to precalculate these tables on a decent computer and load the tables to the embedded device. 但是,正如@unwind建议的那样,您可能希望尝试在正常的计算机上预先计算这些表并将表加载到嵌入式设备。

If your answer doesn't have to be very exact, the lookup table would be rather small, and you'll be able to store it in your device's memory. 如果您的答案不一定非常精确,那么查找表会相当小,您将能够将其存储在设备的内存中。 If you need higher accuracy, you'll need to calculate it within the device. 如果您需要更高的精度,则需要在设备中进行计算。 It's a tradeoff between memory, time and required precision; 这是记忆,时间和所需精度之间的权衡; the answer relies on the specific nature of your project. 答案取决于项目的具体性质。

In some cases one can manage with just IIR filter, tuned to resonance on needed frequency. 在某些情况下,可以使用IIR滤波器进行管理,调谐到所需频率的谐振。 Look here: http://www.ee.ic.ac.uk/pcheung/teaching/ee3_Study_Project/Sinewave%20Generation(708).pdf 看这里: http//www.ee.ic.ac.uk/pcheung/teaching/ee3_Study_Project/Sinewave%20Generation(708).pdf

I'm a bit late to the party, but anyway I want to share a ready-made efficient solution that uses lookup table (table generator included) : DFTrig . 我有点迟到了,但无论如何我想分享一个现成的高效解决方案,使用查找表(包括表生成器): DFTrig

DFTrig consists of two parts: DFTrig由两部分组成:

  • Lookup table generator tablegen (written in Java, but that doesn't matter much) that receives several options and produces C code (const struct with lookup table) 查找表生成器tablegen (用Java编写,但无关紧要)接收多个选项并生成C代码(带查找表的const结构)
  • Small C module that works with lookup table generated by tablegen . 小型C模块,与tablegen生成的查找表tablegen

Of course, lookup table contains only minimal information: sine values for just a single quadrant, ie [0, 90] degrees. 当然,查找表仅包含最少的信息:仅一个象限的正弦值,即[0, 90]度。 That is fairly enough to calculate sine / cosine for any angle. 这相当于计算任何角度的正弦/余弦。

The behavior is quite customizable. 行为是可定制的。 You may specify: 您可以指定:

  • Factor by which each item in the lookup table is multiplied (on per-table basis); 查找表中每个项目乘以的因子(基于每个表);
  • Step in degrees between each item in the table (on per-table basis); 在表格中的每个项目之间进行度数(基于每个表格); Type of items in the table (common for the whole C project). 表中的项目类型(整个C项目通用)。

So, depending on your needs, you may: 因此,根据您的需求,您可以:

  • Generate single table for the whole application with max factor, so that any subsystem of your C project may use that single table, providing desired factor, and it will be recalculated if requested factor is other than that of the table; 使用max factor为整个应用程序生成单个表,以便C项目的任何子系统可以使用该单个表,提供所需的因子,如果请求的因子不是表的因子,则将重新计算;
  • Generate multiple tables, each with ad hoc factor, and each subsystem of your C project uses its dedicated table. 生成多个表,每个表都有ad hoc因子,C项目的每个子系统都使用其专用表。 Then, values can be returned from table as is, without recalculation; 然后,可以按原样从表返回值,而无需重新计算; that works faster. 这工作得更快。

I use it in my embedded projects, it works nicely. 我在我的嵌入式项目中使用它,它工作得很好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM