Sie sind auf Seite 1von 120

1

Components used in building a small automatic robot Robo-11

68HC11 Micro-controller Activity Board It comes with a CX-4 cable to download the program. This board is used to control the operation of the robot. It has a 32KB memory, 21 analog input channels, 9 digital inputs, 9 digital outputs, and it drives 4 DC motors and 6 RC servo motors.

Universal Plate Plate size is 160 x 60 mm. There are 341 3-mm size holes with a distance of 5 mm between each hole. Two plates are provided. Motor Gearbox Uses a 6-9 V and 180 mA DC motor with a ratio of 48:1; torque 4kgF/cm; Two sets are provided.

Track There are 3 sizes. Four 8-Joint tracks; Four 10-Joint Tracks; and two 30-joint tracks. Angled Shaft Base Two pieces of each the long base and short base are provided. Metal Axel 4 mm in diameter and 100 mm in length. Four axels come in the set.

2
Wheels There are four different types which are Main Track Wheel (2 Pieces), Large Track Support Wheel (2 pieces), Small Track Support Wheel (10 pieces), and hubs (12 pieces). Knobby Plate This is used to attach the AX-11 with the universal plates. Angled Joiner 20 pieces of varied color joiners made from PVC plastic. They can be connected together or by using screws and 3 mm nuts in installation. Obtuse Joiner 20 pieces of varied color 135 degree obtuse joiners made from PVC plastic. They can be connected together or by using screws and 3 mm nuts in installation. Strength Joiner 20 pieces of varied color joiners made from PVC plastic. They can be connected together or by using screws and 3 mm nuts in installation. Nut and Screw Set There are two 2 mm open-end screws, four 3 x 6 mm screws, thirty 3x10 mm screws, four 3 x 15 mm screws, four 3 x 25 mm screws, and thirty 3 mm nuts. Switch Input The switch input is used to detect collision at logic 0. Two sets along with the connecting cable are provided. IR Reflector Used to detect the perimeter, lines, and the wheel code. The results are in voltage. Three sets along with the connecting cable are provided. IR Ranger Measures distance ranging from 4 to 30 cm using infrared light. The results are in voltage.

BUILDING THE ROBOT


1
Start by putting together the two track wheels, which each wheel using one 30-joint track, one 10-joint track, and two 8-joint track. Connect all tracks together to form one track wheel that is suitable for the size of the robot.

Attach the motor gearbox sets to the universal plate using a 3 x 6 mm and 3 x 10 mm screw. Position the Motor Gearbox sets as shown in the picture below.

Flat plastic joiner

Take the long angled shaft base and attach it to the universal plate. In between the plate and the long angled shaft, place the strength joiner. Screw them all in together using a 3 x 10 mm screw and nut, positioning it at the 8th hole from the side where the motor was attached. The smooth side of the shaft base should be turned outwards as shown in the picture. Tighten the screw and nut.

Turn the universal plate over to the side where the motors are attached. Attach the short angled shaft base at the end of the plate as shown in the picture.

Use a 3 x 10 mm screw and nut to attach the short angled shaft base to the universal plate

Turn the plate bottom up and insert the metal axel into the holes of the long angled shaft in the positions of 1, 4, and 7 (Counting from the side with the installed motor).

Place the small track support wheels over the metal axel with the front of the wheels turned outwards. Insert the hubs over the wheels and use your fingers to press in tightly. Insert a metal axel into the two short angled shaft bases. Then insert the large track support wheels and hub to it.

Attach the main track wheels to the motor axels with the 2 mm open-end screws.

Attach an angled joiner to the universal plate between the two motor gearboxes with a 3 x 10 mm screw and a 3 mm nut. Then attach two more at the Large track support wheels, which is opposite from the motors as shown in the picture.

Take 3 more angled joiners and attach them to the other universal plate as shown in the picture. The position of the angled joiners must be the same as the ones attached to the plate with the motor gearboxes in Step 8.

10

Insert a strength joiner into all 3 angled joiners to create a support base for the plate with the motor gearbox sets. Then place the two universal plates together. This will make it easier to remove the robot structure for any internal modifications that may be needed.

11

Then take the track wheels that were put together in step 1 and place it over the supporting wheels on both sides of the robot. Make sure that both wheels are aligned with one another.

12

Place the knobby plate with the two-sided glue onto the top of the finished robot. Remove the sticker and place the AX-11 board onto the glue surface. This will make it easier to remove or shift the AX-11 board. Then connect the signal cable of the left motor to exterior terminal M0 and the signal cable of the right motor to the interior terminal M-1.

Preparing to Download the Program


Preliminary Preparations in Using Interactive C with the AX-11 board on the Robo-11 robot. The preparations that we are about to talk about is writing the main control program, or what they call the Firmware, into the memory of the AX-11 board. This will be done only once in the beginning, or if the main program data disappears, or if the AX-11 board is unable to receive data from the operational program written by the programmer. Turn on the POWER switch on the AX-11 board. If the voltage of the battery on the AX-11 is enough, the green PWR LED will be lit brightly. If not, the LED will be dimly displayed and the red BATT LED will indicate that the voltage level is low, as shown in Figure A1-1. Use the +12V DC Adaptor that came with the AX-11 board as the power supply instead by connecting it to the outlet on the board. Once power is supplied, the yellow CHARGE LED will light, and the red LED will disappear as shown in Figure A1-2.

10

Take the AX-11 and connect it to the serial port of the computer as shown in Figure A1-3. The green SER LED will light, indicating that the connection of the AX-11 to the serial port of the computer was successful, and is ready for use.

11

Problem Solving if the computer has only one USB port Use a USB port to analog port RS-232 converter, in which we recommend the UCON-232 board. (www.inex.co.th)

Open the Interactive C program by going into Start Program Interactive C 4.30ax Interactive C for AX-11. A title window will appear for an instant before changing to the Select Controller Type window. Choose AX-11.

The Port Selection window will appear for you to choose the serial port of the computer that is to be used to communicate with the AX-11 board. Choose the port you want and click Connect now.

Go to the menu Tools Download firmware. A window will appear to choose the serial port of communication again. Once you have chosen, click Download Firmware.

12

A figure showing the steps in downloading the firmware to the AX-11 board will appear. Start by connecting the download cable to the serial port and to the AX-11 board. Click Next when done.

A window will then appear for you to press the STOP switch on the AX-11 board. While still holding it down, turn on the power of the AX-11 board as indicated in the picture. Then click Next.

If the green SER LED is lit and blinking, click Yes, its blinking.

10

A window will appear to display the status of the AX-11, indicating that the PWR and BATT LED should be off. Then click Both Lights Off >

A window will appear telling you to turn off the power switch. Turn off the POWER switch and click Next.

If the PWR LED is lit, click PWR light still on! An alert message will appear saying it is unable to enter the download mode of the program, and to check the download cable again before repeating the steps for download. If the BATT LED is lit, click BATT light still on! An alert message will appear saying that the voltage supply of the battery is low and needs to be recharged for at least another 30 minutes before using it again.

13
If everything is alright, a window displaying the Firmware download status will appear. Once the download is done, a beep will be heard from the AX-11 board, and the status window of the Interactive C program will display the message Download Successful. The display of the AX-11 will show IC 4.30 on AX-11 Activity Board, ending with a blinking heart. The Interactive C program will then go to the Interaction window, which is used for testing the program. The Robo-11 is now ready for program coding and operation.

Testing the Interactive C Program

After downloading the main control program, or the firmware, the next step is to write a basic function to test the operation of the AX-11.
1

Go to the Interaction window, type in the function Printf (Hello world !\n); Then press Enter. The monitor shows the results from the AX-11, displaying Hello world! on the top sentence. The display of the Interaction window will display the message This means that the AX-11 board can now interact with the Interactive C program.

14

Next we will create a simple Interactive C program to use with the AX-11 board.

Click New to program folder

create

new

Type in the program below, and save it as hello.ic

Click Download to download the program. A window will appear asking to save the file *.ic first. Here, the file is hello.ic. A window displaying the status of the download will then appear.

Run the program by Method 1: Turn off and on the POWER switch once to reset the AX-11 board. Method 2: Run the program by clicking Run Main on the Interactive C window. Then choose the Interaction window, the message below will appear The message Hello world! will appear on the top of the AX-11 display screen.

15

Things to be know when downloading the program to the AX-11


If the AX-11 and Interactive C program is used together continuously without turning off the program, the programmer would be able to download and test the program anytime, even when the POWER switch is turned off. This is because the program is stored in a non-volatile system memory. If the Interactive C program is closed and reopened again while the AX-11 board is still on, and the firmware still operating, the communication between the AX-11 and the Interactive C program must be reestablished. Choose the serial port used to communicate, and then click Connect Now. A window displaying the status of downloading the Interactive C library to the AX-11 board will appear as seen in the picture. Then we will go to the Interaction window, causing the program that was saved in the memory previously to have disappeared; therefore it must be downloaded again. This means that every time the Interactive C program is closed and opened again, the user must always download the program he needs into the memory again. This is because the Interactive C program is a program that needs to be connected to the hardware in order to check its status continuously. Therefore, if the communication is lost because it was turned off, the communication must always be reestablished at the beginning by downloading the programs library to the AX-11 board.

The AX-11 Power Supply


The AX-11 uses 8 serial Nickelmethus-hydride batteries size AA with a voltage of 1.2V 1700mAH or above, therefore resulting in a supply of at least 9.6 1700 mAH. The recommended time in charging the batteries is at least 10 to 15 hours. Low current is used to charge the batteries in order to extend the battery life. If the AX-11 board is fully charged, it can be used continuously for 2-4 hours, depending on the number of peripherals connected and the amount of voltage they use.

16

Changing the Batteries


he batteries that come with the AX-11 board are echargeable nickelmethus-hydride, and can used or approximately 1 year. Therefore, for highest fficiency, the batteries should be changed every ear using the following steps:
1

Prepare the new battery set and attach foam tape to the top of it. Turn off the POWER switch and removed the adapter cable. Use a screwdriver to remove the 4 screws at the corners of the AX-11. Use a flat-head screw driver (or a four-edged screwdriver depending on the type of screws in the terminal block). Loosen the screws at the terminal block with the cables of the original battery set. Remove each cable and use a pincher to cut the ends off. This is to prevent the occurrence of a short circuit. Replace the original batteries with the new set, turning the side with the foam tape upwards. Then peel about 5 mm of the batterys red cable (positive) off and connect it to the + of the terminal block. Use the screwdriver to tighten the screws at the terminal block that hold the cable. Do the same for the black cable (negative) of the battery. This step is very important. It needs to be done one cable at a time to prevent short-circuit of the battery or with other parts of the AX-11 boards. Then place the board back to its original place. Use the screwdriver to screw the 4 screws at the corner of the AX-11 board back to the box. Connect the adapter to the AX-11 board to charge the battery. This should take 10 to 12 hours to charge the batteries for the first time. The AX-11 board should be ready for use after this.

17

ROBO-11 Testing
After the Robo-11 has been put together, we will next write a program to test the functioning of the motor to see whether it is working together properly and if it is ready for its future operations or not. A simple program will be downloaded for the robot to move forward 2 seconds, move backwards 2 seconds, and continue to repeat these steps. Type in the following program code and download it to the Robo-11
/* Example for Robot basic movement Hardware configuration - Motor left connected to DC Motor chanel M-0 - Motor right connected to DC Motor chanel M-1 */ #define pow 50 /* Configuration power drive motor */ void main() { ao(); printf(Press Start!\n); start_press(); while(1) { run_fd(2.0); run_bk(2.0); } } void turn_left(float spin_time) { motor(0,-pow); motor(1,pow); sleep(spin_time); } void turn_right(float spin_time) { motor(0,pow); motor(1,-pow); sleep(spin_time); } void run_fd(float delay) { motor(0,pow); motor(1,pow); sleep(delay); } void run_bk(float delay) { motor(0,-pow); motor(1,-pow); sleep(delay); }

// // // //

All off motor every channel Display message on LCD Wait until Press start key Infinite loop

// Robot forward 2 sec // Robot backward 2 sec

// Motor0 backward for pow define value // Motor1 forward for pow define value // Delay set by parameter spin_time

// Motor0 forward for pow define value // Motor1 backward for pow define value // Delay set by parameter spin_time

// Motor0 forward for pow define value // Motor1 forward for pow define value // Delay set by parameter delay

// Motor0 backward for pow define value // Motor1 backward for pow define value // Delay set by parameter delay

18

Testing It
Place the Robo-11 on the floor and then turn on the POWER switch. The LCD screen displays the message Press Start. Press START on the AX-11. The robot will move forward for 2 seconds, using only 50% of its power. Observe the motor LED on the AX-11 board. Both must be green. Then the robot will move backwards for 2 seconds. Observe the motor LED on the AX-11 that shows the functionality of the motors. Both will turn to red.

If you dont get these results, switch the motor cables terminal charge on the AX-11 until you get the correct results. Use this motor connection for future operations.

Robo-11 Test (2)


From Test (1), the next step would be to include additional conditions for the robot so that the robot can move in the direction or way desired. In this test, the Robo-11 is told to move in a square-like shape. Type in the following program code and download it to the Robo-11
/* Example for Robot movement, program to near square movement Hardware configuration - Motor left connected to DC Motor chanel M-0 - Motor right connected to DC Motor chanel M-1 */ #define pow 40 /*Configuration power drive motor*/ void main() { ao(); printf(Press Start!\n); start_press(); while(1) { run_fd(2.0); turn_left(1.0); } }

// // // //

All off motor every channel Display message on LCD Wait until Press start key Infinite loop

// Robot forward 2 sec // Robot backward 1 sec

19

void turn_left(float spin_time) { motor(0,-pow); motor(1,pow); sleep(spin_time); } void turn_right(float spin_time) { motor(0,pow); motor(1,-pow); sleep(spin_time); } void run_fd(float delay) { motor(0,pow); motor(1,pow); sleep(delay); } void run_bk(float delay) { motor(0,-pow); motor(1,-pow); sleep(delay); }

// Motor0 backward for pow define value // Motor1 forward for pow define value // Delay set by parameter spin_time

// Motor0 forward for pow define value // Motor1 backward for pow define value // Delay set by parameter spin_time

// Motor0 forward for pow define value // Motor1 forward for pow define value // Delay set by parameter delay

// Motor0 backward for pow define value // Motor1 backward for pow define value // Delay set by parameter delay

Testing It
Place the Robo-11 on the floor and then turn on the POWER switch. The LCD screen displays the message Press Start. Press START on the AX-11. The robot will move forward for 2 seconds, using only 50% of its power. Then the robot will turn left for 2 seconds and continue doing so. It can be observed that the robot is moving in a square-like movement. How much the Robo-11 Standard is able to move in a perfect square depends on many factors, such as the current battery level, the current supplied to the motor, movement time, and the friction at the wheels of the robot.

20

Basic Problem Solving


1. If the downloaded program does not work.
Solve by Check the download cable by checking if the SER LED is green. Check the power supply by checking if the BATT LED is red. If it is lighted bright it means that the battery is low. Use the external power from the DC adapter +12V 500 mA Download the firmware again.

2. If the AX-11 cannot Interactive C program.

communicate

with

the

Solve by Check the power supplied to the AX-11 by checking if the PWR LED is green. Check the download cable by checking if the SER LED is green. Check the power supply by checking if the BATT LED is red. If it is lighted bright it means that the battery is low. Use the external power from the DC adapter +12V 500 mA If everything is ok, download the firmware again.

3. If the firmware can not be downloaded


Solve by Check the power supplied to the AX-11 by checking if the PWR LED is green. Check the download cable by checking if the SER LED is green. Check the power supply by checking if the BATT LED is red. If it is lighted bright it means that the battery is low. Use the external power from the DC adapter +12V 500 mA If it is still not working, send the robot back to the manufacturer or distributor to check its functionality

21

IC 4 Programmers Manual
Introduction Interactive C (IC for short) is a C language consisting of a compiler (with interactive command-line compilation and debugging) and a run-time machine language module. IC implements a subset of C including control structures (for, while, if, else), local and global variables, arrays, pointers, structures, 16-bit and 32-bit integers, and 32-bit floating point numbers. IC works by compiling into pseudo-code for a custom stack machine, rather than compiling directly into native code for a particular processor. This pseudo-code (or pcode) is then interpreted by the run-time machine language program. This unusual approach to compiler design allows IC to offer the following design tradeoffs:

Interpreted execution that allows run-time error checking. For example, IC does array bounds checking at run-time to protect against some programming errors. Ease of design. Writing a compiler for a stack machine is significantly easier than writing one for a typical processor. Since IC's p-code is machine-independent, porting IC to another processor entails rewriting the p-code interpreter, rather than changing the compiler. Small object code. Stack machine code tends to be smaller than a native code representation. Multi-tasking. Because the pseudo-code is fully stack-based, a process's state is defined solely by its stack and its program counter. It is thus easy to task-switch simply by loading a new stack pointer and program counter. This task-switching is handled by the run-time module, not by the compiler.

Since IC's ultimate performance is limited by the fact that its output p-code is interpreted, these advantages are taken at the expense of raw execution speed. IC 4 was written by Randy Sargent of the KISS Institute for Practical Robotics. Randy was assisted by Mark Sherman. Portions of the code and the libraries are based on the public distribution of IC 2.8 written by Randy Sargent, Anne Wright and Fred Martin.

22

Using IC When IC is running and has a connection to a compatible processor board such as the Handy Board or RCX, C expressions, function calls, and IC commands may be typed in the command entry portion of the interaction window. For example, to evaluate the arithmetic expression 1 + 2, type in the following: 1 + 2; When this expression is entered from the interaction window, it is compiled by the console computer and then downloaded to the attached system for evaluation. The connected board then evaluates the compiled form and returns the result, which is printed on the display section of console interaction window. To evaluate a series of expressions, create a C block by beginning with an open curly brace { and ending with a close curly brace }. The following example creates a local variable i and prints 10 (the sum of i + 7) to the board's LCD screen: {int i=3; printf("%d", i+7);}

23

IC Interface Both new (unsaved) and saved files can be opened for editing in IC. A row of tabs lists the files that have been opened. Clicking a file's tab activates it for editing. The first tab for the interface is always the interaction window. The File button has standard entries for New, Open, Close, Save, Save As, Print, and Exit. Under File - Save As, if no file name extension is supplied, IC automatically saves with the ".ic" extension. To download the active file, simply click the download button. The active file will also be saved, unless it is new, in which case the user is prompted for a "save as" file name. Remark: a preprocessor command #use has been added to IC to specify any other saved files (personal libraries) that need to be downloaded along with the active file [Note: #use is quite different from the #include prepreocessor command of standard C environments. #include is not implemented for reasons given later in the section describing the ICpreprocessor.] If a downloaded program does not do what is intended, it may corrupt the p-code interpreter, particularly if pointers are being employed. The interface provides an option under the Settings button for downloading the firmware to reinitialize the board. When there is a connection to a board and the downloaded programs include "main", then "main" can be executed using the Run Main button. The Stop button will halt execution of the attached system. Under the Tools button, among other options, are ones for listing downloaded files, global variables, and functions (including library functions). The interface provides additional capabilities for program entry/edit, minor adjustment to the display, and for setting up the serial interface to a board. C programs are automatically formatted and indented. Keywords, library functions, comments, and text strings are high-lighted with color unless this feature is turned off. IC does parenthesis-balance-highlighting when the cursor is placed to the right of any right parenthesis, bracket, or brace.

24

The main() Function After functions have been downloaded to a board, they can be invoked from IC so long as the board is connected. If one of the functions is named main(), it can be run directly from the interface as noted earlier, and otherwise will be run automatically when the board is reset. Note: to reset the Handy Board without running the main() function (for instance, when hooking the board back to the computer), hold down the board's Start button while activating the board. The board will then reset without running main(). IC versus Standard C The IC programming language is based loosely on ANSI C. However, there are major differences. Many of these differences arise from the desire to have IC be "safer" than standard C. For instance, in IC, array bounds are checked at run time; for this reason, arrays cannot be converted to pointers in IC. Also, in IC, pointer arithmetic is not allowed. Other differences are due to the desire that the IC runtime be small and efficient. For instance, the IC printf function does not understand many of the more exotic formatting options specified by ANSI C. Yet other differences are due to the desire that IC be simpler than standard C. This is the reason for the global scope of all declarations. In the rest of this document, when we refer to "C", the statement applies to both IC and standard C. When we wish to specify one or the other, we will refer to either "IC" or "standard C". When no such qualifiers are present, you should assume that we are talking about IC.

25

A Quick C Tutorial Most C programs consist of function definitions and data structures. Here is a simple C program that defines a single function, called main. /* Simple example IC Programmer's Manual */ void main() { printf("Hello, world!\n"); // Something simple } The expression /* <text> */ forms a multi-line or bracketed comment. In contrast, text that starts with "//" forms a single line comment, which continues only to the end of the line. Comments are ignored by IC when the program is compiled. All functions must have a return type. Since main does not return a value, it uses void, the null type, as its return type. Other types include integers (int) and floating point numbers (float). This function declaration information must precede each function definition. Immediately following the function declaration is the function's name (in this case, main). Next, in parentheses, are any arguments (or inputs) to the function. main has none, but an empty set of parentheses is still required. After the function arguments is an open curly-brace {. This signifies the start of the actual function code. Curly-braces signify program blocks, or chunks of code. Next comes a series of C statements. Statements demand that some action be taken. Our demonstration program has a single statement, a printf (formatted print). This will print the message "Hello, world!" to the LCD display. The \n indicates end-of-line. The printf statement ends with a semicolon (;). All C statements must be ended by a semicolon. Beginning C programmers commonly make the error of omitting the semicolon that is required to end each statement.

26

The main function is ended by the close curly-brace }. Let's look at an another example to learn some more features of C. The following code defines the function square, which returns the mathematical square of a number. int square(int n) { return(n * n); } The function is declared as type int, which means that it will return an integer value. Next comes the function named square, followed by its argument list in parentheses. square has one argument, n, which is an integer. Notice how declaring the type of the argument is done similarly to declaring the type of the function. When a function has arguments declared, those argument variables are valid within the "scope" of the function (i.e., they only have meaning within the function's own code). Other functions may use the same variable names independently. The code for square is contained within the set of curly braces. In fact, it consists of a single statement: the return statement. The return statement exits the function and returns the value of the C expression that follows it (in this case "n * n"). Except where grouped by parentheses, expressions are evaluated according to a set of precedence rules associated with the various operations within the expression. In this case, there is only one operation (multiplication), signified by the "*", so precedence is not an issue. Let's look at an example of a function that performs a function call to the square program. float hypotenuse(int a, int b) { float h; h = sqrt((float)(square(a) + square(b))); return(h); }

27

This code demonstrates several more features of C. First, notice that the floating point variable h is defined at the beginning of the hypotenuse function. In general, whenever a new program block (indicated by a set of curly braces) is begun, new local variables may be defined. The value of h is set to the result of a call to the sqrt function. It turns out that sqrt is a built-in IC function that takes a floating point number as its argument. We want to use the square function we defined earlier, which returns its result as an integer. But the sqrt function requires a floating point argument. We get around this type incompatibility by coercing the integer sum (square(a) + square(b)) into a float by preceding it with the desired type, in parentheses. Thus, the integer sum is made into a floating point number and passed along to sqrt. The hypotenuse function finishes by returning the value of h. This concludes the brief C tutorial. Data Objects Variables and constants are the basic data objects in a C program. Declarations list the variables to be used, state what type they are, and may set their initial value.

28

Variables Variable names are case-sensitive. The underscore character is allowed and is often used to enhance the readability of long variable names. C keywords like if, while, etc. may not be used as variable names. Functions and global variables may not have the same name. In addition, if a local variable is named the same as a function or a global variable, the local use takes precedence; ie., use of the function or global variable is prevented within the scope of the local variable. Declaration In C, variables can be declared at the top level (outside of any curly braces) or at the start of each block (a functional unit of code surrounded by curly braces). In general, a variable declaration is of the form: <type> <variable-name>; or <type> <variable-name>=<initialization-data>; In IC, <type> can be int, long, float, char, or struct <struct-name>, and determines the primary type of the variable declared. This form changes somewhat when dealing with pointer and array declarations, which are explained in a later section, but in general this is the way you declare variables. Local and Global Scopes If a variable is declared within a function, or as an argument to a function, its binding is local, meaning that the variable has existence only within that function definition. If a variable is declared outside of a function, it is a global variable. It is defined for all functions, including functions which are defined in files other than the one in which the global variable was declared.

29

Variable Initialization Local and global variables can be initialized to a value when they are declared. If no initialization value is given, the variable is initialized to zero. All global variable declarations must be initialized to constant values. Local variables may be initialized to the value of arbitrary expressions including any global variables, function calls, function arguments, or local variables which have already been initialized. Here is a small example of how initialized declarations are used. inti=50; /* declare i as global integer; initial value 50 */ longj=100L; /* declare j as global long; initial value 100 */ intfoo() { intx; /* declare x as local integer; initial value 0 */ longy=j; /* declare y as local integer; initial value j */ } Local variables are initialized whenever the function containing them is executed. Global variables are initialized whenever a reset condition occurs. Reset conditions occur when: 1. Code is downloaded; 2. The main() procedure is run; 3. System hardware reset occurs.

30

Persistent Global Variables A special persistent form of global variable, has been implemented for IC. A persistent global variable may be initialized just like any other global variable, but its value is only initialized when the code is downloaded and not on any other reset conditions. If no initialization information is included for a persistent variable, its value will be initialized to zero on download, but left unchanged on all other reset conditions. To make a persistent global variable, prefix the type specifier with the keyword persistent. For example, the statement persistent int i=500; creates a global integer called i with the initial value 500. Persistent variables keep their state when the board is turned off and on, when main is run, and when system reset occurs. Persistent variables will lose their state when code is downloaded as a result of loading or unloading a file. However, it is possible to read the values of your persistent variables in IC if you are still running the same IC session from which the code was downloaded. In this manner you could read the final values of calibration persistent variables, for example, and modify the initial values given to those persistent variables appropriately. Persistent variables were created with two applications in mind:

Calibration and configuration values that do not need to be re-calculated on every reset condition. Robot learning algorithms that might occur over a period when the robot is turned on and off.

31

Constants Integer Constants Integers constants may be defined in decimal integer format (e.g., 4053 or -1), hexadecimal format using the "0x" prefix (e.g., 0x1fff), and a non-standard but useful binary format using the "0b" prefix (e.g., 0b1001001). Octal constants using the zero prefix are not supported. Long Integer Constants Long integer constants are created by appending the suffix "l" or "L" (upper- or lowercase alphabetic L) to a decimal integer. For example, 0L is the long zero. Either the upper or lower-case "L" may be used, but upper-case is the convention for readability. Floating Point Constants Floating point numbers may use exponential notation (e.g., "10e3" or "10E3") or may contain a decimal period. For example, the floating point zero can be given as "0.", "0.0", or "0E1", but not as just "0". Since the board has no floating point hardware, floating point operations are much slower than integer operations, and should be used sparingly. Characters and String Constants Quoted characters return their ASCII value (e.g., 'x'). Character string constants are defined with quotation marks, e.g., "This is a character string.". NULL The special constant NULL has the value of zero and can be assigned to and compared to pointer or array variables (which will be described in later sections). In general, you cannot convert other constants to be of a pointer type, so there are many times when NULL can be useful. For example, in order to check if a pointer has been initialized you could compare its value to NULL and not try to access its contents if it was NULL. Also, if you had a defined a linked list type consisting of a value and a pointer to the next element, you could look for the end of the list by comparing the next pointer to NULL.

32

Data Types IC supports the following data types: 16-bit Integers 16-bit integers are signified by the type indicator int. They are signed integers, and may be valued from -32,768 to +32,767 decimal. 32-bit Integers 32-bit integers are signified by the type indicator long. They are signed integers, and may be valued from -2,147,483,648 to +2,147,483,647 decimal. 32-bit Floating Point Numbers Floating point numbers are signified by the type indicator float. They have approximately seven decimal digits of precision and are valued from about 10^-38 to 10^38. 8-bit Characters Characters are an 8-bit number signified by the type indicator char. A character's value typically represents a printable symbol using the standard ASCII character code, but this is not necessary; characters can be used to refer to arbitrary 8-bit numbers. Pointers IC pointers are 16-bit numbers which represent locations in memory. Values in memory can be manipulated by calculating, passing and dereferencing pointers representing the location where the information is stored. Arrays Arrays are used to store homogenous lists of data (meaning that all the elements of an array have the same type). Every array has a length which is determined at the time the array is declared. The data stored in the elements of an array can be set and retrieved in the same manner as for other variables.

33

Structures Structures are used to store non-homogenous but related sets of data. Elements of a structure are referenced by name instead of number and may be of any supported type. Structures are useful for organizing related data into a coherent format, reducing the number of arguments passed to functions, increasing the effective number of values which can be returned by functions, and creating complex data representations such as directed graphs and linked lists. Pointers The address where a value is stored in memory is known as the pointer to that value. It is often useful to deal with pointers to objects, but great care must be taken to insure that the pointers used at any point in your code really do point to valid objects in memory. Attempts to refer to invalid memory locations could corrupt your memory. Most computing environments that you are probably used to return helpful messages like 'Segmentation Violation' or 'Bus Error' on attempts to access illegal memory. However, you won't have this safety net on the board you are connecting to. Invalid pointer dereferencing is very likely to go undetected, and will likely render invalid your data, your program, or even the pcode interpreter. Pointer Safety In past versions of IC, you could not return pointers from functions or have arrays of pointers. In order to facilitate the use of structures, these features have been added to the current version. With this change, the number of opportunities to misuse pointers have increased. However, if you follow a few simple precautions you should do fine. First, you should always check that the value of a pointer is not equal to NULL (a special zero pointer) before you try to access it. Variables which are declared to be pointers are initialized to NULL, so many uninitialized values could be caught this way.

34

Second, you should never use a pointer to a local variable in a manner which could cause it to be accessed after the function in which it was declared terminates. When a function terminates the space where its values were being stored is recycled. Therefore not only may dereferencing such pointers return incorrect values, but assigning to those addresses could lead to serious data corruption. A good way to prevent this is to never return the address of a local variable from the function which declares it and never store those pointers in an object which will live longer than the function itself (a global pointer, array, or struct). Global variables and variables local to main will not move once declared and their pointers can be considered to be secure. The type checking done by IC will help prevent many mishaps, but it will not catch all errors, so be careful. Pointer Declaration and Use A variable which is a pointer to an object of a given type is declared in the same manner as a regular object of that type, but with an extra * in front of the variable name. The value stored at the location the pointer refers to is accessed by using the * operator before the expression which calculates the pointer. This process is known as dereferencing. The address of a variable is calculated by using the & operator before that variable, array element, or structure element reference. There are two main differences between how you would use a variable of a given type and a variable declared as a pointer to that type. For the following explanation, consider X and Xptr as defined as follows:

35

long X; long *Xptr;

Space Allocation -- Declaring an object of a given type, as X is of type long, allocates the space needed to store that value. Because an IC long takes four bytes of memory, four bytes are reserved for the value of X to occupy. However, a pointer like Xptr does not have the same amount of space allocated for it that is needed for an object of the type it points to. Therefore it can only safely refer to space which has already been allocated for globals (in a special section of memory reserved for globals) or locals (temporary storage on the stack). Initial Value -- It is always safe to refer to a non-pointer type, even if it hasn't been initialized. However pointers have to be specifically assigned to the address of legally allocated space or to the value of an already initialized pointer before they are safe to use.

So, for example, consider what would happen if the first two statements after X and Xptr were declared were the following: X=50L; *Xptr=50L; The first statement is valid: it sets the value of X to 50L. The second statement would be valid if Xptr had been properly initialized, but in this case it has not. Therefore, this statement would corrupt memory. Here is a sequence of commands you could try which illustrate how pointers and the * and & operators are used. It also shows that once a pointer has been set to point at a place in memory, references to it actually share the same memory as the object it points to: X=50L; /* set the memory allocated for X to 50 */ Xptr=&X; /* set Xptr to point to memory address of X */ printf("%d ",*Xptr); /* dereference Xptr; value at address is 50 */ X=100L; /* set X to the value 100 */ printf("%d ",*Xptr); /* dereference again; value is now 100 */ *Xptr=200L; /* set value at address given by Xptr to 200 */ printf("%d\n",X); /* check that the value of X changed to 200 */ Passing Pointers as Arguments Pointers can be passed to functions and functions can change the values of the variables that are pointed at. This is termed call-by-reference; a reference, or pointer, to a variable is given to the function that is being called. This is in contrast to call-by-value, the standard way that functions are called, in which the value of a variable is given the to function being called.

36

The following example defines an average_sensor function which takes a port number and a pointer to an integer variable. The function will average the sensor and store the result in the variable pointed at by result. Prefixing an argument name with * declares that the argument is a pointer. void average_sensor(int port, int *result) { int sum = 0; int i; for (I = 0; I < 10; i++) sum += analog(port); *result = sum/10; } Notice that the function itself is declared as a void. It does not need to return anything, because it instead stores its answer in the memory location given by the pointer variable that is passed to it. The pointer variable is used in the last line of the function. In this statement, the answer sum/10 is stored at the location pointed at by result. Notice that the * is used to assign a value to the location pointed by result. Returning Pointers from Functions Pointers can also be returned from functions. Functions are defined to return pointers by preceeding the name of the function with a star, just like any other type of pointer declaration. int right,left; int *dirptr(int dir) { if (dir==0) { return(&right); } if (dir==1) { return(&left); } return(NULL); } The function dirptr returns a pointer to the global right when its argument dir is 0, a pointer to left when its argument is 1, and NULL" if its argument is other than 0 or 1.

37

Arrays IC supports arrays of characters, integers, long integers, floating-point numbers, structures, pointers, and array pointers (multi-dimensional arrays). While unlike regular C arrays in a number of respects, they can be used in a similar manner. The main reasons that arrays are useful are that they allow you to allocate space for many instances of a given type, send an arbitrary number of values to functions, and provide the means for iterating over a set of values. Arrays in IC are different and incompatible with arrays in other versions of C. This incompatibility is caused by the fact that references to IC arrays are checked to insure that the reference is truly within the bounds of that array. In order to accomplish this checking in the general case, it is necessary that the size of the array be stored with the contents of the array. It is important to remember that an array of a given type and a pointer to the same type are incompatible types in IC, whereas they are largely interchangeable in regular C. Declaring and Initializing Arrays Arrays are declared using square brackets. The following statement declares an array of ten integers: int foo[10]; In this array, elements are numbered from 0 to 9. Elements are accessed by enclosing the index number within square brackets: foo[4] denotes the fifth element of the array foo (since counting begins at zero). Arrays are initialized by default to contain all zero values. Arrays may also be initialized at declaration by specifying the array elements, separated by commas, within curly braces. If no size value is specified within the square brackets when the array is declared but initialization information is given, the size of the array is determined by the number of elements given in the declaration. For example,

38

int foo[]= {0, 4, 5, -8, 17, 301}; creates an array of six integers, with foo[0] equaling 0, foo[1] equaling 4, etc. If a size is specified and initialization data is given, the length of the initialization data may not exceed the specified length of the array or an error results. If, on the other hand, you specify the size and provide fewer initialization elements than the total length of the array, the remaining elements are initialized to zero. Character arrays are typically text strings. There is a special syntax for initializing arrays of characters. The character values of the array are enclosed in quotation marks: char string[]= "Hello there"; This form creates a character array called string with the ASCII values of the specified characters. In addition, the character array is terminated by a zero. Because of this zerotermination, the character array can be treated as a string for purposes of printing (for example). Character arrays can be initialized using the curly braces syntax, but they will not be automatically null-terminated in that case. In general, printing of character arrays that are not null-terminated will cause problems. Passing Arrays as Arguments When an array is passed to a function as an argument, the array's pointer is actually passed, rather than the elements of the array. If the function modifies the array values, the array will be modified, since there is only one copy of the array in memory. In normal C, there are two ways of declaring an array argument: as an array or as a pointer to the type of the array's elements. In IC array pointers are incompatible with pointers to the elements of an array so such arguments can only be declared as arrays. As an example, the following function takes an index and an array, and returns the array element specified by the index: int retrieve_element(int index, int array[]) { return array[index]; } Notice the use of the square brackets to declare the argument array as a pointer to an array of integers.

39

When passing an array variable to a function, you are actually passing the value of the array pointer itself and not one of its elements, so no square brackets are used. void foo() { int array[10]; retrieve_element(3, array); } Multi-dimensional Arrays A two-dimensional array is just like a single dimensional array whose elements are onedimensional arrays. Declaration of a two-dimensional array is as follows: int k[2][3]; The number in the first set of brackets is the number of 1-D arrays of int. The number in the second set of brackets is the length of each of the 1-D arrays of int. In this example, k is an array containing two 1-D arrays; k[0] is a 1-D array of color=blue>int of length 3; k[0][1] is an color=blue>int. Arrays of with any number of dimensions can be generalized from this example by adding more brackets in the declaration. Determining the size of Arrays at Runtime An advantage of the way IC deals with arrays is that you can determine the size of arrays at runtime. This allows you to do size checking on an array if you are uncertain of its dimensions and possibly prevent your program from crashing. Since _array_size is not a standard C feature, code written using this primitive will only be able to be compiled with IC. The _array_size primitive returns the size of the array given to it regardless of the dimension or type of the array. Here is an example of declarations and interaction with the _array_size primitive:

40

int i[4]={10,20,30}; int j[3][2]={{1,2},{2,4},{15}}; int k[2][2][2]; _array_size(i); /* returns 4 */ _array_size(j); /* returns 3 */ _array_size(j[0]); /* returns 2 */ _array_size(k); /* returns 2 */ _array_size(k[0]); /* returns 2 */ Structures Structures are used to store non-homogenous but related sets of data. Elements of a structure are referenced by name instead of number and may be of any supported type. Structures are useful for organizing related data into a coherent format, reducing the number of arguments passed to functions, increasing the effective number of values which can be returned by functions, and creating complex data representations such as directed graphs and linked lists. The following example shows how to define a structure, declare a variable of structure type, and access its elements. struct foo { int i; int j; }; struct foo f1; void set_f1(int i,int j) { f1.i=i; f1.j=j; } void get_f1(int *i,int *j) { *i=f1.i; *j=f1.j; }

41

The first part is the structure definition. It consists of the keyword struct, followed by the name of the structure (which can be any valid identifier), followed by a list of named elements in curly braces. This definition specifies the structure of the type struct foo. Once there is a definition of this form, you can use the type struct foo just like any other type. The line struct foo f1; is a global variable declaration which declares the variable f1 to be of type struct foo. The dot operator is used to access the elements of a variable of structure type. In this case, f1.i and f1.j refer to the two elements of f1. You can treat the quantities f1.i and f1.j just as you would treat any variables of type int (the type of the elements was defined in the structure declaration at the top to be int). Pointers to structure types can also be used, just like pointers to any other type. However, with structures, there is a special short-cut for referring to the elements of the structure pointed to. struct foo *fptr; void main() { fptr=&f1; fptr->i=10; fptr->j=20; } In this example, fptr is declared to be a pointer to type struct foo. In main, it is set to point to the global f1 defined above. Then the elements of the structure pointed to by fptr (in this case these are the same as the elements of f1), are set. The arrow operator is used instead of the dot operator because fptr is a pointer to a variable of type struct foo. Note that (*fptr).i would have worked just as well as fptr->i, but it would have been clumsier. Note that only pointers to structures, not the structures themselves, can be passed to or returned from functions.

42

Complex Initialization examples Complex types -- arrays and structures -- may be initialized upon declaration with a sequence of constant values contained within curly braces and separated by commas. Arrays of character may also be initialized with a quoted string of characters. For initialized declarations of single dimensional arrays, the length can be left blank and a suitable length based on the initialization data will be assigned to it. Multi-dimensional arrays must have the size of all dimensions specified when the array is declared. If a length is specified, the initialization data may not overflow that length in any dimension or an error will result. However, the initialization data may be shorter than the specified size and the remaining entries will be initialized to 0. Following is an example of legal global and local variable initializations: /* declare many globals of various types */ int i=50; int *ptr=NULL; float farr[3]={ 1.2, 3.6, 7.4 }; int tarr[2][4]={ { 1, 2, 3, 4 }, { 2, 4, 6, 8} }; char c[]="Hi there how are you?"; char carr[5][10]={"Hi","there","how","are","you"}; struct bar { int i; int *p; long j; } b={5, NULL, 10L}; struct bar barr[2] = { { 1, NULL, 2L }, { 3 } }; /* declare locals of various types */ int foo() { int x; /* local variable x with initial value 0 */ int y= tarr[0][2]; /* local variable y with initial value 3 */ int *iptr=&i; /* local pointer to integer which points to the global i */ int larr[2]={10,20}; /* local array larr with elements 10 and 20 */ struct bar lb={5,NULL,10L}; /* local variable of type struct bar with i=5 and j=10 */ char lc[]=carr[2]; /* local string lc with initial value "how" */ ... }

43

Statements and Expressions Operators act upon objects of a certain type or types and specify what is to be done to them. Expressions combine variables and constants to create new values. Statements are expressions, assignments, function calls, or control flow statements which make up C programs. Operators Each of the data types has its own set of operators that determine which operations may be performed on them. Integer Operations The following operations are supported on integers:

Arithmetic. addition +, subtraction -, multiplication *, division /. Comparison. greater-than >, less-than <, equality ==, greater-than-equal >=, lessthan-equal <=. Bitwise Arithmetic. bitwise-OR |, bitwise-AND &, bitwise-exclusive-OR ^, bitwise-NOT ~. Boolean Arithmetic. logical-OR ||, logical-AND &&, logical-NOT !. When a C statement uses a boolean value (for example, if), it takes the integer zero as meaning false, and any integer other than zero as meaning true. The boolean operators return zero for false and one for true. Boolean operators && and || will stop executing as soon as the truth of the final expression is determined. For example, in the expression a && b, if a is false, then b does not need to be evaluated because the result must be false. The && operator therefore will not evaluate b.

Long Integers A subset of the operations implemented for integers are implemented for long integers: arithmetic addition +, subtraction -, and multiplication *, and the integer comparison operations. Bitwise and boolean operations and division are not supported.

44

Floating Point Numbers IC uses a package of public-domain floating point routines distributed by Motorola. This package includes arithmetic, trigonometric, and logarithmic functions. Since floating point operations are implemented in software, they are much slower than the integer operations; we recommend against using floating point if you are concerned about performance. The following operations are supported on floating point numbers:

Arithmetic. addition +, subtraction -, multiplication *, division /. Comparison. greater-than >, less-than <, equality ==, greater-than-equal >=, lessthan-equal <=. Built-in Math Functions. A set of trigonometric, logarithmic, and exponential functions is supported. For details, go to the Library Function Descriptions. These functions are included among those itemized as "Math" functions.

Characters Characters are only allowed in character arrays. When a cell of the array is referenced, it is automatically coerced into a integer representation for manipulation by the integer operations. When a value is stored into a character array, it is coerced from a standard 16bit integer into an 8-bit character (by truncating the upper eight bits). Assignment Operators and Expressions The basic assignment operator is =. The following statement adds 2 to the value of a. a = a + 2; The abbreviated form a += 2; could also be used to perform the same operation. All of the following binary operators can be used in this fashion: + - * / % << >> & ^ |

45

Increment and Decrement Operators The increment operator "++" increments the named variable. For example, the construction "a++" is equivalent to "a= a+1" or "a+= 1". A statement that uses an increment operator has a value. For example, the statement a= 3; printf("a=%d a+1=%d\n", a, ++a); will display the text "a=3 a+1=4". If the increment operator comes after the named variable, then the value of the statement is calculated after the increment occurs. So the statement a= 3; printf("a=%d a+1=%d\n", a, a++); would display "a=3 a+1=3" but would finish with a set to 4. The decrement operator "--" is used in the same fashion as the increment operator. Data Access Operators & A single ampersand preceding a variable, an array reference, or a structure element reference returns a pointer to the location in memory where that information is being stored. This should not be used on arbitrary expressions as they do not have a stable place in memory where they are being stored. * A single * preceeding an expression which evaluates to a pointer returns the value which is stored at that address. This process of accessing the value stored within a pointer is known as dereferencing. [<expr>] An expression in square braces following an expression which evaluates to an array (an array variable, the result of a function which returns an array pointer, etc.) checks that the value of the expression falls within the bounds of the array and references that element. . A dot between a structure variable and the name of one of its fields returns the value stored in that field. -> An arrow between a pointer to a structure and the name of one of its fields in that structure acts the same as a dot does, except it acts on the structure pointed at by its left hand side. Where f is a structure of a type with i as an element name, the two expressions f.i and (&f)->i are equivalent.

46

Precedence and Order of Evaluation The following table summarizes the rules for precedence and associativity for the C operators. Operators listed earlier in the table have higher precedence; operators on the same line of the table have equal precedence. Operator () [] Associativity left to right

! ~ ++ -- - (<type>) right to left */% +<< >> left to right left to right left to right

< <= > >= left to right == != & ^ | && || left to right left to right left to right left to right left to right right to left

= += -= etc. right to left , left to right

47

Control Flow IC supports most of the standard C control structures. One notable exception is the switch statement, which is not supported.

48

Statements and Blocks A single C statement is ended by a semicolon. A series of statements may be grouped together into a block using curly braces. Inside a block, local variables may be defined. Blocks may be used in place of statements in the control flow constructs. If-Else The if else statement is used to make decisions. The syntax is: if (<expression>) <statement-1> else <statement-2> <expression> is evaluated; if it is not equal to zero (e.g., logic true), then <statement-1> is executed. The else clause is optional. If the if part of the statement did not execute, and the else is present, then <statement-2> executes. While The syntax of a while loop is the following: while (<expression>) <statement> while begins by evaluating <expression>. If it is false, then <statement> is skipped. If it is true, then <statement> is evaluated. Then the expression is evaluated again, and the same check is performed. The loop exits when <expression> becomes zero. One can easily create an infinite loop in C using the while statement: while (1) <statement> For The syntax of a for loop is the following: for (<expr-1>;<expr-2>;<expr-3>) <statement> The for construct is equivalent to the following construct using while: <expr-1>; while (<expr-2>) { <statement> <expr-3>; }

49

Typically, <expr-1> is an assignment, <expr-2> is a relational expression, and <expr-3> is an increment or decrement of some manner. For example, the following code counts from 0 to 99, printing each number along the way: int i; for (i = 0; i < 100; i++) printf("%d\n", i); Break Use of the break statement provides an early exit from a while or a for loop.

50

LCD Screen Printing IC has a version of the C function printf for formatted printing to the LCD screen. The syntax of printf is the following: printf(<format-string>, <arg-1> , ... , <arg-N>); This is best illustrated by some examples. Printing Examples Example 1: Printing a message The following statement prints a text string to the screen. printf("Hello, world!\n"); In this example, the format string is simply printed to the screen. The character \n at the end of the string signifies end-of-line. When an end-of-line character is printed, the LCD screen will be cleared when a subsequent character is printed. Thus, most printf statements are terminated by a \n. Example 2: Printing a number The following statement prints the value of the integer variable x with a brief message. printf("Value is %d\n", x); The special form %d is used to format the printing of an integer in decimal format. Example 3: Printing a number in binary The following statement prints the value of the integer variable x as a binary number. printf("Value is %b\n", x); The special form %b is used to format the printing of an integer in binary format. Only the low byte of the number is printed.

51

Example 4: Printing a floating point number The following statement prints the value of the floating point variable n as a floating point number. printf("Value is %f\n", n); The special form %f is used to format the printing of floating point number. Example 5: Printing two numbers in hexadecimal format printf("A=%x B=%x\n", a, b); The form %x formats an integer to print in hexadecimal. Formatting Command Summary Format Command Data Type Description %d int decimal number %x int hexadecimal number %b int low byte as binary number %c int low byte as ASCII character %f float floating point number %s char array char array (string)

52

Special Notes

The final character position of the LCD screen is used as a system "heartbeat." This character continuously blinks between a large and small heart when the board is operating properly. If the character stops blinking, the board has failed. Characters that would be printed beyond the final character position are truncated. When using a two-line display, the printf() command treats the display as a single longer line. Printing of long integers is not presently supported.

53

Preprocessor The preprocessor processes a file before it is sent to the compiler. The IC preprocessor allows definition of macros, and conditional compilation of sections of code. Using preprocessor macros for constants and function macros can make IC code more efficient as well as easier to read. Using #if to conditionally compile code can be very useful, for instance, for debugging purposes. The special preprocessor command #use has been included to allow programs to cause a program to download to initiate the download of stored programs that are not in the IC library. For example, suppose you have a set of stored programs in a file named "mylib.ic", some of which you need for your current program to work. /* load my library */ #use "mylib.ic" void main() { char s[32] = "text string wrapping badly\n"; fix (s); /* apply my fix function to s and print it */ printf(s); } Preprocessor Macros Preprocessor macros are defined by using the #define preprocessor directive at the start of a line. A macro is local to the file in which it is defined. The following example shows how to define preprocessor macros. #define RIGHT_MOTOR 0 #define LEFT_MOTOR 1 #define GO_RIGHT(power) (motor(RIGHT_MOTOR,(power))) #define GO_LEFT(power) (motor(LEFT_MOTOR,(power))) #define GO(left,right) {GO_LEFT(left); GO_RIGHT(right);} void main() { GO(0,0); }

54

Preprocessor macro definitions start with the #define directive at the start of a line, and continue to the end of the line. After #define is the name of the macro, such as RIGHT_MOTOR. If there is a parenthesis directly after the name of the macro, such as the GO_RIGHT macro has above, then the macro has arguments. The GO_RIGHT and GO_LEFT macros each take one argument. The GO macro takes two arguments. After the name and the optional argument list is the body of the macro. Each time a macro is invoked, it is replaced with its body. If the macro has arguments, then each place the argument appears in the body is replaced with the actual argument provided. Invocations of macros without arguments look like global variable references. Invocations of macros with arguments look like calls to functions. To an extent, this is how they act. However, macro replacement happens before compilation, whereas global references and function calls happen at run time. Also, function calls evaluate their arguments before they are called, whereas macros simply perform text replacement. For example, if the actual argument given to a macro contains a function call, and the macro instantiates its argument more than once in its body, then the function would be called multiple times, whereas it would only be called once if it were being passed as a function argument instead. Appropriate use of macros can make IC programs and easier to read. It allows constants to be given symbolic names without requiring storage and access time as a global would. It also allows macros with arguments to be used in cases when a function call is desirable for abstraction, without the performance penalty of calling a function.

55

Conditional compilation It is sometimes desirable to conditionally compile code. The primary example of this is that you may want to perform debugging output sometimes, and disable it at other times. The IC preprocessor provides a convenient way of doing this by using the #ifdef directive. void go_left(int power) { GO_LEFT(power); #ifdef DEBUG printf("Going Left\n"); beep(); #endif } In this example, when the macro DEBUG is defined, the debugging message "Going Left" will be printed and the board will beep each time go_left is called. If the macro is not defined, the message and beep will not happen. Each #ifdef must be follwed by an #endif at the end of the code which is being conditionally compiled. The macro to be checked can be anything, and #ifdef blocks may be nested. Unlike regular C preprocessors, macros cannot be conditionally defined. If a macro definition occurs inside an #ifdef block, it will be defined regardless of whether the #ifdef evaluates to true or false. The compiler will generate a warning if macro definitions occur within an #ifdef block. The #if, #else, and #elif directives are also available, but are outside the scope of this document. Refer to a C reference manual for how to use them.

56

Comparison with regular C preprocessors The way in which IC deals with loading multiple files is fundamentally different from the way in which it is done in standard C. In particular, when using standard C, files are compiled completely independently of each other, then linked together. In IC, on the other hand, all files are compiled together. This is why standard C needs function prototypes and extern global definitions in order for multiple files to share functions and globals, while IC does not. In a standard C preprocessor, preprocessor macros defined in one C file cannot be used in another C file unless defined again. Also, the scope of macros is only from the point of definition to the end of the file. The solution then is to have the prototypes, extern declarations, and macros in header files which are then included at the top of each C file using the #include directive. This style interacts well with the fact that each file is compiled independent of all the others. However, since declarations in IC do not file scope, it would be inconsistent to have a preprocessor with file scope. Therefore, for consistency it was desirable to give IC macros the same behavior as globals and functions. Therefore, preprocessor macros have global scope. If a macro is defined anywhere in the files loaded into IC, it is defined everywhere. Therefore, the #include and #undef directives did not seem to have any appropriate purpose, and were accordingly left out. The fact that #define directives contained within #if blocks are defined regardless of whether the #if evaluates to be true or false is a side effect of making the preprocessor macros have global scope. Other than these modifications, the IC preprocessor should be compatible with regular C preprocessors.

57

The IC Library File Library files provide standard C functions for interfacing with hardware on the robot controller board. These functions are written either in C or as assembly language drivers. Library files provide functions to do things like control motors, make tones, and input sensors values. IC automatically loads the library file every time it is invoked. Depending on which board is being used, a different library file will be required. IC may be configured to load different library files as its default; IC will automatically load the correct library for the board you're using at the moment. Separate documentation covers all library functions available for the Handy Board and RCX; if you have another board, see your owner's manual for documentation. To understand better how the library functions work, study of the library file source code is recommended; e.g., the main library file for the Handy Board is named lib_hb.ic. For convenience, commonly a description of commonly used library functions follows.

58

Commonly Used IC Library Functions start_button(); /* returns 1 if button is pressed, otherwise 0 */ stop_button(); /* returns 1 if button is pressed, otherwise 0 */ digital(); /* returns 0 if the switch attached to the port is open and returns 1 if the switch is closed. Digital ports are numbered 7-15. Typically used for bumpers or limit switches. */ analog(); /* returns the analog value of the port (a value in the range 0-255). Analog ports on the handy board are numbered 2-6 and 16-23. Light sensors and range sensors are examples of sensors you would use in analog ports (only on Handy Board). */ knob(); /* returns an int between 0 and 255 depending on knob position */ sleep(<float_secs>); /* waits specified number of seconds */ beep(); /* causes a beep sound */ tone(<float_frequency>, <float_secs>) /* plays at specified frequency for specified time (seconds) */ printf(<string>, <arg1>, <arg2>, ... ); /* prints <string>. If the string contains % codes then the <args> after the string will be printed in place of the % codes in the format specified by the code. %d prints a decimal number. %f prints a floating point number. %c prints a character, %b prints an integer in binary, %x prints an integer in hexadecimal. */ motor(<motor_#>, <speed>) /* controls the motors. <motor_#> is an integer between 0 and 3 (1 less for RCX). <speed> is an integer between -100 and 100 where 0 means the motor is off and negative numbers run the motor in the reverse direction */

59

fd(<motor_#>); /* turns on the motor specified (direction is determined by plug orientation */ bk(<motor_#>); /* turns on the motor specified in the opposite direction from fd */ off(<motor_#>); /* turns off the motor specified */ ao(); /* turns all motor ports off */ Processes Processes work in parallel. Each process, once it is started, will continue until it finishes or until it is killed by another process using the kill_process(<process_id)>); statement. Each process that is active gets 50ms of processing time. Then the process is paused temporarily and the next process gets its share of time. This continues until all the active process have gotten a slice of time, then it all repeats again. From the user's standpoint it appears that all the active processes are running in parallel. Processes can communicate with one another by reading and modifying global variables. The globals can be used as semaphores so that one process can signal another. Process IDs may also be stored in globals so that one process can kill another when needed. Up to 4 processes initiated by the start_process() library function can be active at any time. The library functions for controlling processes are: start_process(<function_name>(<arg1>, <arg2>, . . .)); /* start_process returns an integer that is the <process_id> and starts the function <function_name> as a separate process */ defer(); /* when placed in a function that is used as a process this will cause that process to give up the remainder of its time slice whenever defer is called */ kill_process(<process_id>); /* this will terminate the process specified by the <process_id> */

60

Encoders (Handy Board only) The enable_encoder() library function is used to start a process which updates the transition count for the encoder specified. The encoder library functions are designed for sensors connected to (digital) ports 7,8,12,13. The corresponding <encoder#> values are 0,1,2,3. Every enabled encoder uses a lot of the HB's processor -- so don't enable an encoder unless you are going to use it, and never put an enable statement inside of a loop. enable_encoder(<encoder#>); /* turns on the specified encoder (either 0,1,2, or 3 which are plugged into digital ports 7, 8, 12, 13 respectively). This should be done only once - never enable an already enabled encoder. If an encoder is not enabled, read_encoder will always return 0. */ disable_encoder(<encoder#>) /* turns off the specified encoder */ reset_encoder(<encoder#>) /* sets the specified encoder value to 0 */ read_encoder(<encoder#>) /* returns an int that is the current value of the specified encoder */

61

Controlling the DC Motors To Control the DC Motors, Please ensure that the moors are connected to the MIII Main board before programming.

Procedure - Connect the DC Motors to M-0 and M-1 channel on the Main Board. - Make sure the Interactive C Program is opened. Select a NEW Program or continue with your existing Program. - The Following Sample Code, DC-CODE, shows how you can control the DC Motors. - After you have typed / inserted the code, click on the RUN MAIN button. - Observe the Motor Indicator on the LCD Screen. RESULTS Observe and you will see the following: - GREEN LED Lights Up. - Motor Turns in 1 direction for 2 Seconds - RED LED Lights Up - Motor Turns in faster by 30% in another direction for 2 Seconds - This Operation continues in an endless loop

62

DC-CODE /* Example for drive motor */ /* Hardware configuration - Motor left connected to DC Motor channel M-0 - Motor right connected to DC Motor channel M-1 */ COMMENTS

MAIN PROG void main() { while(1) // Infinite loop { motor(0,50); // Motor0 forward at 50% of maximum power motor(1,50); // Motor1 forward at 50% of maximum power sleep(2.0); // Delay 2 sec motor(0,-80); // Motor0 backward at 80% of maximum power motor(1,-80); // Motor1 backward at 80% of maximum power sleep(2.0); // Delay 2 sec } }

IMPORTANT COMMANDS

While (

) {.}

A represents loops, 1 = INFINITE LOOPS .. represents the code inside

C B

Motor (

);

B represents the board motor number C represents the % of power

Sleep (

);

D represents the number of seconds to wait.

63

Controlling RC-Servo Motors The Set of servo motors the package can also be programmed to be run with board. The main boards can allow up to 6 servo In Interactive C, we can use commands. They are provided in the main capability motors. 2

init_expbd_servos(

);

A represents ON or OFF 1 for ON, 0 for OFF

C B

servo

B represents the board servo number, from 0 to 5. C represents the Servo DRIVE VALUE (Power ).

Procedure Connect the RC Servo motor to Channel 0 on the main board. BE CAREFUL OF THE COLOR CODE. WHITE GOES TO S RED to + BLACK to Make sure the Interactive C Program is opened. Select a NEW Program or continue with your existing Program. The Following Sample Code, SERVO-CODE, shows how you can control the Servo Motors. After you have typed / inserted the code, click on the RUN MAIN button. Observe the Servo Motors Operations.

64

SERVO CODE /* Servo motor test*/ /* Hardware configuration - servo motor connected to ch-0 */ COMMENTS

MAIN PROG void main() { int i=600; // Declare and define servo drive value init_expbd_servos(1); // Enable servo motor driver while(!stop_button()) // Check STOP switch pressed { servo0 = i; // Drive servo motor ch-0 with servo drive value sleep(1.0); // Delay 1 sec i+=100; // Increase value step = 100 if(i>4200) // Check angle>180 deg { i=600; // Set to origin } } init_expbd_servos(1); // Disable servo motor driver beep(); // Sound beep } IMPORTANT COMMANDS

Init_expbd_servos ( servo = ;

);

A represents either 1 or 0. 1 is to turn servo motors ON. 0 is to OFF servo motors.

C B

B represents the Servo Channel. C represents the Drive Value ( POWER ).

65

Controlling the SWITCH Sensor The Main Board allows expandability of up to 9 DIGITAL Inputs.

Procedure - Connect the Switch sensor to DI-5 ( Digital Input 5) on the Main Board. - Make sure the Interactive C Program is opened. Select a NEW Program or continue with your existing Program. - The Following Sample Code, SWITCH-CODE - After you have typed / inserted the code, click on the RUN MAIN button. - Observe the LCD Screen on the Main Board.

66

SWITCH CODE /* Touch sensor test*/ /* Hardware configuration - Touch sensor connected to DI-15 */ COMMENTS

void main() { int result; // Declare keep input from touch sensor while(1) // Infinite loop { result = digital(15); // Keep value from DI-15 channel if(result==1) // Check Touch sensor pressed { printf("Your press!\n"); // Display message for pressed beep(); // Sound beep sleep(1.0); // Delay 1 sec for display message } else { printf("----------\n"); // Display when Touch sensor not pressed sleep(0.1); // Delay 0.1 sec for display message } } } IMPORTANT CODES

MAIN PROG

=digital( beep();

);

A Represents Value of Digital Input. B Represents Channel / Port number. This tells the Main Board to play a BEEP

printf(

);

C Represents what to be displayed on the LCD Screen

67

FIRE DETECTION / LIGHT DETECTION The Main Board allows 21 INPUTS for analog sensors converts physical signals to Light sensors convert physical density into DC Voltage. If it its lower in voltage. If it is its higher in voltage which exceed 5V. Analog which DC Volts. Light is dark, Bright, may

Procedure - Connect the Light Sensor to AI-31 (Analog Input 31) - Make sure the Interactive C Program is opened. Select a NEW Program or continue with your existing Program. - The Following Sample Code, LIGHT-CODE - After you have typed / inserted the code, click on the RUN MAIN button. - Turn the Main Board off and on again to reset the board. - Try these in LIGHT and DARK surroundings. - Observe the LCD Screen on the Main Board.

68

LIGHT CODE /*Light Sensor test */ /* Hardware configuration - Light Sensor connected to AI-31 */ void main() { int value; // Declare keep input from touch sensor // { value = analog(31); // Keep value from AI-31 channel printf("Light %d\n",value); // Display Reflect value sleep(0.1); // Delay 0.1 sec for display } } IMPORTANT CODES COMMENTS

MAIN PROG

A B

=analog(

);

A Represents Value of Analog Input. B Represents Channel / Port number.

69

GP2D12 Readings ( Package & Additional ) The GP2D12 are also Analog use the same ports sensors. Module sensors and therefore as the light

Procedure - Connect the GP2D12 Sensor to AI-6. - Make sure the Interactive C Program is opened. Select a NEW Program or continue with your existing Program. - The Following Sample Code, GP2D12-CODE - After you have typed / inserted the code, click on the RUN MAIN button. - Place an object in-front of the sensor. - Observe the LCD Screen on the Main Board. - Move the object nearer and further from the sensor and observe the LCD Screen again.

70

GP2D12 CODE /* GP2D120 test*/ /* Hardware configuration - GP2D120 connected to AI-6 */ #define base -19 float dis_table[118]={ /*distance value*//*ADC value*/ 32.0,/*19*/ 26.1,/*24*/ 22.3,/*29*/ 19.3,/*34*/ 17.1,/*39*/ 15.5,/*44*/ 13.6,/*49*/ 12.4,/*54*/ 11.6,/*59*/ 10.85,/*64*/ 9.8,/*69*/ 9.0,/*74*/ 8.3,/*79*/ 7.6,/*84*/ 7.1,/*89*/ 6.6,/*94*/ 6.2,/*99*/ 5.85,/*104*/ 5.55,/*109*/ 5.2,/*114*/ 4.9,/*119*/ 4.6,/*124*/ 4.4,/*129*/ 4.1,/*134*/ }; 30.1,/*20*/ 29.5,/*21*/ 28.6,/*22*/ 27.5,/*23*/ 25.3,/*25*/ 24.5,/*26*/ 23.7,/*27*/ 23.2,/*28*/ 22.0,/*30*/ 21.1,/*31*/ 20.5,/*32*/ 20.0,/*33*/ 19.1,/*35*/ 18.4,/*36*/ 17.9,/*37*/ 17.5,/*38*/ 16.5,/*40*/ 16.2,/*41*/ 15.8,/*42*/ 15.6,/*43*/ 15.3,/*45*/ 14.8,/*46*/ 14.2,/*47*/ 13.8,/*48*/ 13.3,/*50*/ 13.1,/*51*/ 12.8,/*52*/ 12.6,/*53*/ 12.2,/*55*/ 12.0,/*56*/ 11.8,/*57*/ 11.7,/*58*/ 11.6,/*60*/ 11.5,/*61*/ 11.4,/*62*/ 11.3,/*63*/ 10.6,/*65*/ 10.3,/*66*/ 10.2,/*67*/ 10.0,/*68*/ 9.7,/*70*/ 9.5,/*71*/ 9.3,/*72*/ 9.2,/*73*/ 8.9,/*75*/ 8.8,/*76*/ 8.6,/*77*/ 8.4,/*78*/ 8.2,/*80*/ 8.0,/*81*/ 7.85,/*82*/ 7.7,/*83*/ 7.5,/*85*/ 7.3,/*86*/ 7.2,/*87*/ 7.15,/*88*/ 7.0,/*90*/ 6.9,/*91*/ 6.8,/*92*/ 6.7,/*93*/ 6.5,/*95*/ 6.4,/*96*/ 6.35,/*97*/ 6.3,/*98*/ 6.15,/*100*/ 6.1,/*101*/ 6.0,/*102*/ 5.9,/*103*/ 5.8,/*105*/ 5.7,/*106*/ 5.65,/*107*/ 5.6,/*108*/ 5.45,/*110*/ 5.4,/*111*/ 5.4,/*112*/ 5.3,/*113*/ 5.1,/*115*/ 5.0,/*116*/ 5.0,/*117*/ 4.9,/*118*/ 4.8,/*120*/ 4.8,/*121*/ 4.7,/*122*/ 4.7,/*123*/ 4.6,/*125*/ 4.5,/*126*/ 4.5,/*127*/ 4.4,/*128*/ 4.3,/*130*/ 4.3,/*131*/ 4.2,/*132*/ 4.2,/*133*/ 4.1,/*135*/ 4.0/*136*/ COMMENTS

DEFINITION

71
MAIN PROG

void main() { int an; // Keep analog value from sensor while(1) // Infinite loop { an = analog(6); // Read analog value from sensor if(an>=19 && an<=136 ) // Distance interval 10-80 cm { printf("dis%f cm adc = %d \n",dis_table[an+base],an); // Show distance value } else { printf(" Out of Range adc = %d\n",an); // Show mesage out of Range } sleep(1.0); // Delay before read new cycle } }

72

SRF04 Readings ( Additional ) The SRF04 has Signals, on the other output For every there is an input for input and output, checking.

Procedure - Connect the Echo Input of the SRF04 to Digital Input Capture C-1 (IC1) - Connect the Trigger Pulse output of the SRF04 to the Digital Input 9 (IN9) - Make sure the Interactive C Program is opened. Select a NEW Program or continue with your existing Program. - The Following Sample Code, SRF04-CODE - After you have typed / inserted the code, click on the RUN MAIN button. - Place an object in-front of the sensor. - Observe the LCD Screen on the Main Board. - Move the object nearer and further from the sensor and observe the LCD Screen again.

73

SRF04 CODE /* Sonar sensor test*/ /* Hardware configuration - echo pulse pin connected to IC1 - trigger pulse pin connected to IN-9 */ #use "srf04_lib.ic" /* Include library srf04_lib.ic*/ COMMENTS

MAIN PROG

void main() { int result; // Declare keep input from touch sensor sonar_init(); // Initial sonar sensor while(1) // Infinite loop { result= sonar_sample(); // Keep distance value if (result != -1 ) // Check result value printf("Distance %d cm\n", result); // Display distance cm scale else printf("Out of Range\n"); // Display massage when out of range sleep(0.3); // Delay 0.3 sec for display } }

74

Add senses to the Robo-11 standard so that it can detect and move along a line, by using the IR Reflector Sensor.

Building Type 1

Using the Robo-11 standard robot, remove the top structure that has the AX11 attached.

Turn the robot upside down. Install the 10 mm plastic spacer using a 3 x 25 mm screw screwed into the universal plate according to the positions as shown in the picture ( positions 5,2 and 5,9 : the first set of numbers refer to the longitude positions from the leftmost side while the second set is the horizontal positions form the top down. )

Take two IR Reflector Sensors (ZX-03) and place them onto the spacers, twisting the screw through the spacer and sensor and screwing it tightly together with a 3 mm nut. Do the same for both sets, and set the robot upright.

75

Replace the top structure that has the AX-11 board on it back onto the bottom part. Then connect the left IR Reflector Sensor (looking down from the top) to terminal Al-31 and the right one to terminal Al-17 of the AX-11 The Robo-11 Liner1 is now complete and ready to search and detect lines.

Robo-11 Liner1 Test After the Robo-11 Liner1 has been put together, we will then write a test program to test the operation of the Robo-11 Liner1 by having it detect a black line and move backwards and change directions once it detects the line. Type in the following program code and download it to the Robo-11 liner1.
/* Example for Robo-11 liner1 : Black line Detection Hardware configuration - Motor left connected to DC Motor chanel M-0 - Motor right connected to DC Motor chanel M-1 - ZX-03 left connected to AI-31 - ZX-03 Right connected to AI-17 */ #define pow 50 /*Configuration power drive motor 50% */ #define ref 70 /*Configuration analog reference 70 */ int left=0,right=0; // To keep input analog value void main(void) { ao(); while(!stop_button()) { printf(Press start!\n); while(!start_button()); printf( Track Line\n); while(!stop_button()) { left = analog(31); right = analog(17); if((left>ref)&&(right>ref) { run_fd(0.01); } else if((left<ref)&&(right>ref)) { turn_right(1.5); } else if((left>ref)&&(right<ref)) { turn_left(1.5); }

// Check STOP button pressed in process // // // // Show message Check START button pressed to run Show message for working Check STOP button pressed in process

// Read left sensor data // Read right sensor data //check out line // Direct forward // check left sensor in line // Turn right 1.5 sec // check right sensor in line // Turn left 1.5 sec

76

else if((left<ref)&&(right<ref)) //check 2 sensor in line { turn_left(1.5); // Turn left 1.5 sec } } printf(Stop..\n); // Show message off all motor ao(); // Off all motor for end program beep(); // Sound beep signal for end program } } void turn_left(float spin_time) { motor(0,-pow); // Motor0 backward for pow define value motor(1,pow); // Motor1 forward for pow define value sleep(spin_time); // Delay set by parameter spin_time } void turn_right(float spin_time) { motor(0,pow); // Motor0 forward for pow define value motor(1,-pow); // Motor1 backward for pow define value sleep(spin_time); // Delay set by parameter spin_time } void run_fd(float delay) { motor(0,pow); // Motor0 forward for pow define value motor(1,pow); // Motor1 forward for pow define value sleep(delay); // Delay set by parameter delay } void run_bk(float delay) { motor(0,-pow); // Motor0 backward for pow define value motor(1,-pow); // Motor1 backward for pow define value sleep(delay); // Delay set by parameter delay }

TIPS ON THE IR REFLECTOR SENSOR


The heart of this sensor circuit is the sensor that detects reflections from infrared light. It consists of the Infrared LED which emits infrared light to the surface. Photo-transistors will then receive the reflected infrared lights. If no infrared light is received, the OUT terminal will have low voltage when measured. In the case that it receives infrared light, whether low or high current passes through the photo-transistor depends on the intensity of the light received which in turn varies according to the distance of the reflection. (Sensor TCRT5000 can be used at a distance of 0.1 1.5 centimeters). Therefore, 0.5 5V can be measured at the OUT terminal, and the AX-11 will get a value of 10 to 255.

77

Create the test field by cutting two 20 cm long and 1 in wide black tape and placing it 50 cm apart on a flat surface.

Testing It
Place the Robo-11 Liner1 on the floor and then turn on the POWER switch. The LCD screen displays the message Press Start. Press START on the AX-11. The robot will move forward using only 50% of its power, while using the IR Reflector Sensor to detect the black line. The robot will immediately change directions if it detects a black line, the direction depending on the operation of the sensors. If the left sensor detects the line first, the robot will turn right. However, if the right sensor detects the line first, it will turn left. If both sensors detect a line, the robot will also turn left. How accurate the Robo-11 Liner1 detects the black line depends on the chosen decision variable, whether is defined as the black line or the white surface. In the test program, the ref parameter is defined as 80. This value may be changed depending on the test area, which may have more or less light. Other factors may include the distance from the sensor to the floor, or if the test field is modified to have white lines on a black surface instead.

78

Building Type 2

The Robo-11 Liner2 will have 3 IR Reflector sensors installed, enabling a more efficient detection. Using the Robo11 standard robot, remove the top structure that has the AX-11 attached.

Turn the robot upside down. Install the 10 mm plastic spacer using a 3 x 25 mm screw screwed into the universal plate according to the positions (5,2), (8,6) and (5,9). The first set of numbers refers to the longitude positions from the leftmost side while the second set is the horizontal positions form the top down.

Place the IR Reflector Sensors (ZX-03) onto the spacers, twisting the screw through the spacer and sensor and screwing it tightly together with a 3 mm nut. Do the same for all sets, and set the robot upright.

Replace the top structure with the AX-11 board back onto the bottom part. Then connect the left IR Reflector Sensor (looking down from the top) to terminal Al-31 and the right one to terminal Al-17 of the AX-11

79

Conditions in testing the Line Sensor


The programmer needs to test reading the values from the line sensor, in this case, detecting a black line and white surface. Then he must calculate the value that is able to differentiate between the reflection from the black line and the white field surface. The program can be written as following: void main() { while(1) // Endless loop { printf(L=%dM=%d R=%d\n,analog(31),analog(25),analog(17)); // Reading all sensors sleep(0.1); // Display delay } The test results in the following: When the black line is detected, the converted analog signals to digital signals will give a value of 40 to 60. When the white surface is detected, the converted analog signals to digital signals will give a value of 40 to 60. Therefore, 80 is chosen as the reference value for the black line detection. Thus, if the value read from the line sensor is less than 80, the sensor will consider it to be on a black line. But if the value read is more than 80, than the sensor is considered to be on the white surface area.

When the Robot Moves


Scenario 1: Robot moves along the line
Results of all sensors are as following:
Left Line Sensor Detected white surface. The value read from input Al31 was more than 80. Central Line Sensor Detected the black line. The value read from input Al25 was less than 80. Right Line Sensor Detected white surface. The value read from input Al17 was more than 80.

When the robot operates in this scenario, the robot must be controlled so that it moves forward and delays briefly.

80

Scenario 2: The robot moves rightwards away of the line Results of all sensors are as following: Left Line Sensor Detected the black line. The value read from input Al-31 was less than 80. Central Line Sensor Detected the black line. The value read from input Al-25 was more than/less than 80. Right Line Sensor Detected white surface. The value read from input Al17 was more than 80.

When the robot operates in this scenario, the robot must be controlled so that it turns left slowly and delays briefly.

Scenario 3: The robot moves leftwards away of the line. Results of all sensors are as following: Left Line Sensor Detected white surface. The value read from input Al31 was more than 80. Central Line Sensor Detected the black line. The value read from input Al-25 was more than/less than 80. Right Line Sensor Detected white surface. The value read from input Al17 was less than 80.

When the robot operates in this scenario, the robot must be controlled so that it turns right slowly and delays briefly.

Scenario 4: The robot meets an intersection


Results of all sensors are as following: Left Line Sensor Detected the black line. The value read from input Al-31 was less than 80. Central Line Sensor Detected the black line. The value read from input Al-25 was less than 80. Right Line Sensor Detected the black line. The value read from input Al-17 was less than 80.

When the robot operates in this scenario, the robot has many options to choose from whether it is to move forward, turn left, or turn right.

81
Robo-11 Liner2 Test After the Robo-11 Liner2 has been put together, we will next write a test program to test the operation of the Robo-11 Liner2 by having it detect and move forward along a black line. Type in the following program code and download it to the Robo-11 Liner2.
/* Example for Robot track line - Motor left connected to DC Motor chanel M-0 - Motor right connected to DC Motor chanel M-1 */ #define pow 50 /*Configuration power drive motor*/ #define ref 80 /*Configuration analog reference */ int left=0,right=0,mid=0; // For keep input analog value void main(void) { ao(); while(!stop_button()) // wait STOP button pressed in process { printf(Press start!\n); // Show begining message while(!start_button()); // Wait START button pressed to run printf( Track Line\n); // Show working message while(!stop_button()) // Wait STOP button pressed in process { left = analog(31); // Read left sensor data mid = analog(25); // Read middle sensor data right = analog(17); // Read right sensor data if((left>ref)&&(mid<ref)&&(right>ref) // Check in line { run_fd(0.01); // Direct forward } else if((left<ref)&&(mid>ref)&&(right>ref)) // Check over right { turn_left(0.1); // Turn left for backing to line } else if((left>ref)&&(mid<ref)&&(right<ref)) // Check in line { turn_right(0.3); // Turn right for backing to line } else if((left>ref)&&(mid>ref)&&(right<ref)) // Check over left { turn_right(0.1); // Turn right for backing to line } else if((left<ref)&&(mid<ref)&&(right>ref)) // Check cross line { turn_left(0.3); // Turn left for backing to line } else if((left<ref)&&(mid>ref)&&(right<ref)) // Check between cross line { turn_left(0.3); // Turn left for backing to line } else // If out of condition { run_fd(0.01); // Direct forward } }

82

printf(Stop..\n); ao(); beep(); } } void turn_left(float spin_time) { motor(0,-pow); motor(1,pow); sleep(spin_time); } void turn_right(float spin_time) { motor(0,pow); motor(1,-pow); sleep(spin_time); } void run_fd(float delay) { motor(0,pow); motor(1,pow); sleep(delay); } void run_bk(float delay) { motor(0,-pow); motor(1,-pow); sleep(delay); }

// Show finish message // Off all motor for ending program // Sound beep signal for ending program

// Motor0 backward with pow value // Motor1 forward with pow value // Delay set by parameter spin_time

// Motor0 forward with pow value // Motor1 backward with pow value // Delay set by parameter spin_time

// Motor0 forward with pow value // Motor1 forward with pow value // Delay set by parameter delay

// Motor0 backward with pow value // Motor1 backward with pow value // Delay set by parameter delay

Testing It
Place the Robo-11 liner2 over the black line on the floor (provided in the set) and then turn on the POWER switch. The LCD screen displays the message Press Start. Press START on the AX-11. The robot will move forward using only 50% of its power. At the same time, the display screen will show the message Track Line. When the intersection is located, the robot will always decide to turn left and will only stop operating when the STOP switch is pressed. How accurately the Robo-11 Liner2 detects the black line depends on the chosen decision variable, whether it is defined as the black line or the white surface, similar to the Robo-11 Liner1. It also depends on choosing the appropriate speed level. If it moves too fast, it may swing out of its course.

83

This robot was further developed from the Robo-11 standard by adding switches that will detect obstacles via collision.

BUILDING THE ATTACKER


1

Using the Robo-11 Standard robot (or the Robo-11 Liner2), take a strength joiner and attach it to the front of the robot with a 3 x 10 screw and 3 mm nut as shown in the picture. It should be twisted outward and installed at approximately 45 degrees.

Next, connect an obtuse joiner to the end of that strength joiner.

At the other end of the obtuse joiner from step 2, attach an angled joiner. This angled joiner will then be used to connect the switch.

84

Take the switch and install it to that robot arm that was built in step 3, by using a 3 mm spacer, 3 x 10 screw, and 3 mm nut and screwing them in together tightly.

Then proceed to build the robot arm for the other side, using the same steps. When finished, connect the signal cable of the left switch to terminal Dl-15 and the signal cable of the right switch to terminal Dl-10 of the AX-11 board. The Robo-11 Attacker is now finished and ready to be tested.

85

ABOUT THE SWITCH CIRCUIT


Pressing the switch results in two occurrences. When the switch is not pressed, let the results be logic 1 When the switch is pressed, let the results be logic 0, and LED1 light up. Since the switch can give two results, it is considered to be a digital input component. Therefore, in connecting it to the AX-11 board, it must be connected to the digital input terminals D1 which has 9 channels altogether, D1-0 to D1-8. In addition, it can also use the LED display on the switch as a digital output by connected it to the digital output terminal D0 which also has 9 channels. The LED on the switch will turn on or off depending on the logic 0 or 1 being sent. When logic 0 is sent, the LED will light (This method of use is not recommended for beginners)

Caution: When the LED display on the switch is used as an output, the switch must not be used or pressed or else the switch terminal ports may be damaged.

Robo-11 Attacker Test


The next step would be to write a test program to test the operation of the Robo-11 Attacker by having it detect objects by touch or collision and then to change directions to avoid that object. Type in the following program code and download it to the Robo-11 Attacker.

86

/* Example for object detection by Touch sensor - Motor left connected to DC Motor chanel M-0 - Motor right connected to DC Motor chanel M-1 - Touch sensor left side connected to DI-15 - Touch sensor right side connected to DI-10 */ #define pow 50 /*Configuration power drive motor*/ void main() { int obj_left,obj_right; // For keep result detect object printf(Press Start!\n); // Display message start_press(); // Wait until START button pressed printf(Robot Move...\n); // Show running message while(!stop_button()) // Infinite loop { obj_left = digital(15); // Keep left sensor detection obj_right = digital(10); // Keep right sensor detection if(obj_left==0 && obj_right==0) // In case both sensor dont detect { run_fd(0.1); // Forward 0.1 second } else if(obj_left==0 && obj_right==1) // In case right sensor detect object only { run_bk(0.5); // Backward 0.5 sec turn_left(0.5); // Turn left 0.5 sec } else if(obj_left==1 && obj_right==0) // In case left sensor detect object { run_bk(0.5); // Backward 0.5 second turn_right(0.5); // Turn right 0.5 second } else if(obj_left==1 && obj_right==1) // In case both sensor detect object { run_bk(0.5); // Backward 0.5 second turn_right(1.0); // Turn right 1.0 second } } ao(); // Off motor all channel beep(); // Sound alarm printf(Stop...\n); // Show ending message } void turn_left(float spin_time) { motor(0,-pow); // Motor0 backward with pow value motor(1,pow); // Motor1 forward with pow value sleep(spin_time); // Delay set by parameter spin_time } void turn_right(float spin_time) { motor(0,pow); // Motor0 forward with pow value motor(1,-pow); // Motor1 backward with pow value sleep(spin_time); // Delay set by parameter spin_time } void run_fd(float delay) { motor(0,pow); // Motor0 forward with pow value motor(1,pow); // Motor1 forward with pow value sleep(delay); // Delay set by parameter delay } void run_bk(float delay) { motor(0,-pow); // Motor0 backward with pow value motor(1,-pow); // Motor1 backward with pow value sleep(delay); // Delay set by parameter delay }

87

Testing It
Place the Robo-11 Attacker on the floor (provided in the set) and then turn on the POWER switch. The LCD screen displays the message Press Start. Press START on the AX-11. The robot will move forward using only 50% of its power. At the same time, the display screen will show the message Robot Move.

When the robot runs into an obstacle with the left arm:
The robot will move backwards for 0.5 seconds and turn right for 0.5 seconds. Then it will continue to move forward.

When the robot runs into an obstacle with the right arm:

The robot will move backwards for 0.5 seconds and turn left for 0.5 seconds. Then it will continue to move forward. The robot will stop when the STOP switch is pressed. The Robo-11 Attacker uses a switch to enable digital communication with the sensor. When the switch is pressed, or activated, the digital signal 0 will be sent. With the proper coding, the Robo-11 Attacker will be able to avoid the obstacle and will also have the capability for Maze Solving if additional sensors are installed.

88

Adding the Infrared Ranger Sensor GP2D120 to the Robo-11 Standard robot enables it to detect obstacles at a distance without having to collide into or touch the object.

BUILDING THE RANGER

Using the Robo-11 Standard robot (or the Robo-11 Liner2 or Attacker), take an angled joiner and attach it to the left and right front of the robot with a 3 x 10 screw and 3 mm nut as shown in the picture. (If the Robo-11 Attacker is used and modified, the position of the switch arm might need to be changed).

Next, insert a strength joiner vertically into both angled joiners.

Take two more angled joiners and attach it to the other ends of the strength joiner.

89

Then attach another angled joiner to the end of the angled joiner in step 3.

Install the GP2D120 module to the end of the angled joiner from step 4. The arms might need to be pulled out a bit for installation. Use a 3 x 10 screw and two 3 mm nuts to install the GP2D120 to the arm from steps 1-4. Then connect the signal cable of the module to the input terminal A1-6 of the AX-11 board. Now the Robo-11 Ranger robot is ready to measure the range and detect obstacles at a distance without having to make any contact with the object.

GP2D12 and GP2D120 Infrared Ranger and Sensor Module


Measures the range using Infrared light Can measure a distance of 10 to 80 cm for the GP2D12 and 4 to 30 cm for the GP2D120 Uses 4.5-5 V voltage and 33 mA Provides 0.4 2.4 V output range at +5V supply. Warning for the GP2D12 and GP2D120 signal cable. Since the GP2D12 and GP2D120 have different terminal layouts than that of the AX-11 board, even though they look the same, a special signal cable was made for the two modules. The cable is already connected to the modules. All the user needs to do is connect this cable to the AX-11 board. The user must not remove this cable at all times and MUST NOT switch the GP2D120 module cable with the cable of other sensor modules.

The GP2D12/GP2D120 are infrared sensor modules that have 3 terminals, which are the voltage input (Vcc), ground (GND), and the voltage output (Vout). The values from the GP2D12 must be read after the initiating period of the module, which usually lasts around 32 52.9 ms. After this time, the voltage output can be measured. For the GP2D120, the output at the 30 cm distance and +5V input is within the 0.25 to 0.55 V range, with the average being 0.4V. Thus, the output variation within the 4 to 30 cm range is 2.25V + 0.3V.

90

Robo-11 Ranger Test


In writing the program to test the Robo-11 Ranger robot, we emphasize on the communication with the GP2D120 module to detect and measure the distance between the object and the robot so that it can avoid the obstacle without having any physical contact. Type in the following program download it to the Robo-11 Ranger. code and

91

/* Example for infrared detector sensor by GP2D120 - Motor left connected to DC Motor chanel M-0 - Motor right connected to DC Motor chanel M-1 - GP2D120 connected to AI-6 */ #use gp2d120_lib.ic /* gp2d120_lib.ic */ #define pow 50 /* Set 50% motor power */ void main() { float result; printf(Press Start!\n); // Show begining message start_press(); // Wait START button pressed printf(Robot Move...\n); // Show running message while(!stop_button()) // Infinite loop { result = distance(); // Get distance value if (result <= 20.0 && result != -1.0 ) // Check distance <=20 ? // if TRUE escape { run_bk(1.0); // Backword 1 second turn_left(0.5); // Turn left 0.5 second } else { run_fd(0.1); // Forward 0.1 second } } ao(); // Off motor all channel beep(); // Sound alarm printf(Stop...\n); // Show ending message } void turn_left(float spin_time) { motor(0,-pow); // Motor0 backward with pow value motor(1,pow); // Motor1 forward with pow value sleep(spin_time); // Delay set by parameter spin_time } void turn_right(float spin_time) { motor(0,pow); // Motor0 forward with pow value motor(1,-pow); // Motor1 backward with pow value sleep(spin_time); // Delay set by parameter spin_time } void run_fd(float delay) { motor(0,pow); // Motor0 forward with pow value motor(1,pow); // Motor1 forward with pow value sleep(delay); // Delay set by parameter delay } void run_bk(float delay) { motor(0,-pow); // Motor0 backward with pow value motor(1,-pow); // Motor1 backward with pow value sleep(delay); // Delay set by parameter delay }

92

Testing It
Place the Robo-11 Ranger on the floor and then turn on the POWER switch. The LCD screen displays the message Press Start. Press START on the AX-11. The robot will move forward using only 50% of its power. At the same time, the display screen will show the message Robot Move.

When the robot obstacle and is distance :

moves closer to the within the specified

The Robo-11 Ranger robot will move backwards 1 second and turn left for 1 second. Then it will move forward. The specified range to detect objects in this test is 20 cm. . The robot will stop when the STOP switch is pressed. The Robo-11 Ranger is another example of analog communication with the sensor. The value read from the sensor is converted to digital data and processed further to provide results. The results in this case is the distance measured from the sensor to the object.

93

Additional sensors and components to measure the movement distance are added so that the user can control the robot to move within a specified distance more accurately.

BUILDING THE SMARTMOVER

Using the Robo-11 standard robot, remove the structure of the robot that is attached to the top of the AX-11 board. On the bottom part, attach the encoder wheel sticker to the two main track wheels.

Take an angled joiner and attach it to the base plate at the positions of 16,3 and 16,9 (counting from the side opposite of the motor gear set) with a 3 x 10 mm screw and a 3 mm nut. The right angle side should be turned outwards as shown in the picture

Attach a 25 mm copper tube to the angled joiner with a 3 x 6 mm screw. The copper tubes should be facing outwards as shown in the picture. Do the same for both sides. .

94

Take the ZX-21 code wheel reflector sensor and attach it to the other end of the copper tube. The infrared reflector sensor should be turned inwards to face the main track wheel. Screw together with a 3 x 6 mm screw and repeat the same for both sides.

In installing the ZX-21, the infrared reflector should be placed in the main track wheels with a distance of 2 to 3 mm away from the code wheel sticker. Practically, if the sensor is attached to the copper tube as in step 5, the distance will be just right.

Then place the top structure that was removed back onto the AX-11 board. Connect the left signal cable from the ZX21 to terminal IN-8, and the right signal cable to terminal IN-7 of the AX-11 board. The Robo-11 SmartMover is now complete.

95

ZX-21 Code Wheel Reflector Sensor


Used with the 18 color tab code wheel sticker; each color making a 20 degree angle. The output is a pulse signal which can be connected directly to a microcontroller.

The heart of this sensor module is the infrared reflector sensor and the code wheel sticker. The infrared light that is emitted from the sensor will reflect on the code wheel sticker. If it hits the black area, the photo-transistor will receive little reflected light, causing logic 1 to be sent to the digital receiver which consists of two notgets. However, if is it reflected onto a white or silver area, more reflection will occur and the photo-transistor will operate well, sending logic 0. When the wheel turns, alternate reflections like these will occur, causing pulse output signals. One complete round of the wheel will give 9 pulse and 18 signals.

Measuring distance Encoder Wheel Sensor

with

the

The ZX-21 Encoder Wheel sensor will work in accordance with the code wheel sticker by detecting the infrared reflections from the code wheel sticker attached to the robot. The code wheel sticker has a diameter of 3.5 cm, with 9 alternating black and silver tab areas each; altogether resulting in 18 color tabs. If the arc of one color area is defined as s and d is the 3.5 cm diameter, thus The circumference of the outer wheel is

2pr = (2*3.14*3.5/2) = 10.99cm


Distance s (one step range) has a value of

pd/18 = (3.14*3.5)/18 = 0.61cm

96

The ZX-21 will count 1 every time the wheel code area shifts position to the next area tab, whether it is from black to silver (white) or silver (white) to black. The change of wheel codes our caused when the wheel turns. When the count changes or increases by 1, it means that the robot has moved 1 step, or a distance of 0.61 centimeters.

Encoder_lib.ic Library
To make it convenient in using the ZX-21 Encoder Wheel and the AX-11 board with the Interactive C program, a library for the wheel encoder to use when measuring the movement range for various operations of the robot was prepared. In this library, you will find a complete set of functions that involve the encoder wheel.
/*encoder_lib.ic*/ /* Hardware Configuration - Encoder left connect to port IN-8 - Encoder right connect to port IN-7 */ int LEFT =1; // Define for encoder left side channel int RIGHT =0; // Define for encoder right side channel int FORWARD = 1; // Define for drive robot forward int BACKWARD = 2; // Define for drive robot backward int SPIN_LEFT = 3; // Define for drive robot spin right int SPIN_RIGHT = 4; // Define for drive robot spin left int TURN_LEFT = 5; // Define for drive robot turn left int TURN_RIGHT = 6; // Define for drive robot turn right int POWER = 40; // Define power for drive robot and initial at 40% float STEP=0.0; // Variable for keep Global step // Function for reset encoder left and right// void reset_encoder_all() { reset_encoder(LEFT); // Reset Encoder left side(IN-8) reset_encoder(RIGHT); // Reset Encoder right side(IN-7) } // Function for initial Encoder before working // void encoder_init() { enable_encoder(LEFT); // Enable count Encoder left side(IN-8) enable_encoder(RIGHT); // Reset count Encoder right side(IN-7) reset_encoder_all(); // Reset twice Encoder } // Function for read step for left/right side Encoder // int read_step(int ch) { read_encoder(ch); // Read count Encoder by channel reference return(read_encoder(ch)); // Return read count value }

97

// Function for read total step // float totel_step() { return(STEP); // Return Global step count } // Function for read total distance // float total_dist() { return(STEP*0.61); // Return Global distance count } // Function for clear total step count // void clear_dist_all() { STEP = 0.0; // Clear Global step count value } // Function for count step by reference // void count_step(int sel_move,int step,int sel_count) { int flag=0,left,right; reset_encoder_all(); // Reset twice Encoder if(sel_move==FORWARD) // Condition forward FD(); else if(sel_move==BACKWARD) // Condition backward BK(); else if(sel_move==SPIN_LEFT) // Condition spin left S_LEFT(); else if(sel_move==SPIN_RIGHT) // Condition spin right S_RIGHT(); else if(sel_move==TURN_LEFT) // Condition turn left T_LEFT(); else if(sel_move==TURN_RIGHT) // Condition turn right T_RIGHT(); while(!flag) // Loop for check count step { left = read_step(LEFT); // Read step left right = read_step(RIGHT); // Read step right if(sel_count==LEFT && left>=step) // Encoder left side complete? flag = 1; // Set flag when count complete else if(sel_count==RIGHT && right>=step) // Encoder right side complete? flag = 1; // Set flag when count complete } ao(); // Off all motor if(sel_move==FORWARD || sel_move==BACKWARD) // Condition update Global step count { STEP = STEP + (float)read_step(sel_count); // Update step count if drive robot forward or backward }r eset_encoder_all(); // Reset twice Encoder } // Function for distance counting by reference // void count_dist(int a,int b,int c) { count_step(a,(b*100)/61,c); // Calculate distance to step count and // drive robot in this result } // Robot forward driving function // void FD() { motor(0,POWER); // Motor 0 forward motor(1,POWER); // Motor 1 forward }

98

// Robot backward driving function // void BK() { motor(0,-POWER); // Motor 0 backward motor(1,-POWER); // Motor 1 backward } // Robot spin left function // void S_LEFT() { motor(0,-POWER); // Motor 0 backward motor(1,POWER); // Motor 1 forward } // Robot spin right function // void S_RIGHT() { motor(0,POWER); // Motor 0 forward motor(1,-POWER); // Motor 1 backward } //- Robot turn left function // void T_LEFT() { off(0); // Motor 0 break motor(1,POWER); // Motor 1 forward } // Robot turn left function // void T_RIGHT() { off(1); // Motor 1 break motor(0,POWER); // Motor 0 forward }

Explanations of the functions


Two ZX-21 encoder wheel sensors are referenced when the user calls upon the functions in the encoder_ib.ic library: the left sensor which is connected to port IN-8 and the right sensor which is connected to port IN-8 of the AX-11 board. The M-0 slot is also used to drive the left motor wheel of the robot and the M-1 to drive the right wheel. In the beginning of the program, if the user wants to use this library, he or she must call upon it by using the command #use encoder_lib.ic. In the first part of the program, and within the main function, the user must call the encoder_init function in order to be able to start using both encoder wheels.

99

1. reset_encoder_all function Used to clear the count values from the encoder wheel sensor and start again. Function Format Void reset_encoder_all () 2. encoder_init function Used to initiate the encoder wheel sensor. In writing a program, this function must be called at the beginning of the main program. Function format Void encoder_init() 3. read_step function Used to read the count value from the encoder wheel sensor Function format Int read_step (int ch) Parameters Ch Used to choose the encoder wheel sensor that the user wants to read. Define Left if you want to read the value from the left encoder wheel Define Right if you want to read the value from the right encoder wheel Return Value The return value is the step count received from the encoder wheel specified.

100

4. Total_step function Used to read the cumulative values from the encoder wheel sensor by measuring the steps only when the robot moves forward and backwards. The variable STEP is used to store the cumulative steps. Function format Float total_step () Return Value The return value is the cumulative step count read from the encoder wheel. 5. Total_dist function Used to read the cumulative distance from the encoder wheel sensor by measuring the distance only when the robot moves forward and backwards. Calculate with 1 step equal to 0.61 centimeters. Function format Float total_dist() Return Value The return value is the cumulative distance read from the encoder wheel. 6. clear_dist_all function Used to clear the cumulative count. Function format Void clear_dist_all()

101

7. count_step function defined. Used to command the robot to move according to the number of steps

Function format Void count_step (int sel_move, int step, int sel_count) Parameter Sel_move used to specify how the robot moves as following: Forward Bacward Spin_left Spin_right Turn_left Turn_right for forward movement for backward movement To rotate left To rotate right To turn left To turn right

Step Used to define the number of steps that the user wants Sel_count Used to choose which encoder wheel sensor to read from, as following Left choose the left encoder wheel Right choose the right encoder wheel 8. count_dist function Used to command the robot to move according to a specified distance; modified from the count_step function. Function format Void count_dist (int a , int b, int c)

102

Parameters a Used to define the robot movement as following for forward movement for backward movement To rotate left To rotate right To turn left To turn right

Forward Bacward Spin_left Spin_right Turn_left Turn_right

b Used to define the distance the user wants in centimeters c Used to choose the encoder wheel sensor that is to be used, as following Left Right 9. FD function Used to drive the robot forward function format 10. void FD() choose the left encoder wheel sensor choose the right encoder wheel sensor

BK function Used to drive the robot backwards

function format 11.

void BK()

S_Left function Used to make the robot to rotate left

Function format

void S_LEFT()

103

12.

S_Right function Used to make the robot to rotate right

Function format 13.

void s_right()

T_Left function Used to make the robot turn left

Function format 14.

T_LEFT ()

T_RIGHT function Used to make the robot turn right

Function format 15.

T_RIGHT ()

POWER variable

Use to define the driving power of the robot, with values from 0% to 100%. If the value is not specified in the program, the initial value is 40% (POWER = 40) as defined in the library.

104

Robo-11 SmartMover Test The test program for the Robo-11 SmartMover robot can be separated into two tests. The first is to let the robot move a specified distance, which is the basic test for the robot and the encoder wheel sensor. Then add another operation for the robot to follow by letting it move in the shape of a character from the alphabet. This shows how the encoder wheel sensor can be used in more complex situations to make the robots turns and changes of direction more accurate. 60 cm-mover: Drive the Robo-11 SmartMover forward for 60 centimeters Type in the following program and download it into the Robo-11 SmartMover

/*Example for Robot samrt movement by reflective encoder sensor and codewheel */ /* - Encodder pulse left connected to IN-8 - Encodder pulse right connected to IN-7 */ #use encoder_lib.ic /*Include Library file encoder_lib.ic*/ void main() { encoder_init(); // Initial Encoder POWER = 50; // Set power at 50% printf(Press Start!\n); // Show begining message while(1) // Infinite loop { while(!start_button()); // Wait START button pressed printf(\n); // Clear LCD display count_dist(FORWARD,60,RIGHT); / Forward 60 cm reference with // Encoder right side printf(STEP %f\n,total_dist()); // Display step count value } }

105

Testing It
Place the Robo-11 SmartMover on the floor and then turn on the POWER switch. The LCD screen displays the message Press Start. Press START on the AX-11. The robot will move forward using only 50% of its power for a distance of 60 centimeters and stops, as well as displaying the distance moved. If the START switch is pressed again, the robot moves forward for another 60 centimeters, stops, and displays the cumulative distance which it moved. The value will have increased from the original value by 60 cm. For this program, the line #use encoder_lib.ic must be used to call upon the functions in the encoder_lib.ic library that will be used with the ZX-21 encoder wheel sensor. Then initiate the encoder wheel sensor by using the function encoder_init, followed by defining the motor power to 50% of its maximum power. Next, a message appears on the LCD awaiting the START switch to be pressed. The robot will then move forward for a distance of 60 centimeters and stops. The robot will display the cumulative distance on the LCD. If the START switch is pressed again, the robot will operate in the same way, while the cumulative value that is displayed will increase by 60 centimeters each time.

U-mover: Driving the Robo-11 SmartMover in a U-Shape


Type in the following program and download it to the Robo-11 SmartMover
/*Example-2 for Robot samrt movement by reflective encoder sensor and codewheel */ #use encoder_lib.ic /*Include Library file encoder_lib.ic*/ void main() { encoder_init(); // Initial Encoder printf(Press Start!\n); // Show begining message while(1) // Infinite loop { while(!start_button()); // Wait START button pressed clear_dist_all(); // Clear total distance printf(\n); // Clear display count_dist(FORWARD,60,RIGHT); // Robot forward 60 cm reference by // Encoder right side count_step(SPIN_RIGHT,18,LEFT); // Robot spin right 18 step reference // by Encoder left side count_dist(FORWARD,60,RIGHT); // Robot forward 60 cm // reference by Encoder right side count_step(SPIN_RIGHT,18,LEFT); // Robot spin right 18 step // reference by Encoder left side count_dist(FORWARD,60,RIGHT); // Robot forward 60 cm // reference by Encoder right side } }

106

Testing It
Place the Robo-11 SmartMover on the floor and then turn on the POWER switch. The LCD screen displays the message Press Start. Press START on the AX-11. The robot will move forward using only 50% of its power for a distance of 60 centimeters and rotate right. Then it will move forward for another 60 centimeters, rotate right again, and move another 60 centimeters. It will continue to repeat these actions. If the user looks down from a top view, he will see that the robots movements are of that similar to the English alphabet U. However, in this program, if the robot needs to make a 90 degree turn to get the desired direction, the user may sometimes have to use the count_step or count_dist function. In this test, to get a 90 degree turn, the following values must be specified count_step (SPIN_RIGHT, 18, LEFT); In the actual results, the robot may not be able to rotate 90 degrees exactly due to the fact that the rotational axis may not always be stable. To fix this problem, test by letting the robot rotate at different step values until it gets the desired angle.

107

With the ZX-08* digital sensor, the robot has yet another means to detecting obstacles by infrared light without making any contact with the object. * Additional component that does not come with the set

BUILDING THE OBJECTOR

Using the Robo-11 Standard robot (or the Robo-11 Liner2), take a strength joiner and attach it to the right corner at the front of the robot with a 3 x 10 screw and 3 mm nut as shown in the picture. Do not screw in tightly yet.

Attach an obtuse joiner onto the strength joiner, with the obtuse angle facing inwards.

Next, place a strength joiner to the end of the obtuse joiner. You will get a robotic arm to place the sensor.

108

Twist the arm to the right, making an angle of 45 degrees with the robot. Then screw in the screw and nut together tightly.

Install the ZX-08 sensor to the strength joiner at the end of the robot arm with a 3 x 10 mm screw and 3 mm nut. Screw in tightly.

Create another robotic arm to install another ZX-08 by using steps 1-4.

Install the ZX-08 to the end of the robotic arm that was just built. Then connect the signal cables as following: (1) Connect Tx at the left of the ZX-08 to terminal OUT-0 (2) Connect Rx at the left of the ZX-08 to terminal Dl010 (3) Connect Tx at the right of the ZX-08 to terminal OUT-1 (4) Connect Rx at the right of the ZX-08 to terminal Dl-11 The Robo-11 Objector is now complete and ready for the test program.

109

ZX-08 Infrared objector


This sensor has both the infrared light receiver and transmitter within itself. The ZX-08 sensor can detect obstacles at a maximum distance of 6 centimeters. The Rx signal cable must be connected to the digital input (Dl or IN), while the Tx must be connected to any digital output (OUT) on the AX-11 board. Once the signal cables are connected, sending logic 1 to Tx will make the infrared LED on the ZX-08 module light up. If there is an obstacle blocking in front, the infrared light will send reflect that object back to the infrared receiver, causing a logic 0 to be sent to the AX-11 input.

110

Robo-11 Objector Test


The next step would be to write a test program to test the operation of the Robo-11 Objector by having it detect objects by not touching or colliding with the objects and then to change directions to avoid that object. Type in the following program code and download it to the Robo-11 Objector.
/* Example for Robot infrared detector sensor by called ZX-08 - Motor left connected to DC Motor channel M-0 - Motor right connected to DC Motor channel M-1 - TX of ZX-08 left side connected to OUT-0 - TX of ZX-08 right side connected to OUT-1 - RX of ZX-08 left side connected to DI-10 - RX of ZX-08 right side connected to DI-11 */ #define pow 50 /*Configuration power drive motor*/ void main() { int obj_left,obj_right; printf(Press Start!\n); start_press(); printf(Robot Move...\n); set_digital_out(0); set_digital_out(1); while(!stop_button()) { obj_left = digital(10); obj_right = digital(11); if(obj_left==0 && obj_right==0) { run_fd(0.1); } else if(obj_left==0 && obj_right==1) { run_bk(0.5); turn_left(0.5); } else if(obj_left==1 && obj_right==0) { run_bk(0.5); turn_right(0.5); } else if(obj_left==1 && obj_right==1) { run_bk(0.5); turn_right(1.0); } }

// // // // // // //

For keep result detect object Show begining message Wait START button pressed Show running message Send TX ir signal to left sensor Send TX ir signal to right sensor Infinite loop

// Get detection result from left sensor // Get detection result from right sensor // If left and right do not detect object // Forward 0.1 second // If right sensor detect object // Backward 0.5 second // Turn left 0.5 second // If left sensor detect object only // Backward 0.5 second // Turn right 0.5 second // If both sensor detect object // Backward 0.5 second // Turn right 1.0 second

111

ao(); beep(); printf(Stop...\n); } void turn_left(float spin_time) { motor(0,-pow); motor(1,pow); sleep(spin_time); } void turn_right(float spin_time) { motor(0,pow); motor(1,-pow); sleep(spin_time); } void run_fd(float delay) { motor(0,pow); motor(1,pow); sleep(delay); } void run_bk(float delay) { motor(0,-pow); motor(1,-pow); sleep(delay); }

// Off motor all channel // Sound alarm // Show ending message

// Motor0 backward with pow value // Motor1 forward with pow value // Delay set by parameter spin_time

// Motor0 forward with pow value // Motor1 backward with pow value // Delay set by parameter spin_time

// Motor0 forward with pow value // Motor1 forward with pow value // Delay set by parameter delay

// Motor0 backward with pow value // Motor1 backward with pow value // Delay set by parameter delay

Testing It
Place the Robo-11 Objector on the floor and then turn on the POWER switch. The LCD screen displays the message Press Start. Press START on the AX-11. The robot will move forward using only 50% of its power. At the same time, the display screen will show the message Robot Move.

When the left sensor finds an object:

The Robo-11 Objector robot will move backwards for 0.5 seconds and turn right for 0.5 seconds. Then it will continue to move forward.

When the right sensor finds an object:

The Robo-11 Objector robot will move backwards for 0.5 seconds and turn left for 0.5 seconds. Then it will continue to move forward. The robot will stop when the STOP switch is pressed.

112

Increase the Robo-11 robots capability in detecting objects at a far distance without any making contact by using the SRF04* Ultra Sonic Sensor * Additional component that does not come with the set.

BUILDING THE SONAR ROBOT


1

Using the Robo-11 Standard robot (or the Robo-11 Liner2), take an angled joiner and attach it to the front of the robot with a 3 x 10 screw and 3 mm nut at position 1, 6 as shown in the picture. Let the right angle face outwards and screw together tightly.

Take another angled joiner and attach it to the angled joiner from step 1. Make sure the other end is facing the left of the robot as shown in the picture.

Then take another angled joiner and attach it to the angled joiner from step 2. . Make sure the other end faces the front of the robot at shown in the picture.

113

Yet another angled joiner is taken and attached to the angled joiner from step 3. This time, let the right angle side face the front of the robot.

Take the SRF04 module and attach it to the ADX-SRF04 board. Then install it to the angled joiner from step 4 using a 3 mm plastic spacer, 3 x 10 mm screw, and 3 mm nut. Attach the ADX-SRF04 to the top right corner (looking in from the front of the robot and SRF04 module)

Connect the signal cables of the ADX-SRF04 board to the ports on the AX-11 board as following: a. Connector ECHO to terminal IC1 of the AX-11 b. Connector PULSE to terminal IN-9 of the AX-11 The Robo-11 Sonar is now complete and ready to be tested.

114

SRF04 ULTRASONIC SENSOR


+5V power supply and 30 mA currency Uses a 40 kHz ultrasonic receiver and transmitter Measures a distance of 3 cm 3m 10 micro-second pulse signal Returns a pulse signal in which the pulse width is proportional to the measured distance. Small in size: 43 mm x 20 mm x 17 mm (w x l x h)

The SRF04 will send the ultrasonic frequency signal out and then measure the time for the signal to reflect back. The output from the SRF04 is in the form of a pulse, in which the width is proportional to the distance of the detected object. The ultrasonic frequency of the SRF04 is 40 kHz.

Robo-11 Sonar Test


The test program of the Robo-11 Sonar will emphasize on communicating with the SRF04 module in order to detect and measure the distance between the robot and an object. The results that were measured will then be used to determine the movements of the robot so that it can avoid the obstacles without having any contact with the object. Type in the following program code and download it to the Robo-11 Sonar.
/*Example for object detection of Robo-11 by sonar sensor */ /* Hardware configuration - ECHO pin connected to IC1 - TRIGGER PULSE pin connected to IN-9 - Motor left connected to DC Motor chanel M-0 - Motor right connected to DC Motor chanel M-1 */ #use srf04_lib.ic /* Include library srf04_lib.ic */ #define pow 50 /*Configuration power drive motor*/ void main() { int result; // Define variable for storing distance value ao(); // Off all motors sonar_init(); // Initial sonar sensor printf(Press Start!\n); // Show begining message while(!start_button()); // Wait START button pressed beep(); // Drive beep sound while (!stop_button()) // Check STOP button pressed { result = sonar_sample(); // Get and store distance value if (result <= 20 && result >= 0 ) // Check distance <=20 and >=0 ? // if TRUE escape

115

{run_bk(0.5); // Backword 0.5 second turn_left(0.5); // Turn left 0.5 second } else { run_fd(0.1); // Forward 0.1 second }} beep(); // Sound beep ao(); // Off all motors } void turn_left(float spin_time) {motor(0,-pow); // Motor0 backward with pow value motor(1,pow); // Motor1 forward with pow value sleep(spin_time); // Delay set by parameter spin_time } void turn_right(float spin_time) {motor(0,pow); // Motor0 forward with pow value motor(1,-pow); // Motor1 backward with pow value sleep(spin_time); // Delay set by parameter spin_time } void run_fd(float delay) {motor(0,pow); // Motor0 forward with pow value motor(1,pow); // Motor1 forward with pow value sleep(delay); // Delay set by parameter delay } void run_bk(float delay) {motor(0,-pow); // Motor0 backward with pow value motor(1,-pow); // Motor1 backward with pow value sleep(delay); // Delay set by parameter delay }

Testing It
Place the Robo-11 Sonar on the floor and then turn on the POWER switch. The LCD screen displays the message Press Start. Press START on the AX-11. The user will hear a beep sound and then robot will move forward using only 50% of its power. When the robot moves closer to the obstacle and is within the specified distance : The Robo-11 Sonar robot will move backwards for 0.5 second and rotate left for 0.5 seconds. Then it will move forward. The specified range to detect obstacles in this test is 20 cm. The robot will stop when the STOP switch is pressed. You will hear the beep again before it stops. The Robo-11 Sonar is an example of using special communication with the sensor by using pulse counts, which is different from the GP2D120 module which returns a voltage value, or the ZX-08 module which returns basic logic signals.

116

Increase the capability for the Robo-11 to locate a position and direction by using the CMPS03 Electronic Compass module which uses a magnetic field sensor in locating a particular direction.

BUILDING THE COMPASSOR

Using the Robo-11 Standard robot (or the Robo-11 Liner2), take an angled joiner and attach it to the front of the robot with a 3 x 10 screw and 3 mm nut at position 1, 6 as shown in the picture. Let the right angle face outwards and screw together tightly.

Take a strength joiner and attach it to the other end of the angled joiner from step 1.

Take another strength joiner and attach it to the other end of the strength joiner from step 2.

117

Yet another strength joiner is taken and attached to the strength joiner from step 3

Take an angled joiner and attach it to the other end of the strength joiner from step 4, making sure the end of the joiner faces the front of the robot. The structure is now ready for the CMPS03 to be installed.

Attach the CMPS03 module to the ADX-CMPS03 board and then install it onto the structure built in steps 15. Use a plastic spacer, a 3 x 10 mm screw, and a 3 mm nut, and screw them in together tightly. Next connect the signal cable from terminal PWM of the ADX-CMPS03 to terminal Dl-14 of the AX-11 board. The Robo-11 Compassor is now complete.

118

CMPS03 Electronic Compass Module


Uses a +5V power supply and 20 mA currency Uses two of Phillips KMZ51 magnetic field sensors 0.1 degree accuracy, with approximately 3-4 degree error rate. Pulse output with a width of 1 to 37 ms and 0.1 ms increment rate. I2C Bus system output which sends data in two formats: 0 to 255 and 0 to 3599.

Robo-11 Compassor Test


Adjust the Reference direction for the Robo-11 Compassor robot In the following preparations, the direction of the CMPS03 Electronic Compass module will be defined and adjusted so that it can be used as the main reference value. The value will then be stored in the internal memory of the CMPS03, which will be done only once. This reference data will not be erased even if there is no power supplied to the CMPS03. 1. Turn the power switch of the Robo-11 Compassor on. 2. Place the robot on an empty field and face it towards the north. Press the switch on the ADX-CMPS03 once and let it go. 3. Then turn the robot so that it is facing east. Press the switch on the ADX-CMPS03 once more and let it go. 4. Then turn the robot to face south. Press the switch on the ADXCMPS03 once more and let it go. 5. Last, turn the robot to face west. Press the switch on the ADXCMPS03 once more and let it go. Now the CMPS03 compass module can tell directions accurately. Writing the test program for the Robo-11 Compassor In this test program for the Robo-11 Compassor, we will imagine that the robot is placed in a very large field with a smooth surface, making it unable to check its movement by touch or by its reflector sensors. The only method left is to use the electronic compass module to detect the magnetic field and use it to determine which direction it should move next. Type in the following program and download it to the Robo-11 Compassor robot.

119

/*Example for Robot movement control by compass sensor */ /* Hardware configuration - PWM channel from adapter board(CMPS03) connected to DI-14 - Motor left connected to DC Motor chanel M-0 - Motor right connected to DC Motor chanel M-1 */ #use cmps03_pwm_lib.ic /* Include library srf04_lib.ic */ #define pow 40 /*Configuration power drive motor*/ void main() { long result; ao(); CMPS03_set_channel(14); printf(Press Start!\n); while(!start_button()); beep(); while (!stop_button()) { result = read_angle(); printf(Angle %d\n,result); if (result > 0L && result <= 40L) { run_fd(0.05); } else { turn_left(0.05); } } beep(); ao(); } void turn_left(float spin_time) { motor(0,-pow); motor(1,pow); sleep(spin_time); } void turn_right(float spin_time) { motor(0,pow); motor(1,-pow); sleep(spin_time); } void run_fd(float delay) { motor(0,pow); motor(1,pow); sleep(delay); } void run_bk(float delay) { motor(0,-pow); motor(1,-pow); sleep(delay); }

// // // // // // // // // // //

Definf variable for storing angle value Off all motors Initial CMPS-03 sensor used DI-14 Show begining message Wait START button pressed Sound beep Check STOP button pressed Keep angle value Display angle Check angle value <=40 ? if TRUE escape

// Forward 0.05 second

// Turn left 0.05 second // Sound beep // Off all motors

// Motor0 backward with pow value // Motor1 forward with pow value // Delay set by parameter spin_time

// Motor0 forward with pow value // Motor1 backward with pow value // Delay set by parameter spin_time

// Motor0 forward with pow value // Motor1 forward with pow value // Delay set by parameter delay

// Motor0 backward with pow value // Motor1 backward with pow value // Delay set by parameter delay

120

Testing It
Place the Robo-11 Compassor on the test field and then turn on the POWER switch. The LCD screen displays the message Press Start. Press START on the AX-11. The user will hear a beep sound. The robot will then locate its position to see which angle or direction it is facing by reading the values from the CMPS03 module. It will also display the results (Angle xxx: where xxx is the angle value read). If the angle is not equal to the specified angle, the robot will rotate left in intervals of 0.05 seconds until it finds the angled desired. The robot will then proceed to move forward using only 40% of its power. The robot will continue to check the angle value as it moves to ensure that it is moving in the right direction. The desired direction is at an angle of 0 to 40 degrees. The robot will stop when the STOP switch is pressed. The user will hear a beep before it stops. The Robo-11 Compassor is an interesting example of developing small automatic robots that can move on its own, with the help of efficient modules such as the CMPS03, a widely used sensor in the RoboCup Junior competition, or the International Football Robot Junior Championship. This is because the competition field usually does not have any reference points for the robot to detect its position, and thus the electronic compass module is very helpful. The values read from the CMPS03 module is the measured width of the PWM signal, which is another example of signal processing that is different from all the other sensors.

Das könnte Ihnen auch gefallen