Change the Sine wave frequency

Mike I already posted the changes and

Where?
I can see no evidence of any changes to the main.c file

Hi I changed following

line 107

static uint32_t counterIncrement ;

line 116

I replaced ul_count ++

with ul_count+=counterIncrement ;

Line 130,131

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

replaced with

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

Neuer Ordner.rar (3.96 MB)

Hi I changed following....

You did on that new code you posted but not on the last code you posted. Are you jerking me about?

You have not changed lines 140, 141, 142 like I told you to:-

When you come to use ul_count as an index to your lookup table you actually use ul_count divided by 100.

Hi Mike thanks for your reply and help I really appreciate it :slight_smile:
No im not jerking about you. I just had to modifiy the code again from my home pc. cause im not at the college any more !

I modified the last issue line 140-142 which I forgot

I cant test it now cause I dont have my arduino board at home and no osciloscope but I will let you tomorrow know it if works or not thanks alot again

...... which I forgot

Which is why I asked to see your code.

Also you have:-
static uint32_t counterIncrement ;
But you have not defined it to be any value!

OK,
Just realised that in one piece I assumed the value in the counter was 10 times more that the increment, but I think we are working on 100 times so that code should be:-

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

Thanks mike I insert the counterIncrement with many vlaues like 100,200 aand 250

I will tell you tomorrow if it will work

Thanks alot :slight_smile:

Morning Mike

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

I modified everything as you said

Please check line

107
116
130,131
140,141,142

I attached the modified code
PS Do I have to change or modifiy the sine array ?
thanks in advance

code.rar (3.97 MB)

4MB of attached code?
Get real.

OK mike you aready downloaded my code yesterday I guess

Just copy and pase this in the main.c

//################################################################################################################
// **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) {
	}
}

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?

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 ?

WTF

Mike I think that my whole project is wrong..

I thought that my next step it to generate the SVPWM

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

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.

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:-

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.

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

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

/* 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 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

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

Main.c (10.3 KB)

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.

Hi Mike and what about omega

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

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.