Lab: Mouse Control With Pushbuttons

Introduction

In this lab, you’ll build an alternative computer mouse using an Arduino Leonardo using pushbuttons to move the mouse left, right, up and down. You’ll see the difference between reading a digital input continually and reading for a change of state.

What You’ll Need to Know

To get the most out of this lab, you should be familiar with the following concepts. You can check how to do so in the links below:

Things You’ll Need

Below are the parts you’ll need for this exercise. Click on any image for a larger view.

A short solderless breadboard with two rows of holes along each side. There are no components mounted on the board.
A solderless breadboard.
An Arduino Leonardo. The USB connector is facing to the left, so that the digital pins are on the top of the image, and the analog pins are on the bottom.
A USB-Native Arduino board. Shown here is an Arduino Leonardo
Three 22AWG solid core hookup wires. Each is about 6cm long. The top one is black; the middle one is red; the bottom one is blue. All three have stripped ends, approximately 4 to 5mm on each end.
22AWG solid core hookup wires.
Resistors. Shown here are 220-ohm resistors. You can tell this because they have two red and one brown band, followed by a gold band.
Resistors. Shown here are 220-ohm resistors.  For this exercise, you’ll need 10-kilohm resistors (10K resistors are brown-black-orange. For more, see this resistor color calculator)
A pushbutton with two wires soldered one to each of the button's contacts.
A pushbutton with two wires soldered one to each of the button’s contacts. Any switch will do the job as well.

 

About mouse control

NOTE: The sketches contained in this lab will cause the Arduino Leonardo to take control of your mouse. Make sure they’re working properly before you add the mouse commands. The example doesn’t introduce the mouse commands until the end of the lab. Instead, messages are printed to the serial monitor to tell you what should happen. When you’ve run this and seen the serial messages occurring when you think they should, then you can add the mouse commands safely.

The sketches here will work on an Uno until you add the mouse commands. So you can test this on an Uno simply by commenting out any line that says Mouse.begin() or Mouse.move().

Prepare the breadboard

Connect power and ground on the breadboard to power and ground from the microcontroller. On the Arduino module, use the 5V and any of the ground connections as shown below in Figure 1:

An Arduino Leonardo on the left connected to a solderless breadboard, right. The Leonardo's 5V output hole is connected to the red column of holes on the far left side of the breadboard. The Leonardo's ground hole is connected to the blue column on the left of the board. The red and blue columns on the left of the breadboard are connected to the red and blue columns on the right side of the breadboard with red and black wires, respectively. These columns on the side of a breadboard are commonly called the buses. The red line is the voltage bus, and the black or blue line is the ground bus.
Figure 1: An Arduino Leonardo on the left connected to a solderless breadboard, right.

 


Made with Fritzing

Add a pushbutton

Attach a pushbutton to digital pin 2 as shown below in Figure 2. Connect one side of the pushbutton to 5 volts, and the other side of the pushbutton to a 10-kilohm resistor. Connect the other end of the resistor to ground. Connect the junction where the pushbutton and the resistor meet to digital pin 2. (For more on this digital input circuit, see the Digital Input Lab).

Schematic drawing of an Arduino Leonardo connected to a pushbutton and two voltage divider inputs. The pushbutton is connected as described in the schematic above. On the left side of the board, two photoresistors are connected to +5 volts. The other sides of the photoresistors are connected to analog inputs A0 and A1, respectively. Two 10-kilohm resistors are also connected to those pins. The other sides of the fixed resistors are connected to ground.
Schematic view of an Arduino Leonardo connected to a pushbutton.
Breadboard drawing of an Arduino Leonardo connected to a pushbutton. The pushbutton straddles the center divide of the breadboard in rows 20 through 22. A red wire connects row 20 on the right center side to the right side voltage bus. A 10-kilohm resistor connects row 22 on the right center side to row 26 on the same side. A black wire connects from row 26 to the ground bus on the right side. A blue wire connects row 22 on the left center side of the board to digital p
Figure 2: Breadboard view of an Arduino Leonardo connected to a pushbutton.

 

Add four more pushbuttons

Repeat the last step, connecting four more pushbuttons to pins 3 through 6 as shown below in Figure 3:

Schematic drawing of a pushbutton and a joystick attached to an Arduino Leonardo. The pushbutton is attached to digital pin 2 on one side, and to +5 volts on the other. there is also a 10-kilohm resistor attached to digital pin 2. Its other side is attached to ground. Four other pushbuttons, with pulldown resistors like this one, are connected to pins 3 through 6 in the same way.
Schematic view of an Arduino Leonardo connected to five pushbutton.
Breadboard drawing of an Arduino Leonardo connected to five pushbuttons. The pushbutton from the previous breadboard drawing has been rearranged, and new buttons have been added, as follows. The pushbuttons straddle the center divide of the breadboard in rows 4-6, 9-11, 14-16, 19-21, and 24-26, respectively. 10-kilohm resistors straddle the center divide in rows 7, 12, 17, and 22, respectively. Each resistor's row on the left center side is connected to the row above it with a wire, thus connecting the pushbuttons and the resistors. Each resistor's row on the right center side is connected to the right side ground bus with a black wire. Each pushbutton's upper row (that is, rows 4, 9, 14, 19, and 23) on the right center side is connected to the right side voltage bus with a red wire. The junction rows, that is, rows 6, 11, 16, 21, and 26, are connected to digital inputs 2 through 6 on the Leonardo, respectively, with blue wires
Figure 3: Breadboard view of an Arduino Leonardo connected to five pushbuttons.

 

Program the module to read the pushbutton

Follow the same steps as you did in the first Mouse Control lab to read when the pushbutton on pin 2 is pressed. Your code should only print out a message when the button changes state.

Similarly, set up a global variable to track whether or not you’re controlling the mouse, called mouseIsActive. Each time the pushbutton on pin 2 is pressed, change the state of this variable from false to true, just like you did in the first mouse control lab.

// Global variables:
int lastButtonState = LOW;            // state of the button last time you checked
boolean mouseIsActive = false;    // whether or not the Arduino is controlling the mouse

void setup() {
  // initialize serial communication:
  Serial.begin(9600);
  pinMode(2, INPUT);
}

void loop() {
  // read the first pushbutton:
  int buttonState = digitalRead(2);

  // if it's changed and it's high, toggle the mouse state:
  if (buttonState != lastButtonState) {
    if (buttonState == HIGH) {
      // if mouseIsActive is true, make it false;
      // if it's false, make it true:
      mouseIsActive = !mouseIsActive;
      Serial.print("Mouse control state: ");
      Serial.println(mouseIsActive);
    }
  }
  // save button state for next comparison:
  lastButtonState = buttonState;
}

Activate the other four buttons

The other four pushbuttons are intended to control the mouse movement: the button on pin 3 should move the mouse right; the one on pin 4 should move it left; the one on pin 5 should move it down; and the one on pin 6 should move it up. If the user holds the button down, the mouse should continue to move in the corresponding direction.

To make this happen, you need to read the buttons’ states. You don’t need to tell when they change from off to on, in this case. You just need to know that they are on. But you shouldn’t do anything unless the mouseIsActive variable is true.

Add code to the setup to set pins 3 through 6 to input using the pinMode command. Then add code to the loop to read whether the mouseIsActive variable is true. If it is, read the four other pushbuttons. For each one, check if it’s high, and if so, print the letter of the direction you’re moving, U, R, L, or D.

 if (mouseIsActive) {
    // read the other buttons:
    int button2State = digitalRead(3);
    int button3State = digitalRead(4);
    int button4State = digitalRead(5);
    int button5State = digitalRead(6);

    if (button2State == HIGH) {
      Serial.println("R");
    }
    if (button3State == HIGH) {
       Serial.println("L");
    }
    if (button4State == HIGH) {
       Serial.println("D");
    }
    if (button5State == HIGH) {
       Serial.println("U");
    }
  }

When you run this sketch, you should see the Mouse Control State message once every time you press the first pushbutton, and the letters R, L, U, or D continuously when you hold down any of the other four pushbuttons. When you’ve got that working, you’re ready to take control of the mouse.

Add commands to control the mouse

The Mouse.begin() command is called in the setup. It initializes mouse control from your Leonardo.

The Mouse.move() command has three parameters: the horizontal movement, the vertical movement, and the scroll wheel movement. All movements are relative, so Mouse.move(1,0,0); moves one pixel to the right; Mouse.move(-1,0,0); moves one pixel to the left; Mouse.move(0,1,0); moves one pixel down; and Mouse.move(0,-1,0); moves one pixel up.

Include the Mouse library at the top of your code. Then modify the setup by adding the command Mouse.begin(). Then, in the loop where you print L, R, U, or D add Mouse.move commands to move as needed.


#include <Mouse.h>
// Global variables:
int lastButtonState = LOW;        // state of the button last time you checked
boolean mouseIsActive = false;    // whether or not the Arduino is controlling the mouse

void setup() {
  // initialize mouse control:
  Mouse.begin();
  // initialize serial communication:
  Serial.begin(9600);
  // make pin 2 through 5 inputs:
  pinMode(2, INPUT);
  pinMode(2, INPUT);
  pinMode(3, INPUT);
  pinMode(4, INPUT);
  pinMode(5, INPUT);
  pinMode(6, INPUT);
}

void loop() {
  // read the first pushbutton:
  int buttonState = digitalRead(2);

  // if it's changed and it's high, toggle the mouse state:
  if (buttonState != lastButtonState) {
    if (buttonState == HIGH) {
      // if mouseIsActive is true, make it false;
      // if it's false, make it true:
      mouseIsActive = !mouseIsActive;
    }
  }
  // save button state for next comparison:
  lastButtonState = buttonState;

  // if the mouse is active, and any button is pressed,
  // move the mouse in the corresponding direction:
  if(mouseIsActive) {
    // read the other buttons:
    int button2State = digitalRead(3);
    int button3State = digitalRead(4);
    int button4State = digitalRead(5);
    int button5State = digitalRead(6);

    if (button2State == HIGH) {
      Serial.println("R");
      Mouse.move(2, 0, 0);      // move right
    }
    if (button3State == HIGH) {
      Serial.println("L");
      Mouse.move(-2, 0, 0);     // move left
    }
    if (button4State == HIGH) {
      Serial.println("D");
      Mouse.move(0, 2, 0);      // move down
    }
    if (button5State == HIGH) {
      Serial.println("U");
      Mouse.move(0, -2, 0);      // move up
    }
  }
}

That’s the whole sketch. When you run this, press the button to enable or disable mouse control, then press any of the other four buttons, and the mouse will move in the appropriate direction.

The full sketch for this can be found on the phys comp github repository, called MouseMoveSimpleButtons.

You can see from this sketch the difference between reading a digital input to look for the state change (the button on pin 2) and reading a digital input just to see the current state (buttons on pins 3 through 6). When you’re designing a response that can repeat infinitely, you can just read the current state. But when you’re designing a response that should happen just once, you need to determine when the button changes state.

Next, try the Mouse Control With Joystick lab.

Originally written on August 25, 2014 by Benedetta Piantella Simeonidis
Last modified on November 8, 2018 by Jim Schmitz