CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

PWM center-alignment

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
jpos99



Joined: 10 Aug 2012
Posts: 14

View user's profile Send private message

PWM center-alignment
PostPosted: Mon May 20, 2013 11:08 am     Reply with quote

Hello everyone,

I'm trying to generate 4 pwm signal to control a H-bridge, but I want them to be center alignment to create a dead time to the bridge output by making the time of one of the igbt a bit longer, so it can desaturate the transformer that I have on the output of the bridge.

So far I can put a PWM in complementary mode working fine with an analog input to change my duty-cycle.

Code:

#include <18f4431.h>
#device *=16
#device adc=10
#fuses INTRC_IO, NOWDT, NOLVP, BROWNOUT
#use delay(clock=8M)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)

void main()
{
   int freq;
   long int adc_val, period;
   
   freq = 10000;

   period = ((2000000/freq)-1)/4;  // having problems here not doing the correct math :)


   setup_power_pwm_pins(PWM_COMPLEMENTARY,PWM_OFF,PWM_OFF,PWM_OFF);
   //PPWM channels 0 and 1 are both on and always opposite values
   setup_power_pwm(PWM_CLOCK_DIV_4|PWM_FREE_RUN,1,0,period,0,1,12);
   //add dead time for reactive loads

   setup_adc_ports(sAN0);   
   setup_adc(ADC_CLOCK_INTERNAL | ADC_CONT_A | ADC_WHEN_PPWM);
   set_adc_channel(0);

   while(true)
   {
      delay_us(10);
      adc_val = read_adc();         
      set_power_pwm0_duty(adc_val*9);
                              
   }
}



|-----------|
1.............2
|--o1 o2--|
3.............4
|-----------|



What I want to do is:
-Turn on 1 and 4
-1/2 Period
-Turn off 1
-Delay 1us for example
-Turn off 4
-Dead time
-Turn on 2 and 3
-1/2 Period
-Turn off 3
-Delay 1us for example
-Turn off 2
-Dead time

Repeat this cycle.

What I can't implement is the center alignment in the CCS code or must I go to ASM to configure the bytes one by one?

This is the new code I'm doing but no signal on the oscilloscope, The signal is 25kHz 50 duty for now.

Code:

#include <18f4431.h>
#device *=16
#device adc=10
#fuses INTRC_IO, NOWDT, NOLVP, BROWNOUT
#use delay(clock=4M)

#byte PTCON0   =0xF7F
#byte PTCON1   =0xF7E
#byte PWMCON0   =0xF6F
#byte PWMCON1   =0xF6E
#byte DTCON      =0xF6D
#byte OVDCOND   =0xF6B
#byte OVDCONS   =0xF6A
#byte FLTCONFIG =0xF6C
#byte PTMRH      =0xF7C
#byte PTMRL      =0xF7D
#byte PTPERL   =0xF7B
#byte PTPERH   =0xF7A
#byte TRISB      =0xF93

void main(){

TRISB       =0;
PTCON0      =0b00000100;
PTCON1      =0b11000000;
PWMCON0      =0b00110011;
PWMCON1      =0b00000001;
OVDCOND      =0b00001111;
OVDCONS      =0b00000000;
FLTCONFIG    =0b00000000;

while (true){

PTMRH    = 0b00001000;   
PTMRL    = 0b00110111;
PTPERL    = 0b11111111;
PTPERH    = 0b00001111;
DTCON   = 0b00001101;

}
}


The duty-cycle I don't understand how to code it.

I'm using a PIC18F4431 and CCS compiler 4.093.

Thanks to you all.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon May 20, 2013 11:59 am     Reply with quote

Quote:
void main(){

TRISB =0;
PTCON0 =0b00000100;
PTCON1 =0b11000000;
PWMCON0 =0b00110011;
PWMCON1 =0b00000001;
OVDCOND =0b00001111;
OVDCONS =0b00000000;
FLTCONFIG =0b00000000;

In PTCON0, you have both of the bottom bits (PTMOD1 and PTMOD0)
set = 0. The data sheet says that setting those bits to 00 will enable
Free Running mode:
Quote:

bit 1-0 PTMOD<1:0>: PWM Time Base Mode Select bits

11 = PWM time base operates in a Continuous Up/Down Count mode with interrupts for double PWM
updates
10 = PWM time base operates in a Continuous Up/Down Count mode
01 = PWM time base configured for Single-Shot mode
00 = PWM time base operates in a Free-Running mode



The 18F4431 data sheet says on page 177:
Quote:
The Continuous Up/Down Count modes
produce center-aligned PWM generation.


This means you should set those two bits to either 11 or 10.

If you set the bits to 11, there are some erratas on it:
http://ww1.microchip.com/downloads/en/DeviceDoc/80192c.pdf
It's probably best if you use the 10 setting.
jpos99



Joined: 10 Aug 2012
Posts: 14

View user's profile Send private message

PostPosted: Mon May 20, 2013 4:21 pm     Reply with quote

Thank you PCM Programmer

I've tried the change that you mentioned but still no signal.
Is the rest correct. The period is well configured, because I've had some difficulties on understanding the "Time base" and "Period".

Can I with the CCS configure these signals? (Meaning can I use the setup_power_pwm(...))

Thanks again.

Tomorrow I will run more tests.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue May 21, 2013 1:24 am     Reply with quote

I got center-aligned PWM working with compiler vs. 4.141. I didn't try it
with any other version yet. To see it working, put your Channel 1
scope probe on Pin D7 and sync on that channel. Then put your Ch.2
probe on pin B0, or on pin B1. Channel 1 shows, roughly, the PWM
Timer status. You're looking at the PWM "cell" or time period.

Then when you look at pins B0 and B1 (which are complements of each
other, because we're running the PWM in Complementary mode) you
will see that when the duty cycle changes, it changes equally on both
sides of the PWM pulse. This demonstrates it is running in center-aligned
mode. If it was in normal "Free Run" mode, only one side of the pulse
would move when the duty cycle is changed.
Code:

#include <18F4431.h>
#fuses HS,NOWDT,PUT,BROWNOUT,NOLVP
#use delay(clock=20M)

// Note: The following numbers work with a 20 MHz oscillator frequency.
#define POWER_PWM_PERIOD 249  // Gives 10 KHz pwm freq with PWM_CLK_DIV_4
#define DEAD_TIME  2    // Gives dead time of 1.6 usec


// In the Up/Down Counting mode (Center-Aligned mode)
// an interrupt occurs each time the value of the PTMR
// register becomes zero and the PWM time base begins
// to count upwards.
//
// The PWMTB interrupt latency and interrupt handler
// overhead are at least 6 usec (at 20 MHz), so you
// see an edge on Pin D7 at least 6 usec after the
// middle of the center-aligned pulse.  The purpose
// of this interrupt is so you can sync on Pin D7
// with your scope, and then look at the PWM output
// on pins B0 and B1.  You can then see the PWM
// pulses expand or contract equally on both sides
// of the pulse as it switches between 40% and 60%
// duty cycle.  This shows that it's doing center-
// aligned PWM.
#int_pwmtb
void pwmtb_isr(void)
{
output_toggle(PIN_D7);     
}

//=======================================
void main()
{
// Setup PWM0 and PWM1 pins as complementary PWM outputs.
// All other PWM pins are configured as OFF (not used).
setup_power_pwm_pins(PWM_COMPLEMENTARY, 0, 0, 0);

// Mode = Up/Down Count 
// Postscale = 1   (1-16) Timebase output postscaler
// TimeBase = 0    (0-65355) Initial value of PWM Timebase
// Period = 249    (0-4095) Max value of PWM TimeBase
// Compare = 0     (Timebase value for special event trigger)
// Compare Postscale = 1 (Postscaler for Compare value)
// Dead Time = 2
setup_power_pwm(PWM_UP_DOWN | PWM_CLOCK_DIV_4 |  PWM_DEAD_CLOCK_DIV_16, 1, 0, POWER_PWM_PERIOD, 0, 1, DEAD_TIME);

// Enable PWM Timebase interrupts.
clear_interrupt(INT_PWMTB); 
enable_interrupts(INT_PWMTB); 
enable_interrupts(GLOBAL); 

// Change the duty cycle every 1/2 second, as a demonstration.
while(1)
  {
   // The last value in this line gives a 40% duty cycle.   
   set_power_pwm0_duty((int16)((POWER_PWM_PERIOD *4) * .4));
   delay_ms(500);

   // The last value in this line gives a 60% duty cycle.   
   set_power_pwm0_duty((int16)((POWER_PWM_PERIOD *4) * .6));
   delay_ms(500);
  }

}
jpos99



Joined: 10 Aug 2012
Posts: 14

View user's profile Send private message

PostPosted: Thu May 23, 2013 7:47 am     Reply with quote

Thanks again PCM Programmer,

The code that you post works fine Very Happy and I've made some changes.

Code:

#include <18F4431.h>
#fuses INTRC_IO,NOWDT,PUT,BROWNOUT,NOLVP
#use delay(clock=8M)

// Note: The following numbers work with a 8 MHz oscillator frequency.
#define POWER_PWM_PERIOD 40  // Gives 25 KHz pwm freq with PWM_CLK_DIV_4
//#define DEAD_TIME  8   


void main()
{
float adc_val;
// Setup pins as ODD ON PWM outputs.

setup_power_pwm_pins(PWM_ODD_ON, PWM_ODD_ON, PWM_ODD_ON, PWM_ODD_ON);

// Mode = Up/Down Count
// Postscale = 1   (1-16) Timebase output postscaler
// TimeBase = 0    (0-65355) Initial value of PWM Timebase
// Period = 40    (0-4095) Max value of PWM TimeBase
// Compare = 0     (Timebase value for special event trigger)
// Compare Postscale = 1 (Postscaler for Compare value)
// Dead Time
setup_power_pwm(PWM_UP_DOWN | PWM_CLOCK_DIV_4 |  PWM_DEAD_CLOCK_DIV_2, 1, 0, POWER_PWM_PERIOD, 0, 1, 0);

// Enable PWM Timebase interrupts.
//clear_interrupt(INT_PWMTB);
//enable_interrupts(INT_PWMTB);
//enable_interrupts(GLOBAL);

setup_adc_ports(sAN0);   //continuously sample and sync with PPWM
setup_adc(ADC_CLOCK_INTERNAL | ADC_CONT_A | ADC_WHEN_PPWM);
set_adc_channel(0);

// Change the duty cycle every 1/2 second, as a demonstration.
while(1)
  {
   delay_us(1);
   adc_val = read_adc();

   // The last value in this line gives a variable duty cycle given by a analog signal.   
   set_power_pwm0_duty((int16)((POWER_PWM_PERIOD *4) * (adc_val/255)));
   set_power_pwm2_duty((int16)((POWER_PWM_PERIOD *4) * (adc_val/255)));
   set_power_pwm4_duty((int16)((POWER_PWM_PERIOD *4) * (adc_val/240)));
   set_power_pwm6_duty((int16)((POWER_PWM_PERIOD *4) * (adc_val/240)));

  }
}


With this I have 4 PWM signal and 2 of them are +/- 500ns longer and center align.

But now I've realized that this is not quite what I was after Question.
I need to have 2 PWM signals with the same frequency but they are delayed T/2. As the code but one of the signals just happens half a period later with the same duty cycle.
Can I use the trigger to go to a interrupt and execute another pwm signal? This said do I have to setup another power pwm?

Thanks to all.
jpos99



Joined: 10 Aug 2012
Posts: 14

View user's profile Send private message

PostPosted: Thu May 23, 2013 10:51 am     Reply with quote

PCM Programmer,

I've been reading the PIC18F4431, and for what I read the Power PWM module is synchronous.

So what I want to do can not be done directly. I manage to do it with some signal manipulation and some values changes, but for some duty cycles the values change abruptly.
When I have the final solution or if I'm stuck again I post it here.

If you have any suggestion please feel free.

Thanks again all.
jpos99



Joined: 10 Aug 2012
Posts: 14

View user's profile Send private message

PostPosted: Fri May 24, 2013 3:37 am     Reply with quote

Hi,

I've been reading and came across these image that controls the bridge like I want.

https://www.dropbox.com/s/2ktm2i0ngvphfpm/signals.jpg


Can anyone help me, because I'm not understanding one thing if the Power PWM is synchronous how can I delay one of the signals S3? Its by changing the time base value?

Thanks all
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri May 24, 2013 10:57 am     Reply with quote

Post a link to the full web page where you got that timing diagram from.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group