Control volume and mouse scroll wheel using arduion leo (rotatory encoder)

Board - Arduino leo
Encoder - ky40
I want to do a project in which I control the volume and mouse scroll wheel using Arduino Leonardo and a rotatory encoder. but somehow volume feature is working but the scroll wheel is not.

Here is my code

#include <HID-Project.h>
#include <HID-Settings.h>

// Rotary Encoder Inputs
const int pinA = 2; // CLK
const int pinB = 3; // DT
const int buttonPin = 4; // SW

int lastStateCLK;
int currentStateCLK;
int lastButtonState = HIGH;
int currentButtonState;

void setup() {
  pinMode(pinA, INPUT);
  pinMode(pinB, INPUT);
  pinMode(buttonPin, INPUT_PULLUP);
  Consumer.begin(); // Start the Consumer device emulation
  lastStateCLK = digitalRead(pinA);
}

void loop() {
  currentStateCLK = digitalRead(pinA);

  // If the state has changed, a pulse occurred
  if (currentStateCLK != lastStateCLK) {
    // Determine the rotation direction
    if (digitalRead(pinB) != currentStateCLK) {
      // Encoder rotated clockwise
      Consumer.write(MEDIA_VOLUME_UP);
    } else {
      // Encoder rotated counterclockwise
      Consumer.write(MEDIA_VOLUME_DOWN);
    }
  }
  lastStateCLK = currentStateCLK;

  // Check for button press to control mouse scroll
  currentButtonState = digitalRead(buttonPin);
  if (currentButtonState != lastButtonState) {
    if (currentButtonState == LOW) {
      // Button pressed, scroll up
      AbsoluteMouse.move(0, 0, 1);
    } else {
      // Button released, scroll down
      AbsoluteMouse.move(0, 0, -1);
    }
    lastButtonState = currentButtonState;
  }
}

Won't this simply scroll up one line when you press the button and then scroll down one line when you release the button?

How did you want this to work?

1 Like

Perhaps you want it to work like this:

#include <HID-Project.h>
#include <HID-Settings.h>

// Rotary Encoder Inputs
const int pinA = 2; // CLK
const int pinB = 3; // DT
const int buttonPin = 4; // SW

int lastStateCLK;
int currentStateCLK;
int lastButtonState = HIGH;
int currentButtonState;

void setup() {
  pinMode(pinA, INPUT);
  pinMode(pinB, INPUT);
  pinMode(buttonPin, INPUT_PULLUP);
  Consumer.begin(); // Start the Consumer device emulation
  lastStateCLK = digitalRead(pinA);
}

void loop() {
  // Check for button press to control mouse scroll
  currentButtonState = digitalRead(buttonPin);
 
  currentStateCLK = digitalRead(pinA);
  // If the state has changed, a pulse occurred
  if (currentStateCLK != lastStateCLK) {
    // Determine the rotation direction
    if (digitalRead(pinB) != currentStateCLK) {
      if (currentButtonState == LOW) {
        // scroll up
        AbsoluteMouse.move(0, 0, 1);
      } else {
        // Encoder rotated clockwise
        Consumer.write(MEDIA_VOLUME_UP);
      }
    } else {
      if (currentButtonState == LOW) {
        // scroll down
        AbsoluteMouse.move(0, 0, -1);
      } else {
        // Encoder rotated counterclockwise
        Consumer.write(MEDIA_VOLUME_DOWN);
      }
    }
  }
  lastStateCLK = currentStateCLK;

}

for example - when I rotate the encoder clockwise, the mouse scrolls up work, and in anti-clockwise motion scrolls down work.
I hope you get what I am trying to say.

What about the volume up/down?

How do you want the encoder to control both volume and scroll?

I want to use the Rotatory encoder in two ways, change between these two options using the button (switch)
First - volume control (worked)
Second - Mouse scroll wheel (not working)

Note - I am not able to figure out why the mouse scroll is not working where whereas volume control works fine without any issue.

Because what you described is not what your code is doing. Your code says to scroll up one line when button is pressed and down one line when button is released. Not very useful. Your code does not say that scrolling should happen when the encoder is rotated.

Did you try my suggested code?

yup, the same problem I tried your code, and the volume control worked but the mouse scroll was not working.
Can you write a specific code for the mouse scroll wheel?
I try to chat GPT, the copilot version of code but none of them working

Did you try holding the button down and turning the encoder at the same time?

yes, I try holding but not worked

I get this when i upload code in my arduino, why there is no mouse.h (is this could be the reason)
In file included from c:\users\prabh-pc\documents\arduino\libraries\hid-project\src\hid-apis\KeyboardAPI.h:29:0, from c:\users\prabh-pc\documents\arduino\libraries\hid-project\src\hid-apis\defaultkeyboardapi.h:27, from C:\Users\Prabh-PC\Documents\Arduino\libraries\HID-Project\src/SingleReport/BootKeyboard.h:30, from C:\Users\Prabh-PC\Documents\Arduino\libraries\HID-Project\src/HID-Project.h:50, from C:\Users\Prabh-PC\Documents\sketch_jun10b\sketch_jun10b.ino:1: c:\users\prabh-pc\documents\arduino\libraries\hid-project\src\keyboardlayouts\improvedkeylayouts.h:54:21: note: #pragma message: Using default ASCII layout for keyboard modules #pragma message "Using default ASCII layout for keyboard modules" ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Is there an example sketch with that library which demonstrates mouse scrolling? Have you tried it?

when I tried to move the mouse with the joystick module, again it didn't work. I think its a problem with the mouse library because the keyboard library works fine.

The mouse library simply says to use Mouse.move(x-axis, y-axis, Scroll_value to control any mouse movement.
Note - I didn't find any useful resource to solve this issue.

But you used

Maybe that's the problem. It is scrolling to absolute positions +1 or -1.

I tried all values which could work.

Share your latest code.

Now I am trying to achive same goal(Mouse control) with joystick module but not working

Here is the code in which i am using joystick

/* HID Joystick Mouse Example
   by: Jim Lindblom
   date: 1/12/2012
   license: MIT License - Feel free to use this code for any purpose.
   No restrictions. Just keep this license if you go on to use this
   code in your future endeavors! Reuse and share.

   This is very simplistic code that allows you to turn the
   SparkFun Thumb Joystick (http://www.sparkfun.com/products/9032)
   into an HID Mouse. The select button on the joystick is set up
   as the mouse left click.
*/
#include <Mouse.h>
int horzPin = A0;  // Analog output of horizontal joystick pin
int vertPin = A1;  // Analog output of vertical joystick pin
int selPin = 9;  // select button pin of joystick

int vertZero, horzZero;  // Stores the initial value of each axis, usually around 512
int vertValue, horzValue;  // Stores current analog output of each axis
const int sensitivity = 200;  // Higher sensitivity value = slower mouse, should be <= about 500
int mouseClickFlag = 0;

//int invertMouse = 1;        //Invert joystick based on orientation
int invertMouse = -1;         //Noninverted joystick based on orientation

void setup()
{
  pinMode(horzPin, INPUT);  // Set both analog pins as inputs
  pinMode(vertPin, INPUT);
  pinMode(selPin, INPUT);  // set button select pin as input
  digitalWrite(selPin, HIGH);  // Pull button select pin high
  delay(1000);  // short delay to let outputs settle
  vertZero = analogRead(vertPin);  // get the initial values
  horzZero = analogRead(horzPin);  // Joystick should be in neutral position when reading these

  Mouse.begin(); //Init mouse emulation
}

void loop()
{
  vertValue = analogRead(vertPin) - vertZero;  // read vertical offset
  horzValue = analogRead(horzPin) - horzZero;  // read horizontal offset

  if (vertValue != 0)
    Mouse.move(0, (invertMouse * (vertValue / sensitivity)), 0); // move mouse on y axis
  if (horzValue != 0)
    Mouse.move((invertMouse * (horzValue / sensitivity)), 0, 0); // move mouse on x axis

  if ((digitalRead(selPin) == 0) && (!mouseClickFlag))  // if the joystick button is pressed
  {
    mouseClickFlag = 1;
    Mouse.press(MOUSE_LEFT);  // click the left button down
  }
  else if ((digitalRead(selPin)) && (mouseClickFlag)) // if the joystick button is not pressed
  {
    mouseClickFlag = 0;
    Mouse.release(MOUSE_LEFT);  // release the left button
  }
}

Hey bro, I don't know why but after restarting my PC joystick mouse works.

Ufh, Finally it worked.

Control Mouse scroll wheel & Mouse x-axis movement
This is the final version of my code

#include <Mouse.h>

// Rotary Encoder Inputs
const int pinA = 2; // CLK
const int pinB = 3; // DT
const int buttonPin = 4; // SW

int lastStateCLK;
int currentStateCLK;
int lastButtonState = HIGH;
int currentButtonState;
bool xControlEnabled = false; // State to control X-axis movement

void setup() {
  pinMode(pinA, INPUT);
  pinMode(pinB, INPUT);
  pinMode(buttonPin, INPUT_PULLUP);
  Mouse.begin(); // Start the mouse emulation

  lastStateCLK = digitalRead(pinA);
}

void loop() {
  currentStateCLK = digitalRead(pinA);

  // If the state has changed, a pulse occurred
  if (currentStateCLK != lastStateCLK) {
    // Determine the rotation direction
    if (digitalRead(pinB) != currentStateCLK) {
      // Encoder rotated clockwise
      if (xControlEnabled) {
        Mouse.move(1, 0, 0); // Move X-axis to the right
      } else {
        Mouse.move(0, 0, 1); // Scroll up
      }
    } else {
      // Encoder rotated counterclockwise
      if (xControlEnabled) {
        Mouse.move(-1, 0, 0); // Move X-axis to the left
      } else {
        Mouse.move(0, 0, -1); // Scroll down
      }
    }
  }

  lastStateCLK = currentStateCLK;

  // Check for button press to toggle X-axis control
  currentButtonState = digitalRead(buttonPin);
  if (currentButtonState != lastButtonState && currentButtonState == LOW) {
    // Toggle the control state
    xControlEnabled = !xControlEnabled;
  }
  lastButtonState = currentButtonState;
}