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.

MSP432 50Hz Servo PWM

I am attempting to drive a 180 degree 50Hz hobby servo with my MSP432 Launchpad. I calculated the frequency using 12Mhz/50Hz to get my tick period. The servo seems to be sort of working, but it drives the servo arm to 180 degrees at a 3ms at a tick cycle of 36000 duty cycle, as opposed to a 2ms tick cycle of 24000 duty cycle, and does not seem to hold well. I will post source code below. Any help would be greatly appreciated! 

/* DriverLib Includes */
#include "driverlib.h"

/* Standard Includes */
#include <stdint.h>

#include <stdbool.h>

/* Timer_A PWM Configuration Parameter */
Timer_A_PWMConfig pwmConfig =
{
TIMER_A_CLOCKSOURCE_SMCLK,
TIMER_A_CLOCKSOURCE_DIVIDER_1,
240000,
TIMER_A_CAPTURECOMPARE_REGISTER_1,
TIMER_A_OUTPUTMODE_RESET_SET,
12000
};

int main(void)
{
/* Halting the watchdog */
MAP_WDT_A_holdTimer();

/* Setting MCLK to REFO at 128Khz for LF mode
* Setting SMCLK to 64Khz */
CS_setDCOCenteredFrequency(CS_DCO_FREQUENCY_12);

/* Configuring GPIO2.4 as peripheral output for PWM and P6.7 for button
* interrupt */
MAP_GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P2, GPIO_PIN4,
GPIO_PRIMARY_MODULE_FUNCTION);
MAP_GPIO_setAsInputPinWithPullUpResistor(GPIO_PORT_P1, GPIO_PIN1);
MAP_GPIO_clearInterruptFlag(GPIO_PORT_P1, GPIO_PIN1);
MAP_GPIO_enableInterrupt(GPIO_PORT_P1, GPIO_PIN1);

/* Configuring Timer_A to have a period of approximately 500ms and
* an initial duty cycle of 10% of that (3200 ticks) */
MAP_Timer_A_generatePWM(TIMER_A0_BASE, &pwmConfig);

/* Enabling interrupts and starting the watchdog timer */
MAP_Interrupt_enableInterrupt(INT_PORT1);
MAP_Interrupt_enableSleepOnIsrExit();
MAP_Interrupt_enableMaster();

/* Sleeping when not in use */
while (1)
{
MAP_PCM_gotoLPM0();
}
}

/* Port1 ISR - This ISR will progressively step up the duty cycle of the PWM
* on a button press
*/
void PORT1_IRQHandler(void)
{
uint32_t status = MAP_GPIO_getEnabledInterruptStatus(GPIO_PORT_P1);
MAP_GPIO_clearInterruptFlag(GPIO_PORT_P1, status);

if (status & GPIO_PIN1)
{
if(pwmConfig.dutyCycle == 36000)
pwmConfig.dutyCycle = 12000;
else
pwmConfig.dutyCycle += 6000;

MAP_Timer_A_generatePWM(TIMER_A0_BASE, &pwmConfig);
}
}

  • Hi Jacob,

    Can you please confirm that your output timer period and duty cycle is as expected? Timer_A0 is a 16-bit timer and TA0CCR0 cannot be loaded with a value above 2^16 (65,536) whereas you try to load a value of 240,000 in the PWM configuration parameter. As you probably know, it is important for a servo motor to operate at 20 ms periods with pulse widths between 1 and 2 ms and you may need to divide your input timer clock source accordingly in order to properly form the desired period.

    Regards,
    Ryan
  • Hi Ryan and Jacob,

    Only a little detail: Even 65536 would be too much, it is ((2^16)-1), so 65535 maximum.

    Dennis

**Attention** This is a public forum