Barry,
Let me reply to your first question. I created an auto mode with a "sequence of events" that were timed. I created two files, 'myAuto.c' and 'myAuto.h' (not really -- I'm simplifying). (BTW, the code examples below haven't been compiled and they probably have at least typo bugs.)
In the .h file I made a list of named states using the C 'enum' construct:
Code:
// myAuto.h
#ifndef MYAUTO_H // don't include it more than once!
#define MYAUTO_H
enum // auton state machine states
{
FIRST_CYCLE,
RUN_TO_TEE,
RAISE_ARM,
STOP
}
C assigns each one of those state names an integer value, probably starting with zero. I show them in time-sequence but that doesn't matter. By convention, these are all UPPERCASE, but they don't have to be.
Also in myAuto.h I #define some constants.
Code:
// machine cycles at about 38 Hz.
// exact rate is 10 MHz / 2^18
#define RUN_TO_TEE_TIME 380 // about 10 seconds ( 38 cycles / sec)
#define RAISE_ARM_RUN_MOTOR_TIME 80 // ~2+ secs
void
runAndRaise( void ); // advertise the function we will create in myAUto.c
// important for calling this function from another file
// that file will need "#include myAuto.h" so it
// knows the form of "runAndRase"
#endif // MYAUTO_H
(Naming constants is good practice for organizing your code. It's bad practice to put "naked constants" in your code, for at least three reasons: first, if one constant needs to appear more than once and you need to change it, you have to change it at each place (and you might forget one). Using #define you can change it in just one place and all uses change at once. Second, if you mis-type a
constant, the compiler won't catch it (all numbers are valid) but if you mis-type a
word you'll probably create something that the compiler can't figure out, and the compiler will catch your mistake for you. And the third reason is the word can say what the number represents (RUN_TO_TEE_TIME), so it is self-documenting.)
Okay, myAuto.c has a static int counter that counts each timed phase. Something like this:
Code:
// myAuto.c
//
#include "myAuto.h" // pick up the enum and #defines
void
runAndRaise( void ) // call this function from
// the file user_routines_fast.c
// inside User_Autonomous_Code() ,
// inside the "if (Clock > Old_Clock)" conditional
// don't forget to put #include "myAuto.h" at the top of
// user_routines_fast.c
{
static int timer = 0; // times each phase (state) of auton.
static unsigned char state = FIRST_CYCLE; // init to first state.
switch( state ) // executes once every .0262144 seconds
{
case FIRST_CYCLE: // let's initialize some things
timer = 0;
state = RUN_TO_TEE; // next time around, jump to this state
break; // that's all for this cycle.
case RUN_TO_TEE:
timer++;
runMotorsAndStuff(); // your code goes here
if ( timer > RUN_TO_TEE_TIME )
{
timer = 0; // reset timer for use in next state
stopMotors(); // your code goes here
runArmWinch(); // your code goes here
state = RAISE_ARM; // next time around jump to this state
}
break;
case RAISE_ARM:
timer++;
if( timer > RAISE_ARM_RUN_MOTOR_TIME )
{
timer = 0; // for consistency: not actually needed by next state.
stopArmWinch(); // your code goes here
state = STOP; // next state is stop
}
break;
case STOP:
// nothing: just sit there until end of auto.
break;
} // switch( state )
}
The "case" statements are shown in time sequence but it doesn't matter. Don't forget the "break" statement at the end of each case, otherwise the execution will just keep going into the code for the next case statement.
Hope that helps!
-Norm