基于Arduino Leonardo和MPU6050模块的手势控制

  • 内容
  • 评论
  • 相关

本文将向你展示如何使用Arduino Leonardo和MPU6050加速计/陀螺仪模块来制作一个类似于任天堂Wii控制器的手势控制装置。手势控制装置主要用于游戏、互动活动和一些基础娱乐。几年前,任天堂创造了一种全新的人机交互模式,手势控制,它允许用户在Wii控制器的帮助下,通过游戏手柄与游戏内容进行交互。Wii控制器使用一个加速度计来识别你当前的手势,然后将手势映射到游戏控制器上。下面,我们也将使用Arduino Leonardo和MPU6050模块来制作一个有线的手势控制器。

 Arduino Leonardo
Arduino Leonardo

工作原理

该装置依赖于两个关键组件:MPU6050和Arduino Leonardo。MPU6050可以帮助我们收集控制装置沿x轴和y轴移动的三维姿态数据。然后,根据传感器的值,我们可以控制光标位置。要实现单击鼠标的效果,需要停止移动光标并将其锁定在一个点上两秒钟(或者将它设置成一个按钮)。

Arduino Leonardo 和 MPU6050
Arduino Leonardo 和 MPU6050

MPU6050是一个IMU传感器,它基于MEMS技术,包含有6个自由度,可以提供6个值作为输出。这六个值中,三个来自加速度计,其余三个来自陀螺仪。

Arduino Leonardo与Arduino Uno外形相同。Arduino Uno配备的是ATmega385芯片,而Leonardo配备了atmega32u4芯片。它有20个数字输入/输出引脚,20个引脚中,7个引脚可作为PWM输出,12个引脚可作为模拟输入,同时它板载了一个微型USB接口,一个电源插口,一个ICSP端口和一个复位按钮。详见Arduino开发板知多少?

连接Arduino Leonardo和MPU6050

需要说明:因为该装置代码中需要引入mouse.h库文件,而该库文件只支持ATmega32U4芯片,所以只有在基于ATmega32U4芯片的Arduino开发板才能支持这个项目。因此,除了选择Arduino Leonardo外你还可以使用 Arduino Pro Mini开发板。

rduino Leonardo和MPU605电路连接图
Arduino Leonardo和MPU605电路连接图
Arduino Leonardo和MPU605实物连接图
Arduino Leonardo和MPU605实物连接图

上传代码

根据上面的图连接好硬件后,就可以将你的Arduino Leonardo连接到电脑上,并将代码上传到你的Arduino上。代码分为两部分,第一部分是校准代码,第二部分是包点击功能的代码。首先上传校准代码:

//calibrate_air_mouse
#include <Wire.h>
#include <I2Cdev.h>
#include <MPU6050.h>
#include <Mouse.h>

MPU6050 mpu;
int16_t ax, ay, az, gx, gy, gz;
int vx, vy;

void setup() {
  Serial.begin(9600);
  Wire.begin();
  mpu.initialize();
  if (!mpu.testConnection()) { while (1); }
}

void loop() {
  mpu.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);

  vx = (gx+300)/150;  // change 300 from 0 to 355
  vy = -(gz-100)/150; // same here about "-100"  from -355 to 0

  Serial.print("gx = ");
  Serial.print(gx);
  Serial.print(" | gz = ");
  Serial.print(gz);
  
  Serial.print("        | X = ");
  Serial.print(vx);
  Serial.print(" | Y = ");
  Serial.println(vy);
  
  Mouse.move(vx, vy);
  
  delay(20);
}

上传代码后,鼠标指针就会映射到传感器上。尝试摇动MPU传感器模块。如果正常,请可以接着上传第二部分代码。如果光标不能与MPU6050的移动而移动,那么需要更改源代码中的一些值。可以打开串口监视器,确保可以x和y值可以归零,也就是静止状态。如果不能归零,请根据校准情况修改源代码中的 vx 或 vy 的值。位置如下:

  vx = (gx+300)/150;  // change 300 from 0 to 355
  vy = -(gz-100)/150; // same here about "-100"  from -355 to 0

校准完成后,就可以上传第二部分的代码,这段代码还添加了单击功能。单击时,是将光标停留在计算机屏幕上的某个点上约两秒钟。代码将检查光标是否在屏幕的10×10像素区域内停留了x秒的延迟,来执行点击效果的。

//air_mouse_with_click
#include <Wire.h>
#include <I2Cdev.h>
#include <MPU6050.h>
#include <Mouse.h>

MPU6050 mpu;
int16_t ax, ay, az, gx, gy, gz;
int vx, vy, vx_prec, vy_prec;
int count=0;

void setup() {
  Serial.begin(9600);
  Wire.begin();
  mpu.initialize();
  if (!mpu.testConnection()) {
    while (1);
    }
}

void loop() {
  mpu.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);

  vx = (gx+300)/200;  
  vy = -(gz-100)/200; 
  
  Mouse.move(vx, vy);
  
  
  if ( (vx_prec-5)<=vx && vx<=vx_prec+5 && (vy_prec-5)<=vy && vy<=vy_prec+5) { // for checking the cursor doesn't move too much from its actual position: (in this case a 10 pixel square)
    count++;                                                                  
    if(count == 100){ // the click will happen after 2 seconds the pointer has stopped in the 10px square
      if (!Mouse.isPressed(MOUSE_LEFT)) {
        Mouse.press(MOUSE_LEFT);
        count = 0;
      }
    }
    else {
      if (Mouse.isPressed(MOUSE_LEFT)) {
        Mouse.release(MOUSE_LEFT);
      }
    }
  }
  else {
    vx_prec = vx; // updating values to check the position of the pointer and allow the click
    vy_prec = vy;
    count = 0;
    }
  
  delay(20);
}