generate sinus wave through pwm

Hello, what is the easiest way to produce a sinus signal with Arduino Uno?
Ive read many threads about generating sinusodial waves and often there is mentionend to use pwm with a table for the values of sinus. Can anyone post and example code how to use this exactly? How do I get a sinussignal through pwm? How do I use the table? Ive tried pwm myself with the following code

int LED = 10;
int dur= 100;
int M=10;

void setup()
{
Serial.begin(9600);
pinMode(LED,OUTPUT);
digitalWrite(LED,LOW);
}

void loop()
{
  for(int i=0; i<M; i++)
  {
      if(i <= M/2){
      pwm(i,M-i,dur); //rise LED's brightness from zero to Max.
      }
      else
      {
       pwm(M-i,i,dur); //dim LED to Min.
      }
}
delay(dur);
}

void pwm(int active, int inactive, long duration)
{
  long time = 0;
  while(time < duration)
  {
    digitalWrite(LED,HIGH);
    delay(active);
    time += active;

    digitalWrite(LED,LOW);
    delay(inactive);
    time += inactive;
  }
}

and it seems to work fine to dim an LED to max and to zero again. But I think, this way, Im getting a triangular signal. So I think I need to map my linear signal somehow to a sine. Im open to any (easier) solutions. (Espacially the one’s mentioning a table).
I only want to drive some speakers with about 1Hz to 30Hz. So I need control over the frequency of the sine.

have a look at

if you do a web search for generating sine wave using pwm you will get plenty of links

I did, and most of those examples vary the timers. Is there any modification for my code to generate a sine?
In the end, I want to drive multiple (up to 8 ) speakers simultaneously and Im not sure, if this is possible if the timers are varied like this. Ive read something on "bit-banging pwm" so I can easily modify the frequency.

how many PWM outputs do you require?

if you are driving many PWM outputs have a look at the Texas Instruments TLC5940

https://playground.arduino.cc/Learning/TLC5940

Well, I see that the Arduino Uno has 6 PWM outputs. Those should be enough.

Instead of
pwm(i,M-i,dur);

...you should have
pwm(table_,M-table*, dur);_
_
...where table is your table holding the sin values. To create that, fiddle with Excel.*_

Thanks, I actually did manage that problem now.

#include <math.h>

int LED = 10;
int Dauer = 20;
int M=30;
int prec = 100;
float pi=3.1415926538;

void setup()
{


Serial.begin(9600);
pinMode(LED,OUTPUT);
digitalWrite(LED,LOW);
}



void loop()
{
for(int i=0; i<M; i++)
{
  float wert = prec*sin(i*pi/(2*M));
  int wertnew = (int) wert; 
  if(i <= M/2)
    {  
      pwm(wertnew,prec-wertnew,Dauer);
    }
    else
    {
      pwm(prec-wertnew,wertnew,Dauer);
    }
Serial.print(wert);
Serial.print(",");
  
}
delay(Dauer);
}

void pwm(int active, int inactive, long duration)
{
  long time = 0;
  while(time < duration)
  {
    digitalWrite(LED,HIGH);
    delay(active);
    time += active;

    digitalWrite(LED,LOW);
    delay(inactive);
    time += inactive;
  }
}

I just hat to cope with rounding issues, so I increased the amplitude of the sine, so I wont get just ones and zeros. And I think, Im on the right way.
The output seems to be going into the right direction (I get sth like: I I¯I I¯¯I I¯¯¯I I¯¯I I¯I I).
Can anyone tell me, what I have to do to get the “real” sine on the osci?

http://henrysbench.capnfatz.com/henrys-bench/arduino-projects-tips-and-more/arduino-lm358-op-amp-pwm-to-voltage-converter/

You probably just need to create a M-entry lookup table from round (127.5*(1+sin(i*2*pi/M)), since analogWrite takes 8 bit values.

Sine table…

//----------------------------------------------------
// Sine wave lookup table... unsigned 8bit values
// - keep this in RAM 'cos it's faster
byte sinetable[256]={
   128, 131, 134, 137, 140, 143, 146, 149, 152, 155, 158, 161, 164, 167, 170, 173, 
   176, 179, 182, 185, 187, 190, 193, 195, 198, 201, 203, 206, 208, 210, 213, 215, 
   217, 219, 222, 224, 226, 228, 230, 231, 233, 235, 236, 238, 240, 241, 242, 244, 
   245, 246, 247, 248, 249, 250, 251, 251, 252, 253, 253, 254, 254, 254, 254, 254, 
   255, 254, 254, 254, 254, 254, 253, 253, 252, 251, 251, 250, 249, 248, 247, 246, 
   245, 244, 242, 241, 240, 238, 236, 235, 233, 231, 230, 228, 226, 224, 222, 219, 
   217, 215, 213, 210, 208, 206, 203, 201, 198, 195, 193, 190, 187, 185, 182, 179, 
   176, 173, 170, 167, 164, 161, 158, 155, 152, 149, 146, 143, 140, 137, 134, 131, 
   128, 124, 121, 118, 115, 112, 109, 106, 103, 100, 97, 94, 91, 88, 85, 82, 
   79, 76, 73, 70, 68, 65, 62, 60, 57, 54, 52, 49, 47, 45, 42, 40, 
   38, 36, 33, 31, 29, 27, 25, 24, 22, 20, 19, 17, 15, 14, 13, 11, 
   10, 9, 8, 7, 6, 5, 4, 4, 3, 2, 2, 1, 1, 1, 1, 1, 
   1, 1, 1, 1, 1, 1, 2, 2, 3, 4, 4, 5, 6, 7, 8, 9, 
   10, 11, 13, 14, 15, 17, 19, 20, 22, 24, 25, 27, 29, 31, 33, 36, 
   38, 40, 42, 45, 47, 49, 52, 54, 57, 60, 62, 65, 68, 70, 73, 76, 
   79, 82, 85, 88, 91, 94, 97, 100, 103, 106, 109, 112, 115, 118, 121, 124
};

// for example...
for( int i=0; i<256; i++ ){
  pwmval= sinetable[i];
}

Yours,
TonyWilk

Thank you.
I think, I got it, using the delay function and letting Arduino calculate the Values for sine (and with that the duration for the duty cycle).

Another problem appeared: How can i generate the negative part of the sine?

Bilo123:
Another problem appeared: How can i generate the negative part of the sine?

You don't.
The PWM output, when filtered, approximates: j + k(sin(x)+1) i.e. it is all positive
(where j is some offset from zero volts and k is the peak-to-peak voltage)

For an audio signal which swings +/- about ground, you would 'ac couple' the signal with a capacitor for example.

Yours,
TonyWilk

To generate an alternate sinusoidal signal around 0V from a PWM, you will need an H bridge like the one in this shield: