Go Down

Topic: Change the Sine wave frequency (Read 11788 times) previous topic - next topic

so3ody

OK mike you aready downloaded my code yesterday I guess

Just copy and pase this in the main.c

Code: [Select]


//################################################################################################################
// **INCLUDE FILES & HEADER DATA****INCLUDE FILES & HEADER DATA****INCLUDE FILES & HEADER DATA**
//################################################################################################################

#include "asf.h"   // ATMEL SOFTWARE  FRAMEWORK
#include "conf_board.h"  // standard Librarey from ASF
#include "conf_clock.h" // Standard Library from ASF
#include "SineArray.h" // Array which contains the sine wave elements

//----------------------------------------------------------------------------------------------------------------




//################################################################################################################
// **Global variables and macros****Global variables and macros****Global variables and macros**
//################################################################################################################




/** PWM frequency in Hz */
#define PWM_FREQUENCY     10000
/** Period value of PWM output waveform */
#define PERIOD_VALUE       4096
/** Initial duty cycle value 0-100 % */
#define INIT_DUTY_VALUE   50

//----------------------------------------------------------------------------------------------------------------

//################################################################################################################
// **GPIO pin definitions for 3 PWM signals****GPIO pin definitions for 3 PWM signals**
//################################################################################################################


/* PIN Definition for the third PWM Channel @ Arduino Due Board = PWM  PIN 07 */
#define PIN_PWM_3DPWM_GPIO     PIO_PC23_IDX
#define PIN_PWM_3DPWM_FLAGS   (PIO_PERIPH_B | PIO_DEFAULT)
#define PIN_PWM_3DPWM_CHANNEL PWM_CHANNEL_6


/* PIN Definition for the second PWM Channel @ Arduino Due Board = PWM  PIN 08 */
#define PIN_PWM_2NDPWM_GPIO     PIO_PC22_IDX
#define PIN_PWM_2NDPWM_FLAGS   (PIO_PERIPH_B | PIO_DEFAULT)
#define PIN_PWM_2NDPWM_CHANNEL PWM_CHANNEL_5


/* PIN Definition for the first PWM Channel @ Arduino Due Board = PWM  PIN 09 */
#define PIN_PWM_1STPWM_GPIO     PIO_PC21_IDX
#define PIN_PWM_1STPWM_FLAGS   (PIO_PERIPH_B | PIO_DEFAULT)
#define PIN_PWM_1STPWM_CHANNEL PWM_CHANNEL_4

//----------------------------------------------------------------------------------------------------------------

/** PWM channel instance  */
pwm_channel_t g_pwm_channel_instance;



//################################################################################################################
// **Interrupt handler for the PWM controller****Interrupt handler for the PWM controller**
//################################################################################################################


void PWM_Handler(void)
{
static uint32_t size; /* Size of the sine array*/
static uint32_t ul_count = 0; /* PWM counter value */
static uint32_t ul_duty1 = INIT_DUTY_VALUE;  /* PWM duty cycle rate */
static uint32_t ul_duty2 = INIT_DUTY_VALUE;  /* PWM duty cycle rate */
static uint32_t ul_duty3 = INIT_DUTY_VALUE;  /* PWM duty cycle rate */
static uint32_t counterIncrement ;

uint32_t events = pwm_channel_get_interrupt_status(PWM);

/* Standard frequency range e.g LENZE VFD 0-300 HZ */
/* Ground sine wave frequency = (PWM_Freq/ Size of sine wave array)
  = 10 000 HZ/ 120 = 83.3 Hz*/


ul_count+=counterIncrement ;
  //ul_count++;



/* to vary the sine wave frequency the  u_count must be re defined due to the desired frequency*/
    //ul_count= ul_count+2 ;


/* to determine the size of the sine array*/
size = sizeof(sine)/2;



if ((ul_count /100) >= size) {
ul_count -= size * 100;

//if (ul_count >= size) {
//ul_count = 0; }
}


/* Overlay a sine wave array to a  PWM signal */
/* each output signal is 120 degree phase shifted to the other one */
ul_duty1 = sine[ul_count/100%size];              // 1st sine wave output 0 degree phase shift
ul_duty2 = sine[(ul_count/100+(size/3)) %size]; // 2nd sine wave output 120 degree phase shift
ul_duty3 = sine[(ul_count/100+(2*size/3))%size];// 3rd sine wave output 240  degree phase shift


/* Set new duty cycle for the 3 pwm signals */

g_pwm_channel_instance.channel = PIN_PWM_1STPWM_CHANNEL;
pwm_channel_update_duty(PWM, &g_pwm_channel_instance, ul_duty1);
g_pwm_channel_instance.channel = PIN_PWM_2NDPWM_CHANNEL;
pwm_channel_update_duty(PWM, &g_pwm_channel_instance, ul_duty2);
g_pwm_channel_instance.channel = PIN_PWM_3DPWM_CHANNEL;
pwm_channel_update_duty(PWM, &g_pwm_channel_instance, ul_duty3);

}



//########################################################################################################
// ******MAIN MENU*************************MAIN MENU*******************************MAIN MENU***************
//########################################################################################################


int main(void)
{
/* Initialize the SAM system */
sysclk_init();
board_init();

/* GPIO Pin configuration */
gpio_configure_pin(PIN_PWM_3DPWM_GPIO, PIN_PWM_3DPWM_FLAGS);  // for PWM PIN 3
gpio_configure_pin(PIN_PWM_2NDPWM_GPIO, PIN_PWM_2NDPWM_FLAGS);  // for PWM PIN 2
gpio_configure_pin(PIN_PWM_1STPWM_GPIO, PIN_PWM_1STPWM_FLAGS);  // for PWM PIN 1

/* Enable PWM peripheral clock */
pmc_enable_periph_clk(ID_PWM);

/* Disable PWM channels */
pwm_channel_disable(PWM, PIN_PWM_1STPWM_CHANNEL); // @ PWM PIN 9
pwm_channel_disable(PWM, PIN_PWM_2NDPWM_CHANNEL);  // @ PWM PIN 8
pwm_channel_disable(PWM, PIN_PWM_3DPWM_CHANNEL);  // @ PWM PIN 7

/* Set PWM clock A as PWM_FREQUENCY*PERIOD_VALUE (clock B is not used) */
pwm_clock_t clock_setting = {
.ul_clka = PWM_FREQUENCY * PERIOD_VALUE,
.ul_clkb = 0, // clock B is disabled
.ul_mck = sysclk_get_cpu_hz()
};
pwm_init(PWM, &clock_setting);


/* Initialize PWM channel for PWM PIN 7 */
/* Period is left-aligned */
g_pwm_channel_instance.alignment = PWM_ALIGN_LEFT;
/* Output waveform starts at a low level */
g_pwm_channel_instance.polarity = PWM_LOW;
/* Use PWM clock A as source clock */
g_pwm_channel_instance.ul_prescaler = PWM_CMR_CPRE_CLKA;
/* Period value of output waveform */
g_pwm_channel_instance.ul_period = PERIOD_VALUE;
/* Duty cycle value of output waveform */
g_pwm_channel_instance.ul_duty = INIT_DUTY_VALUE;
g_pwm_channel_instance.channel = PIN_PWM_3DPWM_CHANNEL;
pwm_channel_init(PWM, &g_pwm_channel_instance);




/* Initialize PWM channel for PWM PIN 8  */
/* Period is left-aligned */
g_pwm_channel_instance.alignment = PWM_ALIGN_LEFT;
/* Output waveform starts at a low level */
g_pwm_channel_instance.polarity = PWM_LOW;
/* Use PWM clock A as source clock */
g_pwm_channel_instance.ul_prescaler = PWM_CMR_CPRE_CLKA;
/* Period value of output waveform */
g_pwm_channel_instance.ul_period = PERIOD_VALUE;
/* Duty cycle value of output waveform */
g_pwm_channel_instance.ul_duty = INIT_DUTY_VALUE;
g_pwm_channel_instance.channel = PIN_PWM_2NDPWM_CHANNEL;
pwm_channel_init(PWM, &g_pwm_channel_instance);

/* Enable channel counter event interrupt */
pwm_channel_enable_interrupt(PWM, PIN_PWM_2NDPWM_CHANNEL, 0);

/* Initialize PWM channel for PWM PIN 9 */
/* Period is left-aligned */
g_pwm_channel_instance.alignment = PWM_ALIGN_LEFT;
/* Output waveform starts at a low level */
g_pwm_channel_instance.polarity = PWM_LOW;
/* Use PWM clock A as source clock */
g_pwm_channel_instance.ul_prescaler = PWM_CMR_CPRE_CLKA;
/* Period value of output waveform */
g_pwm_channel_instance.ul_period = PERIOD_VALUE;
/* Duty cycle value of output waveform */
g_pwm_channel_instance.ul_duty = INIT_DUTY_VALUE;
g_pwm_channel_instance.channel = PIN_PWM_1STPWM_CHANNEL;
pwm_channel_init(PWM, &g_pwm_channel_instance);



/* Disable channel counter event interrupt */
pwm_channel_disable_interrupt(PWM, PIN_PWM_1STPWM_CHANNEL, 0);

/* Configure interrupt and enable PWM interrupt */
NVIC_DisableIRQ(PWM_IRQn);
NVIC_ClearPendingIRQ(PWM_IRQn);
NVIC_SetPriority(PWM_IRQn, 0);
NVIC_EnableIRQ(PWM_IRQn);

/* Enable PWM channels  */
pwm_channel_enable(PWM, PIN_PWM_1STPWM_CHANNEL);  // @ PWM PIN 9
pwm_channel_enable(PWM, PIN_PWM_2NDPWM_CHANNEL); // @ PWM PIN 8
pwm_channel_enable(PWM, PIN_PWM_3DPWM_CHANNEL); //@ PWM PIN 7


//###########################################################################################################
// ******MAIN LOOP*************************MAIN LOOP*******************************MAIN LOOP***************
//###########################################################################################################
while (1) {
}
}

Grumpy_Mike

Quote
It dosent work correctly I always get a wrong frequency when I give
counterIncrement a value of 250 I recive 213 Hz, 100->85 Hz,300->250 Hz

What is wrong with the frequency?
The smaller the increment amount the lower the frequency will be. That seems to be holding.

What are you expecting?

so3ody

yeah it holds but how can I contorl it i mean when I enter 300 I recive 250 Hz actually it should be 300 hz as well or ?

so3ody

WTF

Mike I think that my whole project is wrong..

I thought that  my next step it to generate the SVPWM
http://en.wikipedia.org/wiki/Space_vector_modulation
to be able to vary the output voltage of the pwm signal ( the amplitude) to be able to drive a 3phase ac motor with a vatiable voltage and a variable frequency

This will not work with my code I guess or figured it out today

Grumpy_Mike

Quote
to be able to vary the output voltage of the pwm signal

Yes you have been told on other threads that you can not / do not want to / do not need to do this.

Quote
but how can I contorl it i mean when I enter 300 I recive 250 Hz actually it should be 300 hz as well

No there is no direct collation like that. What is wrong with a look up table to map the two.

There are things you can do to speed up the code like having a multiply factor not of 100 but of a power of two like 256. This means that instead of dividing by 100 you can use the shift operation >> to shift the number 8 places to the right which is much quicker than divide by 256. Also you should pre calculate values that you end up recalculating.
So in this code:-
Code: [Select]
ul_duty1 = sine[ul_count/100%size];              // 1st sine wave output 0 degree phase shift
ul_duty2 = sine[(ul_count/100+(size/3)) %size]; // 2nd sine wave output 120 degree phase shift
ul_duty3 = sine[(ul_count/100+(2*size/3))%size];// 3rd sine wave output 240  degree phase shift

You have a calculation size / 3 calculated twice. Does it change from sample to sample - no so only calculate 'size / 3' and '2* size / 3' once when you calculate size.

so3ody

Quote
Yes you have been told on other threads that you can not / do not want to / do not need to do this.


well I have ben told that but it is wrong

You need a variable voltage in order to control a motor due to the FOC method

You need this SVPWM as i already posted in my last thread


so3ody

Hello Mike thanlks for your tipp with the size/3. I already modified it

So I figured out that I can change the amplitude of my sine wave if i devide one of those 3 lines through a factor
Code: [Select]
/* Overlay a sine wave array to a  PWM signal */
/* each output signal is 120 degree phase shifted to the other one */
ul_duty1 = sine[ul_count/100%size];              // 1st sine wave output 0 degree phase shift
ul_duty2 = sine[(ul_count/100+(size_3)) %size]; // 2nd sine wave output 120 degree phase shift
ul_duty3 = sine[(ul_count/100+(2*size_3/3))%size];// 3rd sine wave output 240  degree phase shift

e.g if i divide
Code: [Select]
ul_duty1 = sine[ul_count/100%size];              // 1st sine wave output 0 degree phase shift through 2
I will get the half of the max amplitude. So I think  I still on the right way devolping my H brdige 3 phase driver
but I still need the phase which is called (omega). Omega is the angle  which tells you in which rotating sector your motor  lies.
Actually I need to tell my software now..e.g sine wave Nr 1 should have e.g. 30 degree omega
http://www.china-power.net/psta/dzkw/212/tu/Cjg2.gif

can I link the two somehow together ? I think with this code it couldnt work or ?

The last modifiucations on my code are attached to this thread
thanks in advance



Grumpy_Mike

You are still dividing by 100 and not doing the shifting type division. This will reduce your overheads a lot.

If it were me I would not use a file for the look up table array but populate it with values you calculate once at the start of run time.
Then you could have two (or more) look up tables for different amplitudes of sin wave and just switch to what ever one you need at the time.

so3ody


Grumpy_Mike

What about it?
I think you are on your own for this.

pjrc

FWIW, ARM Cortex-M3 has a 2-cycle hardware divide instruction for unsigned 32 bit integers.  The compiler is pretty crafty about using divide then subtract to quickly compute integer modulus.  There's little speed benefit to redesigning for a power-of-2 division or modulus.

On 8 bit AVR, integer division is a terribly slow operation, involving a function call to code which loops 32 times, shifting and subtracting (a.k.a. "long division").  When Arduino Zero becomes available, the same will be true, because the Cortex-M0+ lacks hardware divide.

Only the M3 & M4 versions have the fast integer divide instruction.  Arduino Due is based on the Cortex-M3.

Go Up