Generating a sine wave from an Arduino PWM (Pulse Width Modulation) signal involves varying the duty cycle of the PWM signal to create an average voltage proportional to the desired sine wave. This can be achieved by changing the duty cycle of the PWM signal at a frequency corresponding to the desired sine wave frequency.
After generating the PWM sine wave, it can be filtered using an inductor and capacitor to smooth out the waveform and remove the high-frequency components. The inductor with capacitor acts as a low-pass filter, allowing only the lower frequency components of the PWM signal (i.e., the sine wave) to pass through, while attenuating the higher frequency components. The capacitor further smoothens the waveform by filtering out any remaining high-frequency components and creating a more stable and continuous sine wave output.
The combination of the inductor and capacitor forms an LC filter, which is commonly used in power electronics and signal processing applications to filter out unwanted frequencies and achieve a cleaner and more stable output signal. The values of the inductor and capacitor can be chosen based on the desired cut-off frequency, impedance, and power requirements of the specific application. Careful consideration should be given to the selection of components and their ratings to ensure proper filtering and reliable operation.
The following is Arduino Code that generates PWM signal using TimerOne library.
#include <TimerOne.h>
#define outPin 10
#define delayPin 11 // this pin is just used to test the compute time
const float pi = 3.14159 ;
const float T = 100 ; // sample time in microseconds
const float freq = 1000 ; // frequency of tone in hertz
const float omega = 2*pi*freq ;
const float A = 490 ; // amplitude
// next line initializes oscillation with amplitude A
float a[]={0.0, A*sin(omega*T/1000000.0),0.0};
// c1 is the difference equation coefficient
const float c1 = (8.0 - 2.0*pow(omega*T/1000000.0,2))/(4.0+pow(omega*T/1000000.0,2));
void setup () {
Timer1.initialize(T); // set sample time for discrete tone signal
Timer1.pwm(outPin, 0,T); //generates pwm signal on outPin(9), with 0 duty cycle and sample period of T=100us
Timer1.attachInterrupt(compute); //attachInterrupt(function, period) calls function with optional period
pinMode(delayPin, OUTPUT);
}
void loop() {
}
void compute()
{
digitalWrite(delayPin, HIGH);
a[2] = c1*a[1] - a[0] ; // recursion equation
a[0] = a[1] ;
a[1] = a[2] ;
Timer1.setPwmDuty(outPin, int(a[2])+512);
digitalWrite(delayPin, LOW);
}
The code is an Arduino sketch that generates a discrete tone signal using a TimerOne library for controlling PWM output. The tone signal is generated on a specified output pin (outPin) with a specific frequency (freq), amplitude (A), and sample time (T) in microseconds.
The code initializes the TimerOne library with the sample time (T) and sets up the PWM output on the outPin with a duty cycle of 0. The compute() function is attached as an interrupt to the TimerOne library, which is called periodically with the sample time (T) interval.
The compute() function calculates the next value of the oscillation using a difference equation with a coefficient c1. The calculated value is then used to set the duty cycle of the PWM output on outPin using Timer1.setPwmDuty(). The delayPin is used to test the compute time by toggling its state before and after the computation for measuring the execution time.
Note that the frequency of the tone signal is fixed in this code and set to freq = 1000 Hertz, and the amplitude of the tone signal is initialized with A*sin(omega*T/1000000.0), where omega is the angular frequency calculated as 2*pi*freq, and T is the sample time in microseconds.
After generating the PWM signal we can then use low pass filter to convert the PWM into sine wave. In the above code we have set the frequency to 1KHz and so we design low pass filter with cutoff frequency of 1KHz. The following shows the circuit diagram for generating sine wave with Arduino Uno.
The value of the capacitor C=2.4uF, inductor L=10.56mH were computed using the low pass filter calculator. The following shows the sine wave at the output of the filter.
The following is frequency spectrum of the output of the filter which shows that the signal frequency is 1KHz.
In summary, this code sets up Timer1 to generate a PWM signal with a specified frequency and amplitude, and uses an interrupt service routine to update the PWM duty cycle at a fixed sample time. The compute() function performs the calculations for the next value of the oscillation and updates the PWM duty cycle accordingly. The delayPin is used to measure the compute time for debugging purposes. One can modify the code to vary the frequency and amplitude based on
your requirements, for example, by using a potentiometer to control the
frequency or amplitude dynamically. Here we have used PWM signal but we can also use the CTC mode to generate square wave signal and then use RC low pass filter on Arduino output to generate sine wave which is much easier[1].