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.

MSP430FR2311: Servo motor

Part Number: MSP430FR2311


Hello TI community, 

I am working with msp430fr2311 to run a servo motor in clockwise and counter clock wise direction each for 3 seconds with a pause of 6 seconds in between. 

I am trying the following code, but it does not work for me at all. It would be great if you could let me know where I am going wrong. 

Thanks for your time. 

#include <msp430.h>

int main(void)
{
    WDTCTL = WDTPW | WDTHOLD;                 // Stop WDT
    // Configure GPIO
    P2DIR |= BIT0 + BIT1;
    P2SEL0 |= BIT0 + BIT1;
    // Disable the GPIO power-on default high-impedance mode to activate
    // previously configured port settings
    PM5CTL0 &= ~LOCKLPM5;

    TB1CCR0 = 20000-1;                        // PWM Period is 20ms or (20,000/1,000,000 Hz)
    TB1CTL = TBSSEL__SMCLK | MC__UP | TBCLR;  // SMCLK, up mode, clear TBR

    TB0CCTL1 = CAP__COMPARE + CCIE;                             // compare mode + enable interrupts
   TB0CTL = TBSSEL__ACLK  | CNTL__16 | MC__CONTINUOUS | TBCLR   ; //use ACLK, max counter length (TBxR) 16bits, continuous mode, start timer
   // TB0CTL = TBSSEL__ACLK | MC__CONTINUOUS;

    if (TB1CCR1==1800){
        __delay_cycles(3000000);                  // servo moves ccw for 3 seconds
        TB1CCTL1 = OUTMOD_7;                      // CCR1 reset/set
        TB1CCR1 = 1550;                           // Stop the servo

        if (TB1CCR1==1550){
        __delay_cycles(6000000);                //Servo is stopped for 6 seconds
        TB1CCTL1 = OUTMOD_7;                      // CCR1 reset/set
        TB1CCR1 = 1300;                           //Move servo cw

        if(TB1CCR1==1300){
            __delay_cycles(3000000);              //servo moves cw for 3 seconds
            TB1CCTL1 = OUTMOD_7;                  // CCR1 reset/set
            TB1CCR1 = 1550;                       // Stop the servo
                         }

        __bis_SR_register(LPM0_bits);             // Enter LPM0
        __no_operation();
                           }
                        }

    while(1) {
    __bis_SR_register(LPM0_bits + GIE);       // Enter LPM0
    __no_operation();                         // For debugger

    /*
    TB1CCTL1 = OUTMOD_7;                      // CCR1 reset/set
    TB1CCR1 = 1550;                           // Stop the servo

    TB0CCR0 = 32767;                          //I'm not sure this is doing anything
    TB1CCTL1 = OUTMOD_7;                      // CCR1 reset/set
    TB1CCR1 = 1300;                           // move servo Clockwise
    */
    }
}


//Timer_B1 TBCCR1 Interrupt Vector Handler Routine
#pragma vector = TIMER0_B1_VECTOR
__interrupt void TIMER0_B1_ISR (void)
{
  switch(__even_in_range(TB0IV,TB0IV_TBIFG))
  {
      case TB0IV_NONE: break;  //Vector 0: No interrupt
      case TB0IV_TBCCR1:       //Vector 2: TBCCR1 CCIFG. Interrupt source:capture/compare R1. Interrupt Flag: TBxCCR1 CCIFG.
          TB1CCTL1 = OUTMOD_7;                      // CCR1 reset/set
          TB1CCR1 = 1800;                           // CCR1 PWM duty cycle, start servo Counterclockwise

          __bic_SR_register_on_exit(LPM0_bits + GIE); //exit LPM0

          break;
      case TB0IV_TBCCR2: break;//Vector 4: TBCCR2 CCIFG
      case TB0IV_TBIFG: break; //Vector 6: TBIFG.
      default: break;

  }
}

  • What does it do now? From reading, I expect it is idle for 2 seconds, then moves CCW and stays there.

    I suspect you want all those comparisons on TB1CCR1 to be in the while(1) loop. As it is they're executed once only -- actually zero times, since TB1CCR1==0.

    Your while(1) loop will wake up every 2 seconds. Consider using a counter as a clock, and make your CCR1 changes at particular values, e.g. CCW at 2, then middle at (2+6), then CW at (2+6+2).

    If you're using the Launchpad, you probably should remove the jumper on J11 (P2.0 LED).

    Are you fairly certain your servo will run at 3.3V? Many only run at 5V.

    Unsolicited:

    >  __bic_SR_register_on_exit(LPM0_bits + GIE); //exit LPM0

    this disables GIE in main(), which will get you in trouble eventually. Try:

    >  __bic_SR_register_on_exit(LPM0_bits); //exit LPM0

  • Thanks for your reply. 

    My motor currently does not move at all. It works on 5V. 

  • If it's a 5V servo, then your 3.3V "high" PWM level might not register as "high" (Vil) in the servo.

    You can introduce a 3V->5V voltage-translator chip to fix this. It might  be quicker/cheaper to buy a 3V-capable hobby servo. Here's one from Adafruit

    https://www.adafruit.com/product/169

  • Thanks for your reply. So there is no sample code for controlling 5V servo motor using msp430 that I can refer to? 

  • The 3V/5V thing is electrical, so different code won't help. You can try powering the servo with 3V and see what happens. It may or may not work, but it's a quick experiment.

    I haven't seen any sample code from TI to do this. You could probably search github. I think you've got the code pieces you need, you just need to re-arrange them. (I mentioned a couple of possibilities above.)

**Attention** This is a public forum