在不使用标准功能的情况下,在C中生成正弦信号 [英] Generate sine signal in C without using the standard function

查看:106
本文介绍了在不使用标准功能的情况下,在C中生成正弦信号的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在C中生成正弦信号而不使用标准函数sin()来触发LED亮度的正弦形变化。我的基本想法是使用具有40个点并进行插值的查找表。

I want to generate a sine signal in C without using the standard function sin() in order to trigger sine shaped changes in the brightness of a LED. My basic idea was to use a lookup table with 40 points and interpolation.

这是我的第一种方法:

const int sine_table[40] = {0, 5125, 10125, 14876, 19260, 23170, 26509, 29196,
31163, 32364, 32767,  32364, 31163, 29196, 26509, 23170, 19260, 14876, 10125,
5125, 0, -5126, -10126,-14877, -19261, -23171, -26510, -29197, -31164, -32365,
-32768, -32365, -31164, -29197, -26510, -23171, -19261, -14877, -10126, -5126};

int i = 0;
int x1 = 0;
int x2 = 0;
float y = 0;

float sin1(float phase)
{
    x1 = (int) phase % 41;
    x2 = x1 + 1;
    y = (sine_table[x2] - sine_table[x1])*((float) ((int) (40*0.001*i*100) % 4100)/100 - x1) + sine_table[x1];
    return y;
}

int main()
{
    while(1)
    {
    printf("%f      ", sin1(40*0.001*i)/32768);
    i = i + 1;
    }
}

不幸的是,该函数有时返回的值远大于1此外,插值似乎不太好(我用它来创建LED的正弦形亮度变化,但是这些变化非常不平滑)。

Unfortunately, this function sometimes returns values far bigger than 1. Furthermore, the interpolation doesn't seem to be good (I used this to create sine shaped brightness changes of a LED, but these are very unsmoooth).

推荐答案

OP的主要问题是为表的外观生成索引-

OP's main problem is in generating the index for the table look-up.

OP的代码试图访问外部数组 sine_table [40] 导致 未定义行为 。至少解决这个问题。

OP's code attempts to access outside array sine_table[40] leading to undefined behavior. Fix that at least.

const int sine_table[40] = {0, 5125, 10125, ...
    ...
    x1 = (int) phase % 41;                     // -40 <= x1 <= 40
    x2 = x1 + 1;                               // -39 <= x2 <= 41  
    y = (sine_table[x2] - sine_table[x1])*...  // bad code, consider x1 = 40 or x2 = 40,41

建议的更改

    x1 = (int) phase % 40;   // mod 40, not 41
    if (x1 < 0) x1 += 40;    // Handle negative values
    x2 = (x1 + 1) % 40;      // Handle wrap-around 
    y = (sine_table[x2] - sine_table[x1])*...  

还有很多更好的方法,但是下面不关注OP的方法。

There exist much better approaches, yet to focus on OP's method see below.

#include <math.h>
#include <stdio.h>

const int sine_table[40] = { 0, 5125, 10125, 14876, 19260, 23170, 26509, 29196,
31163, 32364, 32767, 32364, 31163, 29196, 26509, 23170, 19260, 14876, 10125,
5125, 0, -5126, -10126, -14877, -19261, -23171, -26510, -29197, -31164, -32365,
-32768, -32365, -31164, -29197, -26510, -23171, -19261, -14877, -10126, -5126 };

int i = 0;
int x1 = 0;
int x2 = 0;
float y = 0;

float sin1(float phase) {
  x1 = (int) phase % 40;
  if (x1 < 0) x1 += 40;
  x2 = (x1 + 1) % 40;
  y = (sine_table[x2] - sine_table[x1])
      * ((float) ((int) (40 * 0.001 * i * 100) % 4100) / 100 - x1)
      + sine_table[x1];
  return y;
}

int main(void) {
  double pi = 3.1415926535897932384626433832795;
  for (int j = 0; j < 1000; j++) {
    float x = 40 * 0.001 * i;
    float radians = x * 2 * pi / 40;
    printf("%f %f %f\n", x, sin1(x) / 32768, sin(radians));
    i = i + 1;
  }
}

输出

         OP's     Reference sin()
0.000000 0.000000 0.000000
0.040000 0.006256 0.006283
0.080000 0.012512 0.012566
...
1.960000 0.301361 0.303035
2.000000 0.308990 0.309017
2.040000 0.314790 0.314987
...
39.880001 -0.020336 -0.018848
39.919998 -0.014079 -0.012567
39.959999 -0.006257 -0.006283






更好的代码不会传递值 i,x1,x2,y 作为全局变量,但作为函数参数或函数变量。


Better code would not pass the values i, x1, x2, y as global variables, but as function parameters or function variables. Perhaps that is an artifact of OP's debugging.


有人能更好地实现吗?

Does anybody have a better idea to implement a sine generator in C?

这是相当广泛的。在速度,精度,代码空间,可移植性或可维护性方面更好? sine()函数很容易制作。高质量的需要付出更多的努力。

This is quite broad. Better as in speed, precision, code space, portability, or maintainability? sine() functions are easy to make. High-quality ones take more effort.

尽管模糊,但OP使用小的查找表是一个不错的开始-尽管我看到它可以毫无浮动地完成点数学。我建议OP构建一个经过测试且可以正常工作的解决方案,并将其发布在代码审查中,以提出改进建议。

Although fuzzy, OP's use of a small look-up table is a good beginning - although I see it can be done without any floating point math. I recommend for OP to construct a tested and working solution and post it in Code Review for improvement ideas.

这篇关于在不使用标准功能的情况下,在C中生成正弦信号的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆