Use rotary encoder as a scroll wheel

i am trying to diy space mouse with

  • micro pro arduino
  • joystick
  • two push buttons (left and right buttons)
  • rotary encoder module

i managed to control the mouse with joystick and buttons but i now i am try to use rotary encoder as wheel (zoom in/out - scroll up and down).

i tried to call the rotary encoder pin and control the scroll with it but no success, so how to use rotary encoder as wheel mouse in the code.

here is my code (i wrote the rotary encoder code away from the joystick and buttons for some reading purposes)

#include <Mouse.h>
int horzPin = A0;  // Analog output of horizontal joystick pin
int vertPin = A1;  // Analog output of vertical joystick pin
int selPin  = 7;  // button of sw 1
int selpin2 = 9;  // button of sw 2

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;       //click check sw 1
int b1flag = 0;               //click check sw2

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

int encoderCLK = 2;
int encoderDT = 15;
int encoderSW = 3;

// Variables
int counter = 0;
int currentStateCLK;
int lastStateCLK;
unsigned long lastButtonPress = 0;


void setup()
{
  pinMode(horzPin, INPUT);  // Set both analog pins as inputs
  pinMode(vertPin, INPUT);
  pinMode(selPin, INPUT);  // set button select pin as input
  pinMode(selpin2, INPUT);  // set button select pin as input
  digitalWrite(selPin, HIGH);  // Pull button select pin high
  digitalWrite(selpin2, 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

 //Pin Initialization
  pinMode (encoderCLK, INPUT);
  pinMode (encoderDT, INPUT);
  pinMode (encoderSW, INPUT);

  // Read Encoders CLK inital state
  lastStateCLK = digitalRead(encoderCLK);

  //initialize mouse control:
  Mouse.begin();

}

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 button 1 is pressed
  {
    mouseClickFlag = 1;
    Mouse.press(MOUSE_RIGHT);  // click the right button down
  }
  else if ((digitalRead(selPin)) && (mouseClickFlag)) // if the button 1 is not pressed
  {
    mouseClickFlag = 0;
    Mouse.release(MOUSE_RIGHT);  // release the right button
  }

// second button
  if ((digitalRead(selpin2) == 0) && (!b1flag))  // if the button 2 is pressed
  {
     b1flag = 1;
     Mouse.click(MOUSE_LEFT);
  }
  else if ((digitalRead(selpin2)) && (b1flag))  // if the button 2 is not pressed
  {
    b1flag = 0;
    Mouse.release(MOUSE_LEFT);  // release the left button
  }
  //Read the current state of CLK
  currentStateCLK = digitalRead(encoderCLK);

  // If last and current state of CLK are different, then pulse occurred
  // React to only 1 state change to avoid double count
  if (currentStateCLK != lastStateCLK  && currentStateCLK == 1){

    // If the DT state is different than the CLK state then
    // the encoder is rotating CCW so decrement
    if (digitalRead(encoderDT) != currentStateCLK) {
      counter --;
    } else {
      // Encoder is rotating CW so increment
      counter ++;
    }
    
    //Serial Debuging
    /*Serial.print(" | Counter: ");
    Serial.println(counter);*/
  }

  // Remember last CLK state
  lastStateCLK = currentStateCLK;

  // Read the button state
  int btnState = digitalRead(encoderSW);

  //If we detect LOW signal, button is pressed
  if (btnState == LOW) {
    //if 50ms have passed since last LOW pulse, it means that the
    //button has been pressed, released and pressed again
    if (millis() - lastButtonPress > 50) {
      Mouse.click(MOUSE_MIDDLE);
      //Serial Debuggin
      //Serial.println("Button pressed!");
    }

    // Remember last button press event
    lastButtonPress = millis();
  }
  //Move the Scroll Wheel
  Mouse.move(0, 0, counter);

  //Reset Counter for next move
  counter = 0;
}

schematic

You can modify your code like this:

void loop()
{
  // Your existing code for joystick and buttons

  // Read the current state of CLK
  currentStateCLK = digitalRead(encoderCLK);

  // If last and current state of CLK are different, then pulse occurred
  // React to only 1 state change to avoid double count
  if (currentStateCLK != lastStateCLK  && currentStateCLK == 1){

    // If the DT state is different than the CLK state then
    // the encoder is rotating CCW so decrement
    if (digitalRead(encoderDT) != currentStateCLK) {
      counter--;
    } else {
      // Encoder is rotating CW so increment
      counter++;
    }
  }

  // Remember last CLK state
  lastStateCLK = currentStateCLK;

  // Move the Scroll Wheel only if the counter has changed
  if (counter != 0) {
    Mouse.move(0, 0, counter);
    counter = 0; // Reset counter after scrolling
  }
}

1 Like

based on your schematic, your selPins need to be decalred INPUT_PULLUP not INPUT or else they will be floating when not pressed.

I pointed this out in your other post as well.

It is working for scroll up only, scroll down no, what could be the problem

I edited it and it is more sensitive( working better)
Well done blh64

wheel is a signed char, -128 to 128 max values..

void move(int x, int y, signed char wheel = 0);

arduino-libraries - src/Mouse.h

good luck.. ~q

1 Like

Problem still exist.
When i rotate the screw clockwise it scrolls up
And counterclockwise it scrolls up too

This if() statement is only true when currentStateCLK is HIGH. Try instead,

I tried this before and did not succeed :pensive:

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