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.

synchronizing ePWM modules for motor control

Other Parts Discussed in Thread: TMS320F28335

Hi,

I am using TMS320F28335 processor to control brushless motor, among other things.

I control brushless motor with hall sensors.  TI has some sample code how to do this in general.  One deviation from standard code is that I do four quadrant control, i.e. we pwm both high and low switch.  Problem I am having is that when I clock in new ePWM modules with new period settings, changes don’t happen simultaneously.  It looks like first PWM module goes into effect right away, but second doesn’t until beginning of next pwm period.  This leaves me with a whole pwm period where sometimes I push the current in incorrect direction and unnecessarily heat up the motor.  I toggle the sync bit so the two pwm modules are synced, but once again not until second pwm period.

I tried playing with shadow registers, and sync bits, but with no success.  I realize that it might be impossible to clock in two new pwm settings instantaneously and at the same time.  So I am OK if there is a period delay, but only if both modules are equally delayed and they are in known state while waiting(i.e. they both low or both high). 

I am using ePWM modules to control speed and commutation.  Every time I need to commutate I choose new pair of switches and set them to desired pwm profile.  In general my code works fine.  The only problem I am seeing is in synchronization of newly selected swithes.  Specifically, lets say I am commutating from switch pair (pwm1,pwm2) to (pwm2, pwm3).  I disable pwm1, and set pwm2 and pwm3 to new duty cycle setting.  Disabling of pwm1 appears right away.  Pwm2 and pwm3 appear either stuck, from previews state, or in some random state for about half of pwm period.  Then they appear synchronized and in correct states.

This delay in syncronization is causing hicups in my motor drive.  Is there a prefered way to impose new synchronized state without much delay?

here is code snipet from one of six commutation states...

case COMMU_STATE_0:                                                  
            { 
               // Power In                                                                   
               EPwm1Regs.AQCSFRC.bit.CSFA = 0; // PWM 1a (Ah)                   
               EPwm1Regs.AQCTLA.bit.CAU = 2;   // high when CTR = CMPA on UP
               EPwm1Regs.AQCTLA.bit.PRD = 1;   // low when CTR = PRD            
               EPwm1Regs.CMPA.half.CMPA = pwm_duty_ticks; // PWM duty cycle
               EPwm1Regs.AQCSFRC.bit.CSFB = 0; // Comp PWM with Deadband on 1B  
               EPwm1Regs.DBCTL.bit.OUT_MODE =BP_ENABLE;//deadband(overides CSFB)                               
               // Power Out                                   
               EPwm2Regs.AQCSFRC.bit.CSFA = 0; // Shifted Complement PWM
               EPwm2Regs.AQCTLA.bit.CAU = 1;   // Set Low CMPA on UP-count
               EPwm2Regs.AQCTLA.bit.CBU = 2;   // Set high CPMB on UP-count            
               EPwm2Regs.CMPA.half.CMPA = pwm_shifted_cmp_a; // PWM duty cycle
               EPwm2Regs.CMPB           = pwm_shifted_zero; // PWM duty cycle
               EPwm2Regs.AQCSFRC.bit.CSFB = 1; // OverRidden by DeadBand
               EPwm2Regs.DBCTL.bit.OUT_MODE =BP_ENABLE;//deadband(overides CSFB)                                
               // Unused                                   
               EPwm3Regs.AQCSFRC.bit.CSFA = 1; // Low
               EPwm3Regs.AQCSFRC.bit.CSFB = 1; // Low
               EPwm3Regs.DBCTL.bit.OUT_MODE = BP_DISABLE;                                
               break;
            }

Once I execute one of six states I issue this command for synchronization...

 

// force pwm sync
EPwm1Regs.TBCTL.bit.SWFSYNC = 1;

 

Attached is a scope plot of the observed behavior and additional detail on the code.

ePWM sync.docx
  • Vlad,

    What drives your state machine?  Is it in sync with the PWM modules?

    Regards,
    Daniel

  • Commutation routine is sitting in ISR, which gets triggered by hall sensor transitions.  I am not sure about your question on synchronization with PWM modules.  I don't think there are any problems with higher priority interrupts taking over, because PWM delay that I am seeing is always one period long. 

    In current state, the way the code is now, I always see one period delay in PWM module that remains on in commutation sequence.  During delay that module is set low.  When I play with shadow registers and set the code to take effect on counter equal to zero, I always see one period delay in PWM module that turns on (during that delay module is set high), where PWM module that remains on is fine.  This behavioure makes me think my problem is with the way I use PWM settings.

    Vlad

  • Vlad,

    I am not clear what the timing between the hall sensor and state machine trigger is but I suspect the issue is due to the fact that your Commutation state machine is not synchronized with your PWM switch timing.  What I mean is that the state machine can be triggered at a variable point in the PWM period counter when it adjusts the PWM settings .  In your first post, you commented that

    "Pwm2 and pwm3 appear either stuck, from previews state, or in some random state for about half of pwm period.  Then they appear synchronized and in correct states."

    The "stuck" duration might be due to the code execution time of your state machine and the asynchronous relationship with the PWM counters.  Once the SW sync signal is triggered at the end, I think that is what causes them to be synchronized and in correct states.

    Regards,
    Daniel

  • It is possible that there is delay that waits for PWM counter to reach certain state or because it takes some finite clock cycles to process new register info.  Here is an experiment that should take all of this guess work away. 

    From the picture I uploaded you can tell that although clocking in new PWM info is problematic, setting new static state goes into effect right away. So...

    Once I got into my ISR I forced all modules low (to effectively disable all PWMs and start from known state), then I stopped TB clock, entered new pwm settings, then re-enbled clock (per ePWM manual this supposed to resync all modules).  I still have the same off period problem.  See picture and code below.

    As pink line goes off, there is about 10us time when all modules are low.  Then I turn blue and yellow modules to pwm.  Blue module starts right away, where yellow remains high for about a period.  I get similar picture for all commutation states.  It makes no difference if I am using shadow reg or immediate setting.

     

    Code sample for one commutation state....

                case COMMU_STATE_0:                                                  
                { 
                    // Unused
                    EPwm3Regs.AQCSFRC.bit.CSFA = 1; // Low
                    EPwm3Regs.AQCSFRC.bit.CSFB = 1; // Low
                    EPwm3Regs.DBCTL.bit.OUT_MODE = BP_DISABLE;
                   
                    //Set temp low
                    EPwm1Regs.AQCSFRC.bit.CSFA = 1; // Low 
                    EPwm1Regs.AQCSFRC.bit.CSFB = 1; // Low
                    EPwm2Regs.AQCSFRC.bit.CSFA = 1; // Low     
                    EPwm2Regs.AQCSFRC.bit.CSFB = 1; // Low  
                    EPwm1Regs.DBCTL.bit.OUT_MODE = BP_DISABLE;
                    EPwm2Regs.DBCTL.bit.OUT_MODE = BP_DISABLE;
                    for(i = 0; i < 20; i++)
                       {
                          asm("          NOP");
                       }
                    EALLOW;
                    SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0;
                   
                     // Power In                                                                   
                   EPwm1Regs.AQCSFRC.bit.CSFA = 0; // PWM 1a (Ah)                   
                   EPwm1Regs.AQCTLA.bit.CAU = 2;   // high when CTR = CMPA on UP
                   EPwm1Regs.AQCTLA.bit.PRD = 1;   // low when CTR = PRD            
                   EPwm1Regs.CMPA.half.CMPA = pwm_duty_ticks; // PWM duty cycle
                   EPwm1Regs.AQCSFRC.bit.CSFB = 0; // Comp PWM with Deadband on 1B  
                   EPwm1Regs.DBCTL.bit.OUT_MODE =BP_ENABLE;//deadband(overides CSFB)                               
                   // Power Out                                   
                   EPwm2Regs.AQCSFRC.bit.CSFA = 0; // Shifted Complement PWM
                   EPwm2Regs.AQCTLA.bit.CAU = 1;   // Set Low CMPA on UP-count
                   EPwm2Regs.AQCTLA.bit.CBU = 2;   // Set high CPMB on UP-count            
                   EPwm2Regs.CMPA.half.CMPA = pwm_shifted_cmp_a; // PWM duty cycle
                   EPwm2Regs.CMPB           = pwm_shifted_zero; // PWM duty cycle
                   EPwm2Regs.AQCSFRC.bit.CSFB = 0;//1; // OverRidden by DeadBand
                   EPwm2Regs.DBCTL.bit.OUT_MODE =BP_ENABLE;//deadband(overides CSFB)     
                   
                    EALLOW;
                    SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1;
                    EDIS;                          
                                                   
                   break;
                }     

               EPwm1Regs.TBCTL.bit.SWFSYNC = 1;

     

    I feel my problem is related to post "ePWM PWM1 Module Sync PWM2 Module", which never got resolved.

    Any additional thoughts?

    Thanks,

    vlad

     

  • Sorry.  I tried embedding picture and it didn't work.  Let's try again as attachment 6406.scope shot.docx.

  • When you perform the PWM updates, try resetting the PWM TBCTR register as well.  Even if you stop the counter, if the counter register is at a value beyond the CMPA/B value it will not process.  Also, make sure you disable shadow mode for the CMP registers or they wont update until the next update event (zero/period).

     

  • Shadow function was disabled.  Resetting counter produced interesting but not desired result.  PWM module that was going into effect rightaway acquired a hiccup, I think because instead of continuing to PWM it got reset.  PWM module that was usually delayed by a period was now delayed by a period and more (see attachment, it is second case).

    In attachment I show how waveform changes when I play with SYNCOSEL and PHSEN regisers.  In first two cases, in all commutation trasitions, pwm that was previously on remains on without problem, where pwm that gets turned on is delayed.  In last two cases, in all commutation states, pwm that goes on is on without problem, where the one that was previously on gets a period long hiccup.

    Vlad

    1440.Counter reset.docx

  • Vlad, For PWM1, you do not need to set SYNCOSEL to CTR=Zero event.  This is because you are using SW force instead. However, we should be able to avoid all the hassle involved with forcing PWMs low, disabling clocks, etc. Can you answer the following? 1) how does the hall sensor trigger the commutation state machine? Is it... polling? Interrupt driven? 2) are all PWM periods the same? If they are, we should be able to avoid PWM output interruption, even during updates. 3) do you have access to GPIO pins you can toggle to use as a debug tool? I would like you to toggle a GPIO so we can see the timing relationship between the state machine, hall sensor, and PWM signals. 4) is the commutation order is known? I.e. it goes 1-2-3-4-5-6-1? Regards, Daniel
  • Vlad,

    Without digging much into the code and epwmconfiguration, you can solve the problem using Dan's original suggestion - sync commutation logic with pwm.

    1. Use compare shadow registers. Configure epwm to transfer shadow -> compare register on period/overflow/underflow.

    2. Enable an unused compare to generate a "Load Event" at a convinent count (period/2).

    3. Compute the pwm compare values in your "commutation interrupt", Do not load the values into shadow yet, but enable "Load event" to generate an interrupt here to sync loading with pwm timer/signals. (wish you could enable a dma ch to trigger on Load Event to avoid taking another interrupt).

    3. In the "Load Event" interrupt you transfer the computed compare values into the shadow registers, which "should" be quick and "guaranteed" to load all shadow registers before  transfer of shadow reg to compare reg happens. You don't re-enable the  "Load Event" interrupt here, will be enabled on your next "hall change commutation" interrupt.

    Hope this helps, Joson.

  • Hall sensors are sitting on eCap ISR.  Everytime hall sensor transitions this ecap ISR goes off.  Code checks which hall sensor transitioned and within same ISR chooses new PWM modules.

    All PWM modules are driven at the same frequency/period.  Although they do have different duty cycle.  One of the modes this motor operates is bidirectional, and as result is driven using 4 quadrants.  So commutation sequence is not always the same.

    I do have access to GPIOs for debug.  Can you be more specific about what you want to see with this GPIO?

    Thanks,

    Vlad

  • Vlad.

    Josons suggestion is along the same lines of what I am hoping we can set up for you.

    Regarding the GPIOs, what I would like you to do is toggle a GPIO so that we can see the timings relative to the PWM waveforms.  The toggle points that I would like to (in order of importance):

    1) At the start of the ISR
    2) At the end of the ISR
    3) After PWM reconfiguration is complete (such as at the end of each case statement)
    4) Just before PWM reconfiguration (such as right before the switch statement)

    To keep things simple to read, make sure the GPIO is set low again before the first toggle.

    Let me know if you have you questions about what I want.

  • Vlad,

    Some more explanation regarding why I believe your issue is with timing.  In your scope plots, you say that the PWM that remains on will operate fine but the one you re-enable will often have a delay.  Depending on your commutation states, this might be a problem with the timing of your PWM reconfiguration.

    I've noticed that for each PWM, the action qualifier configuration will change depending on the state it is in.  In some sates, it will have PWM CLEAR on CMPA-Up but in another it will have PWM SET on CMPA-Up.  For a PWM, if the last state it was in used PWM CLEAR on CMPA-Up and the new state uses PWM SET on CMPA-Up, unless you complete the re-configuration before the CMPA-Up event, it will still operate using the old settings (CLEAR).  Since it was never SET via the CMPA-Up event, it will remain LOW for an entire period.  An example with PWM1 would be the state sequence of 3->X->1, where X is a state in which PWM1 was disabled (but not reconfigured).

    Regards,
    Daniel

  • After using debug gpio I think I agree with you.  I can't say that I fully understand the problem, but here is what I observed (you can see attachment for scope shots).

    The key module appears to be the one that gets turned off, or at least I will key of it for further comments.  I will call it "pwm to off' module.  So it looks like whenever I enter switch statement while "pwm to off' module is low, I get the delay problem.  Whenever I enter switch statement while "pwm to off" module is high, there is no delay in making new pwm setting effective right away.  In other words it appear to matter where the counter is when I try to enable new pwm settings.

    In every commutation case I tried to reset the counter to some value, and one of my compare counts did the job.  By the way, resetting all counters to zero did not help. 

    Here is what I don't like about this fix.  First I still don't understand the root cause, i.e. I don't like this random fix.  Second, once in a while and for some reason always in same commutation state, this problem reappears.  Going of debug gpio, this problem reappears when counter for "pwm to off" module happens to be in one specific spot.

    Let me know if you have more insight into this problem.  It appears that Joson might be onto something as well, although I am not thrilled about using another ISR.

    Vlad

    1727.debug trace.docx

  • Vlad,

    After looking at your debug gpio shots and your observations, I would say that the issue we see is due to the timing of your commutation state ISR relative to the PWM counters.  Since the commutation updates can occur at varying points during the PWM counter period, there is no way to guarantee that the new settings go into effect without missing a PWM Compare event.  For example, as I mentioned in my last post, if the PWM's previous setting was CLEAR on CMPA-Up and the new setting is SET on CMPA-Up, if the configuration update occurs after Counter = CMPA, the PWM output will not be correct until the next PWM cycle.  I believe this is the issue you are seeing.

    Here is my understanding of the issue:
    1) PWM module 'A' is forced LOW.  No issue
    2) PWM module 'B' remains on with no changes.  No issue
    3) PWM module 'C' turns on (previously forced low).  Potential 1 PWM cycle delay in output.

    Currently, it appears that you enable/disable/reconfigure the PWMs when you ENTER the new commutation state. 
    1) Hall sensor triggers the ISR
    2) ISR determines the new state
    3) state machine enables/disables the PWMs as needed AND re-configures the PWM module that is turning on.

    Is it possible to know the next commutation state ahead of time based on current state and direction of spin?  If the answer is yes, please try the following:
    1) Hall sensor triggers the ISR
    2) ISR determines the new state
    3) state machine enables/disables the PWMs as needed (one PWM remains same, one PWM turns off, one PWM turns on).
    4) state machine PRE-configures the PWM that was just turned off for when it turns on again.
    Note: You should not need to perform a counter reset or SW sync event.  Shadow load is allowed, if wanted.

    Please note the difference.  In the current setup, the PWM enable/disable occurs at the same time as re-configuration.  In the propsed setup, PWM re-configuration occurs ahead of time.

    Unless you are willing to set up a second ISR that is synchronized with the PWM counters, I believe this option will minimize the chances of a "delay cycle" occuring since it minimizes the number of cycles needed to reconfigure the PWMs (and therefore minimizes the window in which a "delay cycle" can occur).  In other words, you want to miminize the time between pulses 1->3.

    If you want more help regarding the theory of this, I can ask one of our motor control experts to join in. 

    Regards,
    Daniel

  • I seems to me that Daniel has explained the issue, but I would like to make one clarification.

    Software Force CLEAR is used to disable a motor phase.  So when the phase is enabled by Software Force Disable, the output is remains clear until the next Action Qualifier event.  As Daniel stated, this may be as much as a PWM period later (since the AQ events compare 'equal to').

    So for the motor phase that is being enabled, a solution might be to force the outputs in the ISR by doing...

    1) read the PWM count

    2) use Software Force to to set the required output by:

    if (count < compare value)

        software force pwmA High and pwmB Low

    else

        software force pwmA Low and pwmB High

    end if

    3) use Software Force Disable.

    You may need to think about how close Count is to the Compare Value to be sure that this can be done before the PWM AQ event actually happens.

  • Thanks for your insight Greg. 

    Just to clarify what you saying. When you say "Software Force Clear" you mean EPwm3Regs.AQCSFRC.bit.CSFA = 1;?  And when you say "Software Force Disable" you mean EPwm3Regs.AQCSFRC.bit.CSFA = 0;?  Or are you talking about compare clear and set action?

     

    Thanks,

    Vlad

  • That is right:

    AQCSFRC.bit.CSFA = 0 // Software Force Disable

    AQCSFRC.bit.CSFA = 1 // Software Force Set

     

    AQCSFRC.bit.CSFA = 2 // Software Force Clear

    AQCSFRC.bit.CSFA = 3 // Software Force Disable (same as = 0?)

    It occured to be after I posted that I don't know how you have the Dead Band set up or the hardware design of the FET gate drivers.  That information would be need to know how to force the PWM B output.

  • Vlad,

    Your original comment "I realize that it might be impossible to clock in two new pwm settings instantaneously and at the same time." is the real problem. And your scope trace proves it. In your code – Commutation_state4 update pwm3 registers first, then pwm1 - the trace shows pwm3 picked up the updated values and pwm1 missed it until next period. Race condition exists between the CPU updating values into pwm registers and the pwm timer core using those.

    One way to update pwm asynch is to Hold the Timebase clock from counting, update all pwm modules and then release the Timebase clock. This should be included in the pwmModule SYNC feature (TI??).

    Regards,

    Joson.

     

     

  • Hi Joson,

    Stopping the clock seems to be the most robust solution so far.  I stopped using software sync, and instead reset all timers to full period count inside of disable clock statement.  I still get occasianal hiccups, but they mostly from some unknown delay.  I was pretty sure that my ISR had the highest priority, but apperently not.

    Thanks for your help,

     

    vlad

     

     

  • Hi Daniel,

    Unfortunetly I don't always know my next commutation state.  In one of the modes motor has to spin back and forth (think electric toothbrush) so I can't predict if motor going to reverse direction on next commutation or not.

    I think we all agree that my problem has to do with timing between pwm counter and commutation state change.  At this point my fix involves resetting pwm module counter to time right before my compare values kick in to set all modules low.  It doesn't appear to be a perfect fix, but it does work about 99.9% of the time.  I might need to revisit it later, but for now I need to move on to other stuff.

    Speaking of other stuff.  I have one more problem with my motor drive, which has to do with dead band module.  I wanted to keep this thread clean so I started an new one ( "transient dead band behavior").  Do you mind looking at that quick?

    Thanks,

    Vlad