Introduction to Joysticks

Today, I’m going to show you a little bit more of the joystick with an Arduino and what exactly a deadzone is. Let’s hop right in! A deadzone lets you see into people’s future and tell if they’re going to be the next Hitler or not. Wait, no, hold on. That’s the Stephen King novel. Let me start again.

Programming-wise, a deadzone is a region at the center of the joystick that is not recognized by the device. What’s this mean? On most joysticks, there’s going to be a small area where moving the stick does not result in movement of the device. This deadzone area varies from model to model, but it can usually be adjusted. Let’s play with that today.

A photo posted by Dan Royer (@imakerobots) on

Take a look at the joystick we get to play with. It’s fairly similar to the kind you’ll see on your XBOX or PS3 controller. It’s got an x-axis, a y-axis, and if you push straight down you get a button. You’ll remember that we used this joystick in our tetris game.

What you’ll need:

  • Arduino UNO
  • Wires
  • Joystick
  • USB Cable

Wiring

 
Let’s first start off with the hardware. Since there are a bunch of wires overlapping, I’ve colour-coded it to make it easier for you. Take a look:

Arduino Program Joystick png

Code

Plug it all into our computer and we’re good to go. Let’s check out some of the code.

#define JOYSTICK_DEADZONE  (30)
#define JOYSTICK_BUTTON    (2)

void setup() {
                     // get ready to send reports on the serial connection.
                     // make sure your serial window is set to this baud rate
  Serial.begin(57600);
                     // prepare the button
  pinMode(JOYSTICK_BUTTON,INPUT);
}

void loop() {
  int ox = analogRead(0);
  int oy = analogRead(1);
                     // FYI: output = map(intput,from low,from high,to low,to high)
  int mx = map(ox,0,1023,-512,512);
  int my = map(oy,0,1023,-512,512);

  int dx = abs(mx) < JOYSTICK_DEADZONE ? 0 : mx;
  int dy = abs(my) < JOYSTICK_DEADZONE ? 0 : my;

  int b = digitalRead(JOYSTICK_BUTTON);

  Serial.print(ox);  Serial.print('\t');
  Serial.print(oy);  Serial.print('\t');
  Serial.print(mx);  Serial.print('\t');
  Serial.print(my);  Serial.print('\t');
  Serial.print(dx);  Serial.print('\t');
  Serial.print(dy);  Serial.print('\t');
  Serial.print(b );  Serial.print('\n');

  delay(50);
}

Okay – “ox” and “oy” are variables that contain the original raw data. “AnalogRead()” returns a whole number between 0 and 1023, inclusive. This means that when we push the stick to one axis, we get 0, and the other on the same axis and we get 1023.

“mx” and “my” are the mapped values. It’s easier to think of these as a number line ranging from -512 to 512, with the middle area being 0.

“dx” and “dy” are the mapped values after a deadzone has been added. When you let go of the stick, sometimes the “mx” and “my” values aren’t exactly zero. They might be really close to zero (plus or minus a small amount). I found that 30 was a reliable deadzone for me, though your mileage may vary depending on age.

The code that we’ve just made will loop forever, printing out all the numbers from your joystick. You’ll notice that as you stay inside the deadzone, “dx” and “dy” remain zero. As soon as you leave the deadzone, they’ll jump to +/- whatever value you set. For me, it’s +/- 30. Yes! A second map() will smooth the number out.

Questions

  • Let’s try making a frame so you know which way is up. Kind of like an actual PS4 controller.
  • Try changing the code so that the Arduino tells you how long you were holding the buton for.