这篇文章来源于DevicePlus.com英语网站的翻译稿。
在本文中,我们将继续进行Arduino蓝牙手套的开发。我们将建立一个机械系统来获取手指的弯曲信息。同时,我们将会来了解如何整合IMU数据,无线封装和发送数据,使用Kinect以及如何在实际生活中使用Arduino蓝牙手套。我们强烈建议您先阅读Arduino蓝牙手套第一部分—基础来了解有关本项目的基础知识。
硬件
- Arduino UNO R3 x 2
- IMU 传感器 x 2
- 电线
- 电位计 0-10kOhm x 10
- 电阻 10 kOhm x 10
- Xbee USB 适配器
- Bluetooth Bee V2 x 2
- 9V 电池 x 2
- 9V 电池连接器 x 2
- Kinect
- 手套 x 2
- 扣件 x 20
软件
- Arduino IDE
- Autodesk Inventor
- LabVIEW
- LabVIEW Robotics Module
- Microsoft Kinect的 Kinesthesia工具包
- Kinect SDK 1.5
- Github
工具
- PLA 塑料
- 螺母 M3 x 40
- 自锁螺母 M3 x 40
- 烙铁
- 锡
- 焊料
- 胶水
手指弯曲测量
首先,为了测量手指的弯曲(手指弯折)信息,我们必须将手指弯曲程度转换为电位计的旋转度。我们可以通过简单的机械系统来实现这一目的,如下图所示:
为了在现实生活中进行应用,我们需要先在实体建模编辑器(如Autodesk Inventor)中进行建模。
接下来,我们需要将模型用3D打印技术制造出来。STL文件是所有3D打印机中常见的3D模型类型。只需要将所有模型分别导出成STL文件,并发送到3D打印机即可。
取用电位计(不带黑色旋钮/手柄)、螺丝、螺母以及3D打印部件,然后如图4所示进行组装。
如图5所示拧入关节。然后,我们将黑色手柄与拧入的手指关节粘合在一起。
将关节拧紧后,我们要将组装好的手指粘合到手套上。粘合使用的是超强力的多用途胶水。粘合前,表面必须保持清洁和干燥。然后在两个表面涂一层薄薄的胶水,等待10到15分钟后,将表面用力按压几秒钟。如有必要,您可以在每个单元周围也散布一些胶水。建议您将其晾干约24小时。
* 黏贴时请切勿将手指伸入手套,使用纸板或其他材料。
现在我们开始粘合手指关节。去除关节部分和两一个粘性扣件,然后将他们黏贴在手指的指甲上方(图8&9)。
将黑色手柄插入电位计孔中,以连接两个组装好的部件。
耐心对每根手指再重复9次相同的操作。
整个模块的接线图如下所示。
现在,我们来对手指进行连线吧!
准备红色和黑色的电线,以及三根分别带有白色、黄色和黑色标记的电线。此处强烈建议将颜色编码,以避免混淆。
如图11所示,将黑色标记和黄色标记的电线焊接到电位计上。
用塑料扎线带捆扎电线,以避免其受任何机械外力破坏。
接下来,您需要将黑色标记的电线与黑色电线以及黄色和白色标记的电线焊接到电阻上。红色电线必须焊接到电阻的另一端,白色标记的电线连接至Arduino模拟输入端。
焊接完所有单元后,我们将用热缩管对电线进行收缩,并用束线带将电线整合。
组装完成!我们继续进行编程部分。
安装新版本的 IMU Library。请参考 第一部分了解如何安装该库。
打开bending.ino 并将其上传到Arduino Uno。
#include "glove.h"
TFinger Finger1 = TFinger(A0);
TFinger Finger2 = TFinger(A1);
TFinger Finger3 = TFinger(A2);
TFinger Finger4 = TFinger(A3);
TFinger Finger5 = TFinger(A4);
void setup()
{
Serial.begin (9600); // Open the serial port
Serial.println ("Be ready to set min, in 3...");
delay(1000);
Serial.println ("2...");
delay(1000);
Serial.println ("1...");
delay(1000);
Finger1.setmin();
Finger2.setmin();
Finger3.setmin();
Finger4.setmin();
Finger5.setmin();
Serial.println ("Minimum is set");
Serial.println ("Be ready to set max, in 3...");
delay(1000);
Serial.println ("2...");
delay(1000);
Serial.println ("1...");
delay(1000);
Finger1.setmax();
Finger2.setmax();
Finger3.setmax();
Finger4.setmax();
Finger5.setmax();
Serial.println ("Maximum is set");
Finger1.calibrate();
Finger2.calibrate();
Finger3.calibrate();
Finger4.calibrate();
Finger5.calibrate();
Serial.println ("Calibrated");
}
void loop()
{
Serial.print ( Finger1.read() );
Serial.print ("\t");
Serial.print (Finger2.read());
Serial.print ("\t");
Serial.print (Finger3.read());
Serial.print ("\t");
Serial.print (Finger4.read());
Serial.print ("\t");
Serial.print (Finger5.read());
Serial.println ("\t");
delay(300);
//
}
您将会看到如图20所示的运行结果:
请注意,必须遵循校准程序才能够对数据进行准确测量。
IMU数据融合
在 Arduino蓝牙手套第一部分 – 基础 中,我们介绍了IMU传感器的基础知识。现在,我们将来学习如何整合陀螺仪和加速度计的数据。
首先,我们返回并查看之前的测量结果。
例如,陀螺仪返回12492数字值:
- 如果将陀螺仪配置为“测量范围 ±250 dps”,则该值将乘以0.00875 dps/数位,计算得到109.30 dps角速度。(109.30 dps表示具有该角速度的物体绕测量轴旋转一周大约需要四秒钟)。
- 如果将陀螺仪配置为“测量范围 ±2000 dps”,则该值将乘以0.07 dps/数位,计算得到874.44 dps的角速度。(874.44 dps表示具有该角速度的物体绕测量轴旋转一周大约需要2.5秒钟)。
传感器的灵敏度表示的是该传感器可检测到的最小变化值。请注意,范围约大,您从陀螺仪获得的灵敏度越低。
角速度是通过陀螺仪测量的值。因此,陀螺仪能够估计人体绕某个轴旋转的速度。在实际应用中,需要确定我们手套的位置。我们可以通过整合所有角速度值,然后除以时间变化,来估算当前角位置。
因为角速度的测量不是连续的,而是离散的,所以我们会得到一个叫做漂移的误差。之所以称为“漂移”,是因为即使身体处于静止状态,这些角位置变化的总和也会发生浮动。
我们一起看下面的陀螺仪漂移示例:
#include // Library for I²C
#include // Library for working with IMU modules
Gyroscope gyro; // Create an object to work with Gyroscope
// Time Variables
unsigned long starttime;
unsigned long endtime;
float dt;
int ticker = 0;
bool firstcall=true; // Indicator of a first iteration
// Angle Variables
float gyro_rateX, gyro_rateY, gyro_rateZ;
float Pitch=0;
float Roll=0;
float Yaw=0;
void setup ()
{
Serial.begin (9600); // Open the serial port
Serial.println ("Begin init ..."); // Display a message on the beginning of the initialization
gyro.begin (); // Initialize the gyroscope at 100Hz Output Data Rate
gyro.setRange(RANGE_2000); // set the gyroscope at 2000 dps range sensitivity
Serial.println ("Init completed"); // Display a message about the successful initialization
Serial.println ("Gyroscope");
}
void loop ()
{
endtime = micros(); // End time for the current Measurement
if (firstcall)
{
firstcall=false;
}
else
{
dt = (float)(endtime - starttime)/1000000; // Get time beetween measurements
gyro_rateX=gyro.readX_DegPerSec(); // Current Angle rate around the X-axis
gyro_rateY=gyro.readY_DegPerSec(); // Current Angle rate around the Y-axis
gyro_rateZ=gyro.readZ_DegPerSec(); // Current Angle rate around the Z-axis
Pitch += 1 * gyro_rateX * dt; // Current Angle around the X-axis
Roll += 1 * gyro_rateY * dt; // Current Angle around the Y-axis
Yaw += 1 * gyro_rateZ * dt; // Current Angle around the Z-axis
delay (10);
}
starttime = micros(); // Start time for the next Measurement
if (ticker > 30) // Print Message every 300 ms
{
ticker=0;
Serial.print (Roll); // Output angular velocity around the axis X
Serial.print ("\t");
Serial.print (Pitch); // Output of the angular velocity around the Y axis
Serial.print ("\t");
Serial.print (Yaw); // Output of the angular velocity about the Z axis
Serial.print ("\t");
Serial.println ("");
}
else {ticker++;}
}
如果让IMU传感器保持不动,您将会看到漂移现象(图22)。
如上所述,由于有漂移的趋势,总和将会随着时间的增加产生误差。但我们可以通过计算和利用零速率电平来缓解漂移带来的影响。
有关零速率电平的定义在陀螺仪数据表的“2.6.2 零速率电平”一节中有详细描述。有这一现象的主要原因是在IMU上施加的机械应力,例如,在印刷电路板上焊接之后残留的应力。当有了机械应力之后,零速率电平会随温度略有改变,所以这一变化也许就可以被忽略了。
您可以点击此处查看在新版本IMU库中的执行细节。
经过这些强化后,我们就可以使用陀螺仪数据了,但是只能短期使用。
我们仍需要在长时间内能够保持稳定的信息。加速度计是一种测量加速度的设备。通过使用加速度计,我们可以根据计算获得的重力矢量来确定传感器工作平面的角度。但是,使用智能手套时,传感器将测量所有其他加速度,包括手臂的运动,这可能会破坏所测量的重力矢量。
低通滤波器可用于从随机加速度中过滤掉重力矢量。加速度计的测量值只适用于长期使用。
将传感器数据融合的最常见方法之一是使用功能强大的Kalman滤波器(很难理解,也很难在Arduino上实现)。
我们使用互补滤波器作为整合IMU数据的解决方案,这种滤波器非常易于理解,且容易在Arduino上实现。互补滤波器基本原理如下:
其中,Roll_i – 上一次迭代中计算出的横滚角
gyroRoll_i+1 –基于最近一次陀螺仪数据进行的最近一次测量所得到的角度变化
accelRoll_i+1 –基于最近一次的加速度计数据计算出的横滚角
Roll_i+1 –最新计算得到的带有互补滤波器的横滚角
该滤波器可以在短期内利用陀螺仪的动态特性,并通过加速度计数据在长期内消除误差。您可以自己进行测试,只需在Arduino IDE中打开imu_2.ino并将其上传到您的Arduino IDE即可。
更新信息发送端
当我们获取测量数据时,必须使用无线蓝牙连接来将数据传送到PC。
首先,检查Bluetooth Bee是否已正确配置。将Bluetooth Bee安装在Xbee USB适配器上,将Bluetooth Bee换为AT模式,然后使用“AT+UART?”指令检查UART配置。Bluetooth Bee应返回“115200,0,0”(波特率115200位/秒,一个停止位,无奇偶校验位)。如果不是,请发送“AT+ UART=115200,0,0”指令来配置Bluetooth Bee,然后再次检查UART配置。检查后不要忘记关闭AT模式!
另外需要注意的是位于无线SD扩展板上的“串行选择”开关,该开关将指定将无线连接所读取的数据发送到何处。
将其切换到MICRO位置。当处于MICRO位置时,蓝牙模块会连接到Arduino。请注意,Arduino仍连接到USB串口转换器。如果您从Arduino将数据写入串行端口,数据将会以两种方式发送:USB传送和无线传送。
将messaging.ino上传到Arduino。请注意,每次打开或重置Arduino时,它都会通过三个步骤进行校准:
陀螺仪零速率电平计算;
测量手指位置最小值;
测量手指位置最大值。
在计算陀螺仪零速率电平之前,请保持IMU静止不动。在测量手指位置最小值之前,请戴上Arduino手套并握紧拳头。在测量手指最大位置之前,请戴上Arduino手套并松开拳头。
在Arduino IDE中打开messaging.ino并将其上传到您的Arduino UNO中。
关闭Arduino电源,然后将Bluetooth Bee放置在无线扩展板上。请确保Bluetooth Bee不在AT模式下,并且将无线扩展板串行选择开关切换到MICRO位置。
用9V电池为Arduino Uno供电,并使用“1234”作为密码与您的Bluetooth Bee配对。确认配对成功后,您可以在设备管理器中找到您的无线蓝牙连接作为虚拟COM端口。
从项目浏览器窗口中打开 Messaging.lvproj LabVIEW项目和 Messaging Test.vi。选择相关COM端口并运行。
您将会看到Arduino Uno在串行端口中写入的数据已通过蓝牙传输,并从虚拟COM端口中读取。
添加Kinect测量
表面上看,Kinect 是一款Xbox 360游戏设备控制器,可替代常见的游戏杆。实际上,它是一个功能强大的运动捕捉控制器,可获取您的姿态信息,并使您可以用手或者身体来控制游戏过程。虽然这个设备是为了游戏而开发的,但也可以在实际生活中使用。
想要在LabVIEW环境中使用用于Xbox 360的Kinect,您需要安装以下软件:
- Microsoft Kinect SDK 1.5 (适用于Windows SDK v1.5的Kinect)
- Microsoft .NET 4.0 Framework (Microsoft .NET Framework 4 (独立安装程序))
- 适用于Microsoft Kinect的Kinesthesia LabVIEW工具包
从项目浏览器窗口中打开 Kinect.lvproj LabVIEW Project和 Kinect Test.vi ,然后运行。如果正确安装了所有要求的软件,您将看到类似以下内容的视频和Kinect处理结果:
整合所有内容
现在,我们需要把所有内容整合到一个应用程序中。
打开 Arduino Gloves.lvproj LabVIEW Project。然后从项目浏览器窗口打开 Host Main.vi 。为左右手套蓝牙连接选择相应的COM端口。插入Kinect,并确保可以使用。
然后戴上Arduino蓝牙手套并打开电源,为校准提供所需要的必要条件。
之后,运行 Host Main.vi ,您将会看到以下内容:
请确认对每个手指的弯曲度进行了准确的测量,并且横滚角、俯仰角和偏航角与您的手的实际姿势相对应。
机器人控制
Arduino蓝牙手套在现实生活中的机器人控制应用领域很有用。所有处理过的数据都可以通过UDP信息传输到任何第三方应用程序中。
我们选择工业机器人手臂的模拟器—UDPPuma560 作为第三方应用程序的示例,同时添加了UDP接收器环路。 从项目浏览器窗口打开 Puma560 Simulator.lvproj, Host Main.vi 以及 Puma560 Simulator.vi 。
为左右手套蓝牙连接选择相应的COM端口。插入Kinect并确保可以使用。
然后戴上Arduino蓝牙手套并打开电源,并为校准提供所需的必要条件。
运行完这两个VI后,您将会得到以下结果:
请注意,您必须对从智能手套获取的数据进行正确的解译,而不应该直接使用没有经过任何处理的数据。例如,操作员的右手坐标不可能与机器人的手臂夹持器相同,所以您需要将测量数据从操作员的坐标系转换为机器人的坐标系。
演示: