i want to program a CC430 to drive 5 RC Servos simultaneously. so far, i have written a routine that drives 1 servo reliably. i would like to extend this routine so it drives 5 servos in parallel.
to drive this 1 servo, i am currently using CCR0 as the PWM period counter and and CCR4 for the pulse width. this all works just as expected. what i am struggling with is how to extend the code to drive 5 servos simultaneously without using up all the CCRs. even if i would use 1 CCR for each servo output, i would not have enough of them, as TA0 has only 5 CCR's, and one of them is used for the period. so i am 1 short. unfortunately, the 3 CCR's of TA1 are already used for some other timing tasks.
does anyone have some suggestions on how to drive 5 servos with 4 CCRs? i imagine there must be a way to do this with port mapping more than one PWM output pin to a single CCR and then do altering periods on either of the pins. at least 2 of my servos are not that time critical, so the could be driven with some sort of interleaved scheme.
on a slightly different subject, i would like to use a CCR register just like a variable. how can i store for example "TA0CCR4" and later use the variable so set the register? i tried the following, which didn't work:
u16 myTA0CCR4 = TA0CCR4;
myTA0CCR4 = <some_ccr_value> //compiles, but doesn't work
u16* myTA0CCR4_ptr = (u16*) TA0CCR4;
*(myTA0CCR4) = <some_ccr_value>; //compiles, but doesn't work
for reference, here is my current routine to drive 1 servo:
void driveServo(ServoWorker* servoWorker)
{
u16 ccr;
u8 distance;
//calculate the distance we need to travel (if any)
distance = (servoWorker->targetPosition < servoWorker->currentPosition) ?
(servoWorker->currentPosition - servoWorker->targetPosition) :
(servoWorker->targetPosition - servoWorker->currentPosition);
if(!distance)
return;
//calculate requested position in context of pulsewidth range
ccr = (((unsigned long)servoWorker->targetPosition * (servoWorker->servo->end-servoWorker->servo->start)) / 255) + servoWorker->servo->start;
//set period
TA0CCR0 = servoWorker->servo->speed-1;
//set duty cycle
TA0CCR4 = ccr/2;
//turn PWM on
TA0CTL = TASSEL_1 + MC_3;
//switch on servo
SERVO_ON(servoWorker->servoID);
//wait aproriate time to let servo finish travel
Timer1_A2_Delay(distance*30);
//turn off servo
SERVO_OFF(servoWorker->servoID);
//turn off PWM
TA0CTL &= ~(TASSEL_1 | MC_3);
//set current position to the new position we just drove to
servoWorker->currentPosition = servoWorker->targetPosition;
}