For Project QuickShot, I essentially wrote a gesture-controlled "airmouse" for the ATmega32u4 on the Adafruit featherboard. Here is the final version of the sketch.
//***************************************************** //Project QuickShot v1.0 //Arduino-driven Light Gun Emulator for LCDs //Jan 11, 2019 // //Matthew Eargle //Element14 Presents //element14.com/presents //AirborneSurfer Productions //airbornesurfer.com // //Based on code by Jim Lindblom // //***************************************************** // The SFE_LSM9DS1 library requires both Wire and SPI be // included BEFORE including the 9DS1 library. #include <Wire.h> #include <SPI.h> #include <SparkFunLSM9DS1.h> #include <Mouse.h> LSM9DS1 imu; #define LSM9DS1_M 0x1E // Would be 0x1C if SDO_M is LOW #define LSM9DS1_AG 0x6B // Would be 0x6A if SDO_AG is LOW const int mouseButton = 10; //Refresh rate between polling intervals, lower is smoother movement #define REFRESH_RATE 1 static unsigned long lastRefresh = 0; void setup() { Serial.begin(115200); pinMode(mouseButton, INPUT); Mouse.begin(); // Before initializing the IMU, there are a few settings // we may need to adjust. Use the settings struct to set // the device's communication mode and addresses: imu.settings.device.commInterface = IMU_MODE_I2C; imu.settings.device.mAddress = LSM9DS1_M; imu.settings.device.agAddress = LSM9DS1_AG; // The above lines will only take effect AFTER calling // imu.begin(), which verifies communication with the IMU // and turns it on. if (!imu.begin()) { Serial.println("Failed to communicate with LSM9DS1."); Serial.println("Double-check wiring."); Serial.println("Default settings in this sketch will " \ "work for an out of the box LSM9DS1 " \ "Breakout, but may need to be modified " \ "if the board jumpers are."); while (1) ; } } void loop() { digitalWrite(mouseButton, HIGH); int clickState = digitalRead(mouseButton); // Update the sensor values whenever new data is available if ( imu.accelAvailable() ) { // To read from the accelerometer, first call the // readAccel() function. When it exits, it'll update the // ax, ay, and az variables with the most current data. imu.readAccel(); } // if the mouse button is pressed: if (clickState == LOW) { // if the mouse is not pressed, press it: if (!Mouse.isPressed(MOUSE_LEFT)) { Mouse.press(MOUSE_LEFT); } } // else the mouse button is not pressed: else { // if the mouse is pressed, release it: if (Mouse.isPressed(MOUSE_LEFT)) { Mouse.release(MOUSE_LEFT); } } if ((lastRefresh + REFRESH_RATE) < millis()) { moveMouse(); lastRefresh = millis(); } } void moveMouse() { // Now we can use the ax, ay, and az variables as we please. Serial.print("Move X,Y: "); int xMove = ((imu.calcAccel(imu.ax) * 10)); Serial.print(xMove); Serial.print(", "); int yMove = ((imu.calcAccel(imu.ay) * -10)); Serial.print(yMove); Mouse.move(xMove, yMove, 0); Serial.println(); }