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.

MSP430F5418A: I need to change the PWM frequency to control Heater levels

Part Number: MSP430F5418A

Hi,

I'd prefer to use the driverlib code, though setting registers is OK, too.

The Heater is on P1.4, should be 10kHz. I need to use different frequencies for different Heater levels.

  • Which timer do I need? TIMER1_A0 or  TIMER0_A1? (TIMER0_A0 is already used as the main system timer)
  • How do I change frquencies while the program is running?

In the Picollo DSP28035 was able to change the PWM frequency by changing the CTRMODE to 

TB_COUNT_DOWN  // heater off
TB_COUNT_UPDOWN  // heater 50%
TB_COUNT_UP  // heater 100%

I need to do something similar using with the MSP430:

    switch (Param.Heater_Mode)
    {
       case HEATER_OFF:       // Constantly off
   		  EPwm7Regs.TBCTL.bit.CTRMODE = TB_COUNT_DOWN;  // 0%
   		  HeaterState = HEATER_OFF;
       break;

       case HEATER_AUTO_HI: // Automatic
       case HEATER_AUTO_LO: // Automatic
    	   EPwm7Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP;  // 100%  // for now
    	   HeaterState = HEATER_ON_HI;
       break;

       case HEATER_ON_LO:  // Constantly on low
    	   EPwm7Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN;  // 50%
    	   HeaterState = HEATER_ON_LO;
       break;

       case HEATER_ON_HI:  // Constantly on high
    	   EPwm7Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP;  // 100%
    	   HeaterState = HEATER_ON_HI;
       break;

       default:
		  EPwm7Regs.TBCTL.bit.CTRMODE = TB_COUNT_DOWN;  // 0%
		  HeaterState = HEATER_OFF;
       break;
    }

Thanks for any help,

Mechi

  • Per data sheet (SLAS655F) Table 6-43, P1.4 is TA0.3, so you want TimerA0, CCR3. Set the period (Up mode) with CCR0 (1MHz/10kHz=100-1), and set/vary the duty cycle with CCR3.

    There's a non-dynamic example using TA1.1 in msp430x54xA_ta3_16.c here:

    https://dev.ti.com/tirex/explore/node?node=ADYyfmJIbXBLdAiF5.SUGg__IOGqZri__LATEST

  • Point of order, it is not the frequency that affects the heater power but the duty cycle. As long as you keep the pulse width the same as you are changing the frequency, you are changing the duty cycle.

  • And just to check - I can at any time change the mode direction? Somehow I found that changing between modes gives me the 3 settings - though I will have to experiment with different duty cycles to realize the full potential of the heater.

    Thanks,

    Mechi

  • I put the following in my code:

      // Set up PWM for heater
      //P1.4 output and options select
      P1SEL |= HEATER_BIT;                      // P1.4 options select
      TA0CCR0 = 512-1;                          // PWM Period
      TA0CCTL3 = OUTMOD_7;                      // CCR3 reset/set
      TA0CCR3 = 384;                            // CCR3 PWM duty cycle
      TA0CTL = TASSEL_2 + MC_1 + TACLR;         // SMCLK, up mode, clear TAR
    
      //__bis_SR_register(LPM0_bits);             // Enter LPM0
    

    if the line

    __bis_SR_register(LPM0_bits);             // Enter LPM0

    is not commented, the Heater works - but I don't get any other interrupts and the system stops.

    Without this line, the heater doesn't work.

    How do I start the PWM and TA0 in a way that won't bother the rest of the system?

  • Can I change the PWM duty cycle (TA0CCR3) during the program? Do I have to stop and start anything, or can I just set the register at will?

  • With this code I receive the output pictured below.

    4kHz frequency and 75% duty cycle - which is what I expected.

    But why is there a 15+ms break between activity? As if the PWM itself works on a 50% duty cycle.

  • I figured this out - the gap was because the code linked to SMCLK (TASSEL_2) - and when I linked to TACLK (TASSEL_0), there isn't a gap.

    But if I'm linked to any other clock - I can only get 50% duty cycle.

    I'm going back to SMCLK - so that I can change the kHz frequency and the duty cycle.

    Again - why are there the gaps?

  • You can change the mode (MC) and/or the CCR pretty much any time.

    Changing the mode on the fly is a very unusual usage (there is no Down mode, so you can't use it to invert the PWM).

    Changing the CCR is routine. The TimerA CCRs aren't buffered, so the effect is immediate. This can cause glitches depending on the momentary state of the counter (TA0R). For a fast PWM, and a slow device (heater as LPF), these glitches probably don't matter to you.

    Going into LPM0 does not disable interrupts, nor does it enable them. If you've enabled interrupts (GIE) elsewhere I don't know what would cause your symptom.

    LPM does affect the program flow, in that main() halts at that point until explicitly awakened. (Do Not use LPM in an ISR.)

    I don't see anything in the code you've presented that would cause that PWM pause. I suspect the cause is in some other code (not shown).

  • The program has RS232 communication and A2D readings as well as the heater.

    When running in the debugger, the program stops at this line and doesn't continue.

    What is meant by "until explicitly awakened"?

    Why must it be awakened? Isn't there a way to start the PWM without stopping...so it should be continuous and doesn't need any intervention?

    Thanks,

    Mechi

  • "explicitly awakened" by an ISR issuing a "LPM0_EXIT;" [Ref User Guide (SLAU208Q) Sec 1.4].

    The PWM does not require any intervention. It runs until you stop it. (One way to stop it is to stop its clock, but SMCLK is not stopped in LPM0.) That example I mentioned above goes into LPM0 (with interrupts disabled) at the end. Its main() will never proceed, but the PWM continues to run.

    Since your code is doing other things, are you sure you want to use LPM here?

    [Edit: In case it needs to be said: You don't need to use LPM to use PWM. That LPM0 at the end of the Example is not part of the PWM. It's just part of the demonstration -- they ran out of things to do, so they (deliberately) stopped the CPU (forever) there, rather than, say, spinning in a "while(1);". ]

  • I don't want to use LPM0.

    But if I remove that line, then the PWM doesn't work at all.

    That's my question.

  • Hello Mechi,

    Have you tried replacing __bis_SR_register(LPM0_bits); with __bis_SR_register( GIE ); and then if you need to enter a low power mode you do that on a separate line. The __bis_SR_register( GIE ); will enable interrupts globally and shouldn't force you into a LPM.

    Luke

  • It really sounds like some other part of your system is interfering with you, and going into LPM right then prevents that other part from running (and getting in the way).

    Prime suspects would be anything that messes with the (a) TA0 or (b) P1SEL/P1DIR configuration.

    [Edit: Messing with P1DIR could cause trouble as well.]

  • Thanks Bruce.

    You're right - I thought of this also after work yesterday - and there is something that's interfering with the clock.

    I changed the main clock to TB0 and now the device is working with the heater.

    Thanks,

    Mechi

**Attention** This is a public forum