Arduino computer mouse click control

Hi, I'm fairly new to this. I have a disability where I have limited use of my hands which makes researching a little challenging so I'm hoping to get some assistance.

This project is intended to create a custom switch which can operate as the left click button of a computer mouse using my foot. (I am aware there are commercial options available, however for a multitude of reasons, none of them function in a way that is suited to my body.) I want the switch to operate in the same manner as a computer mouse, e.g being able to hold the click down to drag. I tried to achieve this in the code with the Mouse.release() action.

I have already had the mouse built and wired. It does work but not in the same way a normal mouse would. This is the last code which I tried (there have been several). It mostly seems to behave as follows:

Click acts as click and hold (no release)
second click will either release or continue to be held down.

I'm using Arduino Leonardo

Any help or advice would be greatly appreciated :slight_smile:

// Include the Mouse library
#include <Mouse.h>

// Define the pin for the momentary switch
const int switchPin = 3; // changed from 2 to 3

// Define the variables for the switch state
bool switchState = false; // current state of the switch
bool lastSwitchState = false; // previous state of the switch
bool mouseState = false; // current state of the mouse

void setup() {
  // Initialize the switch pin as an input with pullup resistor
  pinMode(switchPin, INPUT_PULLUP);
  
  // Initialize the Mouse library
  Mouse.begin();
  
  // Initialize the serial monitor
  Serial.begin(9600);
}

void loop() {
  // Read the switch state
  switchState = digitalRead(switchPin) == LOW;
  
  // Check if the switch state has changed
  if (switchState != lastSwitchState) {
    // If the switch is pressed, toggle the mouse state
    if (switchState) {
      mouseState = !mouseState;
      // If the mouse state is true, send a mouse press
      if (mouseState) {
        Mouse.press();
        Serial.println("Left click"); // added to print left click
      }
      // If the mouse state is false, send a mouse release
      else {
        Mouse.release();
        Serial.println("Mouse Release");
      }
    }
    // Update the last switch state
    lastSwitchState = switchState;
  }
  // Add a delay of 350 milliseconds
  delay(350); // added to the code
}


Hi Angelo; I built something similar for a client, around a micro pro. She could not hold the mouse still and click at the same time.
I provided a set of three buttons with different actions - (sadly due to dementia she could never remember what they did)

Hope you find this useful.

sorry this is long but for convenience I've put the code here

/*
   Example program mousebuttons for Arduino Micro Pro  23 Jan 2022
   to provide mouse clicks for disabled lady
   produces time-controlled clicks as follows:
   left button (L_Mouse) single left click (& hold - ie not released until button released)
   middle button (L2_Mouse) double left click & hold
   right button - R_Mouse single RIght click & hold
   debounce time and dleay between button clicks adjustable.
   When testing can uncomment serial prints and comment out calls to click routines.
*/

#include "Mouse.h"

//pin assignments
const byte L_Mouse = 7; //buttons to GROUND & pulled HIGH so active low
const byte L2_Mouse = 6; //double left click
const byte R_Mouse = 5;
const byte Yel = 8; //LED_L   leds on 8 & 9 via resistors to GROUND so active HIGH
const byte Red = 9; //LED_R

bool L_State, L2_State, R_State;
int tRepeat;  //diagnostic; used in debugging tDelay

unsigned long tDebounce = 200; //time switch state must be continuous to count as stable
unsigned long tDelay = 1000; //delay before a new stable switch condition can cause a click
unsigned long tNow;
unsigned long tLastChange;  //time of the most recent change on ANY button

struct condition { //declares a type named "condition"
  int switchPin; // pin to read for this switch
  bool lastState; //condition when last read
  bool stableVal; // last stable value
  unsigned long changeTime; //time of last change
};

condition sw[3] = {  //array of three variables of type "condition"
  {L_Mouse, 1, 1, 0}, //switch on pin 5
  {L2_Mouse, 1, 1, 0}, //switch on pin 6
  {R_Mouse, 1, 1, 0}  //switch on pin 7
};

void setup() {
  Serial.begin(57600);
  delay(500);
  pinMode(L_Mouse, INPUT_PULLUP);
  pinMode(L2_Mouse, INPUT_PULLUP);
  pinMode(R_Mouse, INPUT_PULLUP);
  pinMode(Yel, OUTPUT);
  pinMode(Red, OUTPUT);
  digitalWrite(Red, LOW);
  digitalWrite(Yel, LOW);
  tLastChange = millis();
  //Serial.println("Setup complete");
}

void loop() {
  //has s1 changed?
  L_State = digitalRead(sw[0].switchPin);
  if (L_State != sw[0].lastState) { //s1 has changed
    sw[0].lastState = L_State; //record current state to look for new changes
    //flashLeft(1); //diagnostic
    //now - has it been stable for > tDebounce?
    tNow = millis();
    if ((tNow - sw[0].changeTime) > tDebounce) {
      //its a valid change
      sw[0].stableVal = L_State;
      //here stableVal represents the true condition of the S1 button
      digitalWrite(Yel, !sw[0].stableVal);
      LClick(sw[0].stableVal);  //only executes a press or release if not already set

      tLastChange = tNow;
      //Serial.print(" Lbutton tLastChange is: ");
      //Serial.println(tLastChange);
    }
    else {
      //not a valid change so not stable; update time of last change
      sw[0].changeTime = tNow;
    }
  }

  //has s2 changed?
  L2_State = digitalRead(sw[1].switchPin);
  if (L2_State != sw[1].lastState) { //s1 has changed
    sw[1].lastState = L2_State; //record current state to look for new changes
    flashLeft(1);

    //now - has it been stable for > tDebounce?
    tNow = millis();
    if ((tNow - sw[1].changeTime) > tDebounce) {
      //its a valid change
      sw[1].stableVal = L2_State;
      //here stableVal represents the true condition of the S1 button
      digitalWrite(Yel, !sw[1].stableVal);
      L2Click(sw[1].stableVal);  //only executes a press or release if not already set
      tLastChange = tNow;
      //Serial.print(" L2button tLastChange is: ");
      //Serial.println(tLastChange);
    }
    else {
      //not a valid change so not stable; update time of last change
      sw[1].changeTime = tNow;
    }
  }

  R_State = digitalRead(sw[2].switchPin);
  if (R_State != sw[2].lastState) { //s3 has changed
    sw[2].lastState = R_State; //record current state to look for new changes
    //now - has it been stable for > tDebounce?
    tNow = millis();
    if ((tNow - sw[2].changeTime) > tDebounce) {
      //its a valid change
      sw[2].stableVal = R_State;
      //here stableVal represents the true condition of the S3 button
      digitalWrite(Red, !sw[2].stableVal);
      RClick(sw[2].stableVal);  //only executes a press or release if not already set

      tLastChange = tNow;
      //Serial.print(" Rbutton tLastChange is: ");
      //Serial.println(tLastChange);
    }
    else {
      //not a valid change so not stable; update time of last change
      sw[2].changeTime = tNow;
    }
  }

  //if any state has changed, AND all buttons released, delay before next is allowed
  if (sw[0].stableVal && sw[1].stableVal && sw[2].stableVal) {
    while ((millis() - tLastChange) <= tDelay) {
      //tRepeat = millis() - tLastChange;
      //Serial.print(" tRepeat is: ");
      //Serial.println(tRepeat);
      delay(100);
    }
  }
} // loop

and the functions

void flashLeft(int count){
  for(int i = 0; i<count; i++){
   //flash LEFT LED
    digitalWrite(Yel, HIGH);
    delay(50);
    digitalWrite(Yel, LOW);
    delay(100);
  }
}

void LClick(bool valueL) {
  if (valueL == 0) { //button is depressed
    if (!Mouse.isPressed(MOUSE_LEFT)) {
      Mouse.press(MOUSE_LEFT);
    }
  }
  else {  //button released
    if (Mouse.isPressed(MOUSE_LEFT)) {
      Mouse.release(MOUSE_LEFT);
    }
  }
}

void L2Click(int valueL) {
  if (valueL == 0) { //button is depressed
    if (!Mouse.isPressed(MOUSE_LEFT)) {
      Mouse.press(MOUSE_LEFT);
      delay(50);
      Mouse.release(MOUSE_LEFT);
      delay(50);
      Mouse.press(MOUSE_LEFT);
      delay(50);
    }
  }
  else {  //button released
    if (Mouse.isPressed(MOUSE_LEFT)) {
      Mouse.release(MOUSE_LEFT);
    }
  }
}

void RClick(int valueR) {
  if (valueR == LOW) {
    if (!Mouse.isPressed(MOUSE_RIGHT)) {
      Mouse.press(MOUSE_RIGHT);
    }
  }
  else {  //button released
    if (Mouse.isPressed(MOUSE_RIGHT)) {
      Mouse.release(MOUSE_RIGHT);
    }
  }
}
#include <Mouse.h>// Include the Mouse library

const byte switchPin = 3; // Define the pin for the momentary switch
bool switchState = false; // current state of the switch
bool lastSwitchState = false; // previous state of the switch

void setup() {
  pinMode(switchPin, INPUT_PULLUP);
  Mouse.begin();
  Serial.begin(9600);
}

void loop() {
  if (digitalRead(switchPin) != lastSwitchState) { // Check if the switch state has changed
    lastSwitchState = !lastSwitchState;
    if (lastSwitchState) {  // If the switch is pressed, toggle the mouse state
      Mouse.release();
      Serial.println("Mouse Release");
    }
    else {
      Mouse.press();
      Serial.println("Left click"); // added to print left click
    }
  }
  delay(50); // Add a delay of 350 milliseconds // 350is too many
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.