Change the Sine wave frequency

Modified thread " now its posted in thr right way I guess "

I try to generate a sine wave through vaaring the PWM duty cycle. IT works so far

I have a fixed PWM frequency of 10 KHz and I tried to cary the sine wave frequency in the ISR throught counting each second item from the sine array--> this will result a doppel frequency

counting each 4th item of the sine aeeay will result a ground frequency*4

This method is not so good cause I cant really have a fractions

The only part I need to change now to vary the frequency is this one

/* 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++;
			/* to vary the sine wave frequency the  u_count must be re defined due to the desired frequency*/
		//ul_count= ul_count+2 ;

Can anyone tell me how to make it in another way to change thefrequency not only in 2,4,6,8 way ?

Thanks in advance this is my code
Code:

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

#include "asf.h" // ATMEL SOFTWARE  FRAMEWORK
#include "conf_board.h" 
#include "conf_clock.h"
#include "SineArray.h"

//##############################################################################################
// **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 */
#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 */
	
	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++;
			/* 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 >= 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%size];//  // 1st sine wave output 0 degree phase shift
				ul_duty2 = sine[(ul_count+(size/3)) %size]; // 2nd sine wave output 120 degree phase shift
				ul_duty3 = sine[(ul_count+(2*size/3))%size];// 3rd sine wave output 240  degree phase shift 
			/* Set new duty cycle */
				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) {
	}
}

i see you ditched the arduino analogWrite() and so on.. congrats. i'm also using less and less of that.

if you want something else as 2,4,6,8, etc (integers) try looking up "fixed point arithmetic". just reserve a couple of bits behind the comma. Introduction to Fixed Point Number Representation this may be a nice place to start..

You have 98 posts and still do not know how to post code.
Post it correctly by modifying your post and I will tell you how to do it.

@ Grumpy Mike so I changed it now

earx:
i see you ditched the arduino analogWrite() and so on.. congrats. i'm also using less and less of that.

if you want something else as 2,4,6,8, etc (integers) try looking up "fixed point arithmetic". just reserve a couple of bits behind the comma. Introduction to Fixed Point Number Representation this may be a nice place to start..

Hi yes In try to get rid of Arduino commands at least for this apllication.

Thanks for your hint about the fixed point.

SO shallI make my sine array with a fixed point or ?

Can you please tell me what do i have to change in my code ? its commented in a good way I guess

You have ul_count++ incrementing the count through the look up table.
Instead of this you have something like :-

ul_count += countIncrement;

Where count increment can be 100 times the amount you need. So for 2 times the frequency countIncrement is 200 for 4 times the frequency countIncrement is 400 and for 2.5 times the frequency countIncrement is 250, and so on.

When you come to use ul_count as an index to your lookup table you actually use ul_count divided by 100.
Also when you wrap round, that is ul_count becomes greater than your maximum index you subtract the range of your indexes from ul_count rather than just setting them to zero. This way you keep the fractional part of the count.


I have described this in terms of base 10. For an increase in speed have this in terms of a byte. In other words the ul_count will be divided by 256, which is simply a shift to the right 8 times, and the countIncrement is 256 times the frequency you want. It is exactly the same idea but the division and wrap round is easier.

@ Mike thanks for your reply but it dosent work

I recive no signal anymore .. see screenshot

Would you please modifiy the stuff you described before ? I think I didnt understand it in a right way this is why it dosent work
Thanks in advance

I plan after everything works to post the project in this forum Hardware and software.. it will be then easier for everyone to use arduino due to drive a H bridge driver

but it dosent work

Then you haven't done it right.
please post what you have done.

Hi Mike
I just replaced

ul_count ++;

with

ul_count += countIncrement;

and gave counterIncrement a value
I think that I didnt understand your explenation

I think that I didnt understand your explenation

Well at least you understood that much.

So let's take it one step at a time then:-

  1. What value have you set countIncrement to be?

  2. When you come to use ul_count as an index to your lookup table you actually use ul_count divided by 100. Have you done that? if not ask what you don't understand about it.

  3. when you wrap round, that is ul_count becomes greater than your maximum index you subtract the range of your indexes from ul_count rather than just setting them to zero.
    Have you done that? Again if not ask about what you do not understand.

Hello

  1. What value have you set countIncrement to be?

I set 400,250 and 300 as test values to counterIncrement

  1. When you come to use ul_count as an index to your lookup table you actually use ul_count divided by 100. Have you done that? if not ask what you don't understand about it.

Yes I divided my variable ul_count/100

  1. when you wrap round, that is ul_count becomes greater than your maximum index you subtract the range of your indexes from ul_count rather than just setting them to zero.
    Have you done that? Again if not ask about what you do not understand.

No Ididnt cause I dont understand it and dont know how to reialize it in a c code

Thanks in advance

Can anyone tell me how to make it in another way to change thefrequency not only in 2,4,6,8 way

Google "phase accumulator"

AWOL:
Google "phase accumulator"

Yes that is what I am trying to implement with him.

  1. when you wrap round, that is ul_count becomes greater than your maximum index you subtract the range of your indexes from ul_count rather than just setting them to zero.

Currently you have:-

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

In your new code you should have:-

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

Next as you do not seem to know very much about what you are doing you must post ALL your code so far. That includes attaching any files you have included like the look up table.
That is real Arduino code not the rubbish you posted at the start of this thread.

Hi Mike
thanks for your reply this the sine array which I didint post the the beginning

/*
 * SineArray1.h
 *
 * Created: 26.05.2014 13:25:56
 *  Author: Administrator
 */ 


#ifndef SINEARRAY_H_
#define SINEARRAY_H_

 

/** Sine wave array which will be overlayed to the pwm signals */
// The size of the sine array is 120
uint16_t sine[] = { 0x7ff, 0x86a, 0x8d5, 0x93f, 0x9a9, 0xa11, 0xa78, 0xadd, 0xb40, 0xba1,
	0xbff, 0xc5a, 0xcb2, 0xd08, 0xd59, 0xda7, 0xdf1, 0xe36, 0xe77, 0xeb4,
	0xeec, 0xf1f, 0xf4d, 0xf77, 0xf9a, 0xfb9, 0xfd2, 0xfe5, 0xff3, 0xffc,
	0xfff, 0xffc, 0xff3, 0xfe5, 0xfd2, 0xfb9, 0xf9a, 0xf77, 0xf4d, 0xf1f,
	0xeec, 0xeb4, 0xe77, 0xe36, 0xdf1, 0xda7, 0xd59, 0xd08, 0xcb2, 0xc5a,
	0xbff, 0xba1, 0xb40, 0xadd, 0xa78, 0xa11, 0x9a9, 0x93f, 0x8d5, 0x86a,
	0x7ff, 0x794, 0x729, 0x6bf, 0x655, 0x5ed, 0x586, 0x521, 0x4be, 0x45d,
	0x3ff, 0x3a4, 0x34c, 0x2f6, 0x2a5, 0x257, 0x20d, 0x1c8, 0x187, 0x14a,
	0x112, 0xdf, 0xb1, 0x87, 0x64, 0x45, 0x2c, 0x19, 0xb, 0x2,
	0x0, 0x2, 0xb, 0x19, 0x2c, 0x45, 0x64, 0x87, 0xb1, 0xdf,
	0x112, 0x14a, 0x187, 0x1c8, 0x20d, 0x257, 0x2a5, 0x2f6, 0x34c, 0x3a4,
0x3ff, 0x45d, 0x4be, 0x521, 0x586, 0x5ed, 0x655, 0x6bf, 0x729, 0x794};


#endif /* SINEARRAY1_H_ */

And the rest of the arduino code?
That you posted at the start had no setup or loop functions defined?

Mike thats all what I have

so3ody:
Mike thats all what I have

No you have been making changes to the code so I would like at least to see the changes.

If I put that code into the arduino IDE it will not compile.
I have not got the files:-
"asf.h"
"conf_board.h"
"conf_clock.h"
There is also no setup or loop functions. Arduino IDE code will not compile without those.

Have you actually been trying to write any code or are you just trawling round the internet at random grabbing code with absolutely no idea of what is going on and getting mugs to try and modify it to what you want?

Ah now I know what you mean :slight_smile:

yes im trying to write the code.. as you can see
but I have problems cause im new in programming microcontroller

code.rar (3.97 MB)

Mike It dindt work

So this is what I modified

I added a new variable

 static uint_32t counterIncrement ;

then I replaced

ul_count++;

with

ul_count+=counterIncrement

and then

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

with

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

I just recive nonsence

can you tell me whats wrong ? Thankls in advance

// The size of the sine array is 120Phase accumulators are much easier to implement if the table size is an integer power of two in length.
log2 (120) is not an integer.