2006-2007
Interactive C Tutorial
Written by E. Fiore
CHS Robotics Team
a motor
b sleep
c augments
III) Defining Variables
V) LCD Screen Printing Overview
VII) Looking Up Functions in the XBC Manual
VIII) Macros and the Preprocessor
a #use
b #define
c Function or Macro? How to choose
IX) The XBC Camera
a X/Y Coordinate Getting Program
If you are reading this, then hopefully you wish to program in IC. Short for Interactive C, IC is a type of C language, like C++. Both C and C++ are used primarily for working out equations, but IC is different. IC has C commands plus unique commands that move motors and check sensors. In other word, the CHS Robotics Team uses this language to make our robots come to life.
You cannot meaningfully program for something that is not there. Programming is among many steps to a working robot; the first step is Design. Before you can build a robot, you should at least have a fairly good idea of what it should do and how it should do it. As a general rule (but there are always exceptions), think about how it would move, sense obstacles, identify targets, and move between points. Once you have that idea, the next thing to do is to Build it. This can be more difficult than it sounds. Often times your original design will have to be modified to make it possible to work. Be sure to test motors and sensors before you make them impossible to remove without destroying the entire frame. The next step is Programming. This is what makes your robot think and move, becoming more than just a pile of Legos. Programs can vary in complexity from just going forward to finding and picking up a colored ball. This tutorial will cover how to program IC for the XBC microcomputer, as well as how to use the XBC camera. One final step is necessary after programming: Testing. Test until you are certain it will do it right every single time, then test it once more. Debugging is essential to programming.
Like all programming languages, IC has a rigid syntax, or how to write the commands. For anyone who knows a C language, the syntax will be familiar. Otherwise, the most basic rules will be covered in this tutorial. To begin, let’s create a simple program that does nothing other than exist:
void main ()
{
}
This is how you should begin every IC program. The word “void” tells the compiler, or the program that changes the words you write into machine readable code, that the following function ends when it reaches the closing brace. The phrase “main ()” tells the compiler that this is the actual program to execute. If you misspell main, then the computer will not know what to do and gives you an error. The body of the program is included in the braces, { }. It is important to always have a closing brace for every opening brace, and visa versa, otherwise the computer will become confused and generate an error. Never assume the computer can figure out what you mean. It may be able to keep track of numbers better than you, but it is most definitely not as smart as you are. It does exactly what you tell it to do, whether that is what you want it to do or not. When you tell it to do something that it does not understand or cannot do, it generates an error.
Next, let’s make a program that tells an imaginary robot with motors plugged into motor ports 1 and 2 to go forward. You start this out the way you start out every program:
void main ()
{
motor(1,100);
motor(2,100);
}
In this program we have added the motor command. The motor command tells the compiler to turn on the specified motor at a certain power level. These are specified in the parenthesis. For example, the first command looks like motor (1,100). The first number tells the computer which motor port to use. The second number tells the computer what percent power to turn the motor at. The first number, when using the XBC, can be any real port, or a number 0 – 3. The second number can be anywhere from -100 to 100, with the “-” symbol meaning that percent power in the reverse direction. The second command tells the motor in port 2 to turn forward at full power. If wheels are attached correctly to the motors, the robot would move forward.
Notice that there is a semicolon at the end of both motor commands. THIS IS ABSOLUTELY NECESSARY!!! You need to put a semicolon at the end of every command, after the parenthesis. This tells the computer that you are done with that command and are ready to start the next one. After spelling, a forgotten semicolon is the most likely reason for an error. The semicolon is like a period. You can’t forget it.
The above program is good, but it is far from perfect. For example, it has no way to turn off the motors. The robot would have to be turned off to get it to stop. This is bad. To solve this, you might write this:
void main ()
{
motor (1,100);
motor (2,100);
motor (1, 0);
motor (2, 0);
}
The two inserted commands tell motors 1 and 2 to turn at 0% power, or not to turn at all. This may seem good, but since the computer executes the commands right after each other, it never moves. What you need to do is tell it to wait before turning off. To do this, use the sleep command.
void main ()
{
motor (1,100);
motor (2,100);
sleep (2.0);
motor (1, 0);
motor (2, 0);
}
This program tells the computer to turn on the motors, wait for two seconds, and then turn the motors off. Now is a good time to learn about a couple different things: augments and types of numbers. Every function has augments. Augments tell the function where to do its job and sometimes how. Functions can have any number of augments. The “main” function has no augments, hence the empty set of parenthesis. The sleep function has one augment, and that is how long to wait. The motor function takes two augments, which port and the speed. Another thing that you should notice is the augment for sleep; it is a decimal number. There are several types of numbers in IC, each with their own set of similar rules. They include int, float, long, and char. char stands for a character, but is not commonly used in basic IC programming. int, float, and long, however, are important to learn the syntax of. int stands for integer. You can assign a positive or negative whole number to an int. A float is a floating point number, or a decimal number. If a float is needed, a decimal point must be there. long is slightly different from the other two. A long is just a bigger int, or it can hold numbers of higher magnitude. Use long numbers when you need to work with large numbers. The format for a long number is the number followed by a capital “L” (ex. 11000L). It is important to not confuse the different formats of numbers. Errors occur if you try to mix types directly, such as trying to multiply a float and an int. There is a way to do this by converting the type of a number, but this will be covered later. Returning to the above program, you will notice that the motor command takes two int augments, while the sleep command takes one float augment. It is important to remember what types of augments each command takes, so errors will not occur in the program.
Telling a robot to move around and wait is good, but a robot that only does this is not truly smart. That is where sensors come in. The most basic sensor to use is the touch sensor. These sensors tell the robot when something is pressing on the button. Say you had a robot with a touch sensor plugged into port 8 and want it to start out forward, wait for two seconds, stop, and then if the touch sensor is pressed it will go backward for a second.
void main ()
{
motor (1,100);
motor (2,100);
sleep (2.0);
if (digital (8) == 1)
{
motor (1,-100);
motor (2,100);
sleep (1.0);
}
ao ();
}
Before delving into how the if statement works, let me point out the new function I used. The function ao () turns all motors off. It takes no augments. It is good for basic programs where you don’t have various motors to keep track of.
Now is also a good time to explain the parts of a function. Take a void function for format:
void (<augments>)
{
<body functions>
}
The void tells the computer that the function will not have a return statement in there; do not worry about return for now. The augments in parenthesis help the function’s body. The body is the meat of the function; this is where things actually happen. The if statement is similar to a function, the only difference is that instead of augments, it has conditionals. The conditional of an if statement is evaluated to see if it is true or false. This is done by using operators that compare: ==, <, >, <=, or >=. In order, the operators are equal to, less than, greater than, less than or equal to, and greater than or equal to. It is important not to confuse = and ==, since the first one is used to assign values to variables. Also included in the above program is the function digital (8). This is the function for accessing the touch sensor. Touch sensors must always be plugged into ports 8 and above, as the other ports are reserved for analog functions. The way digital works is that if the touch sensor is pushed, it returns a value of 1 to the computer, and a value of 0 if it is not pressed. The above if statement checks if digital (8) is equal to 1. If it is, it will execute the functions inside the braces; if it is not true, it will skip the braces. The braces are just like the ones following the void main () function, since they enclose only the function.
There is another statement necessary to know about in basic IC programming, the while statement. The while statement has the same format as the if statement, except it repeats the functions in the braces as long as the conditional is true. For example, while (1==1) would repeat forever. As this is not usually wanted, the word break followed by a semicolon will exit out off the innermost while loop. By using the while loop, continuous programs can be made. This program, using the same imaginary robot as the previous program, will go forward until it hits something, and then go back for two seconds. Since the program is enclosed in a while loop that is always true, the program will not stop on its own; it will continue bouncing until the person hits the manual stop button.
void main ()
{
while (1==1)
{
motor (1,100);
motor (2,100);
if (digital (8) == 1)
{
motor (1,-100);
motor (2,-100);
sleep (2.0);
}
}
}
With the while statement, all that you need to know to program basic IC is covered. Understand that this barely scratches the surface of the IC language. It is enough to make a robot with the beginnings of intelligence, and more than enough to start your own experiments with. Before attempting more advanced programming, try this exercise. Build a robot with two touch sensors on either side. Make the robot so that if it hits an obstacle, it will back up, turn in a direction to get the obstacle out of its way, and then continue. (Hint: One way to turn is to have the wheels going in opposite directions.)
It is possible to program almost anything with the methods discussed in the previous section. However, using just the functions you already know, the computer cannot really do any math. The difference between a computer that can do calculations and one that can’t is like the difference between a person that can see and one that is blindfolded. While it is possible to get around when blindfolded, it is extremely inefficient. To enable the XBC to do calculations, you need it to have variables to work with. Take the search-bot you should have made to avoid objects. Say that if it hits three objects, it turns all the way around. For the sake of the program, let’s say that it takes three seconds to spin all the way around, and only one second to turn. Also let us assume that the left hand touch sensor is in port 8, and the right one in port 9.
void main ()
{
int counter;
counter = 0;
while (1==1)
{
motor (1,100);
motor (2,100);
if (digital (8) ==1)
{
motor (1,-100);
motor (2,-100);
sleep (2.0);
motor (1,100);
motor (2,-100);
sleep (1.0);
counter++;
}
if (digital (9) ==1)
{
motor (1,-100);
motor (2,-100);
sleep (2.0);
motor (1,-100);
motor (2,100);
sleep (1.0);
counter++;
}
if (counter == 3)
{
sleep (2.0);
counter = 0;
}
}
}
There are a few new things in this program to explain. The first is how you initiate a variable. In general, the form is: type (<variable name>); this tells the XBC to make memory for a variable of type named (<variable name>). You cannot assign any other type of number to the variable other than its type. Also, you can only do operations on numbers of the same type. Examples of operators are =, +, -, *, and /. (Note: The next few lines will only work with integers, aka int. To use them for other types of variables, just remember what the differences between them are.) To assign a number to an int variable named number, you would write: number = 5; or whatever int you want. Note that the thing being changed is always on the left of the equals sign, or prefix to it. 5 = number would generate an error, since 5 is has a constant value (it cannot be changed). Constant values should always be postfix to the operator. If you want your variable number to equal another int called input, you would write: number = input; this would assign whatever number is in input to number, making the two be the same. All operators (excluding the = sign) should always be postfix to the = sign. BE CAREFUL! The * symbol is also used for pointers. Pointers hold the address of a variable so you can manipulate them from other functions, but for now, just be sure to keep the * symbol postfix to the = operator. For example, number = 3 + 4; assigns the value 7 to the variable number, and: number = 25 / 5; assigns the value of 5 to number. If you wanted to increment or decrement a number, there are a couple of different ways to do it. One way is to write: number = number + 1; or: number = number – 1; depending on whether you want to increment or decrement it. However, this is not the most efficient way to write it. To increment it without the equals sign, you would write: number++; this adds one to the current value. Like wise, type in: number--; to decrement it. Although this is quicker, you have to be careful when using it. If you have two variables, x and y, and you want to make x be equal to one more than y, you might write this: x = y++; THIS WILL NOT DO WHAT YOU THINK IT DOES! The compiler will first assign the value of y to x, and then it will increment y. In the end, y is one more than x is, and x is what y was. It would be better to write: x = y+1; this will leave y alone and give x the correct value. Variables are very useful, but you have to be sure to write them correctly, other wise they will not work.
There are many little mistakes that can be made just by forgetting what type of variable you are using. Programs can fall apart if ints are used in the place of floats. But, you may argue, I need a variable to have this type of number for compatibility with a function I’m using. There is a simple, elegant, and possibly confusing solution to this.
float number = 1.345;
int other_number = ((int) (number));
This would save the value of 1 to other_number. In general, the format for the conversion is ((<type to change to>) (<equation>)), where <equation> uses all the same types of variables, unless you compound the statements. These conversion statements can be compounded, but can get very confusing. Try to keep things as simple as possible, and always try to make one change at a time, and avoid combining them into one huge expression. Long expressions are not fun to debug, as the compiler only tells you the line that the error is on.
Conversions are wonderful, but you have to be careful about where you place them. Remember, int variables always lose the end decimals when dividing or doing other math functions more complicated then addition and subtraction. To prevent the loss of significant figures for as long as possible, try to convert floats to ints one line before they are used in the function that needs them, or in the function itself (motor(1, ((int) (float_power)));). However, as you can see, the parentheses stack up quickly. Try to avoid this, but it can be the most efficient way to do it, if not the most readable.
Now that you know how to make variables, you have to know how to debug them. It is impossible to program in specifics if you have no way of telling what even the general range should be. With the LCD screen, however, you can get the XBC to tell you what the value of a variable is or just simply that it reached a certain point in your code. The function used to print to the screen is printf.
void main()
{
int the_number = 5;
printf(“Checking number…\n”);
printf(“The number is %d\n”, the_number);
printf(“Done\n”);
}
-- print buffer –
Checking number…
The number is 5
Done
-- end –
The printf command is one of the most variable commands in IC. As you can see, it can have a variable number of augments, but must always have one augment. The first augment is a character array, or character string. Strings are always enclosed in quotation marks, and are much easier to declare than an array with each separate character typed in individually. Some “characters”, however, like the return or tab commands, are represented differently. They use a backslash ( \ ) before a key letter. For example, \n is representative of new line, or enter. \t is replaced by a tab. There are other ones, but \n is the most common one used. But how do you print a value? This is where it might get confusing. You use a % sign in front of a key letter designating the type of variable to substitute in, and after the string ends, separated by a comma, you type in the variable to get the value from. Multiple variables can by used in the same statement so long as the order is correct. In general, use %d for int, %l for long, %f for float, and %s for char arrays.
If you feel confused, that is OK. The printf function is probably the most complicated to understand. To prevent further confusion, try to just use one variable per statement.
A function is one of the most useful tools you have when programming IC. It allows you to only have to type in a set of commands once, and can then be re-used anywhere in the program. Marcos are another way to get repeatability, but are much more confusing to work with due to a picky syntax. To begin, take the robot you made in the Basic IC Programming section. Say you were getting tired of typing in the motor commands to go forward and go back repeatedly. You could make a function to do it for you.
void go_forward ()
{
motor (1, 100);
motor (2, 100);
}
void main ()
{
go_forward ();
sleep (1.0);
ao ();
}
When the program runs, it will start with the main () function, as always. When it sees the command go_forward (), the flow of execution jumps to the commands in the go_forward () function, which will turn the motors on. As you may recall, since go_forward () is a void function, it does not need a return statement. When it reaches the bottom, it will simply go back to the function that called it. In this case, the function is main ().
Notice a few things about the declaration of this function. It is declared outside of the main function. You want to always declare functions outside of any other function. Another thing is that there are no spaces in the name. There are different conventions for how to replace spaces in function names. One way is go_forward, but another way is goForward. However you do it, do it consistently so as not to confuse yourself. Be sure to name your functions with descriptive names. For example, you will never remember what function_one does if you walk away from your program for a while. A much better name would be say_hello or a more appropriate name. Also, try not to name a function inappropriately; for example, do not name a function that finds the average of two numbers say_hello. It is confusing to everyone who has to look at your program.
True, the go_forward () function is useful, but why bother? It is only two easy to remember lines, anyways. To really unlock the power of functions, you would have to pass in augments, like with the motor command.
void go_forward_at (int power)
{
motor (1, power);
motor (2, power);
}
void main ()
{
go_forward_at (75);
sleep (1.0);
ao ();
}
When this is run, the program will look at the first line and jump to the go_forward_at command definition. It then takes the augment, which in this case is 75, and assigns that value to the variable power. Then it starts the code, and substitutes in 75 when it calls the motor commands. If you had typed in go_forward_at (56), it would go forward at 56% power. Now is a good time to mention something about how long variables live for. Unless a variable is created outside of any functions, a variable only exists inside that function. When the function returns, all variables created in that function are destroyed. If you call the function again, they must be created all over again. Since it works this way, you cannot access variables created in main () with any other function. Even if you name them the same thing, they are different variables. If you really want to have a universal variable, then you must use global variables. To make a global variable, you simply declare it outside of any functions. BE VERY CAREFUL! Since they can be affected by any function, if a global variable has the wrong value somehow, it is extremely difficult to locate the source. In general, try to avoid them unless they are absolutely necessary.
It is important to note that the above code is not good. It is very easy to pass in what looks like a perfectly good value and get junk in return. If you pass in go_forward_at (101), for example, it will not move. Luckily, the XBC is smart enough to realize that it cannot do that, so it just does nothing. However, you probably do not want it to do nothing. You want it to go forward. While we are fixing it up, we might also want to fool-proof it so it cannot go backwards, either.
void go_forward_at (int power)
{
if (power > 100)
power = 100;
if (power < 0)
power = 0;
motor (1, power);
motor (2, power);
}
This example of the function is much better. It only allows the robot to go forward, and it will go forward at full power if it is given a value that is too big for the motor command. In general, it is a good idea to assume that other people will have to use your functions, so you want to make them understandable and easy to use.
Say you need to find the average of numbers throughout a program. You would want to make a function to average the two numbers together. For accuracy, let’s say they are float type variables.
float average (float numa, float numb)
{
float ans;
ans = (numa + numb) / 2.0;
return ans;
}
void main ()
{
float thisnum = 6.48;
float thatnum = -7.0;
float aver = average (thisnum, thatnum);
printf (“\nThe average is %f\n”, aver);
}
-- Print Buffer –
The average is -0.2600
-- End Buffer –
As you can see, the function average will take two float numbers and take their average. Then the function has to have some way to give that value back to the main () function so it can be used. To accomplish this, the keyword return is used. It is important to note that the value being returned must match the function type. In the above example, the function type is float, and the variable ans is also a float. If you tried to return any other type of variable, you would get a compile time error. If you want to return a different type, my recommendation is to just covert the variable type when you are returning it. For example, return ((float) (someint)); would work fine in the above function.
Looking up Functions in the
XBC Manual
Although at first it may not seem like something you would have to understand how to use, it is important to know what the function index is telling you. If you do not know what it is saying, then you will not be able to use it or understand why it makes your program crash. Take this excerpt from the XBC Manual:
move_relative_position [Category: Motors]
Format:
void move_relative_position(int m, int speed, long pos)
Moves motor m at velocity vel from its
current position curr_pos to curr_pos + pos. The speed range is 0 to 1000 ticks per second.
Example:
move_relative_position(1,275,-1100L);
Just looking at this, you may not be able to understand what this function does, and even worse, you may think you know how to use it. The first thing is the title. This tells you what the function is called and what category it is in. In the above example, the function move_relative_position is a motor command. It has to do with motors. The next section is the format. This is not to just be copied and pasted into your program! It tells you a lot about the function, but it cannot be copied directly out of the manual; it has to be understood first. The first word, void in this case, tells you how returns. This function returns void. The next part is the function itself. When writing it into your programs, this is the first thing you type in to use that function. Next, it lists the augments. This, also, must be understood, not copied. The description directly below the format describes what the function does and tells you how the different augments are used. The words int and long tell you what kind of variable to pass in as an augment. You do not write them in, you just make sure the values written in there match the type specified. Some definitions also have an example. This shows you how you would actually use the function in a program, that is, how it would look like.
The preprocessor is a powerful thing to use, but it can be dangerous. Simply put, the preprocessor is the program that runs before the compiler runs. As you should recall, the compiler is what turns human-readable code into language that the computer can read. What the preprocessor does when it runs is it looks for commands denoted by the pound (“#”) symbol, and, according to the commands, changes the code that the compiler sees accordingly. The most basic preprocessor command is #use.
void main()
{
track_update();
}
Although this code does not really do anything, it demonstrates how to use #use. As will be covered in the next section, to be able to use the camera function track_update(), the function has to be defined. Although it may not seem it, every function you use has to be defined. The reason functions like motor and sleep work without having to type in #use is that they are already assumed to be included by the IC editor. If you really want to look at what makes the “built-in” functions work, they are in the file “libxbc.ic” However, I do not recommend modifying that file in any way! Since it is what makes your files work, it is not a good idea to be editing it. Anyways, since the camera library (xbccamlib.ic) is not used in every file, it is not automatically included. This saves memory, but as a result, you have to say #use to access the function definitions. When the preprocessor sees the command #use followed by a program name, it writes in the contents of that file where the command is. This is very useful, since it saves you the pain of rewriting your functions out every time you write a program.
We have already seen that the preprocessor can rewrite files. Using macros, it can replace key phrases you have previously defined using the command #define.
#define RIGHT_WHEEL 1
#define LEFT_WHEEL 2
void main()
{
motor (RIGHT_WHEEL, 100);
motor (LEFT_WHEEL, 100);
sleep(1.0);
ao();
}
When the preprocessor runs, it sees #define and makes a macro. In the rest of the program, when ever it sees the phrase RIGHT_MOTOR, it replaces it with the phrase 1. It does not replace it with the number 1; it replaces it directly with the phrase “1”. It does not care whether it is in an appropriate position or not, it just makes the substitution. It will be the compiler that catches the error. It is up to you, the programmer, to make sure that it does not make an inappropriate substitution. You also must be careful with how you write your macros. Unlike with functions, macros are picky about spacing. Not enough or too many spaces can ruin a macro. For simple macros, you must have #define, a space, the phrase to look for, a space, and whatever to replace it with. However, macros can also take augments. This is when it gets confusing. What is the difference between these two definitions?
#define TWO (x) ( (x) * 2 )
#define TWO(x) ( (x) * 2 )
The difference is that the second one will work, while the first will not. Remember that the macro defines the first section as the thing after the space. In the first one, since it has a space directly after TWO, it would replace the word TWO with (x) ( (x) * 2 ), which will generate a compile error. The second one will work correctly. For instance, if it sees in the code TWO(5), it will recognize the 5 as being the x. The preprocessor would then replace that snippet of code with ( (5) * 2 ), which would evaluate to 10. You might wonder why there are so many parentheses. The answer is simply to prevent the macro from being stupid. You might be tempted to write TWO(x) as such:
#define TWO(x) x * 2
While this appears to work fine, it
has one major flaw. It will fall apart if a more complex phrase is passed in.
Say you typed in TWO(2 + 3). You would expect to get 10, but with the above
definition, you would get 8. To understand why, you have to analyze what it
does. When it looks at
TWO(2 + 3), it then looks at your definition and replaces it with exactly what
it sees, which is 2 + 3 * 2. However, keep in mind this is before the compiler analyzes it. When the computer sees it, it will
follow the correct order of operations, and will evaluate 2 + (3 * 2) = 2 + 6 =
8. All of the extra parenthesis prevents mistakes like this from happening by
assuring you of the grouping of operations.
You can also write functions using #define, but they have their limits. For one thing, the entire macro must be on one line. This can get overwhelming for more complicated functions. However, it can be useful for something like this:
#define GO_FORWARD_FOR(sec) { motor(1,100); motor(2,100); sleep(sec); ao(); }
If it can all fit on one line, then macros can be used as simple functions such as the one above. However, the programmer has to decide whether to use a macro or a function. The main deciders are memory and time. Macros are written in every single time they are written in the text. If it is long, then it is worth the slight time delay to just call a function instead of eating up all the memory. However, if the snippet is short, then macros are the way to go, simply for speed.
The camera is probably the most involved piece of equipment on the whole XBC. Its ability to recognize up to three different colors makes it invaluable to finding things. However, it is the most difficult thing to program. I am not going to explain every single function that uses the camera here in this tutorial; this is more of a general set of instructions. If you want to learn more, just look up the functions in the IC manual. This will cover the most basic ways to use the camera.
The XBC can remember up to three colors at a time. It saves the definition of these colors in a location in its memory called the color models. The models are labeled 0 to 2. It does not remember the colors as “blue” or “red,” but as a range of hues. How to set color models and more information about them can be found in the IC manual.
To begin programming using the camera, you have to write #use “xbccamlib.ic” as your first line of code. As explained in the macros section, this allows you to use the camera functions.
The instruction manual says you have to use a function called init_camera() before any camera functions work. I am fairly certain that this is not true. I have never called init_camera() before in any of my programs, and they always worked fine. Every time I tried using init_camera(), it crashes my program. This may be just for me, so you should experiment yourself to figure out what works.
One of the most important functions is track_update(). What this does is it takes a snapshot using the camera and saves it to memory. This picture is available until you call track_update() again, when it is replaced by a new picture.
Another two useful functions are track_x(int ch, int i) and track_y(int ch, int i). These functions return the x and y coordinates, respectively, of the blob whose color matches the color model ch. i is any number greater than or equal to zero, and less than ch. I do not know what use it is, and would be interested if someone told me. When I say x/y coordinates, I mean where the center of the blob is in pixels on the LCD screen.
When working with the camera, you have to be careful. Enormous mistakes may be made simply by not updating the camera. In general, try to call track_update() before any time you evaluate the camera information, especially if you are moving your robot.
Probably one of the hardest things is trying to figure out where you want the robot to be according to the numbers you are receiving from the camera. This program is good for figuring out where the robot is in respect to a certain blob.
void main()
{
int x_val;
int y_val;
int col_mod=0; // Change
this number to the color model you want to work with
while (b_button()==0)
// Press the B button to exit
{
track_update();
x_val=track_x(col_mod,0);
y_val=track_y(col_mod,0);
display_clear();
printf(“The x value is %d\n”, x_val);
printf(“The y value is %d\n”, y_val);
sleep(0.3); // Keeps the screen readable
}
}
You will probably notice that I added something new to this code. The green words are comments. Open comments using a double slash (//). Called a C++ style comment, these make the compiler ignore all code after the double slash until the next line break. Comments are good for explanations of what part of your code does. Chances are, if you have not looked at your code for a while, you will not understand everything in it. Comments are good for explanations and reminders.
What the above code does is that it looks for the defined color model. It is set to 0, but you can change that as needed. It then checks the camera ever three tenths of a second, and prints the x and y coordinates of the center of the blob. It is good to get ideas of ranges and approximate numbers in programs.
There are many different camera functions. If you want to know how to use them, just look them up in the help manual.