Problem with Arduino DUE PWM synchronous mode

Hi i try to devolp a driver for an H bridge to drive a 3 phase motor..

I used the ASF example

"pwm_sync" in order to get 3 pwm signals which are 120 degree phase shifted to each other.

The first two pwm signals which are used by Atmel in the ASF example looks very good on the oscilloscope see and I can generate the signals I need. Please see Attachment Image 1

But once I initialize the third pwm channel I get some kind of strange interference its seems like i have 3 sine wave signals at each pwm output channel. Image Nr. 2 will make this clear for you

/* Initialize PWM channel of 3 */
sync_channel.channel = PIN_PWM_3DPWM_CHANNEL;
pwm_channel_init(PWM, &sync_channel);

please checkl the attachment to get the images and the code

I tried to explain every thing in details if you have any questions please contact me.

Thanks in advance

Code.rar (3.74 MB)

Attachment.pdf (255 KB)

'Scope artifacts?

Show the waveform with the timebase at 100us or so

Mark thanks for your reply

Ni it has nothing with the oscilloscope it ha ssomthing to do with

for (i = 0; i < (120);i++) { 
 g_us_duty_buffer[i * 3] = (sine[(i+80)%120]); 
 g_us_duty_buffer[i * 3 + 1] = (sine[(i+40)%120/2]); 
 g_us_duty_buffer[i * 3 + 2] = (sine[i]);// signal 1

or somthing with the DMA controller ...

I actually dont understand exactly how this for loop works ..

I searched for this thread after realizing your apparent confusion in the thread you started on combining a DIGITAL PWM signal and an ANALOG sine wave. I have two points for this aspect of your problem.

  1. MarkT asked to see the scope waveforms, not because he thought the problem was with the scope, but because actually seeing the problem you were attempting to describe can help diagnose the problem--hence why we use scopes in the first place.

  2. If your third PWM signal is using one of the same counters as the other two PWM phase different signals, that could be the cause of your issue.

Hi thanks for your reply

Here you have a screen shot of my 3 pwm signals

Im now able to get 3 PWM signals with variable duty cycle and frequencys as you can see in image screen shot

my next step is : I want to make add a sine wave array or an equation atnd overlay it to my 3 pwm signals

to get 3 sine waves with a variable duty cycle and frequency each signal must be 120 degree phase shifted to the other one in order to be able to drive a 3 phase motor

As you see in the second image "next step" I already did it before to generate a sine wave through pwm varing of the duty cycle but some how I cant integrate it in this code... I programmed it in that way :

This was my sine wave array

** Sine wave array which will be overlayed to the pwm signals */
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};

and this was how I overlayed it to the s pwm signals

for (i = 0; i < (120);i++) {
		g_us_duty_buffer[i * 3] = (sine[(i+80)%120]);
		g_us_duty_buffer[i * 3 + 1] = (sine[(i+40)%120]);
		g_us_duty_buffer[i * 3 + 2] = (sine[i]);// signal 1
	}

can any one tell me how to integrate it to this code ??
Thanks in advance

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

/** PWM frequency in Hz */
#define PWM_FREQUENCY      5000
/** Period value of PWM output waveform */
#define PERIOD_VALUE       100
/** Initial duty cycle value */
#define INIT_DUTY_VALUE   75




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

/**
 * \brief Interrupt handler for the PWM controller.
 */
void PWM_Handler(void)
{
	static uint32_t ul_count = 0;  /* PWM counter value */
	static uint32_t ul_duty = INIT_DUTY_VALUE;  /* PWM duty cycle rate */
	static uint8_t fade_in = 1;  /* LED fade in flag */
	uint32_t events = pwm_channel_get_interrupt_status(PWM);

	/* Interrupt on PIN_PWM_9_CHANNEL */
	if ((events & (1 << PIN_PWM_2NDPWM_CHANNEL)) ==
			(1 << PIN_PWM_2NDPWM_CHANNEL)) {
		ul_count++;

		/* Fade in/out */
		if (ul_count == (PWM_FREQUENCY / (PERIOD_VALUE - INIT_DUTY_VALUE))) {
			/* Fade in */
			if (fade_in) {
				ul_duty = INIT_DUTY_VALUE;
				if (ul_duty == PERIOD_VALUE) {
					fade_in = 0;
				}
			} else {
				/* Fade out */
				ul_duty = INIT_DUTY_VALUE;
				if (ul_duty == INIT_DUTY_VALUE) {
					fade_in = 1;
				}
			}

			/* Set new duty cycle */
			ul_count = 0;
			g_pwm_channel_instance.channel = PIN_PWM_2NDPWM_CHANNEL;
			pwm_channel_update_duty(PWM, &g_pwm_channel_instance, ul_duty);
			g_pwm_channel_instance.channel = PIN_PWM_1STPWM_CHANNEL;
			pwm_channel_update_duty(PWM, &g_pwm_channel_instance, ul_duty);
			
			g_pwm_channel_instance.channel = PIN_PWM_3DPWM_CHANNEL;
			pwm_channel_update_duty(PWM, &g_pwm_channel_instance, ul_duty);
		}
	}
}





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);// 1st PWM output
	pwm_channel_disable(PWM, PIN_PWM_2NDPWM_CHANNEL);// 2nd PWM output
	pwm_channel_disable(PWM, PIN_PWM_3DPWM_CHANNEL);// 3rd PWM output

	/* 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 disabeld
		.ul_mck = sysclk_get_cpu_hz()
	};
	pwm_init(PWM, &clock_setting);

	/* 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 center-aligned */
	g_pwm_channel_instance.alignment = PWM_ALIGN_LEFT;
	/* Output waveform starts at a high 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);



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



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

	/* Infinite loop */
	while (1) {
	}
}

Last update

I got it now I can generate 3 pwm signals and overlay them to a sine wave array. signals are 120 degree phase shifted to each other

An as you can see it works without any external hardware components to generate a sine wave signal.

Thanks alot for your help guys..I have to devolp the programm after that I will post a library which will enable arduino due users to drive 3 phase ac motor :slight_smile:

Glad its working. BTW have been reading this book recently, I recommend it:

It goes into many ac motor driver strategies at a high level.

@ Mark T thanks I already have many german books about motors

my next step is to modifiy the PWM to get a SVPWM ( Space vector modulated PWM)

Well I understand how it works with the 8 sectors but I cant imagine how to programm it in my code do you have any experience dealing with SVPWM

Can you help me ?

Hi,

Don't know whether you are still on here.

Question: Would you mind to use your code for further studies?

If so, where and how to get the includes from (see below) as they seem not to be part of the Arduino IDE?

Thanks in advance!

Best regards,

Gerhard

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


so3ody:
Hi thanks for your reply

Here you have a screen shot of my 3 pwm signals

Im now able to get 3 PWM signals with variable duty cycle and frequencys as you can see in image screen shot

my next step is : I want to make add a sine wave array or an equation atnd overlay it to my 3 pwm signals

to get 3 sine waves with a variable duty cycle and frequency each signal must be 120 degree phase shifted to the other one in order to be able to drive a 3 phase motor

As you see in the second image "next step" I already did it before to generate a sine wave through pwm varing of the duty cycle but some how I cant integrate it in this code... I programmed it in that way :

This was my sine wave array

** Sine wave array which will be overlayed to the pwm signals */

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};





and this was how I overlayed it to the s pwm signals 


for (i = 0; i < (120);i++) {
g_us_duty_buffer[i * 3] = (sine[(i+80)%120]);
g_us_duty_buffer[i * 3 + 1] = (sine[(i+40)%120]);
g_us_duty_buffer[i * 3 + 2] = (sine[i]);// signal 1
}




can any one tell me how to integrate it to this code ??
Thanks in advance 



Is this the waveforms you are trying to get with 3 synchro Space Vector Modulated PWM ?