ardunio 鼠标控制

我想使用ardunio lenonardo来模拟鼠标运动。
我使用旋转编码器来控制鼠标运动,转速越大,鼠标运动越快,mouse.move 只在y轴上运动。低速转动时鼠标反应还好,但当旋转编码器高速转动时鼠标并未灵敏反应。

ardunio代码如下
#include <Mouse.h>
#define encoderPin  A0
#define maxEncoderValue  1023

volatile unsigned int currentEncoder0Pos = 0;
volatile unsigned int previouscurrentEncoder0Pos = 0;

long wheelValue = 0;

bool isWheelValuePositive = true;
unsigned long lastActivationTime = 0; // 上次激活的时间
const unsigned long activationDelay = 5000; // 延迟时间,单位为毫秒

void setup() {
  pinMode(encoderPin, INPUT);
  pinMode(11,INPUT);//left mouse
  Mouse.begin();
  Serial.begin (9600);
  pinMode(6, OUTPUT); // Direction
  pinMode(5, OUTPUT); // Step
  pinMode(7, OUTPUT);
  pinMode(4, INPUT); // FeedingTouch
  pinMode(3, INPUT); // Stop
  pinMode(8, INPUT);
  digitalWrite(7, LOW);
}

void loop() {

  updateMouseWheel();
  currentEncoder0Pos = analogRead(encoderPin);
  
}



// output mousewheel positive value when going in one direction
// and output a negative value when going in the opposite direction
void updateMouseWheel()
{
  
  
  // 检查编码器的位置是否发生了变化
  if(previouscurrentEncoder0Pos != currentEncoder0Pos)
  {
    // 如果当前的读数大于上一次的读数,那么认为是顺时针旋转
    if(currentEncoder0Pos > previouscurrentEncoder0Pos)
    {
      // 如果滚轮之前是在反方向滚动,那么将滚轮值重置为0
      if(!isWheelValuePositive)
      {
        wheelValue = 0;
        isWheelValuePositive = true;
      }
      // 使滚轮值递增
      wheelValue++; 
    }
    // 如果当前的读数小于上一次的读数,那么认为是逆时针旋转
    else if(currentEncoder0Pos < previouscurrentEncoder0Pos)
    {
      // 如果滚轮之前是在顺时针方向滚动,那么将滚轮值重置为0
      if(isWheelValuePositive)
      {
        wheelValue = 0;
        isWheelValuePositive = false;
      }
      // 使滚轮值递减
      wheelValue--;
    }

    // 更新前一次的编码器位置为当前位置
    previouscurrentEncoder0Pos = currentEncoder0Pos;

    // 在串口打印出滚轮值
    Serial.println (wheelValue);
    

    // 模拟鼠标在y轴上的移动
    Mouse.move(0,wheelValue,0);
  }
}
#include <Mouse.h>

#define encoderPinA A0
#define encoderPinB A1
#define encoderButtonPin 2
#define movementSpeed 5

int encoderPos = 0;
int lastEncoderPos = 0;

void setup() {
  pinMode(encoderPinA, INPUT_PULLUP);
  pinMode(encoderPinB, INPUT_PULLUP);
  pinMode(encoderButtonPin, INPUT_PULLUP);
  
  attachInterrupt(digitalPinToInterrupt(encoderPinA), updateEncoder, CHANGE);
  
  Mouse.begin();
}

void loop() {
  if (encoderPos != lastEncoderPos) {
    int movement = (encoderPos - lastEncoderPos) * movementSpeed;
    Mouse.move(0, movement);
    lastEncoderPos = encoderPos;
  }
  
  if (digitalRead(encoderButtonPin) == LOW) {
    Mouse.click(MOUSE_LEFT);
    delay(200); // 延时以避免连续点击
  }
}

void updateEncoder() {
  static int previousState = 0;
  int currentState = digitalRead(encoderPinA);

  if (currentState != previousState) {
    if (digitalRead(encoderPinB) != currentState) {
      encoderPos++;
    } else {
      encoderPos--;
    }
  }

  previousState = currentState;
}

把串口输出去掉就好了

Ardunio Leonardo本身的计算能力和响应速度有限的,move()函数传递给鼠标的Y轴变化量并不连续

c语言入门之用游戏操纵杆摸拟鼠标
可以参考下
https://www.xin3721.com/ArticleHB/hb_5570.html

看下你的旋转编码器与Arduino的连接正常,检查连接线是否牢固,并确保旋转编码器的引脚与Arduino的引脚正确连接。
其次,可能是由于旋转编码器的精度问题导致鼠标运动不灵敏,可以尝试在低速转动时进行调试,确保编码器能够正确地捕捉到鼠标的运动。
还有就是,在高速转动时,鼠标的运动可能会受到一定的影响。可以尝试在代码中添加适当的延迟,以使鼠标有足够的时间来响应旋转编码器的变化。

旋转编码器的分辨率不够高,无法准确地捕捉到鼠标的每一个移动。可以尝试使用更高分辨率的编码器或者增加编码器的采样率来提高精度。

可以尝试使用Arduino库函数来模拟鼠标运动

你可以试试将activationDelay设置为更小的值,好处是能更频繁地读取编码器的位置变化

TechWhizKid参考GPT回答:

  • 代码中存在一些可能的问题,这可能会影响你的设备的反应灵敏度。
  1. void updateMouseWheel()函数中,你只检查了当前编码器位置是否发生变化,但是,旋转编码器可能会在两次检查之间转动更多次,这可能导致某些变化被遗漏,特别是在快速转动的时候。为了解决这个问题,你可能需要一个更高效的方法来检测旋转编码器的变化。

  2. Mouse.move(0,wheelValue,0)这个函数在Arduino中用于模拟鼠标的移动。这个函数的第二个参数是y轴的移动距离,它取决于wheelValue的值。但在你的代码中,wheelValue可能会非常大,尤其是在快速旋转编码器的时候。鼠标可能会达到它的极限速度,这就会导致看起来鼠标没有反应。这里你可以试试将wheelValue缩小一些,比如除以一个常数,这样可以防止鼠标移动速度过快。

  3. 旋转编码器的读数通常有噪声,这也可能影响到检测的准确性。你可以试试使用一些软件去抖动的技巧来提高读数的准确性。

  4. 你的代码中使用了analogRead函数来读取旋转编码器的值,然而,大多数的旋转编码器是使用两个数字信号来工作的,它们通常被称为A和B信号。你可能需要使用两个digitalRead函数来读取这两个信号,然后根据两个信号的变化来确定旋转编码器的旋转方向和速度。

修改后的代码

#include <Mouse.h>
#include <Encoder.h>

// 定义旋转编码器连接的两个引脚
#define ENCODER_DO_NOT_USE_INTERRUPTS
#define encoderPinA 2
#define encoderPinB 3

Encoder myEncoder(encoderPinA, encoderPinB);

// 设定最大和最小的鼠标移动速度
#define MAX_SPEED 20
#define MIN_SPEED -20

void setup() {
  Mouse.begin();
  Serial.begin (9600);
}

void loop() {
  long encoderValue = myEncoder.read();
  
  // 将编码器的值映射到鼠标的移动速度
  long mouseSpeed = map(encoderValue, -1024, 1024, MIN_SPEED, MAX_SPEED);
  
  // 将编码器的读数重置为0
  myEncoder.write(0);
  
  // 模拟鼠标在y轴上的移动
  Mouse.move(0, mouseSpeed, 0);
  
  // 在串口打印出鼠标的移动速度
  Serial.println(mouseSpeed);
}


这个代码会将旋转编码器的值映射到一个鼠标的移动速度范围内,这样,无论你如何旋转编码器,鼠标的移动速度都不会超过它的极限速度。同时,通过使用Encoder库,可以更有效地检测旋转编码器的变化,提高反应的灵敏度。你可以根据需要调整MAX_SPEED和MIN_SPEED的值来调整鼠标的移动速度的最大和最小限制。

引用chatgpt内容作答:
根据你提供的代码,你正在使用Arduino Leonardo来模拟鼠标运动,并通过旋转编码器控制鼠标的运动速度。根据你描述的问题,当旋转编码器以高速旋转时,鼠标的反应速度并不敏感。

有几个可能的原因导致这个问题:

1、旋转编码器的速度限制:旋转编码器可能有一个最大的旋转速度,超过这个速度它可能无法准确地检测到旋转。你可以检查旋转编码器的规格和文档,看是否有关于最大旋转速度的说明。

2、Arduino Leonardo的处理能力限制:Arduino Leonardo是一个较低功率的微控制器,处理速度有限。当旋转编码器以非常高速旋转时,Arduino可能无法及时处理所有的旋转事件,从而导致鼠标反应不灵敏。

为了解决这个问题,你可以尝试以下几点:

1、增加编码器的分辨率:如果你的旋转编码器支持调整分辨率,尝试增加分辨率以提高其灵敏度。

2、优化代码性能:检查你的代码是否存在性能瓶颈,尽量优化代码逻辑,减少不必要的延迟或计算量,以提高Arduino的处理速度。

3、考虑更高性能的硬件:如果以上方法无法解决问题,你可能需要考虑使用更高性能的硬件,如Arduino Due或其他处理能力更强的微控制器。

请注意,Arduino Leonardo并不是专门设计用于模拟鼠标运动的硬件,它的主要功能是作为一个USB HID设备,用于模拟键盘和鼠标输入。对于需要更高精度和响应速度的鼠标模拟应用,可能需要考虑使用专门的鼠标模拟器硬件或其他更高级的解决方案。

我可以为你提供一些建议和改进方向,帮助你解决问题。

首先,你可以尝试使用Arduino的中断功能来优化编码器的读取。使用中断可以确保编码器的旋转事件能够被及时响应,提高鼠标的灵敏度。

以下是修改后的代码示例,使用Arduino的外部中断来读取旋转编码器的值:

#include <Mouse.h>

#define encoderPinA 2
#define encoderPinB 3

volatile int encoderPos = 0;
volatile int lastEncoded = 0;

void updateEncoder() {
  int MSB = digitalRead(encoderPinA);
  int LSB = digitalRead(encoderPinB);

  int encoded = (MSB << 1) | LSB;
  int sum = (lastEncoded << 2) | encoded;

  if (sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) {
    encoderPos++;
  } else if (sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) {
    encoderPos--;
  }

  lastEncoded = encoded;
}

void setup() {
  pinMode(encoderPinA, INPUT);
  pinMode(encoderPinB, INPUT);
  attachInterrupt(digitalPinToInterrupt(encoderPinA), updateEncoder, CHANGE);
  attachInterrupt(digitalPinToInterrupt(encoderPinB), updateEncoder, CHANGE);

  Mouse.begin();
  Serial.begin(9600);
}

void loop() {
  // 处理编码器的值,转换为鼠标的移动速度
  int speed = map(encoderPos, -100, 100, -10, 10);

  // 模拟鼠标在y轴上的移动
  Mouse.move(0, speed);

  // 打印编码器的值和鼠标的速度
  Serial.print("Encoder: ");
  Serial.print(encoderPos);
  Serial.print("  Speed: ");
  Serial.println(speed);

  delay(100); // 延迟一段时间,可根据需要调整
}

上述代码只是示例,可能需要根据你的硬件连接和需求进行适当的修改。此示例使用两个引脚(encoderPinA和encoderPinB)来连接旋转编码器,并使用外部中断来读取编码器的值。然后,根据编码器的值计算鼠标的移动速度,并模拟鼠标在y轴上的移动。

希望这可以帮助你改进代码并解决鼠标反应不灵敏的问题。