Creation of a sinusoidal wave in arduino leonardo

Hi!
I am trying to create a sine wave with 2V of amplitude and 3V of offset.
This is the code I am using:

const int pwmPin = 6;
const int sinePin = 5;  // Pin de salida para la onda sinusoidal
const float offset = 3.0; // Voltaje de compensación
const float amplitude = 2.0; // Amplitud de la onda sinusoidal

void setup() {
  pinMode(sinePin, OUTPUT);
  pinMode(pwmPin, OUTPUT);
}

void loop() {
  int DutyCycle = 127 ;
   analogWrite(pwmPin, DutyCycle); // depending on the duty cycle

  // Generar una onda sinusoidal directa
  for (int i = 0; i < 360; i++) {
    float sinValue = offset + amplitude * sin(i * PI / 180.0);
    int dutyCycle = map(sinValue, offset - amplitude, offset + amplitude, 0, 255);
    analogWrite(sinePin, dutyCycle);
    delay(4);
  }
}

Keep in mind that I also want to generate a PWM signal.

The output signals I get are the following:

where channel 1 represents the PWM and channel 2 the sinusoidal wave

The following line generates a nice sinewave that ranges in value between 1 and 5 :

float sinValue = offset + amplitude * sin(i * PI / 180.0);

You then use the map( ) function to calculate dutyCycle.
The map( ) function uses integer arithmetic, so you end up with only 5 different values generated for dutyCycle.

Here I have printed the value of 'dutyCycle' out to the serial plotter:

You can get round this problem by changing the offset to 300, and the amplitude to 200.
You then get a nice sinewave again:

1 Like

After using the map() function, the amplitude of the sinewave that the code generates is no longer controlled by your constant 'amplitude'.

Because you mapped the duty cycle to go between 0 and 255, then the output will go down to 0V and up to 5V, giving an amplitude of 5V peak to peak.

To get the amplitude and offset that you require you would have to change your mapping to the following:

int dutyCycle = map(sinValue, offset - amplitude, offset + amplitude, 51, 255);

You will need to pass the sinewave PWM signal through a low pass filter to see it as a sinewave.

Perfect!!! Thanks!! Do you know if there is a way to center the PWM at 0V so that it goes from -2.5V to +2.5V ?

I was going to say the answer is no, because the output can only vary between GND and 5V.

However, I realised that if you put an oscilloscope on to "AC Coupling", then it displays what you just asked for.

So it might be possible to generate a signal that goes from -2.5V to +2.5v by feeding the PWM signal in to a Low Pass Filter, and then feeding the output of the Low Pass Filter in to a High Pass Filter.

The cut-off frequencies of the two filters would need to be carefully set to get good results.

The Low Pass Filter needs to have a cut-off frequency between the original PWM frequency and the desired output frequency.
The High Pass Filter needs to have a cut-off frequency lower than the output frequency.

Maybe an active filter using 2 op-amps would work:
Low Pass Filter & High Pass Filter

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.