第一部分:模块原始数据

拿到模块,在网上查了一圈,发现基本没什么有用的资料,很多都是一些相关但是没有实际价值的东西。许多论文都是再谈怎么去做,而没有实实在在的去完成这么一个过程。

废话不多说,直接步入正题。

昨天在网上才发现这个软件,据评论说是这款串口软件很好用。

RealTerm的下载地址https://realterm.sourceforge.io/

这是通过单片机的232通信例程直接接收得到的原始数据,也就是参考手册中的数据流。其中小包数据,是每秒512个大概,大包数据是每秒1个。

小包的格式是AA AA 04 80 02 xxHigh xxLow xxCheckSum前面的AA AA 04 80 02 是不变的,后三个字节是一只变化的,xxHigh和xxLow组成了原始数据rawdata,xxCheckSum就是校验和。所以一个小包里面只包含了一个对开发者来说有用的数据,那就是rawdata,可以说一个小包就是一个原始数据,大约每秒钟会有512个原始数据。
      从小包中解析出原始数据:

rawdata = (xxHigh << 8) | xxLow;if(rawdata > 32768){   rawdata ­=65536;  }

根据手册,在计算原始数据之前,要先检查检验和:

sum = ((0x80 + 0x02 + xxHigh + xxLow)^ 0xFFFFFFFF) & 0xFF。

就是把头文件AA AA 04后面的四个数据加起来,取反,在取低八位。当检验码不对时,直接丢弃该包。

在大包数据里面可以解析Signal,Attention,Meditation和8个EEG的信号值,大包的格式是固定的:

AA 同步
AA 同步
20 是十进制的32,即有32个字节的payload,除掉20本身+两个AA同步+最后校验和
02 代表信号值Signal
C8 信号的值
83 代表EEG Power开始了
18 是十进制的24,说明EEG Power是由24个字节组成的,以下每三个字节为一组
18 Delta 1/3
D4 Delta 2/3
8B Delta 3/3
13 Theta 1/3
D1 Theta 2/3
69 Theta 3/3
02 LowAlpha 1/3
58 LowAlpha 2/3
C1 LowAlpha 3/3
17 HighAlpha 1/3
3B HighAlpha 2/3
DC HighAlpha 3/3
02 LowBeta 1/3
50 LowBeta 2/3
00 LowBeta 3/3
03 HighBeta 1/3
CB HighBeta 2/3
9D HighBeta 3/3
03 LowGamma 1/3
6D LowGamma 2/3
3B LowGamma 3/3
03 MiddleGamma 1/3
7E MiddleGamma 2/3
89 MiddleGamma 3/3
04 代表专注度Attention
00 Attention的值(0到100之间)
05 代表放松度Meditation
00 Meditation的值(0到100之间)
D5 校验和

想要获得某个EEG信号值,只需将相应信号的1/3值左移16位,2/3值左移8位,3/3值不变,然后将他们或运算:

delta=(payload[i]<<16) | (payload[(i+1)]<<8)  | (payload[(i+2)])。

第二部分:串口接收处理

将数据处理移植到STM32上,采用串口的DMA接收模式,注意的是DMA_MODE采用Circular,DMA_BufferSize>(8*512+36=4132)(小包8个字节,每秒512个,完整的大包36个字节)。

代码如下:

void usart_init()
{//声明结构体//GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;//时钟打开//RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);//DMA1时钟//GPIO配置//GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;//TXGPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;GPIO_Init(GPIOA,&GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;//RXGPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;GPIO_Init(GPIOA,&GPIO_InitStructure);//USART配置//USART_InitStructure.USART_BaudRate=57600;USART_InitStructure.USART_WordLength=USART_WordLength_8b;//传送数据长度USART_InitStructure.USART_StopBits=USART_StopBits_1;//停止位长度USART_InitStructure.USART_Parity=USART_Parity_No;//校检USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;//硬件流DMAUSART_InitStructure.USART_Mode=USART_Mode_Tx|USART_Mode_Rx;//接受发送USART_Init(USART1,&USART_InitStructure);USART_Cmd(USART1,ENABLE);
}    //DMA接收//void USART1_DMA_Recv(void){DMA_InitTypeDef DMA_InitStructure;    NVIC_InitTypeDef NVIC_InitStructure;DMA_InitStructure.DMA_PeripheralBaseAddr=(u32)&(USART1->DR);//外设基地址DMA_InitStructure.DMA_MemoryBaseAddr=(u32)&buffer;//内存基地址DMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralSRC;//SRC作为数据传送的来源DMA_InitStructure.DMA_BufferSize=5000;//数据传输长度!!!!!!DMA_InitStructure.DMA_PeripheralInc=DMA_PeripheralInc_Disable;//外设地址不自增DMA_InitStructure.DMA_MemoryInc=DMA_MemoryInc_Enable;//内存地址自增DMA_InitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Byte;//外设数据单位字节DMA_InitStructure.DMA_MemoryDataSize=DMA_PeripheralDataSize_Byte;//内出数据单位DMA_InitStructure.DMA_Mode=DMA_Mode_Circular;//传输模式!!!!!DMA_InitStructure.DMA_Priority=DMA_Priority_High;//优先级DMA_InitStructure.DMA_M2M=DMA_M2M_Disable;//禁止内存到内存传输DMA_Init(DMA1_Channel5,&DMA_InitStructure);DMA_ClearFlag(DMA1_FLAG_TC5);NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);NVIC_InitStructure.NVIC_IRQChannel=DMA1_Channel5_IRQn;NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;NVIC_Init(&NVIC_InitStructure);DMA_ITConfig(DMA1_Channel5,DMA_IT_TC,ENABLE);//DMA1传送完成产生中断USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE);DMA_Cmd(DMA1_Channel5,ENABLE);}void DMA1_Channel5_IRQHandler(void)//中断函数
{  if (DMA_GetITStatus(DMA1_IT_TC5)==1){DMA_ClearITPendingBit(DMA1_IT_TC5); DMA_Cmd(DMA1_Channel5, DISABLE);flag = 1;  //将下面的程序放到main的while中,不然运行容易丢包
//          for(i=0;i<5000;i++)
//              {
//                    parseByte( buffer[i]);
//              }
//          DMA_Cmd(DMA1_Channel5,ENABLE);}
}

这部分代码还需要进一步修改……我们是依靠蓝牙传输信号,在下面会解决如何通信的问题。

下一部分将会讲述当STM3原2接收到始数据后,怎样将它处理后得到signal,attention,meditation和eeg信号的值

第三部分:数据解析

待续……通信协议部分还是比较关键的

第四部分:数据通信

这一部分在我另一篇文章里有示例性的图文介绍

https://blog.csdn.net/seek97/article/details/81333701

我使用的是HC05和BT06俩个蓝牙模块

1、【AT模式】HC05蓝牙模块的PIO11接VCC,上电后即进入HC05AT指令模式,对于BT06蓝牙直接上电进入AT模式,用USBT06转TTL模块连接到电脑的USBT06接口。

2、【打开串口调试助手】开启2个串口调试窗口,一个打开HC05的COM口,一个打开BT06的COM口。【HC05默认波特率一般为38400,BT06默认是9600】.

3、【恢复HC05默认设置】串口调试助手HC05,将HC05恢复默认设置:AT+ORGL【即回车、换行,在串口调试助手上输入一个回车即可】

4、【设置HC05配对码】串口调试助手HC05,配置蓝牙HC05的配对码:AT+PSWD=1234【蓝牙HC05与蓝牙BT06的配对码相同,这样才能成功配对,配对码随意】

5、【设置HC05主模式】串口调试助手HC05,将蓝牙HC05配置为主机模式:AT+ROLE=1

6、【恢复BT06默认设置】串口调试助手BT06,将蓝牙BT06恢复默认设置:AT+ DEFAULT

7、【设置BT06配对码】串口调试助手BT06,配置蓝牙BT06的配对码与蓝牙HC05一致:AT+PIN 1234

8、【设置BT06从模式】串口调试助手BT06,将蓝牙BT06配置为从机模式:AT+ ROLE

9、【 查询BT06地址 】串口调试助手BT06,查询蓝牙BT06的地址:AT+LADDR    【如20:15:02:12:07:58】

10、【蓝牙HC05绑定蓝牙BT06】串口调试助手HC05,蓝牙HC05绑定蓝牙BT06地址:AT+BIND=0101,01,010101

【注意把地址的冒号换成逗号,同时注意这个格式,实验多次,只有这样写,HC05才可以绑定该地址】

11、【设置波特率】根据各自的命令符号修改各自的波特率 HC05:AT+UART=57600,0,0。BT06:AT+BAUD7.

12、【常规工作模式】2个模块断电,重新上电后进入常规工作模式,自动完成配对。之后, HC05就能接收到BT06的数据了。

【注意事项】:确保2个蓝牙模块的配对码(PSWD)相同,都上电后两个模块会自动相连。

【设置蓝牙的连接模式】:默认是:0—指定蓝牙地址连接模式,这样HC05才能自动连接绑定的地址,如果不是模式0,设置为模式0:AT+CMODE=0

第五部分:数据处理

待续……这部分会涉及一些算法,比如BP神经网络模型提速特征值

第六部分:系统控制

待续……这部分比较简单,把小四轴的代码理解完成,也就可以实现控制了。

第七部分:论文写作

待续....这部分应该贯穿于整个项目研究过程,注重将学习成果记录

意念控制四旋翼 学习笔记相关推荐

  1. 视觉SLAM十四讲学习笔记-第六讲-非线性优化的状态估计问题

    专栏系列文章如下: 视觉SLAM十四讲学习笔记-第一讲_goldqiu的博客-CSDN博客 视觉SLAM十四讲学习笔记-第二讲-初识SLAM_goldqiu的博客-CSDN博客 视觉SLAM十四讲学习 ...

  2. 《Real-Time Rendering》第四版学习笔记——Chapter 9 Physically Based Shading(一)

    一.光的物理特性 光与物体的交互形成了基于物理着色的基础. 在物理层面上,光的模型为电磁横波.每个波都有一个单一的波长λ\lambdaλ.具有单一波长的光叫单色光(monochromatic ligh ...

  3. 《Real-Time Rendering》第四版学习笔记——Chapter 9 Physically Based Shading(二)

    上接文章:<Real-Time Rendering>第四版学习笔记--Chapter 9 Physically Based Shading(一) 六.微观几何 每个可见的表面点都包含了很多 ...

  4. C++程序设计教程(钱能)第四章 学习笔记

    C++程序设计教程(钱能)第四章 学习笔记 4.1 名词解释与操作符 4.1.1 名词解释 4.1.2 操作符汇总 4.1.3 操作符的说明 4.2 算数运算问题 4.2.1 周而复始的整数 4.2. ...

  5. [视觉SLAM十四讲]学习笔记2-关于欧拉角和万向锁

    [视觉SLAM十四讲]学习笔记2-关于欧拉角和万向锁 1 欧拉角 1.1 维基百科定义 1.2 ZYX欧拉角与rpy角 2 万向锁 2.1 万向节 2.1 万向锁的产生 1 欧拉角 1.1 维基百科定 ...

  6. [视觉SLAM十四讲]学习笔记1-刚体运动之旋转矩阵与变换矩阵

    [视觉SLAM十四讲]学习笔记1-刚体运动之旋转矩阵与变换矩阵 1点.向量和坐标系 2 坐标系间的欧式变换 2.1 欧式变换之旋转 2.2 欧式变换之平移 3 变换矩阵与齐次坐标 4 Eigen库的简 ...

  7. 《Real-Time Rendering》第四版学习笔记——Chapter 9 Physically Based Shading(三)

    前文: <Real-Time Rendering>第四版学习笔记--Chapter 9 Physically Based Shading(一) <Real-Time Renderin ...

  8. 机电传动控制第二周学习笔记

    机电传动控制第二周学习笔记 经过第二周的学习,我了解了电机的发展历史.从奥斯特发现电生磁的现象,到法拉第电磁回转实验,再到后来的电机一步步的发展至今.它充满了巧合,但是它又必然一步步向更完美走去.电机 ...

  9. 机电传动控制第一周学习笔记

    机电传动控制第一周学习笔记: 1 这一周主要讲述了概论和机电传动控制系统动力学基础两个章节内容. 2 绪论中说明了<机电传动控制>课程主要内容为下图所示: 3机电传动控制系统动力学基础章节 ...

最新文章

  1. 任正非未来出行三谈,在攀登无人驾驶珠峰路上沿途下蛋...
  2. 【封装那些事】 缺失封装
  3. 讯飞输入法皮肤制作_讯飞输入法拍了拍你 粤语专项计划进展神速应用广泛
  4. 报名|第2期“DI极客说”,揭秘决策AI创新应用带来的行业变革
  5. Python数据结构学习笔记——链表:无序链表和有序链表
  6. jQuery Mobile里xxx怎么用呀? (事件篇)
  7. Laravel 使用 Aliyun OSS 云存储
  8. 设计模式 - 依赖倒置原则
  9. spring传播机制注意点
  10. 无法连接iphone软件更新服务器_NX许可证错误:无法连接至许可证服务器系统。SPLM_LICENSE_SERVER错误[15]...
  11. 百度地图POI数据爬取,突破百度地图API爬取数目“400条“的限制11。
  12. 2018年高二计算机试题,2018年上学期高二信息技术期末考试试题.pdf
  13. mysql数据库校对_mysql数据库校对原则
  14. 04:输出保留3位小数的浮点数
  15. Codeforces 15C Industrial Nim 简单的游戏
  16. ajax上传图片的方法,ajax上传图片的方法
  17. 常微分二阶线性齐次微分方程的通解推导
  18. MongoDB 极简实践入门
  19. leetcode 咒语和药水的成功对数
  20. 电脑右键菜单中没有“打开方式”怎么办

热门文章

  1. 99.9%的努力毁于0.1%的失误
  2. C语言及程序设计初步例程-4 C语言程序初体验
  3. 刺激2019:从AWS和阿里云看云计算疯狂的一年
  4. 多并发编程基础 之协成
  5. python基础篇1(print函数,转义字符,保留字和标识符,变量,数据类型和数据类型转换)
  6. Excel VBA开发自动发送邮件
  7. 移动IP技术研究(转)
  8. WCF自定义扩展,以实现aop!
  9. 《软件工程导论》第六版_张海藩
  10. 【SQL】通过SQL 语句创建学生信息表(学号、学生姓名、班级)、学习成绩表(学号、学科、成绩)