简体   繁体   中英

sine wave generation in c++

I am trying to generate a set of points, which when plotted as a graph represent a sine wave of 1 cycle. The requirements are :

  • a sine wave of 1 cycle
  • lower limit = 29491
  • upper limit = 36043
  • no of points = 100
  • Amplitude = 3276
  • zero offset = 32767

Code :

int main()
{
    ofstream outfile;
    outfile.open("data.dat",ios::trunc | ios::out);
    for(int i=0;i<100;i++)
    {
        outfile << int(3276*sin(i)+32767) << "\n";
    }
    outfile.close();
    return 0;
}

I am generating and storing the points in a file. When these points are plotted I get the following graph.

在此输入图像描述

But I only need one cycle. How can I do this?

taking into the formula of sine wave :

 y(t) = A * sin(2 * PI * f * t + shift) 

where:

A = the amplitude, the peak deviation of the function from zero.
f = the ordinary frequency, the number of oscillations (cycles)
t = time
shift = phase shift

would be:

y[t] = AMPLITUDE * sin (2 * M_PI * 0.15 * t + 0) + ZERO_OFFSET;
                                   ^^^ f = 15 cycles / NUM_POINTS = 0.15 Hz

To have one full-cycle, loop from y[0:t) where t is the time or number of points it takes to have a full cycle (ie wavelength)

It appears you need 100 samples for one cycle, so you probably need this:

...
#define _USE_MATH_DEFINES
#include <math.h>
...
#define NB_OF_SAMPLES 100
...
  double angle = 0.0;
  for (int i = 0; i < NB_OF_SAMPLES; i++)
  {
    outfile << int(3276 * sin(angle) + 32767) << "\n";
    angle += (2 * M_PI) / NB_OF_SAMPLES;
  }
...

Or better:

#define NB_OF_SAMPLES 100
#define OFFSET        3276
#define AMPLITUDE     32767

...
  double angle = 0.0;
  for (int i = 0; i < NB_OF_SAMPLES; i++)
  {
    outfile << int(AMPLITUDE * sin(angle) + OFFSET) << "\n";
    angle += (2 * M_PI) / NB_OF_SAMPLES;
  }
...

The maths sine function std::sin takes its argument in radians:

arg - value representing angle in radians, of a floating-point or Integral type

If you need 1 cycle and 100 points then, knowing that there are 2pi radians in one cycle, you need something like

double rads;
for(int i=1;i<=100;i++)
{
    rads = 2.0*M_PI*i/100;
    // your expression in terms of std::sin(rads)
}

If, on the off chance your compiler/library doesn't have M_PI out of the box, then look here for flags that should make it available.

One thing that hasn't been touched on is the exact interval that you should generate. If you need the closed interval [0,2pi] then you will need to adjust your step sizes. I've given a half-open interval (0,2pi] and @Michael Walz has given the other half-open interval [0,2pi).

You need to change the for loop to iterate from 0 to 2(pi). That is one cycle for the sine wave. You might also want to change the loop counter to a double instead of integer and increment by 0.1 or something instead. screenshot from WolframAlpha.com

A full cycle consists of 360 degrees. samples needed is 100.
So step size is 3.6

int main()
{
    ofstream outfile;
    outfile.open("data.dat",ios::trunc | ios::out);
    for(int i=0;i<101;i++)
    {
        float rads = M_PI/180;
        outfile << (float)(3276*sin(3.6*i*rads)+32767) << endl;
    }
    outfile.close();
    return 0;
}

If number of samples is 200, then step size if 360/200 = 1.8

int main()
{
    ofstream outfile;
    outfile.open("data.dat",ios::trunc | ios::out);
    for(int i=0;i<201;i++)
    {
        float rads = M_PI/180;
        outfile << (float)(3276*sin(1.8*i*rads)+32767) << endl;
    }
    outfile.close();
    return 0;
}

Output:

在此输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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