The Arduino Mouse library: move the pointer from a board
Mouse.h lets a board with native USB act as a mouse. Like the Keyboard library it needs an ATmega32U4 board (Leonardo, Micro, Pro Micro) or another board whose chip is a USB device; an Uno cannot do it. The computer sees an ordinary three-button mouse with a scroll wheel.
Built in on Mokxi: #include <Mouse.h> and it builds, with nothing to install. Free, and no account needed.
What Mouse does
A mouse reports relative motion, not a position. Mouse.move(x, y) means "move this many counts from wherever the pointer is now", each from -128 to 127, and the computer’s pointer speed setting decides how far that is on screen. To steer it with a thumb joystick, read the two axes, subtract the center reading, scale it down to a few counts, and send that every 10 ms or so.
Buttons are held or tapped: click() is a quick press and release, while press() and release() let a sketch drag. A stray mouse that never stops moving makes a computer very hard to use, so keep an on and off switch in every sketch while you develop.
| Library Manager name | Mouse |
|---|---|
| Author | Arduino |
| Include | #include <Mouse.h> |
| Boards | Arduino Leonardo, SparkFun Pro Micro, Arduino Micro |
| In the simulator | Runs, with a gap the note below names. |
Install it
It builds on Arduino Leonardo, SparkFun Pro Micro, Arduino Micro.
In Mokxi it is built in: #include <Mouse.h> and the sketch compiles, with no download, no zip and no Library Manager.
On a real board it comes with the board package (Arduino), so the Arduino IDE has it as soon as the board is installed: there is nothing to add from the Library Manager.
The calls you will use
In the order a sketch meets them.
Mouse.begin()
Starts acting as a mouse. Call once in setup().
Mouse.move(xDistance, yDistance, wheel)
Moves the pointer by that many counts, each from -128 to 127. The third number scrolls the wheel; leave it out for 0.
int x = (analogRead(A0) - 512) / 64;
int y = (analogRead(A1) - 512) / 64;
Mouse.move(x, y, 0);
delay(10);Mouse.click(MOUSE_LEFT)
Presses and releases a button. MOUSE_RIGHT and MOUSE_MIDDLE are the others.
Mouse.press(MOUSE_LEFT)
Holds a button down, for dragging, until release() is called.
Mouse.release(MOUSE_LEFT)
Lets the held button go.
Mouse.isPressed(MOUSE_LEFT)
True while the sketch is holding that button, handy to avoid sending the same press twice.
Mouse.end()
Stops sending mouse reports.
Example: Key matrix numpad
On the SparkFun Pro Micro. It runs in the browser exactly as printed.
// Matrix numpad: twelve keys, twelve diodes, layers, a knob and per-key RGB.
//
// This is the firmware of a small custom keyboard, written out in one sketch
// so every part of it can be read: the matrix scan, per-key debounce, a
// layered keymap, an encoder and reactive lighting. It is not QMK or KMK.
// Those are complete keyboard firmwares with far more in them (tap-hold
// keys, combos, a configurator, split support, NKRO over USB); this is the
// same set of ideas small enough to read in one sitting, and to try before
// you solder.
//
// # The matrix
//
// Twelve keys on twelve pins would use twelve pins. A matrix puts them on a
// grid of rows and columns instead, so 4 rows and 3 columns need 7 pins, and
// a 4 x 12 ortholinear board needs 16 for 48 keys. Every key joins its row to
// its column. To read the grid, the sketch drives one row LOW, leaves the
// others floating, and reads every column with its pull-up on: a column that
// reads LOW has a pressed key in that row. Then the next row.
//
// rows R1 to R4 on pins 2, 3, 4 and 5 (driven LOW one at a time)
// columns C1 to C3 on pins 8, 7 and 6 (inputs with pull-ups)
//
// Each key has a diode in series, anode at the switch, cathode (the band)
// toward the row: QMK calls this COL2ROW. Without diodes, holding three keys
// on the corners of a rectangle makes the fourth corner read as pressed too,
// because current finds a way around through the three closed switches. That
// is ghosting. The diode only lets current flow one way, so that path is
// blocked and every key reads true however many are held.
//
// The USB report is a separate limit: the Keyboard library sends the boot
// keyboard report, which holds six keys at once (6KRO). The matrix itself
// has no such limit.
//
// # The rest of the board
//
// encoder A on A1, B on A2, push on A3 per-key RGB WS2812B strip on 1
//
// In Mokxi: click and hold the keys, turn the knob by dragging or scrolling,
// and click it. The Serial Monitor shows each layer change and what the
// keyboard would type, one [Keyboard] or [Mouse] line per report.
#include <Adafruit_NeoPixel.h>
#include <Keyboard.h>
#include <Mouse.h>
// ---------------------------------------------------------------------------
// Your board.
// ---------------------------------------------------------------------------
const uint8_t ROWS = 4;
const uint8_t COLS = 3;
const uint8_t ROW_PINS[ROWS] = {2, 3, 4, 5};
const uint8_t COL_PINS[COLS] = {8, 7, 6};
const uint8_t ENC_A = A1;
const uint8_t ENC_B = A2;
const uint8_t ENC_PUSH = A3;
const uint8_t LED_PIN = 1;
// A key change must hold this long before it counts, which is QMK's default.
const unsigned long DEBOUNCE_MS = 5;
// Keycodes. A plain key is its Keyboard.h code or character; the high bits
// add modifiers, so CTRL('z') is Ctrl+Z. MO(n) holds layer n while the key is
// held, TG(n) toggles it, and ____ falls through to the layer below, as in
// QMK's keymaps.
typedef uint16_t Key;
#define CTRL(k) ((Key)(0x0100 | (k)))
#define SHIFT(k) ((Key)(0x0200 | (k)))
#define MO(n) ((Key)(0xF000 | (n)))
#define TG(n) ((Key)(0xF100 | (n)))
#define ____ ((Key)0xFFFF)
#define NOKEY ((Key)0x0000)
// Higher layers win, so NAV sits above EDIT: hold the bottom-left key while
// EDIT is on and NAV's TG(EDIT) is there to turn EDIT off again.
enum Layer : uint8_t { NUM, EDIT, NAV, LAYERS };
const char *const LAYER_NAMES[LAYERS] = {"NUM", "EDIT", "NAV"};
// Laid out as the keys are, top row first.
const Key KEYMAP[LAYERS][ROWS][COLS] = {
{ // NUM, the base layer
{KEY_KP_7, KEY_KP_8, KEY_KP_9},
{KEY_KP_4, KEY_KP_5, KEY_KP_6},
{KEY_KP_1, KEY_KP_2, KEY_KP_3},
{MO(NAV), KEY_KP_0, KEY_KP_ENTER},
},
{ // EDIT, toggled on and off from NAV
{CTRL('z'), CTRL('y'), CTRL('s')},
{CTRL('x'), CTRL('c'), CTRL('v')},
{CTRL('a'), CTRL('f'), SHIFT(KEY_TAB)},
{MO(NAV), KEY_TAB, KEY_RETURN},
},
{ // NAV, held on the bottom-left key
{KEY_HOME, KEY_UP_ARROW, KEY_PAGE_UP},
{KEY_LEFT_ARROW, KEY_ESC, KEY_RIGHT_ARROW},
{KEY_END, KEY_DOWN_ARROW, KEY_PAGE_DOWN},
{____, KEY_BACKSPACE, TG(EDIT)},
},
};
// What the knob does on each layer: one key for each direction, or NOKEY to
// scroll the mouse wheel instead.
const Key KNOB_CW[LAYERS] = {NOKEY, CTRL('y'), KEY_RIGHT_ARROW};
const Key KNOB_CCW[LAYERS] = {NOKEY, CTRL('z'), KEY_LEFT_ARROW};
// Per-key lighting: each layer's color, and the flash a pressed key gets.
const uint32_t LAYER_COLOR[LAYERS] = {0x0030FF, 0xFF9000, 0x00FF40};
const uint8_t LAYER_LEVEL = 40; // the layer color's brightness, out of 255
// ---------------------------------------------------------------------------
// The matrix scan.
// ---------------------------------------------------------------------------
bool raw[ROWS][COLS]; // what the last scan read
bool down[ROWS][COLS]; // the debounced state the keymap sees
unsigned long changedAt[ROWS][COLS];
Key active[ROWS][COLS]; // the key each held switch pressed, kept until release
void scan(unsigned long now) {
for (uint8_t r = 0; r < ROWS; r++) {
pinMode(ROW_PINS[r], OUTPUT);
digitalWrite(ROW_PINS[r], LOW);
delayMicroseconds(30); // let the column lines settle, as QMK does
for (uint8_t c = 0; c < COLS; c++) {
bool pressed = digitalRead(COL_PINS[c]) == LOW;
if (pressed != raw[r][c]) {
raw[r][c] = pressed;
changedAt[r][c] = now;
}
}
// Let the row float again rather than driving it HIGH: two keys held in
// one column then never put a driven HIGH against a driven LOW.
pinMode(ROW_PINS[r], INPUT);
}
}
// ---------------------------------------------------------------------------
// Layers.
// ---------------------------------------------------------------------------The sketch is cut short here; the editor has every line of it.
Open it in the editor, wired and ready to run · Key matrix numpad: the project page
Common errors and how to fix them
The pointer drifts on its own with the joystick at rest
A centered joystick rarely reads exactly 512. Subtract its real resting reading taken at start-up, and ignore small values (a dead zone of 10 or 20 counts) before calling move().
The pointer flies across the screen and the computer is unusable
The sketch sends large moves too often. Divide the readings down, add a short delay between reports, and guard the whole thing with a switch read by digitalRead() so you can turn the mouse off.
'Mouse' not found, or Mouse.h does not build
Include Mouse.h at the top of the sketch and pick a board with native USB such as a Leonardo, Micro or Pro Micro. An Uno or Nano cannot act as a mouse.
Try Mouse without installing anything
Open the example, change the sketch, and keep your version in a free account.