使用加速度计进行DIY手势控制的基于Arduino的空中鼠标

original: https://circuitdigest.com/microcontroller-projects/diy-gesture-controlled-arduino-air-mouse-using-accelerometer

使用加速度计进行DIY手势控制的基于Arduino的空中鼠标

ARDUINO项目

经过**马达夫** 2019年6月24日修改
在这里插入图片描述

曾经想知道我们的世界如何朝着身临其境的现实迈进。我们一直在寻找使用虚拟现实,混合现实,增强现实等与周围环境进行交互的新方法和方法。每天,随着这些快速起步技术的出现,新设备不断涌现,它们的新交互技术给我们留下了深刻的印象。

这些身临其境的技术被用于游戏,互动活动,娱乐和许多其他应用中。在本教程中,我们将了解这种交互式方法,该方法为您提供了一种与系统进行交互的新方法,而无需使用无聊的鼠标。我们的游戏极客必须知道,任天堂在几年前就出售了一种3D交互式方法的想法,这种方法是借助称为Wii控制器的手持控制器与控制台进行交互的。它使用加速度计来定位您的游戏手势并将其无线发送到系统。如果您想进一步了解这项技术,可以查看其专利EP1854518B1,这将使您对这项技术的工作原理有一个完整的了解。

在这里插入图片描述任天堂Wii模块

受此想法的启发,我们将制作一个**“空中鼠标”,**仅通过在空中移动控制台即可与系统进行交互,但是我们将仅使用二维坐标引用,而不是使用3维坐标引用,因此我们可以模仿计算机鼠标的动作,因为鼠标在X和Y二维上起作用。

这种无线3D空中鼠标的概念非常简单,我们将使用加速度计来获取“空中鼠标”沿x和y轴的动作和运动的加速度值,然后基于加速度计,我们将在计算机上运行的python软件驱动程序的控制下,控制鼠标光标并执行某些操作。

先决条件

  • Arduino Nano(任何型号)
  • 加速度计ADXL335模块
  • 蓝牙HC-05模块
  • 按按钮
  • 安装了Python的计算机

要了解有关在计算机上安装python的更多信息,请遵循Arduino-Python LED Controling上的上一教程。

电路图

在这里插入图片描述
在这里插入图片描述

用手的运动来**控制计算机,**您需要一个加速度计,该加速度计沿X和Y轴发出加速度,并使整个系统无线,蓝牙模块用于将信号无线传输到您的系统。

此处使用的是ADXL335加速度计,它是基于MEMS的三轴模块,可输出沿X,Y和Z轴的加速度,但是如前所述,控制鼠标时,我们只需要沿X和Y轴的加速度即可。了解有关在以前的项目中将ADXL335加速度计与Arduino结合使用的更多信息:

此处,加速度计的Xout和Yout引脚连接至Arduino的Analog,A0和A1引脚,并且此处用于将信号从Arduino传输至系统蓝牙模块HC-05,因为蓝牙在Tx和Rx上工作引脚连接,因此我们使用软件串行引脚D2和D3。它使用软件串行进行连接,因为如果我们将蓝牙与硬件串行连接并开始通过python控制台获取读数,则由于蓝牙将以其自己的波特率与python通信,因此会显示波特率不匹配的错误。通过使用包括Arduino在内的不同微控制器的各种基于蓝牙的项目来了解有关使用蓝牙模块的更多信息。

在这里,我们使用了三个按钮-一个用于触发Air鼠标,另外两个用于左右单击,如下图所示:
在这里插入图片描述

空中鼠标的处理流程

流程图显示了基于Arduino的Air Mouse的处理流程:
在这里插入图片描述

1.系统会持续检查是否要按下机械触发器,直到没有按下机械触发器,我们才能使用计算机鼠标正常进行操作。

2.当系统检测到按钮按下时,鼠标的控件将转移到空中鼠标。

3.按下触发按钮后,系统开始将鼠标的读数传输到计算机。系统读数由加速度计读数以及左键和右键单击的读数组成。

4.系统读数由1字节或8位的数据流组成,其中前三位由X坐标组成,后三位由Y坐标组成,后第二位是要获取的状态位鼠标左键单击的状态,最后一位是获取右键单击状态的状态位。

5.前三个位的值(即X坐标)可以在100 <= Xcord <= 999的范围内,而Y坐标的值可以在100 <= Ycord <= 800的范围内。右击和左击的值是二进制值0或1,其中1表示进行了单击,0表示用户未进行单击。

6.为了不使按钮弹跳影响光标的位置,每次单击鼠标的触发按钮后,将保持4秒的已知延迟。

7.对于空中鼠标中的左右单击,我们必须首先按下左或右按钮,然后,我们必须按下触发按钮以移动到所需的空中鼠标的位置。

编程Arduino for Air Mouse

Arduino应该编程为读取X和Y轴上的加速度值。最后给出了完整的程序,下面是代码中的重要片段。

设置全局变量

如前所述,我们将使用软件串行引脚连接蓝牙模块。因此,要设置软件序列,我们需要声明软件序列库,并设置Tx和Rx的引脚。在Arduino Nano和Uno中,Pin 2和3可以用作软件序列。接下来,我们从软件串行库中声明Bluetooth对象,以设置Tx和Rx的引脚。

#include <SoftwareSerial.h>
const int rxpin = 2, txpin = 3;
SoftwareSerial bluetooth(rxpin, txpin);
const int x=A0;
const int y=A1;
int xh, yh;
int xcord, ycord;
const int trigger = 5;
int lstate = 0;
int rstate = 0;
const int lclick = 6;
const int rclick = 7;
const int led = 8;

void setup()

设置功能中,我们将设置变量以告诉程序它们将充当输入还是输出。触发按钮将被设置为输入上拉,而左键和右键将被声明为输入,并被设置为高电平以使其充当输入上拉。

还要将串行和蓝牙通信的波特率设置为9600。

  void setup()
{ 
  pinMode(x,INPUT); 
  pinMode(y,INPUT); 
  pinMode(trigger,INPUT_PULLUP)
  pinMode(lclick,输入); 
  pinMode(rclick,INPUT); 
  pinMode(led,OUTPUT); 
  digitalWrite(lclick,HIGH); 
  digitalWrite(rclick,HIGH); 
  Serial.begin(9600); 
  bluetooth.begin(9600); 
}

void loop()

由于我们需要触发器按钮来告知何时需要向系统发送数据流,因此我们在while循环中设置了整个代码,该代码将连续监视上拉触发器的数字状态,当它变低时,它将将其进一步传递以进行处理。

由于我们已安装了LED指示灯,以便在按下触发按钮时了解系统状态,因此我们最初将led设置为在while循环外的默认状态下设置为低,while循环内将其设置为高电平*,*这将使led点亮每当按下触发按钮时

读取左右单击按钮**的状态,**我们已全局声明了两个变量lclickrclick,它们的值最初设置为0。

然后在循环中,根据左右单击按钮的数字状态设置这些变量的值,以检查按钮是否被按下。

我们将使用AnalogRead函数读取加速度计的X和Y out引脚的值,并将这些值映射到屏幕尺寸,以使鼠标指针在整个屏幕上移动。由于屏幕尺寸是屏幕中的像素,因此我们需要相应地进行设置,并且由于我们需要将输出值设置为三位数,因此我们特意将X的范围设置为100 <= X <= 999。 Y的值是100 <= Y <= 800。请记住,像素是从左上角读取的,即,左上角的值为(0,0),但是由于我们已经声明了x和y的三位数,因此将从点(100,100)读取值。

此外,借助Serial.printbluetooth.print函数,可以打印坐标值以及串行和Bluetooth上的单击状态,它们有助于通过蓝牙在串行监视器和系统上获取这些值。

最后,由于按钮的弹跳,可能会重复单个值,这将导致鼠标光标停留在单个位置上,因此要消除此情况,我们必须添加此延迟。

void loop()
{
digitalWrite(led,LOW);
  while(digitalRead(trigger)==LOW)
  {
    digitalWrite(led, HIGH);
    lstate = digitalRead(lclick);
    rstate = digitalRead(rclick);
    xh=analogRead(x);
    yh=analogRead(y);
    xcord=map(xh,286,429,100,999);
    ycord=map(yh,282,427,100,800);
    Serial.print(xcord);
    Serial.print(ycord);
    if (lstate == LOW)
    Serial.print(1);
    else
    Serial.print(0);
    if (rstate == LOW)
    Serial.print(1);
    else
    Serial.print(0);
    bluetooth.print(xcord);
    bluetooth.print(ycord);
    if (lstate == LOW)
    bluetooth.print(1);
    else
    bluetooth.print(0);
    if (rstate == LOW)
    bluetooth.print(1);
    else
    bluetooth.print(0);
    delay(4000);
   } }

适用于计算机的****Python驱动程序脚本

到目前为止,我们已经完成了硬件及其固件部分,现在要使空中鼠标正常工作,我们需要一个驱动程序脚本,该脚本可以将来自空中鼠标的信号解码为光标移动,因此,我们选择了Python。Python是一种脚本语言,这里所说的脚本是指它可以帮助我们控制其他程序,因为这里我们要控制鼠标光标。

因此,打开您的python shell并使用以下命令安装以下库:

pip install serial
pip install pyautogui

该***系列*是为Python库,帮助我们摆脱串行接口如COM端口的数据,也让我们对其进行操作,而*pyautogui***是库蟒蛇,并得到了GUI功能的控制,在这种情况下,鼠标。

现在让我们看一下驱动程序的代码,我们要做的第一件事是导入串行和pyautogui库,然后从串行库中,我们必须以9600的波特率设置用于通信的com端口,即与Bluetooth.serial相同。为此,您必须将蓝牙模块连接至系统,然后在系统设置中必须检查其已连接到哪个com端口。

接下来的事情是读取从蓝牙到系统的串行通信,并使其保持连续运行,并在while 1的帮助下将其余代码保持在连续循环中。

如前所述,Arduino将发送8位,前6位用于坐标,后两位用于单击按钮的状态。因此,在ser.read的帮助下读取所有位并将其长度设置为8位。

接下来,将光标坐标和点击的位置划分为多个部分,然后将其进一步划分为X和Y坐标。左键单击和右键单击相同。

现在,从通信中,我们得到一个字节字符串,我们需要将其转换为整数,以便它们适合坐标,我们通过解码它们,然后将其类型转换为整数来做到这一点。

现在要移动光标,我们使用pyautogui moveto函数,该函数将那些整数坐标作为参数并将光标移动到该位置。

下一步检查点击,我们使用后两位和pyautogui的click函数来完成,其默认点击为左,但是我们可以通过将按钮值声明为right来将其设置为right,我们也可以定义点击的次数通过将clicks参数设置为2来将其设置为双击。

以下是要在计算机上运行完整Python代码

import serial
import pyautogui
ser=serial.Serial('com3',9600)
while 1:
    k=ser.read(8)
    cursor=k[:6]
    click=k[6:]
    x=cursor[:3]
    y=cursor[3:]
    l=click[0]
    r=click[1]
    xcor=int(x.decode('utf-8'))
    ycor=int(y.decode('utf-8'))
    pyautogui.moveTo(xcor,ycor)
    if l==49:
        pyautogui.click(clicks=2)
    elif r==49:
        pyautogui.click(button='right', clicks=2)

测试Arduino Air Mouse

因此,要操作Air Mouse,请为其连接电源。它可以来自Arduino Nano USB插槽,也可以来自使用7805 IC的5v稳压电源。然后通过设置蓝牙连接的com端口运行python驱动程序脚本。当脚本运行时,您会在蓝牙闪烁中看到一个时间滞后,这意味着它已连接到您的系统。然后,对其进行操作,单击“触发”按钮,您将看到坐标的位置将发生变化;如果要单击左键或右键,则首先同时按左或右按钮和触发按钮,您将在以下位置看到单击的动作:光标的位置已更改。
在这里插入图片描述

查看下面的详细工作视频

Python Script:


import serial
import pyautogui
ser=serial.Serial('com3',9600)
while 1:
    k=ser.read(8)
    cursor=k[:6]
    click=k[6:]
    x=cursor[:3]
    y=cursor[3:]
    l=click[0]
    r=click[1]
    xcor=int(x.decode('utf-8'))
    ycor=int(y.decode('utf-8'))
    pyautogui.moveTo(xcor,ycor)
    if l==49:
        pyautogui.click(clicks=2)
    elif r==49:
        pyautogui.click(button='right', clicks=2)


Arduino Code:


#include <SoftwareSerial.h>
const int rxpin = 2, txpin = 3;
SoftwareSerial bluetooth(rxpin, txpin);
const int x=A0;
const int y=A1;
int xh, yh;
int xcord, ycord;
const int trigger = 5;
int lstate = 0;
int rstate = 0;
const int lclick = 6;
const int rclick = 7;
const int led = 8;

void setup()
{
  pinMode(x,INPUT);
  pinMode(y,INPUT);
  pinMode(trigger,INPUT_PULLUP);
  pinMode(lclick,INPUT);
  pinMode(rclick,INPUT);
  pinMode(led, OUTPUT);
  digitalWrite(lclick,HIGH);
  digitalWrite(rclick,HIGH);
  Serial.begin(9600);
  bluetooth.begin(9600);
}

void loop()
{
digitalWrite(led,LOW);
  while(digitalRead(trigger)==LOW)
  { 
    digitalWrite(led, HIGH);
    lstate = digitalRead(lclick);
    rstate = digitalRead(rclick);
    xh=analogRead(x);
    yh=analogRead(y);
    xcord=map(xh,286,429,100,999);
    ycord=map(yh,282,427,100,800);
    Serial.print(xcord);
    Serial.print(ycord);
    if (lstate == LOW)
    Serial.print(1);
    else 
    Serial.print(0);
    if (rstate == LOW)
    Serial.print(1);
    else 
    Serial.print(0);
    bluetooth.print(xcord);
    bluetooth.print(ycord);
    if (lstate == LOW)
    bluetooth.print(1);
    else 
    bluetooth.print(0);
    if (rstate == LOW)
    bluetooth.print(1);
    else 
    bluetooth.print(0);
    delay(4000);
   }
}


Python driver script


import serial
import pyautogui
ser=serial.Serial('com3',9600)
while 1:
    k=ser.read(8)
    cursor=k[:6]
    click=k[6:]
    x=cursor[:3]
    y=cursor[3:]
    l=click[0]
    r=click[1]
    xcor=int(x.decode('utf-8'))
    ycor=int(y.decode('utf-8'))
    pyautogui.moveTo(xcor,ycor)
    if l==49:
        pyautogui.click(clicks=2)
    elif r==49:
        pyautogui.click(button='right', clicks=2)

  • 1
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 可以参考这个网站上的例子:https ://github.com/ControlEverythingCommunity/ADXL355/blob/master/Arduino/ADXL355_Accelerometer/ADXL355_Accelerometer.ino。 ### 回答2: 以下是使用Arduino编写的获取ADXL355加速度计数据的代码: ``` #include <Wire.h> #define ADXL355_ADDR 0x1D // ADXL355加速度计的I2C地址 #define START_ADDR 0x08 // 数据寄存器的起始地址 #define X_AXIS_REGISTER 0x08 // X轴加速度寄存器地址 #define Y_AXIS_REGISTER 0x0A // Y轴加速度寄存器地址 #define Z_AXIS_REGISTER 0x0C // Z轴加速度寄存器地址 #define SCALE_FACTOR 1000 // 加速度的缩放因子,用于转换为g单位 void setup() { Serial.begin(9600); // 初始化串口通信 Wire.begin(); // 初始化I2C总线 delay(100); // 设置ADXL355加速度计的配置寄存器 Wire.beginTransmission(ADXL355_ADDR); Wire.write(0x28); // 配置寄存器地址 Wire.write(0x03); // 设置为测量模式,输出数据为高分辨率,范围为±2g Wire.endTransmission(); } void loop() { // 读取X轴加速度数据 int16_t xAccel = readAccel(X_AXIS_REGISTER); // 读取Y轴加速度数据 int16_t yAccel = readAccel(Y_AXIS_REGISTER); // 读取Z轴加速度数据 int16_t zAccel = readAccel(Z_AXIS_REGISTER); // 打印加速度数据 Serial.print("X轴加速度: "); Serial.print(xAccel); Serial.print(" g, "); Serial.print("Y轴加速度: "); Serial.print(yAccel); Serial.print(" g, "); Serial.print("Z轴加速度: "); Serial.print(zAccel); Serial.print(" g"); delay(100); // 延迟以便读取下一帧数据 } // 读取加速度计数据的函数 int16_t readAccel(uint8_t regAddr) { Wire.beginTransmission(ADXL355_ADDR); Wire.write(regAddr); Wire.endTransmission(); Wire.requestFrom(ADXL355_ADDR, 2); while (Wire.available() < 2); uint8_t lowByte = Wire.read(); uint8_t highByte = Wire.read(); int16_t accelData = (highByte << 8) | lowByte; accelData = accelData / SCALE_FACTOR; // 根据缩放因子转换为g单位 return accelData; // 返回加速度数据 } ``` 这个代码会初始化ADXL355加速度计,将其配置为测量模式,并通过I2C总线读取X、Y、Z三个轴的加速度数据。读取到的加速度数据会通过串口打印输出,单位为g。需要将ADXL355连接到Arduino的I2C接口上,并根据实际情况调整代码中的ADXL355加速度计地址(ADXL355_ADDR)。 ### 回答3: ADXL355是一款具有高精度和高测量范围的数字三轴加速度计,可以用于获取肢体的加速度信息。以下是使用Arduino编写的代码来获取肢体加速度的步骤: 1. 首先,确保你已经将ADXL355连接到Arduino开发板上。将ADXL355的VDD、GND和CS脚分别连接到Arduino的3.3V、GND和任意数字IO口(例如D10),将ADXL355的SDO、SDA和SCL脚分别连接到Arduino的SDA和SCL引脚。 2. 在Arduino的开发环境中创建一个空白的新项目,然后将下面的代码复制粘贴到项目中: ```c // 引入Wire库,用于I2C通信 #include <Wire.h> // 定义ADXL355的I2C地址 #define ADXL355_ADDR 0x1E // 初始化ADXL355 void initADXL355() { Wire.beginTransmission(ADXL355_ADDR); Wire.write(0x28); Wire.write(0x0F); Wire.endTransmission(); Wire.beginTransmission(ADXL355_ADDR); Wire.write(0x2D); Wire.write(0x08); Wire.endTransmission(); } // 读取ADXL355的X、Y、Z加速度值 void readADXL355(int16_t *xAccel, int16_t *yAccel, int16_t *zAccel) { uint8_t buf[6]; Wire.beginTransmission(ADXL355_ADDR); Wire.write(0x08); Wire.endTransmission(); Wire.requestFrom(ADXL355_ADDR, 6); for (int i = 0; i < 6; i++) { buf[i] = Wire.read(); } *xAccel = ((buf[1] << 8) | buf[0]); *yAccel = ((buf[3] << 8) | buf[2]); *zAccel = ((buf[5] << 8) | buf[4]); } // 设置Arduino串口的波特率 void setup() { Serial.begin(9600); Wire.begin(); initADXL355(); } // 获取肢体加速度 void loop() { int16_t xAccel, yAccel, zAccel; readADXL355(&xAccel, &yAccel, &zAccel); Serial.print("X轴加速度:"); Serial.print(xAccel); Serial.print(",Y轴加速度:"); Serial.print(yAccel); Serial.print(",Z轴加速度:"); Serial.println(zAccel); delay(500); // 设置采样频率 } ``` 3. 将Arduino开发板通过USB连接到电脑,并上传上述代码到开发板上。 4. 打开Arduino串口监视器,设置波特率为9600,然后就可以在串口监视器上看到连续输出的X、Y和Z轴加速度值了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值