Programming the Robot Controller

From FIRSTwiki

Jump to: navigation, search

Programming the FRC is necessary to get the most out of the control system. For simple robots, the default code will be sufficient. But for more advanced control, custom code must be added. This article attempts to explain how to begin modifying the default code to meet your specific purposes. The article assumes a familiarity with the C programming language (see Resources for C programming), and primarily focuses on that.

Note that prior to 2004, a the a BASIC stamp was used, which was programmed in PBASIC. 2004 marked a major switch in the Robot Controller, making PIC C the programming language of choice (along with assembly).

This article follows the structure of the 2004 Programming Reference Guide.

The PICmicro can be programmed in C or assembly. MPLAB IDE is the name of the free Windows program used to edit, compile, and debug programs. To download a program, IFI loader must be used. This software is included in the kit of parts, and is availalbe on the Innovation FIRST website (see Resources below).

Contents

About C

Comments

Comments are text within a program that the compiler ignores, but is present for the benefit of the programmer and others reading the code. Comments are used to explain what a specific piece of code does, or how it fits in the larger structure of the program. They do not affect in any way how the program runs. The C-style comment is deliminated with /* */, with text going in between. Comments can span multiple lines, but may not be nested. For example:

 /* This is
      allowed. */
 /*  but  /* this */ is most distinctively not */

When commenting, it is important to remember that what seems obvious at the time will become archaic in a few months. It is also important to remember that other people will often be examining the code, some which are trying to learn from it. Therefore, it is generally considered good practice to heavily comment program code. A good rule of thumb is that if you ever had to look at code and wonder "What does that do again?" then you need to comment. Keep in mind, however that comments should be high level code like this, for instance: x = y + z; /* adds y and z and puts the sum in x */ adds nothing. Finally, be concise.

Also allowed by the compiler, but not documented, are what are known as C++ style comments (so called because they were added in C++ and are not in the original C). They begin with 2 slashes and end at the end of the line.

//This is a comment
This_isnt_a_Comment();

There are several advantages to this:

  • Can be placed within a /* */ comment (aka a muliline comment)
  • You can use multi-line comments to comment out code w/o having to go through each line and add /* at the beginning

Variables

C is a heavily typed language. What this means is that when a variable is created, it must be a specific data type -- e.g., it could be an integer, or maybe a floating point number. (See List of data types for more information.) Variables are declared like this:

 unsigned int loop_counter_for_function_x = 0;

Note that it is possible to intialize variables when they are declared (set to 0 above), but this is not necessary. Also note that it is important to establish some sort of naming convention, preferably with less verbose names than above -- a general rule of thumb is that variables that are used most often should be shorter variable names, since they are typed out more, but less frequently used variables can have more informative, and hence longer, names.

It is possible to share variables between files, and is often quite important. For instance, if the variable arm_pos represents the position of the robot's arm, it might be useful to have in both user_routines.c and user_routines_fast.c (this way in can be used in normal control as well as autonomous mode). To do this, declare the variable in user_routines.c and then put the following statement in user_routines_fast.c:

 extern unsigned int arm_pos;

Macros as Aliases

Macros provide alternate and often shorter names for constants, variables, and sub-divisions of variables. This is significant because it can save on typing, and also allows for a certain layer of abstraction. Aliases are used extensively in the default code to provide convenient names for analog inputs, digital i/o, relay outputs, solenoid outputs, and PWM outputs. Aliases used by the default code are located in ifi_aliases.h; custom aliases might be placed in user_routines.h. Note that aliases are taken care of by the pre-processor by simple text substitution, and do not require any additional memory -- therefore they may be used liberally with little consequence. They are defined like this:

 #define AUTO_SEL_POT p2_wheel

Note that no semicolon is used -- if a semicolon is placed at the end of the line, it will be substituted when the alias is used, typically causing errors. Aliases can be useful because they allow for a bit of abstraction. For instance, if a potentiometer in p2_wheel is changed to p3_wheel, the rest of the code does not care -- only the alias has to be changed (this is preferred, of course, as opposed to changing many references).

Macros as Constants

Aside from aliases, macros also prove useful as standing for constants. They make the code more readable, that is, more understandable to the human. It also aids in adjusting the code for future use. For instance, if the program makes use of the value pi, rather than putting 22/7 in all the locations it is used, a macro would allow simply saying PI. Then, if more accuracy is desired, the define statement can be altered. E.g.,

 #define PI 22/7    
         /* first go */

NOTE:

Avoid putting comments on the same line as a #define. These lines have no punctuation. They are commands directly to the compiler. You are telling the compiler to use the following information whenever you use the macro in the c-code. The compiler will then stuff any comments into the code along with the defined variable. This can lead to strange reported errors.
 #define PI 3.14     
        /* more accurate */
 #define PI 3.14159  
        /* every milimeter counts! */

Also, imagine that for the autonomous mode, the robot needs to travel at a certain forward speed during a particular stage. Having that speed defined in an easily accessible location with other adjustable parameters makes changing it much easier. In general, macros aid in the development process.

Macros as Functions

Macros may also take arguments. Examples:

 #define SGN(Value) (((Value) < 0) ? -1 : (((Value) > 0) ? 1 : 0))
 #define ABS_DIF(Num1,Num2) (((Num1) > (Num2)) ? ((Num1) - (Num2)) : ((Num2) - (Num1)))
  • Don't put spaces between arguments, as that will cause it to end the name at the space (eg ABS_DIF(Num1,)
  • If an expresion is given as an argument, it is still compiled as a string replace. eg:
ABS_DIF(foo + bar, bar - foo)

would be compiled as

(((foo + bar) > (bar - foo)) ? ((foo + bar) - (bar - foo)) : ((bar - foo) - (foo + bar)))

About the default code

Initialization

Initialization takes place in main.c. First, the function IFI_Initialization is called. This should not be tampered with, as it is important for setting up the processor to handle the rest of the code. Next, however, the function User_Initialization is called. This function is in user_routines.c. Often there are things that the program only needs to execute the first time through. It is not necessary to create a variable and a conditional statement to handle this anymore, as the code can simply be placed in User_Initialization. For instance, it might be necessary to read in a sensor value, assign that to a setpoint, and then react in some way if it is in a certain range. In general, it is good practice to intialize most variables in this function that need initialization, rather than when they are declared, so that they are easy to get to and change when necessary.

Main loop

In main.c there is a while loop with the condition of 1. In C, 1 is always true, meaning that it is in effect, an infinite loop. It is important to understand this concept when programming the FRC. The program reads in data, processes it, then outputs other data, then repeats. For this reason, custom code will almost never include additional looping structures, and alogirthms must be adopted to this.

Process_Data_From_Master_uP

See also: MPLAB, Downloading a program, Robot Controller, Electronics and circuitry

Personal tools