神念TGAM模块的脑电波应用

  • 前言
  • 前期准备
    • 网上收集TGAM模块的资料
    • 了解蓝牙
  • 项目架构
    • 理想级架构
    • 现实级架构
  • 代码讲解
    • 脑电波接收端
    • 树莓派控制端
  • 结尾

前言

接触TGAM脑电波模块是在年初的时候。刚好临近毕业,指导老师找到了我,想让我加入他负责的毕业课题。在此之前有用过Tensorflow做过一个菜品识别的小程序,当时第一步的构思就是收集大量的脑电波数据,用TF训练机器学习模型,但是后来因为考HCIE跟公司项目的事情耽搁了几个月,又临近了毕业答辩,就只是简单的利用了TGAM模块收集到的专注值跟放松值对灯泡进行了一个简单的控制。

前期准备

网上收集TGAM模块的资料

网上介绍TGAM的模块的资料实在是太少了,找了挺久的,找到了一个“基于神念TGAM的脑波小车”的项目,链接如下:https://www.cnblogs.com/fangyuanjili/archive/2018/04/01/8687844.html 。这个项目对TGAM模块发送过来的包的讲解非常的详细。接下来就是进行解包操作,还是由于时间问题,解包的步骤是参考这个老哥的,链接如下:https://blog.csdn.net/y786256773/article/details/80167900

了解蓝牙

刚好公司的上一个项目是一个蓝牙控制器的小程序,手里有一些蓝牙模块,了解了一下蓝牙的工作原理。主要是手贱,把模块给弄坏了,用某宝的物品识别竟然找到了相同型号的SPP模块,艰难的手动焊了一个上去,完美修复。(滑稽)

ps:接收端是用的千月的蓝牙适配器(有点想吐槽)

项目架构

理想级架构

现实级架构

不放了,放了丢人

代码讲解

整个项目分:脑电波接收端、树莓派控制端.

脑电波接收端

脑电波接收端用了pyqtgraph库,用于显示脑波数据跟专注值/放松值

//数据显示
class ShowThread(threading.Thread):def __init__(self, parent=None):super(ShowThread, self).__init__(parent)self.is_started = threading.Event()self.win = pg.GraphicsWindow(title="脑电波")self.win.resize(1000, 600)self.win.setWindowTitle('脑电波检测值')pg.setConfigOptions(antialias=True)self.p2 = self.win.addPlot(title="专注值(蓝色)/放松值(绿色)")self.p6 = self.win.addPlot(title="脑电波值")self.curve = self.p6.plot(pen='y')self.curve2 = self.p2.plot(pen=(0, 255, 0), name="放松值")self.curve3 = self.p2.plot(pen=(0, 0, 255), name="专注值")self.ptr = 0self.ptr2 = 0def run(self):while True:self.curve.setData(data)self.curve2.setData(data2)self.curve3.setData(data3)self.is_started.wait(timeout=0.2)
//接收eeg数据
class EEGThread(threading.Thread):def __init__(self, parent=None):super(EEGThread, self).__init__(parent)self.ip = "http://192.168.43.10"self.com = "COM9"self.bps = 57600self.vaul = []self.is_open = Falseself.is_close = Truedef checkList(self,list,num):list_num = 0for i in list:if i > num:list_num += 1return list_num//检测接收的eeg信号包中的delta值是否持续大于200,此方法是我写的一个粗糙的检测眨眼等生物电流的算法,当监测到之后执行关灯操作def checkEeg(self):old_num = 0delta_num = 0for old in old_data:if self.checkList(old,200)>5:old_num += 1delta_num =self.checkList(delta_data, 50000)if old_num > 3 and delta_num > 4:return Trueelse:return Falsedef run(self):global data,data2,data3,old_data,delta_datatry:t = serial.Serial(self.com, self.bps)b = t.read(3)requests.get(self.ip + "/gpio", params={"oper": "startr"})print(str(time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time())))+"脑电波设备配对中")while b[0] != 170 or b[1] != 170 \or b[2] != 4:b = t.read(3)if b[0] == b[1] == 170 and b[2] == 4:print(str(time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time())))+"配对成功。")requests.get(self.ip+"/gpio", params={"oper": "startb"})a = b + t.read(5)if a[0] == 170 and a[1] == 170 and a[2] == 4 and a[3] == 128 and a[4] == 2:while 1:try:a = t.read(8)sum = ((0x80 + 0x02 + a[5] + a[6]) ^ 0xffffffff) & 0xffif a[0] == a[1] == 170 and a[2] == 32:y = 1else:y = 0if a[0] == 170 and a[1] == 170 and a[2] == 4 and a[3] == 128 and a[4] == 2:p = 1else:p = 0if sum != a[7] and y != 1 and p != 1:b = t.read(3)c = b[0]d = b[1]e = b[2]while c != 170 or d != 170 or e != 4:c = dd = ee = t.read()if c == (b'\xaa' or 170) and d == (b'\xaa' or 170) and e == b'\x04':g = t.read(5)if c == b'\xaa' and d == b'\xaa' and e == b'\x04' and g[0] == 128 and g[1] == 2:a = t.read(8)breakif a[0] == 170 and a[1] == 170 and a[2] == 4 and a[3] == 128 and a[4] == 2:high = a[5]low = a[6]rawdata = (high << 8) | lowif rawdata > 32768:rawdata = rawdata - 65536sum = ((0x80 + 0x02 + high + low) ^ 0xffffffff) & 0xffif sum == a[7]:self.vaul.append(rawdata)if sum != a[7]:b = t.read(3)c = b[0]d = b[1]e = b[2]while c != 170 or d != 170 or e != 4:c = dd = ee = t.read()if c == b'\xaa' and d == b'\xaa' and e == b'\x04':g = t.read(5)if c == b'\xaa' and d == b'\xaa' and e == b'\x04' and g[0] == 128 and g[1] == 2:a = t.read(8)breakif a[0] == a[1] == 170 and a[2] == 32:c = a + t.read(28)delta = (c[7] << 16) | (c[8] << 8) | (c[9])# print(delta)data = self.vaulold_data.append(data)if len(old_data) > 10:old_data = old_data[-10:]delta_data.append(delta)if len(delta_data) > 10:delta_data = delta_data[-10:]flag = self.checkEeg()data2.append(c[32])if len(data2) > 20:data2 = data2[-20:]data3.append(c[34])if len(data3) > 20:data3 = data3[-20:]if self.is_open and flag and not self.is_close:print(str(time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time())))+"关闭灯成功")requests.get(self.ip+"/gpio", params={"oper": "stopall"})# requests.get(self.ip + "/gpio", params={"oper": "startr"})self.is_close = Trueself.is_open = Falseif c[32] > 70 and not self.is_open and self.is_close and not flag:print(str(time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time())))+"开启灯成功")requests.get(self.ip+"/gpio", params={"oper": "startg"})requests.get(self.ip+"/gpio", params={"oper": "start"})self.is_open = Trueself.is_close = Falseself.vaul = []except Exception as e:# print(e)sse =1except Exception as e:# print(e)sse = 1

树莓派控制端

树莓派利用GPIO串口对led灯进行开关操作,led灯泡一头接gnd,一头接入程序设定的串口上,这里我做了指示灯跟照明灯,使用flask框架向外提供url接口

//flask设置的路由
api.add_resource(GPIORoute, '/gpio')
class GPIORoute(Resource):def get(self):try:self.parser = reqparse.RequestParser()self.parser.add_argument('oper', type=str, help='status: type is str')self.args = self.parser.parse_args()self.oper = self.args['oper']if self.oper == "start":gpio.jox_start("LED")elif self.oper == "stop":gpio.jox_stop("LED")elif self.oper == "startr":oper=""gpio.jox_start("RED")elif self.oper == "startg":gpio.jox_start("GREEN")elif self.oper == "startb":gpio.jox_start("BULE")elif self.oper == "stoprgb":gpio.jox_stop("RGB")elif self.oper == "stopall":gpio.jox_stop("LED")gpio.jox_start("RED")elif self.oper == "exit":gpio.jox_exit()except Exception as e:print(e)return "erro"

//控制GPIO串口的线程类,这里使用的是13、19、26串口
class GPIO(Thread):def __init__(self):Thread.__init__(self)self.LED = 15self.SLEDR,self.SLEDG,self.SLEDB =13,19,26RPi.GPIO.setmode(RPi.GPIO.BCM)RPi.GPIO.setup(self.LED, RPi.GPIO.OUT)self.pwm = RPi.GPIO.PWM(self.LED, 70)self.pwm.start(0)RPi.GPIO.setup(self.SLEDR, RPi.GPIO.OUT)RPi.GPIO.setup(self.SLEDG, RPi.GPIO.OUT)RPi.GPIO.setup(self.SLEDB, RPi.GPIO.OUT)self.pwmR = RPi.GPIO.PWM(self.SLEDR, 70)self.pwmG = RPi.GPIO.PWM(self.SLEDG, 70)self.pwmB = RPi.GPIO.PWM(self.SLEDB, 70)self.pwmR.start(0)self.pwmG.start(0)self.pwmB.start(0)def jox_start(self,jox_type):print(jox_type+":start")try:  if jox_type == "LED":self.led_exit = Event()self.pwm.ChangeDutyCycle(100)elif jox_type == "RED":self.pwmR.ChangeDutyCycle(100)self.pwmG.ChangeDutyCycle(0)self.pwmB.ChangeDutyCycle(0)elif jox_type == "GREEN":self.pwmR.ChangeDutyCycle(0)self.pwmG.ChangeDutyCycle(100)self.pwmB.ChangeDutyCycle(0)elif jox_type == "BULE":self.pwmR.ChangeDutyCycle(0)self.pwmG.ChangeDutyCycle(0)self.pwmB.ChangeDutyCycle(100)except Exception as e:print(e)def jox_stop(self,jox_type):print(jox_type+":stop")try:if jox_type == "LED":self.pwm.ChangeDutyCycle(0)elif jox_type =="RGB":self.pwmR.ChangeDutyCycle(0)self.pwmG.ChangeDutyCycle(0)self.pwmB.ChangeDutyCycle(0)except Exception as e:print(e)def jox_exit(self):try:RPi.GPIO.cleanup()except Exception as e:print(e)

结尾

写得有点菜,欢迎各位大佬指正,github地址:https://github.com/jon-son/jox-egg

神念TGAM模块+树莓派GPIO控制灯泡(脑电波控制物联网应用示例)相关推荐

  1. #小车记4--树莓派 GPIO PWM 实现初步控制

    树莓派 GPIO PWM 实现初步控制 写在前面的废话 1.L298N与树莓派的连线 2.Python 编程控制 (1).GPIO (2).PWM 写在前面的废话 有兴趣的读者,可以去看看本人主页里的 ...

  2. python控制树莓派led_Python 控制树莓派 GPIO 输出:控制 LED 灯

    树莓派 GPIO 控制输出的入门应该都是从控制 LED 灯开始的吧. 树莓派版本:Model 3B+ 树莓派系统:Raspbian Stretch with desktop and recommend ...

  3. python控制灯_Python 控制树莓派 GPIO 输出:控制 LED 灯

    树莓派 GPIO 控制输出的入门应该都是从控制 LED 灯开始的吧. 树莓派版本:Model 3B+ 树莓派系统:Raspbian Stretch with desktop and recommend ...

  4. python控制树莓派gpioled,Python 控制树莓派 GPIO 输出:控制 LED 灯

    树莓派 GPIO 控制输出的入门应该都是从控制 LED 灯开始的吧. 树莓派版本:Model 3B+ 树莓派系统:Raspbian Stretch with desktop and recommend ...

  5. Linux学习~树莓派gpio控制

    WiringPi 是应用于树莓派平台的 GPIO 控制库函数,WiringPi 遵守 GUN Lv3.wiringPi 使用 C 或者 C++ 开发并且可以被其他语言包转,例如 Python.ruby ...

  6. 树莓派GPIO控制/使用的教程

    树莓派GPIO控制/使用的教程 介绍 使用说明 (一)导入库 (二)设置编码规范 (三)引脚设置 (四)电平控制 (五)读取引脚的输入状态 (六)释放GPIO资源 (七)示例代码 (八)PWM设置 一 ...

  7. 树莓派GPIO和PWM控制教程

    树莓派GPIO和PWM 1. 目的 在汽车电子开发中,CAN通讯是很难避开的一个技术点,当前CAN已经形成了行业内较为稳定的开发及相关测试验证方法,其中一种较为主流的就是使用CANoe和开发相应的CA ...

  8. 树莓派 GPIO 控制

    常用开源工程简介 树莓派内核中已经编译自带了 gpio 的驱动,我们常通过一些第三方写好的库函数来完成具体的操作,比较常见的操作库函数有: python GPIO 开发语言--python 简单介绍- ...

  9. 实例2:树莓派GPIO控制外部LED灯闪烁

    实例2:树莓派GPIO控制外部LED灯闪烁 实验目的 通过背景知识学习,了解四足机器人mini pupper搭载的微型控制计算机:树莓派. 通过树莓派GPIO操作的学习,熟悉GPIO的读写控制. 通过 ...

  10. [RPi]树莓派GPIO入门之控制LED灯

    本文部分资料及图片来自网络 一.所需材料 树莓派4B.LED灯.面包板.杜邦线.电阻.Python程序 二.认识硬件材料 这里介绍下LED灯.面包板.杜邦线.电阻 LED灯:LED灯引脚长的一端为正极 ...

最新文章

  1. C言语for轮回语句
  2. 永洪Desktop安装——windows版
  3. Python提升“技术逼格”的6个方法
  4. 【线段树 泰勒展开】Codechef April Challenge 2018 Chef at the Food Fair
  5. 怀孕参加计算机考试有辐射吗,电脑辐射对孕妇的影响大不大 会对胎儿造成什么影响...
  6. 美团点评酒店后台故障演练系统
  7. java runnable 启动_Java多线程:线程的创建与启动
  8. 英语总结系列(二十一):英语也能玩出新花样
  9. JS判断用户手机是IOS还是Android
  10. mysql 在线优化工具_MySQL SQL查询优化工具EverSQL
  11. aforge 相机标定_在C#和WPF中使用Aforge.NET获取网络摄像头流
  12. 工业企业能源管理系统
  13. CAD、mapgis、excel转换为coreldraw技巧方法-来自《地球科学》姚戈
  14. 学习笔记:android下获取sdcard容量大小
  15. 关于Raft的一些问题解答
  16. linux海报制作软件,春节海报制作素材平台-春节海报一键制作app下载v1.0.0-Linux公社...
  17. linux设备模型一(基础知识)
  18. 你是真的“C”——宏与函数的英雄本色
  19. nb-iot_IoT项目:Arduino使用Parse.com的Temboo向Android发送推送通知
  20. 高效开发PHP的5款编辑器

热门文章

  1. 设计模式(讲的比较好-思路清晰,非泛泛而谈)
  2. NPR——卡通渲染(二)
  3. DCGAN生成动漫人物头像---pytroch版
  4. recover-quack-data-structure
  5. android之银行卡手机号码自动补齐空格
  6. 《Photoshop 2020从入门到精通》读书笔记1
  7. 是 jsv 而不是 jsx:这可能是尤雨溪更想要的vue代码编写方式
  8. 八股文-ArrayList
  9. learn the python in hard way习题16~20的附加习题
  10. 李白打酒加强版(dp)