Generate sine signal in C without using the standard function

后端 未结 11 742
情歌与酒
情歌与酒 2021-02-02 09:41

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 lo

11条回答
  •  一生所求
    2021-02-02 09:55

    Unless your application calls for real precision, don't kill yourself coming up with an algorithm for a 40 point sine or cosine wave. Also, the values in your table should match the range of your LED's pwm input.

    That said, I took a look at your code and it's output and figured you weren't interpolating between points. With a little modification, I fixed it, and the error between a excel's sign function and yours is off by a max of about 0.0032 or thereabouts. The change is pretty easy to implement and has been tested using tcc, my personal go-to for C algorithm testing.

    First off, I added one more point to your sine array. The last point is set to the same value as the first element in the sine array. This fixes the math in your sine function, in particular when you set x1 to (int)phase%40, and x2 to x1+1. Adding the extra point isn't necessary, as you could set x2 to (x1+1)%40, but I chose the first approach. I'm just pointing out different ways you could accomplish this. I also added the calculation of a remainder (Basically phase - (int)phase). I'm using the remainder for the interpolation. I also added a temporary sine value holder and a delta variable.

    const int sine_table[41] = 
    {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, 0};
    
    int i = 0;
    int x1 = 0;
    int x2 = 0;
    float y = 0;
    
    float sin1(float phase)
    {
        int tsv,delta;
        float rem;
    
        rem = phase - (int)phase;
        x1 = (int) phase % 40;
        x2 = (x1 + 1);
    
        tsv=sine_table[x1];
        delta=sine_table[x2]-tsv;
    
        y = tsv + (int)(rem*delta);
        return y;
    }
    
    int main()
    {
        int i;  
        for(i=0;i<420;i++)
        {
           printf("%.2f, %f\n",0.1*i,sin1(0.1*i)/32768);
        }
        return 0;
    }
    

    The results look pretty good. Comparing the linear approximation vs the system's floating point sine function gave me the error plot shown below.

提交回复
热议问题