意念控制四旋翼 学习笔记(一)

      第一部分:模块原始数据 

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

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

       

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

          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;//TX
    GPIO_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;//RX
    GPIO_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;//硬件流DMA
    USART_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神经网络模型提速特征值

第六部分:系统控制

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

第七部分:论文写作

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

猜你喜欢

转载自blog.csdn.net/seek97/article/details/81328542