Created
February 27, 2025 19:38
-
-
Save panayotoff/c8c3ff088a7c02c9e2e70715fc11889b to your computer and use it in GitHub Desktop.
Simple mouse juggler for ESP32S3 XIAO
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "USB.h" | |
#include "USBHIDMouse.h" | |
#include "USBHID.h" | |
USBHIDMouse Mouse; | |
// Configuration | |
const unsigned long MIN_INTERVAL = 30000; // 30 seconds in milliseconds | |
const unsigned long MAX_INTERVAL = 60000; // 60 seconds in milliseconds | |
const int LED_PIN = LED_BUILTIN; // Built-in LED pin | |
const int FLASH_DURATION = 200; // LED flash duration in milliseconds | |
// Mouse movement patterns | |
const int NUM_MOVEMENTS_PER_CYCLE = 15; // Number of small movements to make per cycle | |
const int MOVEMENT_DELAY = 20; // Delay between small movements (ms) | |
const int MAX_MOVE_DISTANCE = 5; // Maximum pixels to move in a single micro-movement | |
// Variables | |
unsigned long lastMoveTime = 0; | |
unsigned long nextMoveInterval = 0; | |
int currentX = 0; | |
int currentY = 0; | |
int targetX = 0; | |
int targetY = 0; | |
void setup() { | |
// Initialize serial for debugging | |
Serial.begin(115200); | |
// Set the LED pin as output | |
pinMode(LED_PIN, OUTPUT); | |
digitalWrite(LED_PIN, LOW); // Ensure LED is off initially | |
// Set USB device name | |
USB.manufacturerName("Logitech"); | |
USB.productName("MX Anywhere 3S"); | |
// Initialize the USB stack | |
USB.begin(); | |
// Initialize Mouse HID | |
Mouse.begin(); | |
// Small delay to ensure USB is ready | |
delay(1000); | |
// Set the initial random interval | |
nextMoveInterval = random(MIN_INTERVAL, MAX_INTERVAL + 1); | |
// Initialize random seed using analog noise | |
randomSeed(analogRead(0)); | |
// Serial.println("Natural mouse movement simulator started."); | |
// Serial.print("Next movement in "); | |
// Serial.print(nextMoveInterval / 1000); | |
// Serial.println(" seconds"); | |
} | |
void flashLED(int times) { | |
for (int i = 0; i < times; i++) { | |
digitalWrite(LED_PIN, HIGH); | |
delay(FLASH_DURATION); | |
digitalWrite(LED_PIN, LOW); | |
// Add a small gap between flashes if not the last flash | |
if (i < times - 1) { | |
delay(FLASH_DURATION); | |
} | |
} | |
} | |
// Creates a natural-looking mouse movement pattern | |
void moveMouseNaturally() { | |
// Decide on a movement style (0-3) | |
int movementStyle = random(0, 4); | |
// Serial.print("Performing natural mouse movement (style "); | |
// Serial.print(movementStyle); | |
// Serial.println(")"); | |
switch (movementStyle) { | |
case 0: // Gentle circle | |
for (int i = 0; i < 20; i++) { | |
float angle = i * (2 * PI / 20); | |
int dx = round(10 * cos(angle)); | |
int dy = round(10 * sin(angle)); | |
Mouse.move(dx - currentX, dy - currentY); | |
currentX = dx; | |
currentY = dy; | |
delay(MOVEMENT_DELAY); | |
} | |
// Return to origin | |
Mouse.move(-currentX, -currentY); | |
currentX = 0; | |
currentY = 0; | |
break; | |
case 1: // Random small movements | |
for (int i = 0; i < NUM_MOVEMENTS_PER_CYCLE; i++) { | |
int dx = random(-MAX_MOVE_DISTANCE, MAX_MOVE_DISTANCE + 1); | |
int dy = random(-MAX_MOVE_DISTANCE, MAX_MOVE_DISTANCE + 1); | |
Mouse.move(dx, dy); | |
currentX += dx; | |
currentY += dy; | |
delay(MOVEMENT_DELAY); | |
} | |
// Return close to starting position to avoid drifting off-screen | |
Mouse.move(-currentX, -currentY); | |
currentX = 0; | |
currentY = 0; | |
break; | |
case 2: // Straight line with slight jitter | |
targetX = random(15, 30) * (random(0, 2) ? 1 : -1); | |
targetY = random(15, 30) * (random(0, 2) ? 1 : -1); | |
for (int i = 0; i < 10; i++) { | |
int dx = targetX / 10 + random(-1, 2); | |
int dy = targetY / 10 + random(-1, 2); | |
Mouse.move(dx, dy); | |
currentX += dx; | |
currentY += dy; | |
delay(MOVEMENT_DELAY * 2); | |
} | |
// Return to origin | |
Mouse.move(-currentX, -currentY); | |
currentX = 0; | |
currentY = 0; | |
break; | |
case 3: // Mouse acceleration simulation | |
targetX = random(20, 40) * (random(0, 2) ? 1 : -1); | |
targetY = random(20, 40) * (random(0, 2) ? 1 : -1); | |
// Gradually accelerate | |
for (int i = 1; i <= 5; i++) { | |
int dx = (targetX / 15) * i / 5; | |
int dy = (targetY / 15) * i / 5; | |
Mouse.move(dx, dy); | |
currentX += dx; | |
currentY += dy; | |
delay(MOVEMENT_DELAY * 2); | |
} | |
// Move at max speed | |
for (int i = 0; i < 5; i++) { | |
int dx = targetX / 15; | |
int dy = targetY / 15; | |
Mouse.move(dx, dy); | |
currentX += dx; | |
currentY += dy; | |
delay(MOVEMENT_DELAY); | |
} | |
// Gradually decelerate | |
for (int i = 5; i >= 1; i--) { | |
int dx = (targetX / 15) * i / 5; | |
int dy = (targetY / 15) * i / 5; | |
Mouse.move(dx, dy); | |
currentX += dx; | |
currentY += dy; | |
delay(MOVEMENT_DELAY * 2); | |
} | |
// Return to origin | |
Mouse.move(-currentX, -currentY); | |
currentX = 0; | |
currentY = 0; | |
break; | |
} | |
} | |
void loop() { | |
// Check if it's time to move the mouse | |
unsigned long currentTime = millis(); | |
if (currentTime - lastMoveTime >= nextMoveInterval) { | |
// Flash LED twice | |
flashLED(2); | |
// Perform natural mouse movement | |
moveMouseNaturally(); | |
// Update the last move time | |
lastMoveTime = currentTime; | |
// Generate next random interval between 30 and 60 seconds | |
nextMoveInterval = random(MIN_INTERVAL, MAX_INTERVAL + 1); | |
// Serial.print("Next movement in "); | |
// Serial.print(nextMoveInterval / 1000); | |
// Serial.println(" seconds"); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment