Computer without hands

43
Computer without hands

Story

Read more

Custom parts and enclosures

middle-laser-cut

Schematics

bottom-laser-cut

Code

codesanslesmains.txt

Arduino
#include <BleMouse.h>
#include <BleKeyboard.h>

// Déclaration des constantes pour les entrées physiques
const int JOY_X = A0;
const int JOY_Y = A1;
const int BTN_LEFT = 13;
const int BTN_SHIFT = 12;
const int BTN_RIGHT = 27;
const int BTN_SCROLL = 33;
const int BTN_UNDO = 15;

// Zone morte
const int DEADZONE_RADIUS = 600;

// État scroll toggle
bool scroll_active = false;
bool lastScroll = HIGH;

// Suivi d’état pour click press/release
bool leftPressed = false;
bool rightPressed = false;
bool comboActive = false;
// Variable d'état (à déclarer en haut du fichier si pas encore fait)
static bool shiftComboActive = false;

void setup() {
  Serial.begin(115200);

  pinMode(JOY_X, INPUT);
  pinMode(JOY_Y, INPUT);
  pinMode(BTN_LEFT, INPUT_PULLUP);
  pinMode(BTN_RIGHT, INPUT_PULLUP);
  pinMode(BTN_SHIFT, INPUT_PULLUP);
  pinMode(BTN_SCROLL, INPUT_PULLUP);
  pinMode(BTN_UNDO, INPUT_PULLUP);

  Keyboard.begin();
  Serial.println("ESP32 BLE Keyboard + Mouse Ready");
}

void loop() {
  if (bleDevice.isConnected()) {
    // --- DEBUG BOUTONS ---
    Serial.print("[DEBUG] BTN_LEFT: ");
    Serial.print(digitalRead(BTN_LEFT));
    Serial.print(" | BTN_RIGHT: ");
    Serial.print(digitalRead(BTN_RIGHT));
    Serial.print(" | BTN_SHIFT: ");
    Serial.print(digitalRead(BTN_SHIFT));
    Serial.print(" | BTN_SCROLL: ");
    Serial.print(digitalRead(BTN_SCROLL));
    Serial.print(" | BTN_UNDO: ");
    Serial.println(digitalRead(BTN_UNDO));

    // --- Lecture joystick
    int x = analogRead(JOY_X);
    int y = analogRead(JOY_Y);
    int dx = x - 2048;
    int dy = y - 2048;

    // Zone morte
    if (abs(dx) < DEADZONE_RADIUS) dx = 0;
    if (abs(dy) < DEADZONE_RADIUS) dy = 0;

    // Si bouton SCROLL maintenu → scroll avec joystick
    if (digitalRead(BTN_SCROLL) == LOW) {
      if (dy != 0) {
        int scrollAmount = dy / 1000;
        Mouse.move(0, 0, -scrollAmount);  // Scroll vertical
        Serial.print("[SCROLL] ");
        Serial.println(scrollAmount);
      }
    } else {
      // Déplacement souris normal
      dx = dx / 200;
      dy = dy / 200;
      if (dx != 0 || dy != 0) {
        Mouse.move(dx, dy);
      }
    }

    // --- Bouton gauche
    if (!digitalRead(BTN_LEFT)) {
      if (!leftPressed) {
        Mouse.press(MOUSE_LEFT);
        leftPressed = true;
      }
    } else {
      if (leftPressed) {
        Mouse.release(MOUSE_LEFT);
        leftPressed = false;
      }
    }

    // --- Clic droit seul et combo SHIFT + clic droit
    bool shiftPressed = digitalRead(BTN_SHIFT) == LOW;
    bool rightPressedNow = digitalRead(BTN_RIGHT) == LOW;

    // --- Combo: SHIFT + clic droit
    if (digitalRead(BTN_SHIFT) == LOW) {
      if (!shiftComboActive) {
        Serial.println("[SHIFT] shift + click droit");
        Keyboard.press(KEY_LEFT_SHIFT);
        Mouse.press(MOUSE_RIGHT);
        shiftComboActive = true;
      }
    } else {
      if (shiftComboActive) {
        Keyboard.release(KEY_LEFT_SHIFT);
        Mouse.release(MOUSE_RIGHT);
        shiftComboActive = false;
      }
    }

    // --- Clic droit simple (sans SHIFT)
    if (!shiftPressed) {
      if (rightPressedNow && !rightPressed) {
        Serial.println("[CLICK] Droit seul");
        Mouse.press(MOUSE_RIGHT);
        rightPressed = true;
      } else if (!rightPressedNow && rightPressed) {
        Mouse.release(MOUSE_RIGHT);
        rightPressed = false;
      }
    }

    // --- Ctrl + Z (Windows/Linux) et Cmd + Z (macOS)
    if (digitalRead(BTN_UNDO) == LOW) {
      Serial.println("[UNDO] Ctrl+Z + Cmd+Z");

      // Ctrl + Z
      Keyboard.press(KEY_LEFT_CTRL);
      Keyboard.press('w');
      delay(50);
      Keyboard.release(KEY_LEFT_CTRL);
      Keyboard.release('w');

      delay(50); // Petite pause entre les deux

      // Cmd (GUI) + Z
      Keyboard.press(KEY_LEFT_GUI);  // Cmd on macOS
      Keyboard.press('w');
      delay(50);
      Keyboard.release(KEY_LEFT_GUI);
      Keyboard.release('w');
    }
  }

  delay(10);
}

Credits

Cecile Pacoret
7 projects • 1 follower
Jean Noël
19 projects • 38 followers
pedagogical director at L'école LDLC https://www.linkedin.com/in/jnlootsidebox/
matthias “exart” exbrayat
1 project • 0 followers
Romain Bourdariat
1 project • 0 followers
Arthur-GALY
1 project • 0 followers

Comments