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.

CCS/TM4C123GH6PM: Using PWM with TivaWare_C

Part Number: TM4C123GH6PM

Tool/software: Code Composer Studio

Hello!!

I need a advice to use PWM with TivaWare_C.

I'm trying to update PWM period and pulse width value when PWM counter reaches 0.

I think using a function like below would work but I'm not sure.

---------

PWMGenConfigure(PWM1_BASE, PWM_GEN_2, PWM_GEN_MODE_DOWN|PWM_GEN_MODE_SYNC);

---------

Do I have to use additional functions or flags or it's fine with only above sentence?

Look forward for the answer.

Thank you!

  • The "PWM_GEN_MODE_SYNC" parameter is only if you need to synchronize multiple PWM channels. Any change to the period or pulse width will automatically take place only when the counter is zero. If changing both the period and pulse width, I suggest you do that in an interrupt routine based on the counter equal to zero. Then, unless you have a long interrupt latency, both will be updated the next time the counter reaches zero. You might want to look at the example routine in TivaWare:
    C:\ti\TivaWare_C_Series-2.1.4.178\examples\peripherals\pwm\reload_interrupt.c
  • young yoon said:
    I'm trying to update PWM period and pulse width value when PWM counter reaches 0.

    May I generally agree w/vendor's guidance - but for his (gentle) push for you to, "Violate KISS" - and add the (IMO) "too early" complication wrought by interrupts.

    Instead - I would direct you to a focused review of the, "Peripheral Library Driver User Guide" - which greatly details this vendor's extensive "API" (Application Programming) and is certain to advise & insure your progress.

    You sought two specific PWM "objectives" - and your review (as just directed) will quickly/easily note 2 (precisely answering) functions:

    • PWMPeriodSet()

    and

    • PWMPulseWidthSet()

    Note that neither function "binds you" to an interrupt - and as a long-term believer in/disciple of "KISS" - I feel that's a "good thing."      KISS teaches one to "Focus upon a small goal - achieve it - and only then - add the "risk of refinement."     Attempting too much - "in one go" - has proven "time & time again" - across both here and many forums/disciplines - to derail, delay and even destroy - user morale & effort!

    The manual listed specifies the parameter fields which are required by each function.    Once you've mastered both functions - then we can move to tying the PWM update to a specific trigger.    (yet for now - I stand with KISS - and its resulting speed & simplicity - which drives (even this reporter) - "sometimes" to success...)

  • Might I suggest keeping it even simpler and avoiding updating the period while running. While I have had need of such capability before I haven't needed to do it regularly.

    Updating the period while running is tricky, especially reducing the period. You can get very long pulse widths if there is any mistake.

    Robert
  • Ah ... Yes - such WOULD be a "KISS Violation" - thus cb1 stands elevated, "Now - Hoist by his own petard..."

    Indeed - during our "Motor Optimization Runs" we do indeed "Vary the PWM Frequency" - but "always & only" when the Motor is Stopped!     Just as you  well noted - doing so "Live/dynamically" introduces a very "NON-KISS-Like" potential for "unpleasantness!"

    Our poster does not specifically state his as a "Motor App" yet the likelihood for damage - springing from an "overly long pulse" - may cause damage to (other - non motor) equipment or devices - as well.     As always, "Safe trumps Sorry!"       (and - if available - would be LIKEd!)

  • cb1_mobile said:
    Indeed - during our "Motor Optimization Runs" we do indeed "Vary the PWM Frequency" - but "always & only" when the Motor is Stopped!     Just as you  well noted - doing so "Live/dynamically" introduces a very "NON-KISS-Like" potential for "unpleasantness!"

    The one time I had to do it involved braking where a very low duty cycle was necessary and only obtainable by lowering the frequency. The optimizations necessary to make it work (outside of the HW PWMs operating range) were interesting. The resulting PWM has a near random frequency output during that phase of operation.

    Robert

  • Robert Adsett said:
    The one time I had to do it (altered the PWM Frequency "LIVE") involved braking where a very low duty cycle was necessary and only obtainable by lowering the frequency.

    That's very well constructed - duly noted - yet might I (very slightly) tweak to: "...low duty cycle was necessary - and only obtainable - and "only then proved sufficient" - by lowering the frequency.   

    If I've "read your application correctly" - you required, "Sufficient Brake ON-TIME" - yet interspersed w/"Brake OFF" - so that (both) the mechanical & electrical (power) stage remained w/in their respective, "Safe Areas of Operation" during "Braking" - while the deceleration (and halt) specs. were met...

  • cb1_mobile said:
    If I've "read your application correctly" - you required, "Sufficient Brake ON-TIME" - yet interspersed w/"Brake OFF"

    Close, yes. The limiting factor was that the deadband did not allow a controlled smaller on time so it was necessary to increase the off time in order for the duty cycle to be controllably and repeatedly small.

    Quite correct about the SOA, although the usual failure mode sometimes produced very pleasant (albeit uncontrollable) braking w/o actually damaging anything. The strength of the braking and whether it induced a current limit was very dependent on the motor.

    Robert

  • As your (extra-vendor ... i.e. "inspired") Tag notes - such "Motor Plugging" is likely to be induced by:

    • overly aggressive motor Braking (either too harsh, too sustained - or (RIP dear Motor) both!
    • Motor Reversal - while at Speed (especially if under load)

    Such "plugging" may (substantially) "demagnetize" a BLDC motor's rotor - and must be avoided!    

    As friend Robert has noted - (very) fast yet accurate "current monitoring/limiting" - and confining "motor reversal" to only those (lowered) speeds deemed "safe" - provide the best defense against such motor destruction...

  • cb1_mobile said:

    Such "plugging" may (substantially) "demagnetize" a BLDC motor's rotor - and must be avoided!

    Note that I referred to traction motors. These are DC motors with no magnets and no separate field control. In such motors, at least in the applications we were targeting, plugging is the primary braking mechanism (and yes, at full load).

    Robert

  • The restriction to "traction motors" evaded my recognition...
    Guidelines I presented are "very much" in play for BLDC Motors. (gaining immensely in popularity across "many" application areas...)
  • I too thought updating period and pulse width values at zero interrupt routine is the too much time-dependent method,

    so I'm going to update both values at down compare match interrupt and control GPIO by other independent pins when compare match and load interrupts occur.

    Do you think my way would not violate KISS?

    If there's a more simple way to use, your help would be appreciated.

  • Thank you for your reply.
    I have another question for you.

    I want to stop PWM at down compare match and reset PWM Generator counter.
    So I checked datasheet and TivaWare, and I found PWMSyncTimeBase function uses PWMSYNC to reset counter to 0.

    But as I tried to use PWMSyncTimeBase, counter didn't go back to 0 value.
    Is there a necessary condition like generator should be enabled or something?

    Look forward to your reply.
    Thank you
  • Hi Young Yoon,

    The best practice with PWM generators as CB1/Robert point out is to at first be friend with KISS.

    To answer your last question making sudden and wild changes to all generators counts can lead to catastrophic results in the DC inverter. Namely shoot through, the 1/2 bridge destructor must be arrested via accurately and timely controlled software/hardware constraints. Match count GEN updates COMP down may at first seem a good choice, the results may affect the outer current control loop in a bad way.

    By adding an outer control loop of (gradual) pulse width update cycles (1-2ms) at desired PWM frequency and timed control of dead band ST can be arrested while adding precision to PWM wave form generation.  

    For example C2000 adds CPU scavenging cycles to get PWM precision in a closed loop system. TM4C1294 leverages CPU speed (120Mhz) to keep the outer loop serviced in PWM duty cycle updates without skipping or missing update cycles.

  • young yoon said:
    I too thought updating period and pulse width values at zero interrupt routine is the too much time-dependent method,

    Let me explain my suggestion better. If you need to update both the period and the pulse width, the danger is that if they don't both get updated at the same time you can create a "too long" or "too short"  pulse. That might happen if, for example, you needed to increase the period, but wanted to keep the duty cycle roughly the same by also increasing the pulse width. Since the actual change only happens at count =0 (counting down), there is no issue if you call both PWMPeriodSet() and PWMPulseWidthSet() before the counter reaches zero. However, if you do not somehow synchronize your software to the counter, you run the risk that the call to PWMPeriodSet() might come before the counter reaches zero and the call to PWMPulseWidthSet() comes after the counter reaches zero. Then you will have one pulse with the new period, but the old pulse width.

    One simple, but inefficient way to do this is to read the counter. If the value is large enough, update both period and pulse width. If the value is too small, wait in the loop until the counter is reloaded. The first problem is that you will often waste CPU time if you pick a counter value too large. The second problem is how large is large enough? This can be difficult to determine particularly if the system is running with interrupts.

    OK, here is how it is really done. (Yes, this is a gentle nudge to go beyond KISS, but you can do this in steps.) Write a small routine for updating the period and width that stores the desired period and width in static variables and enables the PWM interrupt on counter equal to zero. Then in the PWM interrupt routine you quickly call PWMPeriodSet() and PWMPulseWidthSet() with the value in the static variables. This follows the principle that interrupt routines should be short. You actually have the entire period to get the new period and pulse width set, more time than if you use a down compare interrupt. The downside of this method is that it takes an additional cycle before the new values are updated.

    You can do a hybrid of the two methods. If the count value is high, just call PWMPeriodSet() and PWMPulseWidthSet() immediately. If the value is too low, enable the interrupt to do it. That way you get a fast update with no wasted time.

    Finally, if you only update the pulse width, or only update the period, you don't need to do anything put call the proper routine.