Go Down

Topic: SOLVED How to generate SINE PWM SOLVED (Read 66191 times) previous topic - next topic

so3ody


so3ody

So this is my code for the sine pwm wave
Code: [Select]


// SINUS Signal über DAC an PWM Pin ausgeben


//1kHz
int sine[] = {2048,2305,2557,2802,3034,3251,3449,3625,3777,3901,3995,4059,4092,4092,4060,3996,3902,3778,3628,3452,3254,3037,2805,2560,2308,2051,1795,1542,1297,1065,847,649,473,321,197,102,37,4,4,35,99,193,316,466,642,839,1056,1288,1533,1785,2041};

// the setup routine runs once when you press reset:
void setup() {               
  // initialize the digital pin as an output.
// pinMode(led, OUTPUT);   
  pinMode(2, OUTPUT); 
  pinMode(9, OUTPUT); 
}

// the loop routine runs over and over again forever:
void loop() {
  for(int i = 0; i<50;i++){
      if(sine[i]>4095) {
         sine[i]=4095;
    //     digitalWrite(led, LOW);
     }
    analogWriteResolution(12);
    analogWrite(2, sine[i]);
      analogWrite(9, sine[i]);
   
   //( delayMicroseconds(14);
   
   delay(10);
  }
}


And those are the  scrren shot images  the first one is the pwm signal, the second one is the filterd pwm signal



my question is how to get a 120 degree phase shift between the pwm signals ?

Grumpy_Mike

Quote
how to get a 120 degree phase shift between the pwm signals

You need to access the second wave with an index that is one third further into the wave table than the first.
The best thing is if you have another variable for the second waves index that initially you start one third the way along then increment it each time in the loop and make sure it wraps round when it exceeds the table's length, sort of like this:-
Code: [Select]

// at the start of the loop function
static int k = tableLength /3;
// then later on when it comes to outputting the waveform
      analogWrite(2, sine[i]); // for your original wave
    k++;
  if(k > tableLength) k=0;
      analogWrite(9, sine[k]); // for the 120 degree shifted wave

so3ody

@ Grumpy_Mike Thanks for you reply..

Quote

// at the start of the loop function
static int k = tableLength /3;
// then later on when it comes to outputting the waveform
      analogWrite(2, sine); // for your original wave
    k++;
  if(k > tableLength) k=0;
      analogWrite(9, sine[k]); // for the 120 degree shifted wave




Questions:
What do you actually mean with table length? Do you mean the number of the values of my sine look up table ?

The second question is can I actually apply your tipp to get not only 2 sognals in phase but three ?

My aim actually is to control an asynchrons motor

Grumpy_Mike

Quote
What do you actually mean with table length? Do you mean the number of the values of my sine look up table ?

Yes.
And yes, two thirds along.

You might want to have the number of samples in the table divisable by three.

so3ody

#35
Mar 18, 2014, 11:45 pm Last Edit: Mar 19, 2014, 12:05 am by so3ody Reason: 1
@ Grimpy_Mike

Thanks for your reply.

So I modified my code to get 120 degree phase shift between each of the three signals

Here is my code firestly
Code: [Select]



// SINUS Signal über DAC an PWM Pin ausgeben


//1kHz

int sine[] = {2048,2305,2557,2802,3034,3251,3449,3625,3777,3901,3995,4059,4092,4092,4060,3996,3902,3778,3628,3452,3254,3037,2805,2560,2308,2051,1795,1542,1297,1065,847,649,473,321,197,102,37,4,4,35,99,193,316,466,642,839,1056,1288,1533,1785,2041};
static int k = 50/3; //length of the sine table =51
static int j= 33; //(2/3)*50 length of the sine table

// the setup routine runs once when you press reset:
void setup() {  


 // initialize the digital pin as an output.
// pinMode(led, OUTPUT);  
 pinMode(2, OUTPUT);  //Phase 1
 pinMode(9, OUTPUT);  //Phase 2
 pinMode(12,OUTPUT);  //Phase 3
}

// the loop routine runs over and over again forever:
void loop() {
 

 for(int i = 0; i<50;i++){
     if(sine[i]>4095) {
        sine[i]=4095;
   //     digitalWrite(led, LOW);
    }
   analogWriteResolution(12);
   analogWrite(2, sine[i]); // original wave
 
  k++;
 if(k>51) k=0;
 
  analogWrite(9,sine[k]);//   for the 120 degree shifted wave
 
 
  j++;
  if(j>51) j=0 ;
  analogWrite(12,sine[j]);//   for the 240 degree shifted wave for the third wave
     
  //( delayMicroseconds(14);
 
  delay(10);
 }
}


Questions :

1:I didnt find an Arduino name to measure the length of an array like getlength() or so. So I wrote the array length per hand
2: I applied your  
Code: [Select]
  k++;
 if(k>51) k=0;
But I dont  know if it is true..

3: This is the output of my three signals. But I cant recognize any phase shift. Where is my failure ?
See pdf  :)

Im really glad for your help

Grumpy_Mike

#36
Mar 19, 2014, 12:06 am Last Edit: Mar 19, 2014, 12:08 am by Grumpy_Mike Reason: 1
You have to look at the signals on a two or four channel scope to see the phase shift.
Or use the externals trigger on one signal and look at the other two in turn.

so3ody

@Grumpy_Mike

Thanks

Do you think that my code modification cause of the phase shift is right ?

Im not sure

What do you think ?

pjrc

You have a 2 channel scope.  Use the 2nd channel to look at one of the 2 other waveforms, while still showing the 1st waveform.

so3ody

Hi here are some screen shots
The first signal is the orignial one
The second signal is the one which should be 120 degree phase shifted



Grumpy_Mike

I looks right but why not look at the filtered signals so you can see the sin waves.

so3ody

#41
Mar 19, 2014, 02:51 pm Last Edit: Mar 19, 2014, 03:05 pm by so3ody Reason: 1
@Grumpy_Mike

So here is a screen shot of my three sine waves


Grumpy_Mike

Looks good.
Now you can reduce the noise by doing one or more of the following:-
1) get a better filter or change it's cut of frequency.
2) Increases the PWM frequency so that it is further down the filter's responce

so3ody

Hi
Grumpy_Mike

The filter is not that important cause I will actually uses the signals to drive an H bridge. This means I will actually filter the output of my H bridge to get a sine wave to drive my motor later..

I still have a problem with the sine wave frequency.

I actually have two frequencies  the first one is the pwm. I can variy it without any problems
The second one is the Sine wave frequency ..I can just vary at the moment with a delay order...do you think I can make it in a better way ?

Here is my code comented
Code: [Select]

#include "pwm01.h"



int sine[] = {2048,2305,2557,2802,3034,3251,3449,3625,3777,3901,3995,4059,4092,4092,4060,3996,3902,3778,3628,3452,3254,3037,2805,2560,2308,2051,1795,1542,1297,1065,847,649,473,321,197,102,37,4,4,35,99,193,316,466,642,839,1056,1288,1533,1785,2041};

static int k = sizeof(sine)/sizeof(int)/3; //length of the sine table =51
static int j= k*2; //(2/3)*50 length of the sine table
//static int test= sizeof(sine)/sizeof(int) ;



void setup()
{
    uint32_t  pwm_duty =0.75* 65535;//2^16=65536
    uint32_t  pwm_freq2 = 5000;

    // Set PWM Resolution
    pwm_set_resolution(16); 

    // Setup PWM Once (Up to two unique frequencies allowed
    //-----------------------------------------------------   

    pwm_setup( 7, pwm_freq2, 2);  // Pin 7 freq set to "pwm_freq2" on clock B
    pwm_setup( 8, pwm_freq2, 2);  // Pin 8 freq set to "pwm_freq2" on clock B
    pwm_setup( 9, pwm_freq2, 2);  // Pin 9 freq set to "pwm_freq2" on clock B
     
    // Write PWM Duty Cycle Anytime After PWM Setup
    //-----------------------------------------------------   
   // pwm_write_duty( 7, pwm_duty );  // 75% duty cycle on Pin 7


   // delay(30000);  // 30sec Delay; PWM signal will still stream
       
    // Force PWM Stop On All Pins
    //-----------------------------   

/* pwm_stop( 6 );
    pwm_stop( 7 );
    pwm_stop( 8 );
    pwm_stop( 9 );*/
}

void loop()

  while(1){
   for(int i = 0; i<50;i++){
    pwm_write_duty( 7, sine[i]*16 );  // 16 is a factor to improve the resoultion of the sine wave
    pwm_write_duty( 8, sine[(i+k)%51]*16);  // 75% duty cycle on Pin 8
    pwm_write_duty( 9, sine[(i+j)%51]*16 );  // 75% duty cycle on Pin 9
   
    delay(5); // The sine wave frequency is determinded in this way Sine index = 51*10 milli seconds delay= 510, Frequncy=1/510
   
     }
     }
 
}



Grumpy_Mike

Quote
I can just vary at the moment with a delay order

You can change it also by having more or fewer samples in your code.

Quote
this means I will actually filter the output of my H bridge to get a sine wave to drive my motor later.

What sort of current have you got there? You will struggle to get a capacitor that will handle a lot of ripple current.


Go Up