So You Want To Make A Sine Wave In Arduino

So a bunch of blog posts back I posted how easy it was to get a square wave out of an arduino to do things with like generate your 600hz tone for CW etc. But we can go 1 further than that and use the arduino to generate sine waves. Of course you can filter the crap out of a 600hz square wave and make a sine, but to be honest, who really wants to wind inductors in the mH range or for that matter build a suitable LC filter to cut out the harmonics sufficiently to make a sine wave. But alas poor Yorick, there is a way and its called PWM.

 

So above we have a 31khz pwm signal that is being used to generate a sine wave. Through the wonders of mathematics and other nerd endeavours that PWM signal can be used to make sine waves, in my case a 600hz sine wave. Now obviously you still need to filter off the crap to see the sine wave, but its there and below is the filtered output. Now the good thing is you can filter with RC filters and make life simple. In my case i am using a 2 pole RC filter using 100nf caps and 2K resistors, and as you can see it looks rather sinusoidal.

So the following software is not mine, its something i found on the net and did some simple modifications to make work with an arduino UNO. Output is from PIN 11. Take a read, you should be able to work out how it works, using interrupts and timers to get some semblance of accuracy. Anyway, enjoy and have fun.

So I have cleaned up the original code to make it easier to read and to remove the stuff in there that was really doing nothing. And here is a link back to the original article. http://interface.khm.de/index.php/lab/interfaces-advanced/arduino-dds-sinewave-generator/

Facebooktwittergoogle_plusredditpinterestlinkedin

2 thoughts on “So You Want To Make A Sine Wave In Arduino

  1. Hello Mr. Powell,
    I would be glad if you could answer a few questions about your project, because I wanted to test it on my Arduino once.

    1.)
    To save myself the manual entry of 255 sine values ​​into an array, I tried to do this with the following code:
    ———————————————————————————————–#include
    #include

    int sinusArray[] = {};

    for (int i = 0; i < 255; i++)
    {
    const int sinusArray[i] PROGMEM = {sin((2*PI*i)/255)};
    }
    ———————————————————————————————–
    As you expect, this does not work for several reasons:
    – You can not change const variables, but variables in flash memory must be const type.
    – You can not release or write to flash memory from a running program, but a for loop can only be used in a running program.

    What are the advantages of saving the sine values ​​in flash memory and not in the RAM or EEPROM ?
    Do you know a way to realize what I wanted to do, or the manual entry is the only possible way ?

    2.)
    In the comments you make some calculations that I can not understand:

    In line 26, you name a "measured" PWM-clock of 31376.6 Hz, but how did you measure it?

    In line 69, you give a calculated value of 31472.55 Hz for the same measure, I assume you calculated it with the formula f (PWM) = f (clk) / (N * 510) from the Atmega8 user manual.
    I have read the whole section in the user manual about the phase correct PWM mode, but there is no reference to the value 510 or where it came from. How does this value of 510 come about?

    In line 72 you call a runtime of 8 milliseconds. Where did you get this value from?
    I did not find anything about runtime computation in the User Guide.

    3.)
    From line 82 to 85, use the following code:
    ———————————————————————————————–
    if(icnt1++ == 125) { // increment variable c4ms all 4 milliseconds
    c4ms++;
    icnt1=0;
    }
    ———————————————————————————————–
    I do not quite understand what this code is for.
    At first I thought it was needed to reset the timer or interrupt, but I actually thought that these would be reset automatically after reaching the count value in the timer register, since the timer is in overflow mode.
    Furthermore, I do not understand how you have calculated the values ​​used (125 and 4 milliseconds).
    Is the 4 milliseconds halfway through 8 milliseconds?
    Are the 125 almost half the cycle time for the array with the 254 sine values?
    Furthermore, I am irritated that the varialbe "icnt1" appears here only once if it is incremented and set to 0, but nowhere else in the program code.

    I apologize for the long text, it would help me if you answered only one of the questions.

    Sincerely,
    Peter Bears

    1. #include
      #include

      int sinusArray[] = {};

      for (int i = 0; i < 255; i++) { int sinusArray[i] = {sin((2*PI*i)/255)}; }

      Take out the const and remove it from progmem and it will compile and run. But you are doing math computations very tick almost and it will put load on the processor. Its easier to just lookup a value from a table and use it.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.