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.

F2812 Eva and Evb drifting

Hi,

We are using F2812 eva to generate PWM  1 & 2 and evb to generate PWM 12.

Independently, the PWM 1 & 2 and PWM12 can be generated with the correct frequency. So no issue there.

however, there is a drift between PWM12 and PWM 1 & 2.  

We don't mind if there is a fixed offset, as long as it is fixed, but in our case, the offset seems not be fixed at all.

See picture below.  Can you please advise on how to keep the Timer1 and Timer4 in a fixed offset?

Yellow line is the PWM 12.  Blue / Purple is the PWM 1 & 2

Thank you so much for your help.

Henry

  • Henry,

    Providing the timers are clocked from the same source there should be no drift.  The answer lies somewhere in the way the EVs have been configured.  Can you say a little more about how you are using the EVs and comparators please?

    Also, how is timer 4 involved?  The PWM12 timebase comes from GP Timer 3.

    Regards,

    Richard

  • Hi Richard,

    Thanks for getting back to us.  

    On the configuration, PWM1 and PWM2 are configured to be triggered in compared mode running by T1 counter.

    Here is how set it up:

    void InitEva()
    {

    // Initalize EVA Timer1
    EvaRegs.T1PR = 0x0085; // Timer1 period (133 yields 10.5uS)
    // EvaRegs.T1CMPR = 0x0000; // Timer1 compare
    EvaRegs.T1CMPR = 0x1C00; // Timer1 compare
    EvaRegs.T1CNT = 0x0;
    // TMODE = continuous up/down
    // Clock prescale = 1
    // Timer enable
    // Clock source is internal (HSPCLK)
    // Reload compare register when counter hits 0
    // Timer compare disable
    // EvaRegs.T1CON.all = 0x0842;

    EvaRegs.T1CON.bit.TMODE = 0x1; //Continuous up/down count (01)
    EvaRegs.T1CON.bit.TPS = 0x0; //Clock prescale = 1 (0)
    EvaRegs.T1CON.bit.TCLKS10 = 0x0; //Clock source is internal (HSPCLK)
    EvaRegs.T1CON.bit.TCLD10 = 0x0; //Reload compare register when counter hits 0
    EvaRegs.T1CON.bit.TECMPR = 0x1; //Timer compare is enable , disabled is (0)
    // H.Nguyen, change from Enable of 1 to disable of 0
    // enable / disable will be handle in the set dynamic case
    EvaRegs.T1CON.bit.TENABLE = 0x0; //Timer1 enabled

    // Initalize EVA Timer2
    EvaRegs.T2PR = 0x6300; // Timer2 period configured for blanking on changing of emex output level
    // HPSCLK = 25.344 MHz. To get to 1 ms, it requires 25344 counts or 0x6300
    EvaRegs.T2CMPR = 0x0000; // Timer2 compare
    EvaRegs.T2CNT = 0x0000; // Timer2 counter
    // TMODE = continuous up
    // Timer disable
    // Timer compare disable
    // EvaRegs.T2CON.all = 0x0842;

    EvaRegs.EVAIMRB.bit.T2PINT = 1; //enable interrupt
    EvaRegs.EVAIFRB.bit.T2PINT = 1; // clear flag
    EvaRegs.GPTCONA.bit.T2TOADC = 0; // do not start ADC conversion on T2 interrupt

    EvaRegs.T2CON.all = 0x1002; //Timer2 Disabled


    // Setup T1PWM and T2PWM

    // EvaRegs.GPTCONA.bit.TCMPOE = 1; // Drive T1/T2 PWM by compare logic
    // EvaRegs.GPTCONA.bit.T1PIN = 1; // Polarity of GP Timer 1 Compare = Active low
    // EvaRegs.GPTCONA.bit.T2PIN = 2; // Polarity of GP Timer 2 Compare = Active high

    // Enable compare for PWM1-PWM6
    // EvaRegs.CMPR1 = 0x0C00;
    // EvaRegs.CMPR1 = 0x0050;
    EvaRegs.CMPR1 = PWM_TABLE[0][0]; //initialize
    EvaRegs.CMPR2 = 0x3C00;
    EvaRegs.CMPR3 = 0xFC00;

    // Compare action control. Action that takes place
    // on a cmpare event
    // output pin 1 CMPR1 - active high (PWM1)
    // output pin 2 CMPR1 - active high (PWM2)
    // output pin 3 CMPR2 - active high
    // output pin 4 CMPR2 - active low
    // output pin 5 CMPR3 - active high
    // output pin 6 CMPR3 - active low
    EvaRegs.ACTRA.all = 0x0002; //PWM1 Active Hight, PWM2 Forced Low
    EvaRegs.DBTCONA.all = 0x0000; // Disable deadband
    // EvaRegs.COMCONA.all = 0xA600;
    EvaRegs.COMCONA.bit.CENABLE = 0x1; //Compare Enable (1)
    EvaRegs.COMCONA.bit.CLD = 0x0; //Reload compare on underflow only (00)
    EvaRegs.COMCONA.bit.ACTRLD = 0x0; //Reload ACTRA on underflow only (00)
    EvaRegs.COMCONA.bit.FCOMPOE = 0x1; //Enables compare outputs

    //Clear all EVA INT Flags
    EvaRegs.EVAIFRA.all = 0xFFFF; //Writing a "1" resets flag

    //Enable Peripheral level interrupt(s)
    EvaRegs.EVAIMRA.bit.T1UFINT = 1; //Enable T1 Underflow (Cnt = 0) interrupt


    }

    PWM 12 is from evb. here is its setup:

    void InitEvb()
    {

    // EVB Configure T3PWM, T4PWM and PWM7-PWM12
    // Step 1 - Initialize the Timers

    // Initialize EVB Timer3
    // Timer3 controls T3PWM and PWM7-12
    EvbRegs.T3PR = 0x640; // Timer3 period
    EvbRegs.T3CMPR = 0x0320; // Timer3 compare
    EvbRegs.T3CNT = 0x0000; // Timer3 counter
    // TMODE = continuous up/down
    // Timer enable
    // Timer compare enable
    EvbRegs.T3CON.all = 0x1002;

    // Initialize EVB Timer4
    // Timer4 controls T4PWM
    EvbRegs.T4PR = 0x0640; // Timer4 period is used to generate the emex sync signal
    // Timer4 period configured for generating the emex sync signal to the sonde
    // Timer4 period, HPSCLK = 25.344 MHz; want sync=15.84 Khz ==>1600 times or 0x640
    EvbRegs.T4CMPR = 0x0320; // Timer4 compare
    EvbRegs.T4CNT = 0x0000; // Timer4 counter
    // TMODE = continuous up/down
    // Timer enable
    // Timer compare enable
    EvbRegs.T4CON.all = 0x1002;

    // Setup T3PWM and T4PWM
    // Drive T3/T4 PWM by compare logic
    // EvbRegs.GPTCONB.bit.TCMPOE = 1;
    // Polarity of GP Timer 3 Compare = Active low
    // EvbRegs.GPTCONB.bit.T3PIN = 1;
    // Polarity of GP Timer 4 Compare = Active high
    // EvbRegs.GPTCONB.bit.T4PIN = 2;

    // Enable compare for PWM7-PWM12
    EvbRegs.CMPR4 = 0x0C00;
    EvbRegs.CMPR5 = 0x3C00;
    EvbRegs.CMPR6 = 0x0320;

    // Compare action control. Action that takes place
    // on a cmpare event
    // output pin 1 CMPR4 - active high
    // output pin 2 CMPR4 - active low
    // output pin 3 CMPR5 - active high
    // output pin 4 CMPR5 - active low
    // output pin 5 CMPR6 - active high
    // output pin 6 CMPR6 - active low
    // EvbRegs.ACTRB.all = 0x0666;
    EvbRegs.ACTRB.bit.CMP12ACT = 2;
    EvbRegs.ACTRB.bit.CMP11ACT = 0;

    EvbRegs.DBTCONB.all = 0x0000; // Disable deadband
    // EvbRegs.COMCONB.all = 0xA600;
    EvbRegs.COMCONB.bit.CENABLE = 0x1; //Compare Enable (1)
    EvbRegs.COMCONB.bit.CLD = 0x0; //Reload compare on underflow only (00)
    EvbRegs.COMCONB.bit.ACTRLD = 0x0; //Reload ACTRA on underflow only (00)
    EvbRegs.COMCONB.bit.FCOMPOE = 1;
    }

    i tried to reload them at the same scenario.

    Thanks,

    Henry

  • Henry,

    I get the PWM12 setup, but there must be something more going on with PWM1/2. The initialisation code alone won't produce the patterns in the scope traces. The code comments imply you are enabling and disabling timer 1 somehow. Can you elaborate please?

    Thanks.

    Regards,

    Richard
  • Hi Richard,

    Ah, i forgot to mention that we have the ISR set to keep changing the PWM 1 & 2 period and duty cycle because we are driving the sinusoidal signal output. Here is the ISR for it:

    Here is the PWM table that we prepare ahead of time in the RAM based on the power level that we want to drive:

    const unsigned int PWM_TABLE[12][6] ={ //3 Pulse PWM, 12 levels DC Table, Level "0" is OFF
    {123, 112, 123, 123, 112, 123}, //Level 1, Min PWM
    {119, 103, 119, 119, 103, 119}, //Level 2, etc.
    {114, 95, 114, 114, 95, 114},
    {110, 87, 110, 110, 87, 110},
    {106, 78, 106, 106, 78, 106},
    {102, 70, 102, 102, 70, 102},
    {97, 61, 97, 97, 61, 97},
    {93, 53, 93, 93, 53, 93},
    {89, 45, 89, 89, 45, 89},
    {85, 36, 85, 85, 36, 85},
    {81, 28, 81, 81, 28, 81},
    {77, 20, 77, 77, 20, 77}
    };

    interrupt void T1UFINT_ISR(void) // EV-A
    {
    //NOTE:
    // COMCONA is set up for CMP1 and ACTRA to load on underflow (T1CNT = 0)
    // so CMP1 will load immediately on generation of this INT
    // as will ACTRA. So in this routine you load not the next
    // CMPR1 value (after the one that caused this int) but the one
    // after that - since the previous buffered value has already loaded.

    // Note that following exampel is for a 3-pulse PWM
    //
    // 0: Var(Entry) Var(Exit) Buffered
    // PWMIndex 0 1 // PWMctr 0
    // CMPR1 PWM_TABLE[0][0] PWM_TABLE[0][1] PWM_TABLE[0][2] This ISR causes [1] to be loaded into CMP1 (automatically)
    // ACTRA 0x0002 0x0002
    //
    // 1:
    // PWMIndex 1 2
    // CMPR1 PWM_TABLE[0][1] PWM_TABLE[0][2] PWM_TABLE[0][3]
    // ACTRA 0x0002 0x0002
    //
    // 2:
    // PWMIndex 2 3
    // CMPR1 PWM_TABLE[0][2] PWM_TABLE[0][3] PWM_TABLE[0][4]
    // ACTRA 0x0002 0x0002 0x0008
    //
    // 3:
    // PWMIndex 3 4
    // CMPR1 PWM_TABLE[0][3] PWM_TABLE[0][3] PWM_TABLE[0][5]
    // ACTRA 0x0008 0x0008
    // 4:
    // PWMIndex 4 0
    // PWMctr 4 5
    // CMPR1 PWM_TABLE[0][4] PWM_TABLE[0][4] PWM_TABLE[0][0]
    // ACTRA 0x0008 0x0008
    //
    // 5:
    // PWMIndex 0 1
    // PWMctr 5 6
    // CMPR1 PWM_TABLE[0][0] PWM_TABLE[0][0]
    // ACTRA 0x0008 0x0008 0x0002


    // Set interrupt priority:
    volatile Uint16 TempPIEIER = PieCtrlRegs.PIEIER2.all;

    //TP28_ON(); //Test


    IER |= M_INT2;
    IER &= MINT2; // Set "global" priority
    PieCtrlRegs.PIEIER2.all &= MG26; // Set "group" priority
    PieCtrlRegs.PIEACK.all = 0xFFFF; // Enable PIE interrupts
    EINT;

    //TEMP_CS_OFF(); // h.n. comment out after using it

    switch (PWMIndex)
    {

    case 0:
    EvaRegs.CMPR1 = PWM_TABLE[iPWM][2];
    EvaRegs.T1PR = 0x0085; // Timer1 period (133 yields 10.5uS) // h.n. comment this out to go back to orignal codes

    //TP29_OFF();
    }

    break;

    case 1:

    EvaRegs.CMPR1 = PWM_TABLE[iPWM][3];

    break;

    case 2:

    EvaRegs.CMPR1 = PWM_TABLE[iPWM][4];
    EvaRegs.T1PR = 0x0086; // Timer1 period (134 yields 10.57 us) // h.n. comment this out to go back to orignal codes

    break;

    case 3:
    EvaRegs.CMPR1 = PWM_TABLE[iPWM][5];
    EvaRegs.T1PR = 0x0085; // Timer1 period (133 yields 10.5uS) // h.n. comment this out to go back to orignal codes

    break;

    case 4:

    EvaRegs.CMPR1 = PWM_TABLE[iPWM][0];

    break;

    case 5:

    EvaRegs.CMPR1 = PWM_TABLE[iPWM][1];
    EvaRegs.T1PR = 0x0086; // Timer1 period (134 yields 10.57 us) // h.n. comment this out to go back to orignal codes

    break;
    }


    if(++PWMIndex == 6)
    {
    PWMIndex = 0;
    }


    //acknowledge at PIE level
    // PieCtrlRegs.PIEACK.all = PIEACK_GROUP2; //acknowledge Group 2 interrupt

    //acknowledge at Peripheral level
    EvaRegs.EVAIFRA.bit.T1UFINT = 1; //Clear compare unit 1 interrupt flag

    // for(i = 1; i <= 10; i++) {}

    // Restore registers saved:
    DINT;
    PieCtrlRegs.PIEIER2.all = TempPIEIER;
    //TEMP_CS_ON(); // h.n. comment out after using it

    }

    if this does not work, please let me know the contact email so that i can release a small strip down version of the real project that has these things set up.

    I would not like to release small strip down version in public domain.

    Thanks,
    henry
  • Henry,

    So, timer 1 UF interrupt modulates its own frequency. It looks like when the index counter is 0, 1, 3, or 4, the T1 period is 266 HSPCLK cycles and when the index is 2 or 5, the T1 period is 268 HSPCLK cycles. Timer 4 period is fixed (at 1600 cycles) so you would expect to see the PWM1 & PWM2 waveforms drift with respect to it. Since timer 1 is spending more time in the shorter period I think it must be drifting to the left.

    To verify this, please check what happens if you don't change T1PR in the interrupt code. Are the waveforms then fixed in phase?

    Regards,

    Richard
  • Hi Richard,

    yes, we modulate the PWM period during index counter 2 & 5. But this modulation is needed to keep the total period of 6 PWM 1 & 2 to be 1600 counts of HPSCLK exactly match with the period of PWM 12 which is also 1600 counts of HPSCLK.

    Basically, the PWM 12 is our sync signal which we hope to keep in a "fixed" phase with the PWM 1 & 2.

    So, i can't see how it could match if we do not change the period for index 2 & 5.

    Regards,
    Henry
  • Hi Henry,

    Yes, you're right.  Unfortunately it can't match. 

    The ratio of T1 period to T4 period is either a little above or a little below 6, but switching between them this way won't work because the difference between each ratio and 6 is not a rational number, so I don't think spending a fixed amount of time in each period is going to maintain the phase.  

    Can you live with T4 at 1602 and a fixed T1 period of 267?

    Regards,

    Richard 

  • Hi Richard,

    now i think about it and i think you are right.
    Unfortunately, we can not change the number like that because it will result into changing our OSC clock frequency since all of these numbers are divided down in our application to acquire signal at a specific interval.

    mean while, i found out another solution that take care of our design without changing the board / part and it seems to be ok after few hours of testing in the lab. Thanks again for your help.

    Best Regards,
    Henry Nguyen
  • Hi Richard,

    i played with the event manager some more to understand it and it turned out that the drifting is caused by a misunderstanding or not reading the spec carefully.  The number of count per each of the 1/6 th PWM is ok.

    In the up counting mode, the period is actually PRD + 1 while in the up / count, the period is PRD / 2.  

    so, total 6 PWM periods is 1600 which is what we desired to have and our sync signal period should be 1599 instead of 1600.  put this in and it works beautifully.

    so, i would like to post it here so that other folks can pay attention to.

    Best Regards,

    Henry