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.

MSP430 PWM generation with Varied steps from Interrupt



Hi Everyone,
I've been working on MSP430 Launchpad from few weeks. I've got an issue with evaluating some code in a project which i'm working on.
Please read ahead and help,
1. I have to vary PWM duty cycle in 6 steps by detecting interrupt from P3.1 switch on MSP Launchpad. After this is successful, I've to incorporate IR sensor and have to vary PWM Duty Cycle from that,which is secondary issue.
2. I tried ISR and varying PWM by 7.5% to 45%. This 45% is giving us max required output voltage (1.4 V). That method is only giving 4 steps variation,not 6 steps. 
3. And the present code which i sent has Switch-Case statement in which i'm varying according to the count of the interrupts. This is also giving me only 4 step variation. 
4. Is there anything wrong i'm doing in the code? Or having other time period will resolve?
Is there any other method? Should i use normal polling method or Watchdog timer for the count? If yes, how?
Please help me out in this issue.
Here's the code:
#include "msp430g2553.h"

float D = 7.5;
int /*total*/count = 0;

void main (void)
{
	//float T, X, D = 7;
	WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT

	  P1DIR |= BIT2;                       // P1.2 output
	  P1SEL |= BIT2;                       // P1.2 options select

	  P1REN |= BIT3;
	  P1IE |= BIT3; 					// P1.3 interrupt enabled
	  P1IES |= BIT3;
	  P1IFG &= ~BIT3; 					// P1.3 IFG cleared
	  __enable_interrupt();				 // enable all interrupts

	  TA0CCR0 = 100;                          // PWM Period
	  TA0CCTL1 = OUTMOD_7;                      // CCR1 reset/set
//	  X = D/100; T = 512 * X;
	  TA0CCR1 = 7.5;
	  TA0CTL = TASSEL_2 + MC_1 + TACLR;

	  __bis_SR_register(LPM0_bits);             // Enter LPM0
	  __no_operation();                         // For debugger

	while(1) {}


 }



#pragma vector=PORT1_VECTOR
__interrupt void Port_1(void)
{
//		if ( TA0CCR1 == 45 ) {
//			P1IFG &= ~BIT3;              // P1.3 IFG cleared
//			P1IES ^= BIT3;
//		}          			// toggle the interrupt edge,
//
//			else {

			count++;
				switch( count )
				{
				case 1: D = 15;
//				TA0CCR1 = ( 100 * (D/100) );
//								TA0CTL = TASSEL_2 + MC_1 + TACLR;
//						P1IFG &= ~BIT3;              // P1.3 IFG cleared
//						P1IES ^= BIT3;         			// toggle the interrupt edge,
					break;

				case 2: D = 22.5;
//				TA0CCR1 = ( 100 * (D/100) );
//								TA0CTL = TASSEL_2 + MC_1 + TACLR;
//						P1IFG &= ~BIT3;              // P1.3 IFG cleared
//						P1IES ^= BIT3;         			// toggle the interrupt edge,
					break;

				case 3: D = 30;
//				TA0CCR1 = ( 100 * (D/100) );
//								TA0CTL = TASSEL_2 + MC_1 + TACLR;
//						P1IFG &= ~BIT3;              // P1.3 IFG cleared
//						P1IES ^= BIT3;         			// toggle the interrupt edge,
					break;

				case 4: D = 37.5;
//				TA0CCR1 = ( 100 * (D/100) );
//								TA0CTL = TASSEL_2 + MC_1 + TACLR;
//						P1IFG &= ~BIT3;              // P1.3 IFG cleared
//						P1IES ^= BIT3;         			// toggle the interrupt edge,
					break;

				case 5: D = 45;
//				TA0CCR1 = ( 100 * (D/100) );
//								TA0CTL = TASSEL_2 + MC_1 + TACLR;
//						P1IFG &= ~BIT3;              // P1.3 IFG cleared
//						P1IES ^= BIT3;         			// toggle the interrupt edge,
					break;

				default : D = 7.5;
//				TA0CCR1 = ( 100 * (D/100) );
//								TA0CTL = TASSEL_2 + MC_1 + TACLR;
//						  P1IFG &= ~BIT3;              // P1.3 IFG cleared
//						  P1IES ^= BIT3;         			// toggle the interrupt edge,
						  count = 0;
					break;
				}
				TA0CCR1 = ( 100 * (D/100) );
				TA0CTL = TASSEL_2 + MC_1 + TACLR;
				P1IFG &= ~BIT3;              // P1.3 IFG cleared
				P1IES ^= BIT3;         			// toggle the interrupt edge,
}
//}


  • VenkataSainath Ravikanti said:
    float D = 7.5;

    You can’t use float with this MCU, only integers! Multiply your values with 10; D = 75, 150, 225, 300 etc.

    VenkataSainath Ravikanti said:
    TA0CCR0 = 100; // PWM Period

    Load TA0CCR0 with 1000.

    VenkataSainath Ravikanti said:
    TA0CCR1 = 7.5;

    Loading TA0CCR1 with 7.5 will result in TA0CCR1 = 7.

    The frequency of your PWM is now divided by 10, to change this you need to increase timer frequency and probably correct the TA0CCR values to match the desired frequency.

  • Leo is correct. You could set up TA0CCR0=(200-1); and TA0CCR1=15,30,45,60,75,or 90;

  • Thank you Mr. Leo,

    I did change the floats to integers. And still am not able to get six steps.. I changed the frequency as suggested below and varied the duty cycle in respective respective steps which individually are giving me correct voltages. But as a whole the interrupt is not able give 6-step variation in the output. Can't locate a prob in the code. Logic looks fine and the values are employed correctly now.

  • Thanks to OCY,

    The launchpad switch at P1.3 should be configured? Is there any rising edge and falling edge detection issue with it? Even though everything looks fine,why is it not able to give 6-step as in the algorithm. Is there any crack in the algorithm which i did not notice.???

  • Count should be volatile: volatile count = 0;

  • Hey Ravi kanth,

    Firstly,
    I think Just  for PWM generation your code works fine. Before quoting any thing I just want to know,
    have you checked Button interrupts in your code? I

    Were u a simple push button?

    If so u should not toggle edge selection bit 

    comment out this part 
    P1IES = ^Bit3;

    I thnk then It will run.

    Cheers.

  • Hey Leo, 
    I think, he wont get more than 1 interrupt coz at the end of interrupt he had changed the Edge selection.

  • I’m always too quick and only react on what I see on the fly. But Sri your right, de-bouncing is another issue here. Toggling the edge-level results here in two interrupt each button push (down & up). You should wait until the button is stable pushed, create a de-bounce circuit; Read the port a 100 times until all 100 readings are the same. And remove the edge-toggling.

  • Thanks Leo and Sri,


    I've done modifications according to what you suggested. Took PWM period as 1000 and given Duty Cycles accordingly which is fetching us the required voltage outputs. As Sri said..i've removed the Edge Selection in the both the areas of the code( in ISR and before ISR). It is a normal push button.

    Still I'm getting only four or three stages of PWM duty cycles though i'm coding Six. I think it is the problem of the on board switch. Edge Toggling may be the issue. I'll add a debounce circuit and let you know the result.


    Thank you Leo, Sri and OCY,once again. :)

  • I would sugget you to put some break points at every case statemt and track the flow upon every Button press. This way you can pin point the problem.

    As you say, you were getting four steps figure which of 6 you are getting out. 
    I think you are getting 2,3,4,5 cases but not 1 and 6. :) may be.  ;) .
    I would say track the program along with the register changes you will know what's happening. 

    Still you find problem, dont worry guys are here to help you out.
    cheers!

  • Hi Sri,


    I've done all the modifications and put the breakpoints at every case statement. They are being parsed. No issue in that. I've checked it before too. I think there's an issue with the switch as you guys said. Even after the debounce circuit is attached,there's a skip sometimes. On releasing the switch, after the press, it is changing the state. Press n Hold worked sometimes. Anyway switch is only evaluation,i won't be using it in the future product. I'll use IR sensor with remote controller to change the PWM duty cycle. So i hope there won't be any issue with that.


    Thank you all for the cooperation and help. I'm grateful. :)

  • Always be aware that mechanical switched can bounce a lot, especially when they comes old and dirty, up till 1mS I have seen. The 100 count I cave you is maybe not enough for your switch you can increase it to 1,000 or even to the max 65,000.

    A good way is to use a timer which reads the switch periodically and after n equal readings you have a valid key. This applies also to IR sensors or whatever sensors.

**Attention** This is a public forum