Using a Game Controller
Prerequisite: Working with Motors
Getting Started
The FTC Tetrix kit includes two Logitech Dual Action USB game
controllers but RobotC will work with almost any similar USB game
controller.
Plug the game controller into a free USB port on your computer
making sure that nothing is accidentally touching any of the
buttons or joysticks.
Note: If a joystick is slightly off center when you plug the game controller it will not be calibrated
properly until you unplug it and plug it back in or use the Game Controller calibration tool in the
Windows Control Panel.
Start RobotC and open the program you created in the Working with Motors lesson if it isn’t
already open. Make sure that your NXT is turned on and that RobotC is linked to it either via USB
or Bluetooth. Now go to the Robot menu and select NXT Brick / Joystick Control.
Before you play with the joystick buttons take a
look at the values displayed in the lower left
corner of the window. X1 and Y1 are the
horizontal and vertical values from the left hand
joystick on the controller. X2 and Y2 are the values
for the right hand joystick. Try moving the two
joysticks and watch the values that appear in the
window.
Notice that when you push a joystick forward the
Y value becomes negative and when you pull it
back the values go positive. That is somewhat
counter intuitive and we’ll need to think about it
carefully when we start programming. Also pay attention to the maximum and minimum values
that the joysticks show. Each axis (X and Y) of each joystick (left and right) returns values from
-128 to +127.
Let go of the joysticks. Do the values return to zero or are some of
them slightly above or below zero? It is not unusual for the values
of the joysticks to not return to zero when you let go of them.
We’ll want to keep that in mind also when we start programming.
Try pressing each of the buttons on the game controller. Notice that each button causes a green
square to appear in the Joystick Control window near that button in the picture. Did you notice
that one of the buttons did not seem to do anything in the Joystick Control window? The small
button just above the left hand joystick just makes a small red LED light up on the controller itself.
We will not be using that button. If the red light is on press the button again and turn it off.
The odd looking button on the left hand side of the game controller is
sometimes called the Top Hat or POV (Point of View) button. It rocks in 8
different directions. Try rocking it in different directions and look at the values
displayed for POV in the controller window.
Close the Joystick Control window and insert the following line of code in the blank area between
the #pragma statements and void main().
#include "JoystickDriver.c"
Save the program as “TankDrive.c”. Then recompile your program, download it, open the
debugger and try your program. You should not get any errors and the program should work
exactly the same way it did before. Close the debugger.
What is JoystickDriver.c?
The #include statement tells the compiler to include the contents of the specified file into your
program. Every time you compile your program the compiler will stop reading from your source
code and read everything in the include file before continuing on to read the rest of your file. The
standard include files that come with RobotC are in the folder:
C:\Program Files\Robotics Academy\ROBOTC for Mindstorms\Includes
You could browse out there with the File Open command but there is an easier way to open the
JoystickDriver.c file. Right-Click on the text “JoystickDriver.c” and select “Open document file
'JoystickDriver.c'.” Read the comments at the top of the file and then scroll down until you see the
following:
typedef struct
{
//bool TeamColor;
bool
UserMode;
bool
StopPgm;
short
short
short
short
short
short
"octant".
joy1_x1;
joy1_y1;
joy1_x2;
joy1_y2;
joy1_Buttons;
joy1_TopHat;
// Team Color (true - blue / false - red)
// Autonomous or Telep-Operated mode
// Stop program
//
//
//
//
//
//
-128 to +127
-128 to +127
-128 to +127
-128 to +127
Bit map for 12-buttons
value -1 = not pressed, otherwise 0 to 7 for selected
short
short
short
short
short
short
"octant".
} TJoystick;
joy2_x1;
joy2_y1;
joy2_x2;
joy2_y2;
joy2_Buttons;
joy2_TopHat;
//
//
//
//
//
//
-128 to +127
-128 to +127
-128 to +127
-128 to +127
Bit map for 12-buttons
value -1 = not pressed, otherwise 0 to 7 for selected
Don’t Panic! You don’t actually need to understand all of that. The thing you need to notice is that
there are two groups of “short” declarations with names like “joy1_xxx” and “joy2_xxx”. All of the
names beginning with “joy1_” refer to the buttons and joysticks on the first game controller. All of
the names beginning with “joy2_” refer to the buttons and joysticks on the second game
controller. Since we are only going to be using a single game controller you can ignore all of the
“joy2_xxx” names.
Pull down the View menu and select “Source: Motor forward.c” to return to where we left off.
Now change the main() function to look like this:
task main()
{
while (true)
{
getJoystickSettings(joystick);
motor[motorLeft] = joystick.joy1_y1; // Vert axis of left joystick
motor[motorRight] = joystick.joy1_y2; // Vert axis of right joystick
}
}
The while(true) statement means repeat everything in the braces {} over and over forever. The
getJoystickSettings(joystick) statement fills the joystick structure with the most recent values
received from the game controller. Where does the magic “joystick” variable come from. Just like
the getJoystickSettings() function, the joystick variable is defined in JoystickDriver.c. Once we
have the current values we assign the left and right joystick’s vertical values to the left and right
motors respectively.
Save, compile and download the program. Open the debugger and the Joystick Control window
and then run the program. Now you can drive your robot like a tank (two joysticks, one for each
side). Moving both joysticks the same direction will move the robot forwards and backwards.
Moving the joysticks in opposite directions will cause the robot to spin left or right.
Does moving the joysticks forward move the robot forward? Remember that we noticed that
moving the joysticks forward gave us negative values. Negative values make the motors go
backwards. Use the Stop button in the Debugger window to stop the robot.
We have two choices. We could reverse both motors so that negative values make the robot go
forwards or we can negate the values we get from the joysticks. Let’s leave the motor setup alone
and just adjust the values from the joysticks like so:
motor[motorLeft] = -joystick.joy1_y1; // Vert axis of left joystick
motor[motorRight] = -joystick.joy1_y2; // Vert axis of right joystick
OK, save, compile, download and run it again. Do the joysticks behave the way you think they
should? Do you notice that the last 1/4 of the forwards (or backwards) movement of the joysticks
does not seem to have any effect on the speed of the robot. If you will remember, the values we
get from the joysticks are in the range -128 to +127 but the power values that the motors
understand are in the range -100 to +100. So, once the value from the joystick exceeds +/- 100
the motor is already at full speed and will not go any faster.
How can we change the behavior of the robot so that we can take advantage of the full range of
motion of the joysticks. All we need to do is add a simple algebreic expression to scale the values
that we receive from the joystick to be in the range expected by the motors. So, let’s multiply the
joystick value by 100 and divide by 127. That will give us values between -100 and +100. Change
the code to look like this:
// Vert axis of left joystick
motor[motorLeft] = -(( joystick.joy1_y1 * 100) / 127);
// Vert axis of right joystick
motor[motorRight] = -(( joystick.joy1_y2 * 100) / 127);
OK, save, compile, download and run it again. Moving the joysticks forwards and backwards
should change the speed of the motors over the entire range of the joystick. There is still a minor
problem. Have you noticed that sometimes when you let go of the joysticks the robot keeps
moving? Stop the program again. Remember that we noticed that sometimes the joysticks do not
go all the way back to zero when you let go of them? So, how do we fix that?
Let’s turn our scaling formula into a separate function and add a test to treat very small values as
if they were zero. Insert the following code inbetween the #include “JoystickDriver.c” statement
and the task main() statement.
// PowerFromJoystick
//
// Joysticks Return x and y coordinates ranging from -128 to +127.
// The power range for the motors is from -100 to +100. This function
// Takes a joystick value (x or y) and returns a power value scaled
// to the motor's power range. This is true for the NXT motors and
// the Tetrix 12V motors.
//
int PowerFromJoystick(int y)
{
int pow;
int sign;
if (y < 0)
sign = -1;
else
sign = 1;
// There can be some fluctuations when the joystick is pegged to
// a maximum or minimum value. Keep the power steady.
if (abs(y) >= 127)
pow = 100 * sign;
else if (abs(y) < 10) // We can also get fluctuations at idle.
pow = 0;
// If we very are close to 0 force us to 0.
else
pow = (y * 100) / 127; // Normal case, just scale the value.
return -pow;
// Negate all joystick values to match motor configuration
}
This might seem like a lot of code for what it accomplishes but you’ll never have to write it again.
You’ll be able to reuse it for every NXT or Tetrix robot that you ever create that makes use of a
game controller (or two). Now we need to use the function we just defined by changing main to
look like this:
task main()
{
while (true)
{
getJoystickSettings(joystick);
// Vert axis of left joystick
motor[motorLeft] = PowerFromJoystick(joystick.joy1_y1);
// Vert axis of right joystick
motor[motorRight] = PowerFromJoystick(joystick.joy1_y2);
}
}
Save, compile, download and run it again. The robot should now drive the way you expect and
stop moving every time you let go of the joysticks.
© Copyright 2026 Paperzz