/***************************************************************************
Arm.c
ME 218B Project Hats Off
Team Firefox
March 7, 2010
Upper arm stepper = PS2, PS3, PP0, PP2
Lower arm servo = Timer0 PT2, Timer 6
DDRT = 0x4;
//00000100 for
servo
DDRP = 0x05;
//00000101 for
stepper 1=output
DDRS = 0x0C;
//00001100 for
stepper 1=output
***************************************************************************/
/*-------------------------- Include Files
-------------------------------*/
#include
"Arm.h"
/*-------------------------- Module Definitions
-----------------------------*/
#define CMD fullCmds
typedef enum { HIGH_ARM,
LOW_ARM
} ARM_t;
/*-------------------------- Module Functions
-----------------------------*/
static void pulseServo(unsigned int width);
static void stepMotor(int);
static void StepMotorModule_runMotor(int, int);
/*-------------------------- Module Variables
-----------------------------*/
static unsigned int
servo_desPos; //lower arm servo
static unsigned int
servo_curPos;
static unsigned int
stepper_desPos; //upper arm stepper
static unsigned int
stepper_curPos;
static unsigned int
servo_lastCmdTime;
static unsigned int
lastStepTime, curTime;
static int
curStepStage;
static unsigned int
skipSize;
/*--------------------------
const static ARM_t TargetHeights[16] = { HIGH_ARM, //0
HIGH_ARM, //1
LOW_ARM, //2
HIGH_ARM, //3
HIGH_ARM, //4
LOW_ARM, //5
HIGH_ARM, //6
HIGH_ARM, //7
HIGH_ARM, //8
HIGH_ARM, //9
LOW_ARM, //10
HIGH_ARM, //11
HIGH_ARM, //12
LOW_ARM, //13
HIGH_ARM, //14
HIGH_ARM};//15
//servo minPulseWidth = 1550
--> 0degrees
//servo maxPulseWidth = 8000
--> 180degrees
const static unsigned int
cmdDelayMS = 22;
const static unsigned int
servo_outPos = 1520; //7600; flip to
swing the other way. also switch inequality sign in
//isArmStopped
const static unsigned int
servo_homePos = 7600; //1520;
const static unsigned int
servo_midPos = 4000;
const static unsigned int
servo_waveOutPos = 3000;
const static unsigned int
servo_waveInPos = 4000;
const static unsigned int
stepper_highPos = 450;
const static unsigned int
stepper_lowPos = 500;
const static unsigned int
stepper_homePos = 0;
const static unsigned int
stepper_topPos = 350;
const static unsigned int
stepper_midPos = 100;
const static unsigned int
stepper_attackPos = 220;
const static unsigned int
servo_slowSkip = 120;
const static unsigned int
servo_fastSkip = 200;
const static unsigned int
servo_waveSkip = 80;
const static int
stepper_waitTimeFast
= 4;
const static int
stepper_waitTimeSlow
= 7;
static int
CW = 1;
static int
CCW = 0;
static int
maxSteps = 4;
const static int
fullCmds[] = {10, 9, 5, 6}; //full step drive
const static int
waveCmds[] = {8, 1, 4, 2}; //Wave drive
const static int
halfCmds[] = {10, 8, 9, 1, 5, 4, 6, 2}; //Half step drive
//Initializes OC on the servo to create a higher resolution PWM
void Arm_Init(void) {
MyTimer_Init(); //Already initializes Timer 0 to 3MHz
//TIM0_TSCR1
|= _S12_TEN; //Enable timer
//TIM0_TSCR2
= _S12_PR1 | _S12_PR0; //24MHz/8 = 3MHz
TIM0_TIOS |=
_S12_IOS6; //Set timer0 channel 6 to OC
TIM0_TCTL1 |=
_S12_OL6 | _S12_OM6; //Program a
rise on compare
TIM0_TTOV |=
_S12_TOV6; //Toggle bit6 on overflow
pulseServo(servo_homePos);
servo_desPos =
servo_homePos; //Set servo to home position
stepper_desPos =
stepper_homePos; //Set stepper to home position
lastStepTime = MyTimer_GetTime();
servo_lastCmdTime =
MyTimer_GetTime();
curStepStage = 0;
PTS &=
(BIT2LO); //Turn off
both coils in stepper motor
PTS &=
(BIT3LO);
PTP &=
(BIT2LO);
PTP &=
(BIT0LO);
}
//Steps the motor based on waitTime
static void StepMotorModule_runMotor(int
waitTime, int
dir) {
curTime = MyTimer_GetTime();
if ((curTime - lastStepTime) >= waitTime) {
stepMotor(dir);
lastStepTime =
curTime;
}
}
//Steps the stepper motor using full step drive
static void stepMotor(int dir) {
char
temp;
if
(dir == 0){
curStepStage = curStepStage + 1; //Update current step in array
stepper_curPos++;
}
else{
curStepStage =
curStepStage - 1; //Update current step in array
stepper_curPos--;
}
if (curStepStage < 0) curStepStage
= maxSteps-1; //If overflow the array, loop back
if (curStepStage == maxSteps) curStepStage
= 0;
temp = (char)(CMD[curStepStage]); //CMD
= fullCmds array
//write out to
0 pin PS2
if (temp & BIT0HI) PTS |= BIT2HI;
else PTS &= BIT2LO;
//write out to
1 pin PS3
if (temp & BIT1HI) PTS |= BIT3HI;
else PTS &= BIT3LO;
//write out
to 2 pin PP2
if (temp & BIT2HI) PTP |= BIT2HI;
else PTP &= BIT2LO;
//write out
to 3 pin PP0
if (temp & BIT3HI) PTP |= BIT0HI;
else PTP &= BIT0LO;
}
//Set the pulse width of the rise time on OC.
//A change in width causes a change in servo angle
static void pulseServo(unsigned int width){
TIM0_TC6 =
0xffff-width;
//Sets the pulse width
servo_curPos =
width;
}
//Set servo and stepper to home position
void goToHomePosition(void){
stepper_desPos =
stepper_homePos;
servo_desPos =
servo_homePos;
}
//Set servo and stepper to attack position
void goToAttackPosition(void){
stepper_desPos =
stepper_attackPos;
servo_desPos =
servo_homePos;
}
//Begin the wave sequence in the servo and stepper
void waveArm(void){
stepper_desPos =
stepper_attackPos;
servo_desPos =
servo_outPos;
skipSize = servo_waveSkip;
}
//Checks if the arm has stopped waving.
//Returns 1 if desired position == current position for both
stepper and servo
char isWaveStopped(void){
if
(stepper_desPos
!= stepper_curPos){
if (stepper_desPos > stepper_curPos){ //Send arm
out
StepMotorModule_runMotor(stepper_waitTimeFast,
CCW);
}
else if
(stepper_desPos
< stepper_curPos){ //Bring
arm in
if (stepper_curPos > stepper_topPos){ //When
raising arm after swinging, step slower.
StepMotorModule_runMotor(stepper_waitTimeSlow,
CW); //(otherwise it
skips b/c it can't raise the arm that fast)
}
else
//Step faster after passing the high point.
StepMotorModule_runMotor(stepper_waitTimeFast,
CW);
}
}
if
(servo_desPos
!= servo_curPos){
if ((MyTimer_GetTime() - servo_lastCmdTime) > cmdDelayMS){
servo_lastCmdTime =
MyTimer_GetTime();
if
(servo_desPos
< servo_curPos){ //Wave out
if (servo_curPos <= servo_waveInPos) skipSize
= servo_waveSkip; //Wave beginning
point. Once past, move at
waveSkip
else skipSize = servo_slowSkip; //When not in wave region, move slow
pulseServo(servo_curPos
- skipSize);
}
else if
(servo_desPos
> servo_curPos){ //Wave in
skipSize = servo_waveSkip;
pulseServo(servo_curPos
+ skipSize);
}
}
}
if
(servo_curPos
<= servo_waveOutPos){ //When servo
gets to the end of the wave, bring servo back to wave beginning
servo_desPos =
servo_waveInPos;
}
return
((servo_curPos
== servo_desPos) && (stepper_curPos ==
stepper_desPos));
}
//Swing the arm to the target height (either high or low)
void swingArm(int targetNum) {
ARM_t
pos;
pos =
TargetHeights[targetNum];
if
(pos == HIGH_ARM){
stepper_desPos =
stepper_highPos;
skipSize = servo_slowSkip;
}
else{
stepper_desPos =
stepper_lowPos;
skipSize = servo_slowSkip;
}
}
//Checks to see if the arm has stopped moving
char isArmStopped(void) {
if
(stepper_desPos
!= stepper_curPos){
if (stepper_desPos > stepper_curPos){ //Need to raise arm
StepMotorModule_runMotor(stepper_waitTimeFast,
CCW);
if (stepper_curPos >= stepper_attackPos+1) servo_desPos
= servo_midPos; //Swing out the servo partway
if (stepper_curPos >= stepper_highPos) servo_desPos
= servo_outPos; //Swing servo for attack
}
else if
(stepper_desPos
< stepper_curPos){ //Need to bring back in
if (stepper_curPos > stepper_topPos){
StepMotorModule_runMotor(stepper_waitTimeSlow,
CW);
}
else
StepMotorModule_runMotor(stepper_waitTimeFast,
CW);
}
}
if
(servo_desPos
!= servo_curPos){ //Need to
swing lower servo
if ((MyTimer_GetTime() - servo_lastCmdTime) > cmdDelayMS){
servo_lastCmdTime =
MyTimer_GetTime();
if (servo_desPos > servo_curPos){ //Bring servo back
pulseServo(servo_curPos
+ skipSize);
if (servo_curPos >= servo_midPos) stepper_desPos
= stepper_attackPos;
}
else if
(servo_desPos
< servo_curPos){ //Swing
servo out
pulseServo(servo_curPos
- skipSize);
}
}
}
if
(servo_curPos
<= servo_outPos){ //homePos = 7600, outPos = 1520
servo_desPos =
servo_homePos;
}
return
((servo_curPos
== servo_desPos) && (stepper_curPos ==
stepper_desPos));
}