Because of the Thanksgiving holiday in the U.S., TI E2E™ design support forum responses may be delayed from November 25 through December 2. Thank you for your patience.

This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

SPWM Problem

Other Parts Discussed in Thread: TMS320F28377S, TMS320F28335

Hi,

I used TMS320F28377S Launchpad (Development Kit Launchxl-F28377s).

I want to generate very simple SPWM but I do not. And I dont undersand where I do mistake. I used EPWM interrupt (5kHz)and 50Hz sin wave. this sin wave is generated in main blok only one time and saved into an array and  used for compare value. I analyze pwm signals using an oscilloscope I see fluctuation in the signal. here my all code.

please help me.

thank you so much

#include "F28x_Project.h"

#include "math.h"

 

 

#define EPWM2_TIMER_TBPRD  5000  /for kHz PWM

#define PI 3.14159265358979323846

 

void InitEPwm2Example(void);

__interrupt void epwm2_isr(void);

 

unsigned int i=0,m=0,k=0;

 

unsigned int b[101]={0};

void main(void)

{

 

    InitSysCtrl();

 

/*Here I generate sin look up table for sin values, I have 100 sample for one period 50Hz sin wave.Also I multiple buy -1 of negative values of sin wave.

Sin(w*t)=sin(2*pi*f*t)=sin(2*pi*50*(20ms/100)*sample_number)

Sample number=0,1,2,3,4,……………,100

f=50Hz

m=sample number*/

 

    for(m=0;m<100;m++){

 

 

       a=sin(PI*0.02*m);

       if(sin(PI*0.02*m)<0){

             a=-a;

       }

       b[m]=5000*a;

 

    }

    b[100]=0;

 

GpioCtrlRegs.GPAPUD.bit.GPIO2 = 1;    // Disable pull-up on GPIO2 (EPWM2A)

GpioCtrlRegs.GPAMUX1.bit.GPIO2 = 1;   // Configure GPIO2 as EPWM2A

   DINT;

 

    InitPieCtrl();

 

    IER = 0x0000;

    IFR = 0x0000;

 

    InitPieVectTable();

 

    EALLOW; // This is needed to write to EALLOW protected registers

 

    PieVectTable.EPWM2_INT = &epwm2_isr;

 

    EDIS;   // This is needed to disable write to EALLOW protected registers

    EALLOW;

 

    CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 0;

 

    EDIS;

 

    InitEPwm2Example();

 

    EALLOW;

    CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 1;

 

    EDIS;

    IER |= M_INT3;

 

    PieCtrlRegs.PIEIER3.bit.INTx2 = 1;

 

    CpuSysRegs.PCLKCR2.bit.EPWM2=1;

 

    EINT;  // Enable Global interrupt INTM

    ERTM;  // Enable Global realtime interrupt DBGM

 

    for(;;)

    {

        asm ("    NOP");

    }

}

// Here my interrup ISR

__interrupt void epwm2_isr(void)

{

      

           EPwm2Regs.CMPA.bit.CMPA=b[i];

i++;

   if (i==101){

             i=0; }

 

    EPwm2Regs.ETCLR.bit.INT = 1;

    PieCtrlRegs.PIEACK.all = PIEACK_GROUP3;

 

}

//here epwm init codes

void InitEPwm2Example()

{

    EPwm2Regs.TBPRD = EPWM2_TIMER_TBPRD;         // Set timer period 801 TBCLKs

    EPwm2Regs.TBPHS.bit.TBPHS = 0x0000;          // Phase is 0

    EPwm2Regs.TBCTR = 0x0000;                    // Clear counter

    EPwm2Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // Count up and down

    EPwm2Regs.TBCTL.bit.PHSEN = TB_DISABLE;        // Disable phase loading

    EPwm2Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1;       // Clock ratio to SYSCLKOUT

    EPwm2Regs.TBCTL.bit.CLKDIV = TB_DIV2;

    EPwm2Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO;   

    EPwm2Regs.ETSEL.bit.INTEN = 1;               // Enable INT

    EPwm2Regs.ETPS.bit.INTPRD = ET_1ST;          // Generate INT on 1st event

 

}

  • Enes,

    In your program, how have you declared the variable "a"?

    Regards,

    Richard

  • "a" is declareded as a float variable. but I forgot copy of these part of code sory for this mistake.
  • I think that;
    I have 5kHz carrier triangular wave and every zero point, my code goes EPWM interrupt service rutine and calculate new sin wave value and this value assign to epwm compare register. every zero point of pwm counter I need new sin value and my pwm 5kHz, my sin wave is 50Hz so that I need 5kHz/50Hz=100 sample for one period sinwave. Am I right?
  • Enes,

    Yes, that is correct.

    I have your code building and running.  So far it is doing what I expect.  What is the distortion you are seeing?

    Regards,

    Richard

  • In this code I want to generate SPWM.
    I connect a low pass filter (R=1kohm C=100nF)in the pin 80 (epwm2A pin) to see a 50Hz sin wave. but ı do not see sin wave.
    pwm signal not satisfy the sin wave. pwm signal not switching and It stays in the same position (0 or 1).

    tomorrow, I will share the ossiloscope screen video.
  • Hi Richard, sory for late replay,
    Here my latest code for spwm.this code is modified version "epwm_updown_aq_cpu01.c" project to developted for TMS320F28377S Launchpad examples.
    Can you run this code and sy me whre ı mistake.

    in this link my oscilloscope screen video;
    www.youtube.com/watch

    thank you so much for all replays.
    // Included Files
    //
    #include "F28x_Project.h"
    #include "math.h"
    #define EPWM2_TIMER_TBPRD 5000 // 5kHz PWM Period register
    #define PI 3.14159265358979323846
    void InitEPwm2Example(void);
    __interrupt void epwm2_isr(void);
    unsigned int i=0,m=0,k=0;
    float a=0;
    float b[101]={0};
    // Main

    void main(void)
    {
    InitSysCtrl();

    /*Here I generate sin look up table for sin values, I have 100 sample for one period 50Hz sin wave.Also I multiple buy -1 of negative values of sin wave.

    Sin(w*t)=sin(2*pi*f*t)=sin(2*pi*50*(20ms/100)*sample_number)

    Sample number=0,1,2,3,4,……………,100

    f=50Hz

    m=sample number*/

    for(m=0;m<100;m++){
    a=sin(PI*0.02*m);
    if(a<=0){
    a=-a;
    }
    b[m]=5000*a;
    }
    b[100]=0;
    EALLOW;

    GpioCtrlRegs.GPAPUD.bit.GPIO2 = 1; // Disable pull-up on GPIO2 (EPWM2A)
    GpioCtrlRegs.GPAMUX1.bit.GPIO2 = 1; // Configure GPIO2 as EPWM2A

    EDIS;
    DINT;
    InitPieCtrl();
    IER = 0x0000;
    IFR = 0x0000;
    InitPieVectTable();
    EALLOW;
    PieVectTable.EPWM2_INT = &epwm2_isr;
    EDIS;
    EALLOW;
    CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 0;
    EDIS;
    InitEPwm2Example();
    EALLOW;
    CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 1;
    EDIS;
    IER |= M_INT3;
    PieCtrlRegs.PIEIER3.bit.INTx2 = 1;
    CpuSysRegs.PCLKCR2.bit.EPWM2=1;
    EINT; // Enable Global interrupt INTM
    ERTM; // Enable Global realtime interrupt DBGM

    for(;;)
    {
    asm (" NOP");
    }
    }

    __interrupt void epwm2_isr(void)
    {
    /*Here my code assign a new sin value into compare reg. but negative side of sin wave pwm logic is invertered.*/
    a=sin(PI*0.02*i);
    if (a>=0){
    EPwm2Regs.AQCTLA.bit.CAU = AQ_CLEAR; // Set PWM2A on event A, up
    EPwm2Regs.AQCTLA.bit.CAD =AQ_SET; // Clear PWM2A on event B, down
    EPwm2Regs.CMPA.bit.CMPA =b[i];
    }
    else {
    EPwm2Regs.AQCTLA.bit.CAU =AQ_SET; // Set PWM2A on event A, up
    EPwm2Regs.AQCTLA.bit.CAD = AQ_CLEAR; // Clear PWM2A on event B, down
    EPwm2Regs.CMPA.bit.CMPA =b[i];
    }
    i++;
    if (i==101){
    i=0;
    }
    EPwm2Regs.ETCLR.bit.INT = 1;
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP3;
    }
    void InitEPwm2Example()
    {
    EPwm2Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO; // hem zero hemde TBPRD zamanında intrrupt alıyo.
    EPwm2Regs.ETSEL.bit.INTEN = 1; // Enable INT
    EPwm2Regs.ETPS.bit.INTPRD = ET_1ST; // Generate INT on 1st event
    EPwm2Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // Count up and down
    EPwm2Regs.TBCTL.bit.PHSEN = TB_DISABLE; // Disable phase loading
    EPwm2Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1; // Clock ratio to SYSCLKOUT
    EPwm2Regs.TBCTL.bit.CLKDIV = TB_DIV2;
    EPwm2Regs.CMPCTL.bit.SHDWAMODE = CC_IMMEDIATE;
    EPwm2Regs.CMPA.bit.CMPA =0;
    EPwm2Regs.TBPRD = EPWM2_TIMER_TBPRD; // Set timer period 801 TBCLKs
    EPwm2Regs.TBPHS.bit.TBPHS = 0x0000; // Phase is 0
    EPwm2Regs.TBCTR = 0x0000; // Clear counter
    }
  • Enes,

    Your code is working exactly as I'd expect it to.  Yesterday your code loaded the unsigned integer "b" array with two positive half cycles of a sine wave.  These appeared to be written correctly into the CMPA register so your scope trace probably looked like a rectified sine wave.  That was what you had in the code and what appeared to work for me.

    Today your code has changed because you are changing the sign inside the ISR.  Your array contains float values between 0 and 5000, and you are inverting half of it so it runs between 5000 and 0.  That's why half of it looks the way it does on the scope.  Remember, the compare register expects a positive integer representing duty cycle.

    The safest way to proceed is to use unsigned integers for "b", not floats.  Then, when you construct the sine table, allow for an offset of half range. So in yesterday's code, you have...

       for(m=0;m<100;m++){

    a=sin(PI*0.02*m);
    b[m]=2500*a + 2500;
    }
    b[100]=0;

    Then you'll have table set up right and you won't have to do any sign checking.

    Regards,

    Richard

  • Richard,
    Thank you so much for all reply, I understand very well :)
  •  Hi Enes,

    G mrng..!

    Can u share me the code and guide me with the instructions for F28335.

    Actually i copied the above code and getting errors as below while building.,

  • Hi,

    Nayeem Basha Shaik

    I have never used the F28355.I using F28377s. The attached documentt can help you. 

    In this document, you can see the PWM compare register usued like that;

    EPwm1Regs.CMPA.hlaf.CMPA = value  // may be you can use b[i] as value.

    EPwm1Regs.CMPB = compare value1

    EPwm2Regs.CMPA.hlaf.CMPA = value2

    EPwm2Regs.CMPB = compare value3

    Enhanced Pulse Width Modulator epwm.pdf

  • Ya... I got it dude, anyhow thanks alot or your reply....
  • Hi, can you please share the program to generate SPWM pulses using TMS320F28335?

  • Hi, Please find the below code.

    SPWM.c
    // Included Files//
    
    #include "DSP28x_Project.h"
    #include "math.h"
    #define EPWM2_TIMER_TBPRD 5000 // 5kHz PWM Period register
    #define PI 3.14159265358979323846
    void InitEPwm2Example(void);
    __interrupt void epwm2_isr(void);
    unsigned int i=0,m=0,k=0;
    float a=0;
    unsigned int b[101]={0};
    
    // Main
    
    void main(void)
    {
    InitSysCtrl();
    
    /*Here I generate sin look up table for sin values, I have 100 sample for one period 50Hz sin wave.Also I multiple buy -1 of negative values of sin wave.
    
    Sin(w*t)=sin(2*pi*f*t)=sin(2*pi*50*(20ms/100)*sample_number)
    
    Sample number=0,1,2,3,4,�����,100
    
    f=50Hz
    
    m=sample number*/
    
    for(m=0;m<100;m++){
    a=sin(PI*0.02*m);
    if(a<=0){
    a=-a;
    }
    b[m]=5000*a;
    }
    b[100]=0;
    EALLOW;
    
    GpioCtrlRegs.GPAPUD.bit.GPIO2 = 1; // Disable pull-up on GPIO2 (EPWM2A)
    GpioCtrlRegs.GPAMUX1.bit.GPIO2 = 1; // Configure GPIO2 as EPWM2A
    
    EDIS;
    DINT;
    InitPieCtrl();
    IER = 0x0000;
    IFR = 0x0000;
    InitPieVectTable();
    EALLOW;
    PieVectTable.EPWM2_INT = &epwm2_isr;
    EDIS;
    EALLOW;
    SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0;
    EDIS;
    InitEPwm2Example();
    EALLOW;
    SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1;
    EDIS;
    IER |= M_INT3;
    PieCtrlRegs.PIEIER3.bit.INTx2 = 1;
    SysCtrlRegs.PCLKCR1.bit.EPWM2ENCLK=1;
    EINT; // Enable Global interrupt INTM
    ERTM; // Enable Global realtime interrupt DBGM
    
    for(;;)
    {
    asm (" NOP");
    }
    }
    
    __interrupt void epwm2_isr(void)
    {
    /*Here my code assign a new sin value into compare reg. but negative side of sin wave pwm logic is invertered.*/
    a=sin(PI*0.02*i);
    if (a>=0){
    EPwm2Regs.AQCTLA.bit.CAU = AQ_CLEAR; // Set PWM2A on event A, up
    EPwm2Regs.AQCTLA.bit.CAD =AQ_SET; // Clear PWM2A on event B, down
    EPwm2Regs.CMPA.half.CMPA =b[i];
    }
    else {
    EPwm2Regs.AQCTLA.bit.CAU =AQ_SET; // Set PWM2A on event A, up
    EPwm2Regs.AQCTLA.bit.CAD = AQ_CLEAR; // Clear PWM2A on event B, down
    EPwm2Regs.CMPA.half.CMPA =b[i];
    }
    i++;
    if (i==101){
    i=0;
    }
    EPwm2Regs.ETCLR.bit.INT = 1;
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP3;
    }
    void InitEPwm2Example()
    {
    EPwm2Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO; // hem zero hemde TBPRD zamaninda intrrupt aliyo.
    EPwm2Regs.ETSEL.bit.INTEN = 1; // Enable INT
    EPwm2Regs.ETPS.bit.INTPRD = ET_1ST; // Generate INT on 1st event
    EPwm2Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // Count up and down
    EPwm2Regs.TBCTL.bit.PHSEN = TB_DISABLE; // Disable phase loading
    EPwm2Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1; // Clock ratio to SYSCLKOUT
    EPwm2Regs.TBCTL.bit.CLKDIV = TB_DIV2;
    EPwm2Regs.CMPCTL.bit.SHDWAMODE = CC_IMMEDIATE;
    EPwm2Regs.CMPA.half.CMPA =0000;
    EPwm2Regs.TBPRD = EPWM2_TIMER_TBPRD; // Set timer period 801 TBCLKs
    EPwm2Regs.TBPHS.half.TBPHS = 0x0000; // Phase is 0
    EPwm2Regs.TBCTR = 0x0000; // Clear counter
    }