This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Converting 10kHz PWM into 2kHz PWM codes

Hi

Here is my pseduo-code:

// In my CAPCOM1 initalisation

CC1_T0REL=0xF830; // Generate 10kHz PWM

// Produce 50% duty cycle
Offset=(0xFFFF-CC1_T0REL)>>1;

// This will produce 50% duty cycle of 10kHz  PWM

CC1_CC2=CC1_T0REL+Offset;


Note: I use 100uS for Timer 0 Interrupt

Now I need to convert 10kHz PWM into 2kHz PWM but I am totally lost at the moment. However I tried to divide it by 5 but it doesn't work at all. I would be very very grateful to hear your suggestion or tip.

Kind regards

AJ

Parents
  • Dear Chris

    RECAP:

    You demonstrated me to implement 2kHz at fixed 50% DC starting at 0 degree, 120 degree and 240 degree respectively.
    Then I need to vary duty cycle rather than fixed as I need to produce sine waveform....

    Here is my more codes...

    Bascially what I tried to produce three sine wave at 0 degre, 120 degree and 240 degree respectively
    hence varying duty cycle at CC1_CC2, CC1_CC3 and CC1_CC4 respectively.


    So far I only get a look-like triangular waveform.

    Is it possible to implement it without the use of PEC and Double-register?

    
    #define DEGREE 2.8125
    #define NUMBER_POINT 213
    #define TABLE_SIZE 128
    
    	//Global variables
    
    	unsigned int SineWave[TABLE_SIZE];
    	int offset, Duty_cycle,index,pwm_ref;
    
    	Duty_Cycle=(0xFFFF - 0xEC78)>>1;
    
    	for (index=0; index<NUMBER_POINT; index++)
    	{
    		SineWave[index]=(Duty_Cycle*sin(((index*DEGREE)*3.14159)/180));
    	}
    
    
    void main(void)
    {
    
    	CC1_IOC 	= 0x0004;	// Non-staggered mode
    	CC1_T0  	= 0xEC78; 	// inital value of T0
    	CC1_T0REL 	= 0xEC78;	// Reload value for T0 which is loaded upon an overflow of TO
    
    
    	CC1_T01CON	= 0x0001; 	// Prescaler - 16, (001) hence 2^1
    	CC1_M0		= 0x5500;   // S
    	CC1_M1		= 0x0005;
    
    
    
    	offset1 =((0xFFFF - CC1_T0REL)/3);
    	offset2 =((0xFFFF - CC1_T0REL)/3)*2;
    
    	CC1_CC2 = 0xEC78;
    	CC1_CC3 = CC1_T0REL + offset2;
    	CC1_CC4 = CC1_T0REL + offset1;
    
    	_bfld_(ALTSEL0P6, 0x001C, 0x001C);
    	_bfld_(DP6, 0x001C, 0x001C);
    
    	CC1_OUT = 0x0014;
    
    	CC1_T01CON_T0R=1;
    
    	PSW_IEN=1;
    
    	for(;;)
    	{
    
    	}
    
    }
    
    void CC1_viTmr0(void) interrupt CC1_T0INT
    {
      	int Phase_Int;
    	long int TempLong,Phase_LongInt;
    
    
      	// increment the position of the sine wave table
    	pwm_ref++;
    
    	// if at the end of the look up table then restart
    	if(pwm_ref >= 128)
    	{
    		pwm_ref = 0;
    	}
    	TempLong = 1.0 * 10000;					// save amplitude as a long
    
    	Phase_LongInt = SineWave[pwm_ref]*TempLong;
    	Phase_Int=Phase_LongInt/10000;
    
    	CC1_CC2=Phase_Int+CC1_T0REL;				// Produce sine wave for phase A
    	CC1_CC3=Phase_Int+CC1_T0REL;				// Produce sine wave for phase B
    	CC1_CC4=Phase_Int+CC1_T0REL;				// Produce sine wave for phase C
    
    }
    
    

    Look forward to hear from you asap

    AJ

Reply
  • Dear Chris

    RECAP:

    You demonstrated me to implement 2kHz at fixed 50% DC starting at 0 degree, 120 degree and 240 degree respectively.
    Then I need to vary duty cycle rather than fixed as I need to produce sine waveform....

    Here is my more codes...

    Bascially what I tried to produce three sine wave at 0 degre, 120 degree and 240 degree respectively
    hence varying duty cycle at CC1_CC2, CC1_CC3 and CC1_CC4 respectively.


    So far I only get a look-like triangular waveform.

    Is it possible to implement it without the use of PEC and Double-register?

    
    #define DEGREE 2.8125
    #define NUMBER_POINT 213
    #define TABLE_SIZE 128
    
    	//Global variables
    
    	unsigned int SineWave[TABLE_SIZE];
    	int offset, Duty_cycle,index,pwm_ref;
    
    	Duty_Cycle=(0xFFFF - 0xEC78)>>1;
    
    	for (index=0; index<NUMBER_POINT; index++)
    	{
    		SineWave[index]=(Duty_Cycle*sin(((index*DEGREE)*3.14159)/180));
    	}
    
    
    void main(void)
    {
    
    	CC1_IOC 	= 0x0004;	// Non-staggered mode
    	CC1_T0  	= 0xEC78; 	// inital value of T0
    	CC1_T0REL 	= 0xEC78;	// Reload value for T0 which is loaded upon an overflow of TO
    
    
    	CC1_T01CON	= 0x0001; 	// Prescaler - 16, (001) hence 2^1
    	CC1_M0		= 0x5500;   // S
    	CC1_M1		= 0x0005;
    
    
    
    	offset1 =((0xFFFF - CC1_T0REL)/3);
    	offset2 =((0xFFFF - CC1_T0REL)/3)*2;
    
    	CC1_CC2 = 0xEC78;
    	CC1_CC3 = CC1_T0REL + offset2;
    	CC1_CC4 = CC1_T0REL + offset1;
    
    	_bfld_(ALTSEL0P6, 0x001C, 0x001C);
    	_bfld_(DP6, 0x001C, 0x001C);
    
    	CC1_OUT = 0x0014;
    
    	CC1_T01CON_T0R=1;
    
    	PSW_IEN=1;
    
    	for(;;)
    	{
    
    	}
    
    }
    
    void CC1_viTmr0(void) interrupt CC1_T0INT
    {
      	int Phase_Int;
    	long int TempLong,Phase_LongInt;
    
    
      	// increment the position of the sine wave table
    	pwm_ref++;
    
    	// if at the end of the look up table then restart
    	if(pwm_ref >= 128)
    	{
    		pwm_ref = 0;
    	}
    	TempLong = 1.0 * 10000;					// save amplitude as a long
    
    	Phase_LongInt = SineWave[pwm_ref]*TempLong;
    	Phase_Int=Phase_LongInt/10000;
    
    	CC1_CC2=Phase_Int+CC1_T0REL;				// Produce sine wave for phase A
    	CC1_CC3=Phase_Int+CC1_T0REL;				// Produce sine wave for phase B
    	CC1_CC4=Phase_Int+CC1_T0REL;				// Produce sine wave for phase C
    
    }
    
    

    Look forward to hear from you asap

    AJ

Children
  • Can I ask what are controlling? You said you need to create 12 channels so are you controlling 4 motors? Or 2 and you need complementary channels (6 channels per motor)? Are you using an external three phase driver that also generates the dead-time? Can you use edge aligned PWM's or do they need to be center aligned?

    Did you say you are using an XC167? You know this has 2 CAPCOM timer units and 1 CAPCOM6 timer unit. The CAPCOM6 was specifically designed for three phase motor control.

    Ok, I see a couple of issues with the code. First you have are exceeding your SineWave array (128 entries) by NUMBER_POINT (213). You need TABLE_SIZE to be equal or less than the TABLE_SIZE. When creating the sine table you need to add an offset so the sine wave is all positive values (in your example 2500).

    Since you want to vary the duty cycle and given your other criteria then I would recommend to switch to compare mode three. Compare Mode 3 will only have one event per timer period and the when you have a compare event the signal is set and on the timer event the signal is reset. When writing a new compare value after the event it will only be valid after the next timer period. Note the PWM's would be edge aligned, is this ok?

    In the timer interrupt service routine you need to manage three different indexes (or three sine tables which represent 120 degree phase shifts).

    Are you familiar application note Ap0802211_3-Phase-Currents.pdf on the Infineon website?

  • Can I ask what are controlling? You said you need to create 12 channels so are you controlling 4 motors? Or 2 and you need complementary channels (6 channels per motor)? Are you using an external three phase driver that also generates the dead-time? Can you use edge aligned PWM's or do they need to be center aligned?

    Did you say you are using an XC167? You know this has 2 CAPCOM timer units and 1 CAPCOM6 timer unit. The CAPCOM6 was specifically designed for three phase motor control.

    Ok, I see a couple of issues with the code. First you have are exceeding your SineWave array (128 entries) by NUMBER_POINT (213). You need TABLE_SIZE to be equal or less than the TABLE_SIZE. When creating the sine table you need to add an offset so the sine wave is all positive values (in your example 2500).

    Since you want to vary the duty cycle and given your other criteria then I would recommend to switch to compare mode three. Compare Mode 3 will only have one event per timer period and the when you have a compare event the signal is set and on the timer event the signal is reset. When writing a new compare value after the event it will only be valid after the next timer period. Note the PWM's would be edge aligned, is this ok?

    In the timer interrupt service routine you need to manage three different indexes (or three sine tables which represent 120 degree phase shifts).

    Are you familiar application note Ap0802211_3-Phase-Currents.pdf on the Infineon website?

  • Can I ask what are controlling? You said you need to create 12 channels so are you controlling 4 motors? Or 2 and you need complementary channels (6 channels per motor)? Are you using an external three phase driver that also generates the dead-time? Can you use edge aligned PWM's or do they need to be center aligned?

    Did you say you are using an XC167? You know this has 2 CAPCOM timer units and 1 CAPCOM6 timer unit. The CAPCOM6 was specifically designed for three phase motor control.

    Ok, I see a couple of issues with the code. First you have are exceeding your SineWave array (128 entries) by NUMBER_POINT (213). You need TABLE_SIZE to be equal or less than the TABLE_SIZE. When creating the sine table you need to add an offset so the sine wave is all positive values (in your example 2500).

    Since you want to vary the duty cycle and given your other criteria then I would recommend to switch to compare mode three. Compare Mode 3 will only have one event per timer period and the when you have a compare event the signal is set and on the timer event the signal is reset. When writing a new compare value after the event it will only be valid after the next timer period. Note the PWM's would be edge aligned, is this ok?

    In the timer interrupt service routine you need to manage three different indexes (or three sine tables which represent 120 degree phase shifts).

    Are you familiar application note Ap0802211_3-Phase-Currents.pdf on the Infineon website?

  • Dear Chris

    Yes, the aim is to control 4 motors using 12 channels. I use hardware to generate non-inverted and inverted PWM to drive a motor so we don't implement dead-time. Unfortunately I am working on the XC161 chip at this stage and so I cannot choose different family. However I try to switch XC167 in the future project

    For the sine-wave array, the reason I use 213 arrays because my algorithm allows 3 different phases point at different points. For example, Phase A start at 0, Phase B and C point at 43 and 85 respectively.

    Phase A: 0 to 360 degree which correspond to 0 to 128
    Phase B: 0 to 360 degree which correspond to 43 to 171
    Phase C : 0 to 360 degree which correspond to 85 to 213

    I have written a code to produce 3 sine waveforms by using CAPCOM1's compare mode 3 instead of 1 and 3. I managed to produce Phase A and B in 120 phase shift. I recently found that I could not use the CAPCOM2 for timer 7/8 because the pins are allocated for something else! This forces me to use the General Purpose Timer 1's Timer block 2 and 3 for generating sine wave. Today has been terrible for me and I have not used it before and I know it works in similar principle like CAPCOM but I could not quite manage it.

    You see I selected timer 2 counting downward and enable interrupt for updating the value of T2 in order to produce sine wave. But nothing happens……

    AJ

  • Btw can we keep in touch by email?

    AJ

  • You can reach me at chris.wunderlich(at)infineon.com

  • Im going to keep your email address in my notebook.

    After reading the datasheet regarding General Purpose Timer 1 epsecially implementing PWM. I have noticed that it needs three Timer blocks for producing each tick and pulse width for high and low. I know that T3 can be used to control Pin 3. The question is that is it possible to implement GPT1 with one timer block and toggle any port?

    AJ

  • Yes, you can just use T3 to toggle pin P3.3 (T3OUT). Here is an example that uses the PEC to reload T3 (but only a 50% DC). If you want to use software then you can change the duty cycle for T3 and also use T2 and T4. However you would need to modify a port pin within the interrupt (meaning you would have to deal with the interrupt latency).

    unsigned int T3reload;
    
    void main(void) {
      /* timer 3 works in timer mode
         prescaler factor is 8
         timer counts down
         alternate output function T3OUT (P3.3) is enabled
         timer 3 output toggle latch (T3OTL) is set to 1
      */
      GPT12E_T3CON = 0x0680;
      T3reload     = 0x04E1;   /* 2KHz, 50% DC */
      GPT12E_T3    = T3reload;
    
      /* P3.3 is used for Timer 3 Toggle Output (T3OUT) */
      _bfld_(ALTSEL0P3,0x0008,0x0008); /* select alternate output */
      _bfld_(P3,0x0008,0x0008);        /* set data register */
      _bfld_(DP3,0x0008,0x0008);       /* set direction register */
    
      /* PEC0:(ILVL) = 14, (GLVL) = 0, (GPX) = 0 */
      GPT12E_T3IC = 0x0078;
      PECC0 = 0x00FF;             /* continuous transfer */
      SRCP0 = _sof_ (&T3reload);  /* source pointer */
      DSTP0 = _sof_(&GPT12E_T3);  /* destination pointer */
    
      GPT12E_T3CON_T3R = 1;       /* set timer 3 run bit */
    
      PSW_IEN = 1;
    
      for(;;) {
      }
    }

  • Thank you for illustrating another example of using General Purpose Timer 1. It seems that 3 timer blocks are need to produce PWM especially varying duty cycle. Thank you for letting me know.

    Kind regards

    AJ