Jump to content
43oh

Non-ADC-driven PWM servo control with Launchpad


Recommended Posts

Hey all. I've searched and read through a number of posts about running servos on the launchpad and used some of the code I've found in some of the posts. I'm using the MSP430G2231 on the launchpad with a Futaba S3003. The S3003 wants a 20ms period (50 Hz) with a centering pulse of about 1.5ms.

 

I don't have any pots on me so I was trying to hardcode a centering function.

 

#include 

void main(void)
{
 // Stop watchdog
 WDTCTL = WDTPW + WDTHOLD;

 P1DIR |= BIT0;

 // Set clock to 1 MHz
 DCOCTL= 0;
 BCSCTL1= CALBC1_1MHZ;
 DCOCTL= CALDCO_1MHZ;

 // SMCLK = 1 MHz / 8 = 125 KHz (SLAU144E p.5-15)
 BCSCTL2 |= DIVS_3;

 // Make P1.6 (green led) an output. SLAU144E p.8-3
 P1DIR |= BIT6;

 // P1.6 = TA0.1 (timer A's output). SLAS694C p.41
 P1SEL |= BIT6;              

 // PWM period = 125 KHz / 2500 = 50 Hz = 20ms periods
 TACCR0 = 2500;

 // Source Timer A from SMCLK (TASSEL_2), up mode (MC_1).
 // Up mode counts up to TACCR0. SLAU144E p.12-20
 TACTL = TASSEL_2 | MC_1;

 // OUTMOD_7 = Reset/set output when the timer counts to TACCR1/TACCR0
 // CCIE = Interrupt when timer counts to TACCR1
 TACCTL1 = OUTMOD_7 | CCIE;

 TACCR1 = 188;

 while(1);  
}

 

I simply made a Timer A up mode count with a period of 20ms and first tried doing some math to just have it constantly send a (1.5ms/20ms = 7.5% duty cycle) signal. So I take the 1MHz DCO and divide by 8 for SMCLK to get 125 KHz. 125KHz / 2500 = 50 Hz and gets me my 20 ms times. So TACCR0 = 2500. Then TACCR1 should be ~187-188. When I ran that code it actually tries to drive the servo past the stopper so something isn't right. I tried another S3003 and same thing.

 

So then I took my timer A and just did the following: I put in an interrupt vector and moved TACCR1 around between 10 and 2490 to see if it moved at all and it always stayed stuck at the stopper in the same direction. If I pull the the data line to the servo it resets to a center-ish position and then goes back to the stopper as soon as I plug it back in. If it helps its hitting the clockwise stop. To be honest, I'm not entirely sure its hitting the stop because it doesn't rotate very far (maybe 45 degrees if that) but it seems to be shaking and making noise as if it were trying to rotate further but is on the stop. Here's the code for that stuff...

 

#include 

int up = 0;

void main(void)
{
 // Stop watchdog
 WDTCTL = WDTPW + WDTHOLD;

 P1DIR |= BIT0;

 // Set clock to 1 MHz
 DCOCTL= 0;
 BCSCTL1= CALBC1_1MHZ;
 DCOCTL= CALDCO_1MHZ;

 // SMCLK = 1 MHz / 8 = 125 KHz (SLAU144E p.5-15)
 BCSCTL2 |= DIVS_3;

 // Make P1.6 (green led) an output. SLAU144E p.8-3
 P1DIR |= BIT6;

 // P1.6 = TA0.1 (timer A's output). SLAS694C p.41
 P1SEL |= BIT6;              

 // PWM period = 125 KHz / 2500 = 50 Hz = 20ms periods
 TACCR0 = 2500;

 // Source Timer A from SMCLK (TASSEL_2), up mode (MC_1).
 // Up mode counts up to TACCR0. SLAU144E p.12-20
 TACTL = TASSEL_2 | MC_1;

 // OUTMOD_7 = Reset/set output when the timer counts to TACCR1/TACCR0
 // CCIE = Interrupt when timer counts to TACCR1
 TACCTL1 = OUTMOD_7 | CCIE;

 TACCR1 = 10;

 // LPM0 (shut down the CPU) with interrupts enabled
 __bis_SR_register(CPUOFF | GIE);
}

// This will be called when timer counts to TACCR1.
#pragma vector=TIMERA1_VECTOR
__interrupt void Timer_A1 (void)
{
 int new_ccr1 = TACCR1;

 // Clear interrupt flag
 TACCTL1 &= ~CCIFG;

 if ( new_ccr1 >=  2490)//( 188 + 33 ) )
 {
   up = 0;
 } 
 else if ( new_ccr1 <= 10)//(188 - 33) )
 {
   up = 1;	
 }

 if (up)
 {
 	new_ccr1 += 10;
 }
 else
 {
 	new_ccr1 -= 10;
 }

 P1OUT ^= BIT0;

 // Wait to set the new TACCR1 until TAR has gone past it, so that we
 // don't get interrupted again in this period.
 while (TAR <= new_ccr1);
 TACCR1 = new_ccr1;
}

 

Can anyone see why this wouldn't all work?

 

I could solve this if I had my oscilloscopes from work...On a side topic: what's the cheapest one can buy an oscilloscope either standalone or PC-based?

:?:

 

EDIT: I just did some more research and saw that some servos need 5V for their data line so I may need to hook up an NPN to 5V on the line. I'll look into that some more after some chores...!

Link to post
Share on other sites

Old analog scopes go real cheap anymore, maybe $100 or even free to a good home. Almost like kittens.I got a new Rigol scope I love for $400 digital with all the bells and whistles, 50 Mhz but easy hack to make it a true 100 Mhz if you need to, software only. I have not done it yet no need 50 is fast enough so far.

 

Cheap ones on ebay:http://business.shop.ebay.com/Oscilloscopes-/104247/i.html?LH_Price=..100%40c&rt=nc&LH_ItemCondition=3000&_dmpt=BI_Oscilloscopes&_fln=1&_mPrRngCbx=1&_ssov=1&_trksid=p3286.c0.m282

 

One I just bought new and love http://www.saelig.com/PSBEB100/PSPC016.htm

Link to post
Share on other sites

Okay thanks I'll start shopping! I saw a cool USB oscilloscope for $175 but was hoping there was a sub-$50 kit out there somewhere.

 

I tried using TI's Grace to get the PWM working and got the same results. I'm starting to lean towards the issue being using 3.3V to drive the data line. Does anyone out there have any experience driving the Futaba S3003. It's pretty common so I'm sure some of you use it. If I need 5V, how can I rig that up? I'm a programmer...not EE

Link to post
Share on other sites

Hey Rob. I've read through your code before and must have missed that your 2nd example isn't based on a pot or shift register. Thanks for pointing that out. Bad news is it still doesn't work for me. Same results on pins 1.4-1.7 as I have with my code. I am driving the servo off of a 4 AA battery pack wired straight into the servo and then driving the data line from my launchpad.

Link to post
Share on other sites

I took your code and tested it with my servo.

First one keeps the servo near the center point, second one, see the video (works as expected.)

The only difference between LP's 3.6V and 5V is the speed at which the servo is turning.

One suggestion, try adjusting 20ms delay and see if that helps.

 

BTW, there was a fellow who had a similar problem.

 

Link to post
Share on other sites
Wow! Thanks! I managed to test it on my oscilloscope at work today and it was a good square wave 1.5ms per 20ms cycle just as I wanted. Gonna try powering the servo off the 5v on the launchpad instead of 4 AA pack when I get spare time.

 

I know this post is close to a week old but you need to make sure the grounds between the Launch pad and the servo are connected.

Link to post
Share on other sites

Well I tested it on the 5V and it worked fine. I later found a small line somewhere saying that the data and power line must match voltages so that was the problem. I managed to drive my Hobby Off-road RC cars front wheels with the launchpad and am working on the electronic speed controller for the motor. It operates on a PWM signal too but I can't find the info on its specs (I assume 20ms but doesn't work as expected; intermittent) but that's another story. Anyways I am driving servos and good to go on that now. Thanks all!

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...