AnsweredAssumed Answered

PWM to Generate Analog Waveforms

Question asked by nunya bruh on Mar 28, 2016
Latest reply on Mar 31, 2016 by Stano Arendarik

So I found some example code to generate a sine wave from PWM here:

PWM to Generate Analog Waveforms  | mbed

I've modified it so that the duty cycle gets updated according to an analog input, but I was wondering if there was a way I could have the output track an analog input (from an ADC pin)? For example, if I input a sinewave with a specific +peak and -peak amplitude, I want to output the same sinewave after PWM conversion and filtering. I suspect I'd have to modify the for loop but I'm not sure how to go about doing that. Here's what I have so far:


#include "mbed.h"
//Number of dutycycle steps for output wave
#define SINE_STEPS        32
//Frequency of output sine in Hz
#define SINE_OUT_FREQ     1000
//Constants to compute the sine waveform
#define PI                 3.141592f
#define SINE_STEPS_RAD    (2.0f * PI / (float)SINE_STEPS)

//Frequency of Pulse Width Modulated signal in Hz
#define PWM_FREQ          50000

AnalogIn  adc0in(A0);

//Table to generate the sine waveform using dutycycles
float sine_duty[SINE_STEPS];
//PWM pin
PwmOut PwmPin (D13);

//Ticker to update the PWM dutycycle
Ticker pwm_ticker;
//Ticker calls this fucntion to update the PWM dutycycle
void pwm_duty_updater() {
  static int idx=0;

  PwmPin.write(adc0in);  // Set the dutycycle % to next value in array
  idx++;                         // Increment the idx
  if (idx == SINE_STEPS) idx=0;  // Reset the idx when teh end has been reached 


int main() {
  int i;

  // Init the duty cycle array
  for (i=0; i<SINE_STEPS; i++) {
    sine_duty[i] = ( sin(i * SINE_STEPS_RAD) + 1.0f ) / 2.0f;  // convert sine (-1.0 .. +1.0) into dutycycle (0.0 .. 1.0)
  // Set PWM frequency to 200 KHz (period = 5 us)
  PwmPin.period( 1.0f / (float) PWM_FREQ);
  // Init the Ticker to call the dutycyle updater at the required interval
  // The update should be at (SINE_STEPS * SINE_OUT_FREQ)
  pwm_ticker.attach(&pwm_duty_updater, 1.0f / (float)(SINE_STEPS * SINE_OUT_FREQ));