Skip to content

Arduino - Keyboard Logout

This tutorial demonstrates how to use an Arduino-compatible board as a USB Human Interface Device (HID) to emulate a keyboard. Specifically, we’ll create a device that sends a platform-specific keyboard shortcut to log out of your computer when a button is pressed. This project showcases the power of boards with native USB capabilities, allowing them to directly interact with a host computer.

⚠️ Important Warning: When you use the Keyboard library, the Arduino can take full control of your computer’s keyboard. To prevent accidentally locking yourself out or sending unintended commands, always implement a reliable physical trigger, like the pushbutton used in this tutorial. For more permanent projects, consider adding a master on/off switch.

You will need the following components:

  • 1 × Breadboard
  • 1 × Arduino board with native USB HID support. Examples include: Arduino Leonardo, Micro, Due, Zero, or any board from the MKR Family. The Raspberry Pi Pico (running the Arduino core) is also an excellent choice.
  • 1 × Pushbutton
  • Jumper Wires

We will use the modern Arduino IDE 2.x. The Keyboard.h library is bundled with the board support package for HID-capable boards, so you typically don’t need to install it manually. If you do, use the Library Manager (Tools > Manage Libraries...) to find and install it.

The circuit is simple. We will connect a pushbutton to a digital pin and use the microcontroller’s internal pull-up resistor. This removes the need for an external resistor.

  • Connect one leg of the pushbutton to a digital pin (we’ll use pin 2).
  • Connect the other leg of the pushbutton to the GND pin on the Arduino.
  • When the button is pressed, it will connect pin 2 to ground, pulling the pin’s state from HIGH to LOW.
/*
Keyboard Logout - Modernized Example
This sketch demonstrates using the Keyboard library to send a system logout
command when a button is pressed. It supports Windows, macOS, and Linux (Ubuntu).
This code is for boards with native USB support like Leonardo, Micro, Due, MKR Family, or RP2040 boards.
Circuit:
- A momentary pushbutton connected between digital pin 2 and GND.
*/
#include "Keyboard.h"
// --- Configuration ---
// Set your target operating system here
// Options: OS_WINDOWS, OS_MACOS, OS_LINUX
#define TARGET_OS OS_WINDOWS
// Enum for better platform management
enum OperatingSystem {
OS_MACOS,
OS_WINDOWS,
OS_LINUX
};
// Use 'const' for pin numbers for good practice
const int buttonPin = 2;
// --- Setup Function ---
void setup() {
// Initialize the button pin as an input with an internal pull-up resistor.
// The pin will be HIGH by default and LOW when the button is pressed.
pinMode(buttonPin, INPUT_PULLUP);
// Initialize Keyboard emulation.
Keyboard.begin();
}
// --- Main Loop ---
void loop() {
// Check if the button is pressed (pin is LOW)
if (digitalRead(buttonPin) == LOW) {
// A short delay to debounce the button press.
delay(50);
// Wait for the button to be released to avoid multiple triggers
while (digitalRead(buttonPin) == LOW) {
// Do nothing while button is held down
}
// Execute the logout sequence
performLogout();
// Halt the program to prevent accidental repeated logouts.
// You will need to reset the board to run the code again.
while (true);
}
// A small delay to prevent the loop from running too fast
delay(100);
}
// --- Logout Function ---
void performLogout() {
// A small delay before sending keystrokes to give the OS time to focus
delay(1000);
switch (TARGET_OS) {
case OS_MACOS:
// On macOS: Command + Shift + Q, then Enter
Keyboard.press(KEY_LEFT_GUI); // Press Command key
Keyboard.press(KEY_LEFT_SHIFT); // Press Shift key
Keyboard.press('q');
delay(100);
Keyboard.releaseAll();
delay(1000); // Wait for the confirmation dialog
Keyboard.press(KEY_RETURN);
break;
case OS_WINDOWS:
// On Windows 10/11: Win + X, then U, then I (Sign out)
Keyboard.press(KEY_LEFT_GUI); // Press Windows key
Keyboard.press('x');
delay(100);
Keyboard.releaseAll();
delay(500); // Wait for the menu to appear
Keyboard.press('u');
delay(100);
Keyboard.releaseAll();
delay(500);
Keyboard.press('i');
break;
case OS_LINUX: // Assuming a GNOME-based distro like Ubuntu
// On Ubuntu: Ctrl + Alt + Delete, then Enter
Keyboard.press(KEY_LEFT_CTRL);
Keyboard.press(KEY_LEFT_ALT);
Keyboard.press(KEY_DELETE);
delay(100);
Keyboard.releaseAll();
delay(1500); // Wait for the logout dialog
Keyboard.press(KEY_RETURN);
break;
}
// Release all keys as a final safety measure
Keyboard.releaseAll();
}
  • #define TARGET_OS ...: This preprocessor directive allows you to easily configure the code for your specific Operating System before uploading.
  • const int buttonPin = 2;: We use a constant to define the button pin. This is a modern C++ practice that improves readability and prevents accidental changes to the pin number in the code.
  • pinMode(buttonPin, INPUT_PULLUP);: This configures the pin as an input and activates the internal pull-up resistor. It’s an efficient way to wire a button without external components.
  • if (digitalRead(buttonPin) == LOW): The code continuously checks the button’s state. Because of the pull-up resistor, a LOW signal means the button has been pressed.
  • Debouncing and Release Detection: The short delay(50) and the while loop that waits for the button to be released form a simple but effective debouncing mechanism. This ensures one action per button press.
  • performLogout(): This function encapsulates the OS-specific logic, making the main loop cleaner. The switch statement selects the correct sequence of keystrokes based on TARGET_OS.
  • Keyboard.press() & Keyboard.releaseAll(): Keyboard.press() simulates holding a key down. It’s used for key combinations. Keyboard.releaseAll() releases all currently pressed keys, which is crucial to avoid a “stuck key” state.
  • Code won’t compile or Keyboard not found: You are likely using a board without native USB support (e.g., Arduino UNO R3, Nano). You must use a compatible board like a Leonardo or Micro.
  • Nothing happens when I press the button: Double-check your wiring. Ensure the button is connected to the correct pin and GND. Also, verify you have selected the correct board in the Arduino IDE.
  • The wrong action happens on my computer: The keyboard shortcuts for logging out can vary between OS versions and distributions. You may need to adjust the keystrokes in the performLogout() function to match your specific system.

This simple project is the gateway to creating powerful custom USB devices:

  • Custom Macro Pad: Expand the project with more buttons to trigger complex shortcuts in software like Photoshop, VS Code, or OBS.
  • Accessibility Device: Create custom interfaces for users with motor impairments.
  • Physical Mute Button: Build a dedicated hardware button that sends the mute/unmute shortcut for video conferencing apps like Zoom or Microsoft Teams.
  • Security Note: Be aware that this technology can be used to create malicious devices (often called “BadUSB”). Always be cautious about plugging unknown USB devices into your computer.