Pages: [1]   Go Down
Author Topic: Problem with Arduino DUE PWM synchronous mode  (Read 740 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Full Member
***
Karma: 1
Posts: 129
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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 (3828.26 KB - downloaded 49 times.)
* Attachment.pdf (254.87 KB - downloaded 41 times.)
Logged

0
Offline Offline
Shannon Member
****
Karma: 207
Posts: 12200
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

'Scope artifacts?

Show the waveform with the timebase at 100us or so
Logged

[ I won't respond to messages, use the forum please ]

Offline Offline
Full Member
***
Karma: 1
Posts: 129
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Mark thanks for your reply


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

Code:
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 ..
Logged

Dallas, Texas
Offline Offline
God Member
*****
Karma: 31
Posts: 887
Old, decrepit curmugeon
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

New true random number library available at: http://code.google.com/p/avr-hardware-random-number-generation/

Current version 1.0.1

Offline Offline
Full Member
***
Karma: 1
Posts: 129
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Code:


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




* screenshot.png (36.8 KB, 1024x768 - viewed 10 times.)

* next step.png (77.11 KB, 1024x768 - viewed 9 times.)
Logged

Offline Offline
Full Member
***
Karma: 1
Posts: 129
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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  smiley



* tek00007.png (72.25 KB, 1024x768 - viewed 9 times.)
Logged

0
Offline Offline
Shannon Member
****
Karma: 207
Posts: 12200
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

http://www.amazon.co.uk/Electric-Motors-Drives-Austin-Hughes/dp/0080983324/ref=sr_1_1?s=books&ie=UTF8&qid=1401268212&sr=1-1&keywords=electric+motors+and+drives

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

[ I won't respond to messages, use the forum please ]

Offline Offline
Full Member
***
Karma: 1
Posts: 129
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

@ 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 ?
Logged

Pages: [1]   Go Up
Jump to: