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.

PWM chopper

Other Parts Discussed in Thread: CONTROLSUITE

Hello,

    I have tried to look for PWM chopper module example project in control suite, but couldnt find any. Can anyone let me know how can I get better understanding of it. I need to generate 7 pwms with a gap before the next 7 pwms.

Regards-

  • What device are you using?  

  • F28069 experimenter's kit....

  • Unfortunately, we do not have any examples in controlSUITE for this device as you mentioned.  Have you looked over the PWM Chopper section of the PWM User's Guide?  It is 3 pages (283-286) available here: http://www.ti.com/lit/ug/spruh18c/spruh18c.pdf

    If you poke around with the chopper registers I think you will find it is a relatively simple submodule.  Specifically, you will want to play with the CHPFREQ and CHPDUTY bits in PCCTL.

    Kris

  • Yes, I have gone through it and tried my hands on it. But that didnt help much and therefore I tried searching for an example. The submodule description in the piccolo reference is quite insufficient for clear understanding.

  • Can you post the code you have so far and a detailed description of what you are trying to do?  For example, I believe you said you wanted 7 pulses.  What frequency / duty cycle are you looking for?  Is the first pulse the same width as the following pulses?

    Kris

  • I am trying to interface an analog front end(16 channels) for EMG recordings out of which I want to access 1st 8 channels and it is through SPI protocol and I need to have 3 pwms for this operation. Step, which tells the analog front end to go to next channel(for mux), reset(active low) that tells the chip to start from 1st channel again and convert signal, which tells the ADC to start the conversion.

    I am at home now and will send you the code tomorrow when I reach office. By the way, what I am doing now is my reset signal is having 4KHz freq(TPRD = 10000) and step signal is  having 32KHz and CNV signal is same but inverted. But I dont want the step to be continuous train of pulse. I must have a gap after 7 pulses after which reset is used. You can get a better idea by having a look at the attachment (page 10).

    Regards-

    Intan_RHA2000-EVAL_datasheet.pdf
  • void InitEPwm1Reset()
    {
    // Setup TBCLK
    EPwm1Regs.TBPRD = 10000; // Set timer period 801 TBCLKs
    EPwm1Regs.TBPHS.half.TBPHS = 0x0000; // Phase is 0
    EPwm1Regs.TBCTR = 0x0000; // Clear counter

    // Set Compare values
    EPwm1Regs.CMPA.half.CMPA = 1250; // Set compare A value
    EPwm1Regs.CMPB = 125; // Set Compare B value

    // Setup counter mode
    EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // Count up/down
    EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE; // Disable phase loading
    EPwm1Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1; // Clock ratio to SYSCLKOUT
    EPwm1Regs.TBCTL.bit.CLKDIV = TB_DIV1;

    // Set actions
    EPwm1Regs.AQCTLA.bit.CBU = AQ_CLEAR; // clear PWM1A on event B, up count
    EPwm1Regs.AQCTLA.bit.CAU = AQ_SET; // set PWM1A on event A, up count

    }

    void InitEPwm2Cnv()
    {
    // Setup TBCLK
    EPwm2Regs.TBPRD = 1250; // Set timer period 801 TBCLKs
    EPwm2Regs.TBPHS.half.TBPHS = 0x0000; // Phase is 0
    EPwm2Regs.TBCTR = 0x0000; // Clear counter

    // Setup counter mode
    EPwm2Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // Count up/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_DIV1;

    // Set actions
    EPwm2Regs.AQCTLA.bit.ZRO = AQ_CLEAR; // Clear PWM2A on event zero
    EPwm2Regs.AQCTLA.bit.PRD = AQ_SET; // Set PWM2A on period
    }

    void InitEPwm3Step(void)
    {
    // Setup TBCLK
    EPwm3Regs.TBPRD = 1250; // Set timer period
    EPwm3Regs.TBPHS.half.TBPHS = 0x0000; // Phase is 0
    EPwm3Regs.TBCTR = 0x0000; // Clear counter

    EPwm3Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN;// Count up/down
    EPwm3Regs.TBCTL.bit.PHSEN = TB_DISABLE; // Disable phase loading
    EPwm3Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1; // Clock ratio to SYSCLKOUT
    EPwm3Regs.TBCTL.bit.CLKDIV = TB_DIV1;

    // Set Actions
    EPwm3Regs.AQCTLA.bit.ZRO = AQ_SET; // Set PWM3A on zero
    EPwm3Regs.AQCTLA.bit.PRD = AQ_CLEAR; // Clear PWM3A on period

    // Interrupt where we will receive data from the ADC
    EPwm3Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO; // Select INT on Zero event
    EPwm3Regs.ETSEL.bit.INTEN = 1; // Enable INT
    EPwm3Regs.ETPS.bit.INTPRD = ET_1ST; // Generate INT on 1st event
    }

  • Thank you for the information.  Please allow me some time to review it.  I will get back to you by the end of the week.

    Kris

  • Ok Kris. Thank you.

    Regards-

  • If you have a GPIO (one with a TZ option on it) to spare, I think using a CBC trip is really a better solution for this.  You would just externally connect the reset PWM output to this and set each of the step and CNV waveforms to be forced low on a CBC trip action.  I think we could make the chopper work sufficiently, but using the trip function makes this a true active low reset function.  Let me know your thoughts.

    Kris

  • Hello,

    Actually, I cannot figure out how CBC(TZ) will solve the purpose or in other words, how can I make use of it. Can you let me know how?

    Regards-

  • Sure,

    So what we would do in this case is configure your step signal to generate the proper frequency and duty cycle, not worrying about blanking out the 8th pulse (the trip will take care of this).  We set the other PWM channel to be complimentary of the generated STEP signal for the CNV signal.  So for simplicity let's say STEP is on PWM2A and CNV is on PWM2B.

    Now let's take PWM1A and generate the reset signal.  We would set this up to operate at a 87.5% duty cycle (87.5 = 7/8 since it is only low for 1 pulse out of 8) at whatever frequency gave the low pulse the desired width (the same width as your step/cnv pulses).  Now if we tie the output of this PWM to a TZ and configure PWM2A and PWM2B outputs to always be forced low while the trip is active, this will automatically blank out the 8th pulse for you.  The CBC trip works such that the condition is evaluated every TBCLK- so as long as PWM1A is low, the outputs of PWM2A and PWM2B will stay low.  When the condition clears the PWM2A/B outputs will continue as normal.  I think this will give you more control over your outputs than the chopper would.  For example, if you want to stop transmitting now you can just set the PWM1A output low and the other 2 signals are automatically stopped until you resume operation.

    Kris

  • Hello Kris,

       Let me summarize to let you know if I understood you correctly. So, the trip signal is the reset (when low), and the TZCTL(TZA and TZB) registers must be used to set the action when the trip signal is encountered. I have never worked with this before, so will give it a try and let you know. By the way, what did you mean by saying -

    '' We would set this up to operate at a 87.5% duty cycle (87.5 = 7/8 since it is only low for 1 pulse out of 8) at whatever frequency gave the low pulse the desired width (the same width as your step/cnv pulses).  Now if we tie the output of this PWM to a TZ ''.

    Regards-

  • Correct, PWM2A and PWM2B (or whichever PWMs you decide to use for the STEP / CNV) signal would use the TZ submodule to force the outputs low while the reset signal is low.

    The RESET signal will be generated by another PWM.  From the waveform, it looked like the RESET low pulse was the same width as the high pulses on STEP / CNV.  I'm not sure if this is a requirement by your application or not.  If it's not, you can ignore that statement.  Basically, I was wanting to run the RESET PWM at a slower frequency so that you wouldn't have to modify the registers inbetween periods.  So essentially, 1/8 of the period on the RESET PWM (the low pulse) would be the equivalent to 1/2 the period (the high pulse) on the STEP PWM (assuming this is running at 50% duty cycle).  This is certainly a bit confusing, but running the RESET at a slower frequency keeps the RESET period without ever having to interact with the PWM registers.  Maybe I'm over thinking your application though :)

    EDIT:  I think the 87.5% is incorrect now that I'm thinking about it.  But the idea stays the same.  Might need to play with the numbers some.

    Kris

  • am not very clear:)....Am I correct in the following code...I guess I made some mistake..


    void init(void)
    {

    /* Step 1. Initialize System Control:
    PLL, WatchDog, enable Peripheral Clocks
    */
    InitSysCtrl();


    /* Step 2. Initialize GPIO:
    */
    InitSpiaGpio(); //Setup GPI/O for SPI-A functionality
    InitSciaGpio(); //Setup GPI/O for SCI-A functionality

    InitEPwm1Gpio(); //Setup GPI/O for ePWM1 functionality
    InitEPwm2Gpio(); //Setup GPI/O for ePWM2 functionality
    // InitEPwm3Gpio(); //Setup GPI/O for ePWM3 functionality
    InitTzGpio();

    /* Step 3. Clear all interrupts and initialize PIE vector table:
    Disable CPU interrupts
    */
    DINT;

    /* Initialize PIE control registers to their default state.
    The default state is all PIE interrupts disabled and flags
    are cleared.
    .*/
    InitPieCtrl();

    // Disable CPU interrupts and clear all CPU interrupt flags:
    IER = 0x0000;
    IFR = 0x0000;

    /* Initialize the PIE vector table with pointers to the shell Interrupt
    // Service Routines (ISR).
    // This will populate the entire table, even if the interrupt
    // is not used in this example. This is useful for debug purposes.
    */
    InitPieVectTable();
    EALLOW; // This is needed to write to EALLOW protected registers
    PieVectTable.EPWM3_INT = &epwmstep_isr; //Enable interrupt on pwn3
    EDIS; // This is needed to disable write to EALLOW protected registers

    // Interrupts that are used in this example are re-mapped to
    // ISR functions found within this file.
    EALLOW; // This is needed to write to EALLOW protected registers
    PieVectTable.EPWM2_TZINT = &epwm2_tzint_isr;
    EDIS; // This is needed to disable write to EALLOW protected registers


    // Step 4. Initialize all the Device Peripherals:
    // This function is found in F2806x_InitPeripherals.c
    spi_init(); // Initialize SPI
    spi_fifo_init(); // Initialize the SPI FIFO

    scia_fifo_init(); // Initialize the SCI FIFO
    scia_echoback_init(); // Initialize SCI for echoback

    EALLOW;
    SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0;
    EDIS;
    InitEPwm1Reset();
    InitEPwm2Cnv();
    InitEPwm2Step();
    InitEPwm2Example();
    EALLOW;
    SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1;
    EDIS;


    // Enable CPU INT3 which is connected to EPWM1-3 INT:
    IER |= M_INT3;
    // Enable CPU INT3 which is connected to EPWM1-3 INT:
    IER |= M_INT2;

    // Enable EPWM INTn in the PIE: Group 3 interrupt 1-3

    PieCtrlRegs.PIEIER3.bit.INTx3 = 1;

    // Enable EPWM INTn in the PIE: Group 2 interrupt 1-3
    PieCtrlRegs.PIEIER2.bit.INTx2 = 1;


    // Enable global Interrupts and higher priority real-time debug events:
    EINT; // Enable Global interrupt INTM
    ERTM; // Enable Global real-time interrupt DBGM

    }


    __interrupt void epwm2_tzint_isr(void)
    {


    // Clear the flags - we will continue to take
    // this interrupt until the TZ pin goes high
    //
    EALLOW;
    EPwm2Regs.TZCLR.bit.CBC = 1;
    EPwm2Regs.TZCLR.bit.INT = 1;
    EDIS;

    // Acknowledge this interrupt to receive more interrupts from group 2
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP2;

    }

    void InitEPwm2Example()
    {

    // Enable TZ1 and TZ2 as one cycle-by-cycle trip sources
    EALLOW;
    EPwm2Regs.TZSEL.bit.CBC1 = 1;
    EPwm2Regs.TZSEL.bit.CBC2 = 1;

    // What do we want the TZ1 and TZ2 to do?
    EPwm2Regs.TZCTL.bit.TZA = TZ_FORCE_LO;
    EPwm2Regs.TZCTL.bit.TZB = TZ_FORCE_LO;

    // Enable TZ interrupt
    EPwm2Regs.TZEINT.bit.CBC = 1;
    EDIS;

    // Setup TBCLK
    EPwm2Regs.TBPRD = 1250; // Set timer period 801 TBCLKs
    EPwm2Regs.TBPHS.half.TBPHS = 0x0000; // Phase is 0
    EPwm2Regs.TBCTR = 0x0000; // Clear counter

    // Setup counter mode
    EPwm2Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // Count up/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_DIV1;

    // Set actions
    EPwm2Regs.AQCTLA.bit.ZRO = AQ_CLEAR; // Clear PWM2A on event zero
    EPwm2Regs.AQCTLA.bit.PRD = AQ_SET;

    // Set Actions
    EPwm2Regs.AQCTLB.bit.ZRO = AQ_SET; // Set PWM3A on zero
    EPwm2Regs.AQCTLB.bit.PRD = AQ_CLEAR; // Clear PWM3A on period


    }

    void InitEPwm1Reset()
    {
    // Setup TBCLK
    EPwm1Regs.TBPRD = 10000; // Set timer period 801 TBCLKs
    EPwm1Regs.TBPHS.half.TBPHS = 0x0000; // Phase is 0
    EPwm1Regs.TBCTR = 0x0000; // Clear counter

    // Set Compare values
    EPwm1Regs.CMPA.half.CMPA = 1250; // Set compare A value
    EPwm1Regs.CMPB = 125; // Set Compare B value

    // Setup counter mode
    EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // Count up/down
    EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE; // Disable phase loading
    EPwm1Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1; // Clock ratio to SYSCLKOUT
    EPwm1Regs.TBCTL.bit.CLKDIV = TB_DIV1;

    // Set actions
    EPwm1Regs.AQCTLA.bit.CBU = AQ_CLEAR; // clear PWM1A on event B, up count
    EPwm1Regs.AQCTLA.bit.CAU = AQ_SET; // set PWM1A on event A, up count

    }

    void InitEPwm2Cnv()
    {
    // Setup TBCLK
    EPwm2Regs.TBPRD = 1250; // Set timer period 801 TBCLKs
    EPwm2Regs.TBPHS.half.TBPHS = 0x0000; // Phase is 0
    EPwm2Regs.TBCTR = 0x0000; // Clear counter

    // Setup counter mode
    EPwm2Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // Count up/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_DIV1;

    // Set actions
    EPwm2Regs.AQCTLA.bit.ZRO = AQ_CLEAR; // Clear PWM2A on event zero
    EPwm2Regs.AQCTLA.bit.PRD = AQ_SET; // Set PWM2A on period
    }

    void InitEPwm2Step(void)
    {
    // Setup TBCLK
    EPwm2Regs.TBPRD = 1250; // Set timer period
    EPwm2Regs.TBPHS.half.TBPHS = 0x0000; // Phase is 0
    EPwm2Regs.TBCTR = 0x0000; // Clear counter

    EPwm2Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN;// Count up/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_DIV1;

    // Set Actions
    EPwm2Regs.AQCTLB.bit.ZRO = AQ_SET; // Set PWM3A on zero
    EPwm2Regs.AQCTLB.bit.PRD = AQ_CLEAR; // Clear PWM3A on period

    // Interrupt where we will receive data from the ADC
    EPwm2Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO; // Select INT on Zero event
    EPwm2Regs.ETSEL.bit.INTEN = 1; // Enable INT
    EPwm2Regs.ETPS.bit.INTPRD = ET_1ST; // Generate INT on 1st event
    }

  • This looks pretty close for the TZ setup anyway.  I don't have a device available to run this on at the moment.  You only actually need to enable one CBC source since these are on the same PWM.

    EPwm2Regs.TZSEL.bit.CBC1 = 1;
    EPwm2Regs.TZSEL.bit.CBC2 = 1;

    I would suggest not worrying about the RESET functionality yet.  Just configure TZ1 (or whichever TZ you decide to use) and tie it high.  Start PWM2 and watch the waveform, then tie TZ1 low. You should the PWMs be forced low until you tie TZ1 high again.  

    You have a lot of duplicate code for PWM2.  You should be able to setup the Step functionality and then with very few lines of code just set the B channel to be inverted.  No need to go through all of the TBPRD, TBCTL settings again, etc.  This makes it a bit hard to follow.  It should just be a bit in the AQ somewhere to invert the B output.

    I would recommend playing with the epwm_trip_zone example in controlSUITE to get an idea of how this works (and seeing some example code).  This will give you a better idea if this fits for your application before you throw too many hours at it.

    Kris

  • I can see PWM2A andPWM2B low and high when I configure TZ, but at all instance of time. the example doesn't say how to configure or make use of trip zone if I want to correlate trip zone and a signal (step) at whichever time instance I want. Can you give an example or a code snippet that would be helpful?

    Regards-

  • So you are seeing the trip work as expected?  In other words, when the TZ pin is low the PWM outputs are low?

    If this is the case, then you just need to configure the PWM1 with some waveform and externally connect it to the TZ pin.  If the trip isn't working then I'm not sure I understand what you are seeing.  Can you send a waveform?  I won't have a device to test any code on until sometime next week, but we should be able to get you up and running.

    Kris

  • Actually I am in Sweden and its midnight here. My kit is at office. So canI send you the wave form and code on monday? Will that be ok?

    Regards-