When I came on board as the programming mentor for the TechnoKats in 2004, I didn't know anything about the IFI control system. I did have some clear ideas on software architecture, and they fortunately turned out to match the way things were set up in the system. I have three basic pieces of advice for everyone who starts with the default code.
First, make good use of abstractions. Don't write code that directly names joystick input pins and pwm output pins. Instead, use aliases like this:
Code:
#define OI_LeftDrive p3_y
#define OI_RightDrive p4_y
#define RC_DIG_Pressure rc_dig_in09
#define RC_RLY_Compressor relay6_fwd
#define RC_PWM_LeftFront_CIM pwm09
#define RC_PWM_LeftRear_CIM pwm10
#define RC_PWM_RightFront_CIM pwm11
#define RC_PWM_RightRear_CIM pwm12
Second, try to split the functions that read the operator inputs from the functions that set the motor and relay outputs, and try to keep both of them distinct from the functions that turn inputs into outputs. Put all your OI stuff in the equivalent of
Default_Routine(), and keep track of what your operators are requesting in a global variable structure containing things like desired speed, desired turn rate, desired arm position, etc. Put all your motor control stuff in
Process_Data_From_Local_IO(), basing the outputs on what's in that global variable structure. Put the code that decides how to change from what the robot is doing now to what it's supposed to do next in a separate function that manipulates the global structure based on robot sensors. It might seem inefficient to do it that way, but it permits a lot of flexibility, and the RC has plenty of power.
Finally, try to keep separate tasks in separate functions, but try to keep everything relating to a specific robot subsystem together. Our 2007 program has functions like
Read_OI_Input() and
Write_OI_Feedback() in the
user_routines.c file, and
process_feedback(),
process_drivebase(), and
process_arm() in
user_routines_fast.c.