你想用你的思想来控制事物吗?这个教程描述了如何使用脑电波驾驶遥控卡车。耳机感应到我的脑电波并将它们传输到一台小型计算机。当我提高注意力或眨眼时,计算机会转换信号并将它们传递给卡车的遥控器,我已将其连接到计算机。当我集中注意力时,车轮会旋转。0ne 强烈的眨眼左转。强烈的双眨眼会右转。
耳机是NeuroSky MindWave Mobile 2,电脑是Arduino Uno微控制器,蓝牙模块是HC-05。
一些开发人员已经应用这些想法来帮助瘫痪的人;例如,驾驶轮椅、家庭自动化或在屏幕上选择字母和单词以便在屏幕上或通过语音进行交流。他们的项目可以在 YouTube 上找到。
这个项目有5个主要步骤:
在开始我的项目之前,我在 Internet 上搜索了 NeuroSky 项目,以了解开发人员选择使用哪些脑电波信号。许多项目只使用了注意力和冥想级别,还有一些项目还使用了眨眼。在我的项目中,我决定使用注意力级别来控制向前和停止行驶,单闪左转或双闪右转。
有一个项目采用了非常不同的方法:当用户眨眼时,软件开始循环向前、向后、向左、向右,每个循环 2 秒。如果用户眨了两下眼,那么车辆就会在那个瞬间朝自行车所在的任何方向行驶。这种方法提供了很大的灵活性,但可能会很慢。例如,如果用户右转,他们将无法左转大约 6 秒,
一些开发人员通过蓝牙将他们的 NeuroSky MindWave Mobile 直接连接到 Arduino 板,这是我决定做的。这种方法比下一种方法更容易(如下所述),但检测到眨眼需要更长的时间(略超过 1 秒)。这对我的项目来说没问题。
其他开发人员通过计算机或智能手机对信号进行实时预处理,然后将数据发送到 Arduino。这允许进行更复杂的分析或处理,并且可以更快地检测到眨眼(大约半秒)。NeuroSky 在这个网站上有关于这种方法的教程,适用于 PC Windows、Apple Mac OSX、Android 和 IOS:我决定不使用这种方法,因为它需要学习如何在计算机或智能手机上对软件进行编程。
最大化注意力水平的方法因人而异。以下是一些建议:
眨眼需要很强才能被检测到。正常的眨眼被忽略。
头部应保持静止,以避免错误的眨眼检测。在这个项目中检测眨眼的方法包括检查从耳机接收到的信号的质量。强烈的眨眼会使前额的皮肤移动,从而降低信号的质量,这被解释为眨眼。如果头部移动,耳机的传感器可能会轻微移动,从而降低信号质量,这将被识别为眨眼。
这种检测眨眼的方法不使用大脑的神经信号。我的理解是 NeuroSky 的计算机/智能手机方法可以。
有关详细信息,请查看我之前的一个项目中的步骤 1 和 2:
有两种方法可以将 Arduino 连接到卡车的遥控器:
遥控器可能被黑客攻击如下:移除或绕过由控件推动的开关,然后将 Arduino 连接到控制器的电路板并对 Arduino 进行编程以在适当的电线上施加电压。我的遥控器中的开关非常小,以至于我认为尝试将新电线焊接到电路板上的适当位置太棘手了。如果我犯了一个小错误,董事会可能会被毁掉。
我使用伺服系统来移动控件。将伺服系统连接到遥控器上被证明是一个“有趣”的挑战,但现在一切正常。
幸运的是,经过一些切割和装配后,有一个大小合适的小塑料盒可以将伺服系统连接到卡车的遥控器上。尺寸为 2-56 的螺母和螺栓将盒子的各个部分固定在一起。两个螺丝将盒子固定在遥控器上。
左/右控制的伺服臂末端有一个小凹口,给它一些摆动空间。伺服臂的中心不太可能与控制中心完全对齐。固定该臂末端的螺钉需要稍微松动。
为了连接左/右舵机,我使用了 2-56 尺寸的螺母和螺栓,并且不得不稍微扩大舵机上的螺栓孔。实心线将 Go/Stop 伺服固定到位。
电路如图所示,描述如下:
该代码具有以下主要功能:
Arduino 草图(代码)可以从该项目中包含的.ino 文件中下载,或者可以将以下代码复制并粘贴到新的 Arduino 草图中。(在编写这些指令时,instructables 系统有时会删除位于代码开头的部分#include 语句。第一个应该是#include 后跟左箭头 < 后跟 Servo.h 后跟右箭头 > 和第二个应该是#include,后跟左箭头<,然后是Mindwave.h,然后是右箭头>)。
草图使用一个特殊的库,必须在运行草图之前安装。
这个项目可以不使用库来完成,但是代码会更复杂。从耳机读取数据、提取注意力级别和检查信号质量的代码在本网站包含的示例代码中:
草图应该可以成功编译,但可能会显示 MindWave.cpp 库的警告消息。这可能会被忽略。
//
// 草图使用大脑的注意力水平进行 Go/Stop 和
// 转弯时眨眼。
//
// 硬件:Arduino Uno、HC-05 蓝牙、NeuroSky MindWave Mobile 2。
// 高度关注 = 绿色 LED 亮(开始);低 Att = 绿色 LED 熄灭(停止)。
//第一次闪烁&左转=黄色LED;双闪 = 红色 LED(右)。
// 左右转为 2 秒。
// 信息显示在串行监视器上。
//
#include
#include
思维波思维波;
#define YLED 2 // 定义 LED 引脚
#define GLED 4
#定义 RLED 7
伺服myservoG;// 开始/停止伺服
伺服myservoLR;//左/右舵机
int gosignal = 0; // 走或停指标
int 闪烁信号 = 0; // 第一次闪烁后的信号计数器
int 闪烁 = 0; // 一组闪烁次数
长时间未签名;// 经过时间的变量
无符号长时间0;// 第一次闪烁时间的变量
无符号长时间1;// 从第一次闪烁到第二次闪烁的时间变量
无效设置(){
Serial.begin(MINDWAVE_BAUDRATE);
pinMode(13,输出);// 将 LED 引脚初始化为输出
pinMode(GLED,输出);
pinMode(YLED,输出);
pinMode(RLED,输出);
myservoG.attach(9); // 将 Go/Stop 伺服连接到引脚 9
myservoG.write(90); // 将舵机移动到中点
myservoLR.attach(10); // 将左/右伺服器连接到引脚 10
myservoLR.write(90); // 将舵机移动到中点
延迟(15);// 给伺服时间移动到那里
}
无效 onMindwaveData() {
if (mindwave.quality() < 90) { // 如果质量差,板载 LED 亮起
数字写入(13,高);
} 别的 {
数字写入(13,低);
}
// 检查注意力等级
if ((mindwave.attention() > 70) && (gosignal == 0)) {
Serial.print("Go, ");
Serial.print("\注意:");
Serial.print(mindwave.attention());
时间=毫秒();
Serial.print("\ttime:");
序列号。打印(时间);
序列号.println();
数字写入(GLED,高);// 绿色 LED 亮
信号 = 1; // 表示去
myservoG.write(130); // 机器人前进的伺服
延迟(4000);// 在检查前等待 4 秒
// 如果注意力下降
}
if ((mindwave.attention() < 70) && (gosignal == 1)) {
Serial.print("停止, ");
Serial.print("\注意:");
Serial.print(mindwave.attention());
时间=毫秒();
Serial.print("\ttime:");
序列号。打印(时间);
序列号.println();
数字写入(GLED,低);// 绿色 LED 熄灭
信号 = 0; // 表示停止前进
myservoG.write(90); // 机器人停止伺服
延迟(15);
}
// 第一次闪烁
if ((mindwave.quality() < 95) && (blinksignal == 0)) {
Serial.print("第一次闪烁");
Serial.print("\tquality:");
Serial.print(mindwave.quality());
时间=毫秒();
Serial.print("\ttime:");
序列号。打印(时间);
Serial.print("\tgosignal:");
Serial.print(gosignal);
Serial.print("\tblinksignal:");
串行打印(闪烁信号);
序列号.println();
time0 = 毫秒();
眨眼 = 1;
闪烁信号 = 1;// 第一次闪烁
数字写入(YLED,高);// 黄色 LED 亮
}
// 闪烁后立即显示质量,并增加计数器
// 来自耳机的信号
if ((blinksignal > 0) && (blinksignal < 4)) {
Serial.print("\tquality:");
Serial.print(mindwave.quality());
时间=毫秒();
Serial.print("\ttime:");
序列号。打印(时间);
Serial.print("\tgosignal:");
Serial.print(gosignal);
Serial.print("\tblinksignal:");
串行打印(闪烁信号);
序列号.println();
如果(闪烁信号> 0){
闪烁信号 = 1 + 闪烁信号;// 增加信号计数器
}
time1 = millis() - time0;
}
// 双闪?
if ((mindwave.quality()<95) && (time1 > 1200)){
Serial.print("\tquality:");
Serial.print(mindwave.quality());
时间=毫秒();
Serial.print("\ttime:");
序列号。打印(时间);
Serial.print("\tgosignal:");
Serial.print(gosignal);
Serial.print("\tblinksignal:");
串行打印(闪烁信号);
Serial.print("\ttime1:");
序列号.print(time1);
Serial.print("\tblinks now = 2");
序列号.println();
眨眼 = 2;
}
// 单闪左转
if ((blinks == 1) && (blinksignal > 3)) {
Serial.print("左, ");
Serial.print("\t单闪");
时间=毫秒();
Serial.print("\ttime:");
序列号。打印(时间);
Serial.print("\tgosignal:");
Serial.print(gosignal);
Serial.print("\tblinksignal:");
串行打印(闪烁信号);
序列号.println();
闪烁信号 = 0; // 为下一次闪烁重置
// 机器人左转轮子 2 秒的代码
myservoLR.write(55);
延迟(2000);
数字写入(YLED,低);// 黄色 LED 熄灭
// 机器人将车轮从左转直的代码
myservoLR.write(90);
延迟(15);
}
// 双闪右转
if ((blinks == 2) && (blinksignal > 3)) {
Serial.print("对,");
Serial.print("\t双闪");
时间=毫秒();
Serial.print("\ttime:");
序列号。打印(时间);
Serial.print("\tgosignal:");
Serial.print(gosignal);
Serial.print("\tblinksignal:");
串行打印(闪烁信号);
序列号.println();
数字写入(RLED,高);// 如果右转,红色 LED 亮
数字写入(YLED,低);// 黄色 LED 熄灭
闪烁信号 = 0; // 为下一次闪烁重置
// 机器人右转轮子 2 秒的代码
myservoLR.write(120);
延迟(2000);
数字写入(RLED,低);// 红色 LED 熄灭
// 机器人从右转直的代码
myservoLR.write(90);
延迟(15);
}
}
无效循环(){
mindwave.update(串行,onMindwaveData);
}
将草图上传到 Arduino 后,它可以使用单独的电源,而不是通过 USB 连接到计算机。唯一的区别是没有串行监视器来显示数据。步骤如下:
如果你的 HC-05 的固件是 2 或 3 版本,我的理解是在 AT+INQ 命令之前需要 AT+INIT 命令。我的HC-05的固件是4.0-20190815版本,AT+INIT命令不识别。要检查 HC-05 的版本,请输入以下命令:AT+VERSION
如果您按下 Arduino 的重置按钮,这会将 HC-05 的设置恢复为出厂默认设置。必须重复所有配对步骤。
如果在上传草图之前 HC-05 的 TXD 未与 Arduino 的 RX 断开连接,则会在计算机屏幕上 Arduino 应用程序窗口的底部出现错误消息。以下错误消息重复 10 次:avrdude: stk500_recv(): 程序员没有响应avrdude: stk500_getsync() 尝试 1 of 10: not in sync: resp=0x00
使用舵机时,需要单独的电源,例如 3 节 1.5 伏电池。Arduino 的 GND 必须连接到外部电源的负极。如果没有外部电源,USB 源的电源似乎不足,并且 HC-05 会在伺服激活时失去配对。它在几秒钟后配对,然后在下次伺服激活时取消配对。
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
全部0条评论
快来发表一下你的评论吧 !