├── .gitattributes └── Code └── Code.ino /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /Code/Code.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include "LSM6DS3.h" 3 | #include "Wire.h" 4 | 5 | // Create IMU instance 6 | LSM6DS3 myIMU(I2C_MODE, 0x6A); // I2C address 0x6A 7 | 8 | // BLE HID and Device Info 9 | BLEHidAdafruit blehid; 10 | BLEDis bledis; 11 | 12 | // Define pins 13 | const int LEFT_CLICK_PIN = D1; 14 | const int LED_PIN = LED_BUILTIN; // Use correct built-in LED pin 15 | bool lastClickState = false; 16 | 17 | void setup() { 18 | Serial.begin(115200); 19 | unsigned long startTime = millis(); 20 | while (!Serial && (millis() - startTime < 3000)) 21 | ; // Wait up to 3s 22 | 23 | pinMode(LEFT_CLICK_PIN, INPUT_PULLUP); 24 | pinMode(LED_PIN, OUTPUT); 25 | digitalWrite(LED_PIN, LOW); // Start OFF 26 | 27 | // Initialize IMU 28 | if (myIMU.begin() != 0) { 29 | Serial.println("LSM6DS3 not detected!"); 30 | while (1) 31 | ; 32 | } 33 | 34 | Serial.println("LSM6DS3 ready"); 35 | 36 | // Init BLE 37 | Bluefruit.begin(); 38 | Bluefruit.setTxPower(4); 39 | Bluefruit.setName("XIAO AirMouse"); 40 | 41 | blehid.begin(); 42 | bledis.setManufacturer("Seeed Studio"); 43 | bledis.setModel("XIAO BLE Mouse"); 44 | bledis.begin(); 45 | 46 | Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE); 47 | Bluefruit.Advertising.addTxPower(); 48 | Bluefruit.Advertising.addAppearance(BLE_APPEARANCE_HID_MOUSE); 49 | Bluefruit.Advertising.addService(blehid); 50 | Bluefruit.ScanResponse.addName(); 51 | Bluefruit.Advertising.start(); 52 | 53 | Serial.println("BLE ready. Connect your computer to XIAO AirMouse."); 54 | } 55 | 56 | void loop() { 57 | // Turn LED ON if connected, OFF otherwise 58 | if (Bluefruit.connected()) { 59 | digitalWrite(LED_PIN, HIGH); // May need LOW for some boards 60 | } else { 61 | digitalWrite(LED_PIN, LOW); 62 | delay(100); 63 | return; 64 | } 65 | 66 | // Read gyroscope values 67 | float gx = myIMU.readFloatGyroX(); 68 | float gy = myIMU.readFloatGyroY(); 69 | float gz = myIMU.readFloatGyroZ(); 70 | /* 71 | Serial.print("X - "); 72 | Serial.println(gx); 73 | Serial.print("Y - "); 74 | Serial.println(gy); 75 | Serial.print("Z - "); 76 | Serial.println(gz); 77 | */ 78 | // Setting Speed of Cursor ( 2 - Higher Speed : 10 - Slower Speed) 79 | float vx = -gz / 5.0; 80 | float vy = gy / 5.0; 81 | 82 | // Filtering Micromovements 83 | if (abs(vx) > 0.5 || abs(vy) > 0.5) { 84 | int8_t dx = (int8_t)vx; 85 | int8_t dy = (int8_t)vy; 86 | blehid.mouseMove(dx, dy); 87 | } 88 | 89 | // Handle left click 90 | bool clickPressed = digitalRead(LEFT_CLICK_PIN) == LOW; 91 | if (clickPressed != lastClickState) { 92 | if (clickPressed) { 93 | blehid.mouseButtonPress(MOUSE_BUTTON_LEFT); 94 | } else { 95 | blehid.mouseButtonRelease(); 96 | } 97 | lastClickState = clickPressed; 98 | } 99 | 100 | delay(10); 101 | } --------------------------------------------------------------------------------