嵌入式系统上的三角函数

发布于 2024-08-07 18:48:58 字数 126 浏览 3 评论 0 原文

sincos 函数速度较慢,并且需要大量资源才能在嵌入式系统上运行。如何以更节省资源且更快的方式计算 sincos 函数?

sin and cos functions are slow and need a lot of resources to run on embedded systems. How does one calculate sin and cos functions in a more resource-saving and faster way?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

女皇必胜 2024-08-14 18:48:58

计算 Taylor傅里叶级数总是很耗时的。

在嵌入式系统中,您应该考虑查找表

网上可能还有关于惠普如何在其早期科学计算器中优化此类计算的有趣信息。

我记得当时看到过这样的东西

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

绝不服输 2024-08-14 18:48:58

带插值的查找表无疑是最有效的解决方案。但是,如果您想使用更少的内存,CORDIC 是计算三角函数值的非常有效的算法功能,并且通常在手持计算器中实现。

顺便说一句,使用傅里叶级数表示这些函数没有任何意义,因为您只是创建了一个如何评估级数的正弦/余弦项的循环问题。泰勒级数是一种众所周知的近似方法,但在许多情况下误差大得令人无法接受。

您可能还想查看关于快速三角函数的这个问题及其答案 Java 函数(因此代码可以轻松移植)。其中提到了 CORDIC 和切比雪夫近似等。其中之一无疑会满足您的需求。

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.

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. 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). It mentions both the CORDIC and Chebyshev approximations, among others. One of them will undoubtedly suit your needs.

北城挽邺 2024-08-14 18:48:58

取决于你需要它做什么。如果您对角度精度不是很在意(例如,如果精确到最接近的度数就可以),那么只需使用值查找表即可。如果您没有 FPU,请使用定点

计算 sin/cos 函数的一种简单方法是使用泰勒级数(如三角函数

傅里叶级数计算需要知道一些正弦/余弦值。不过,如果大多数时候您将内容存储在频域中,那么您可能可以节省计算 - 取决于您正在做什么。

Depends on what you need it for. If you are not very fussed about your angle accuracy (e.g. 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.

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.

无声静候 2024-08-14 18:48:58

Dobb 博士的这篇文章:用定点算术优化数学密集型应用 有很好的解释CORDIC 算法的一部分,并为本文讨论的库提供完整的源代码。

This Dr. Dobb's article: Optimizing Math-Intensive Applications with Fixed-Point Arithmetic has a good explanation of CORDIC algorithms and provides complete source code for the library discussed in the article.

荆棘i 2024-08-14 18:48:58
  1. 查找表
  2. 泰勒级数,就像你说的

注意,使用查找表,你通常可以优化通过限制域,例如将角度表示为无符号字符,只为您提供围绕圆的 256 步,但也是一个非常紧凑的表格。可以对值执行类似的操作,例如使用定点。

  1. Lookup-tables
  2. Taylor series, like you say

Note that with lookup-tables, you can often optimize things by limiting the domain, e.g. represent the angle as an unsigned char, giving you only 256 steps around the circle but also a very compact table. Similar things can be done to the value, like using fixed-point.

咿呀咿呀哟 2024-08-14 18:48:58

请参阅 Stack Overflow 问题三角函数如何工作? 已接受的答案其中解释了如何缩小范围,然后使用 CORDIC,然后进行一些进一步优化的一些细节。

See the Stack Overflow question How do Trigonometric functions work? The accepted answer there explains some details of how to do range reduction, then use CORDIC, then do some further optimizations.

苏佲洛 2024-08-14 18:48:58

似乎有一个很好的伪代码示例这里和显式代码此处

但是,正如 @unwind 所建议的,您可能希望尝试在一台像样的计算机上预先计算这些表并将这些表加载到嵌入式设备。

如果您的答案不必非常精确,则查找表会相当小,您可以将其存储在设备的内存中。如果您需要更高的精度,则需要在设备内进行计算。这是内存、时间和所需精度之间的权衡;答案取决于您项目的具体性质。

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.

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.

月朦胧 2024-08-14 18:48:58

在某些情况下,只需使用 IIR 滤波器即可进行管理,并在所需频率上调谐到谐振。
请看这里:http://www. ee.ic.ac.uk/pcheung/teaching/ee3_Study_Project/Sinewave%20Generation(708).pdf

In some cases one can manage with just IIR filter, tuned to resonance on needed frequency.
Look here: http://www.ee.ic.ac.uk/pcheung/teaching/ee3_Study_Project/Sinewave%20Generation(708).pdf

小帐篷 2024-08-14 18:48:58

这可能会有所帮助/启发:
雷神之锤 III 中的神奇平方根

This may be of some help / inspiration:
Magical square root in Quake III

叫思念不要吵 2024-08-14 18:48:58

我参加聚会有点晚了,但无论如何我想分享一个使用查找表(包括表生成器)的现成的高效解决方案:DFTrig

DFTrig 由两部分组成:

  • 查找表生成器 tablegen (用 Java 编写,但这并不重要),它接收多个选项并生成 C 代码(带有查找表的 const 结构) 可以
  • 工作的小型 C 模块带有由tablegen生成的查找表。

当然,查找表仅包含最少的信息:仅单个象限的正弦值,即[0, 90]度。这足以计算任何角度的正弦/余弦。

该行为是完全可定制的。您可以指定:

  • 查找表中每个项目相乘的因子(基于每个表);
  • 表中每个项目之间的步进度数(基于每个表);
    表中项目的类型(整个 C 项目通用)。

因此,根据您的需要,您可以:

  • 为整个应用程序生成具有最大因子的单个表,以便 C 项目的任何子系统都可以使用该单个表,提供所需的因子,如果请求的因子不是桌子的那个;
  • 生成多个表,每个表都有临时因子,并且 C 项目的每个子系统都使用其专用表。然后,可以按原样从表中返回值,无需重新计算;这样效果更快。

我在我的嵌入式项目中使用它,效果很好。

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 consists of two parts:

  • 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)
  • Small C module that works with lookup table generated by tablegen.

Of course, lookup table contains only minimal information: sine values for just a single quadrant, i.e. [0, 90] degrees. 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).

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;
  • Generate multiple tables, each with ad hoc factor, and each subsystem of your C project uses its dedicated table. Then, values can be returned from table as is, without recalculation; that works faster.

I use it in my embedded projects, it works nicely.

御弟哥哥 2024-08-14 18:48:58

您可以看一下这个 8 位 AVR 微控制器的任意定点库:
https://community.atmel.com/projects/afp- Arbitrary-定点库

编辑:链接已更新

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

EDIT: link updated

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文