可穿戴项目总结
项目背景和目的
- 背景是我的毕业设计,整个项目的结构是一个IOT可穿戴设备采集数据,手机app服务器端进行数据存储和处理.
- 目的: 利用可穿戴设备长期监测佩戴者的声音、行为、环境和体征的变化,看看它是否能与心理健康建立一定的联系; 我主要做自闭症倾向的研究。
硬件部分
- 用Altium Designer,我自己设计了四层板PCB板,大小为3.3X3.4厘米
- 语音传感器部分: 两个MEMS麦克风收集左右声道信息,音频编码解码器(wm8978语音芯片 - I2C通信和I2S通信
- 行为传感器部分: 主要采用三轴加速度和三轴陀螺仪(mpu6050) --- I2C 通信
- 环境传感器部分: 主要使用光传感器(bh1750)环境温度和环境压力传感器(bmp180) --- I2C通信
- 体征传感器部分: 主要使用皮肤温度和皮肤湿度的传感器(SI7021) --- I2C通信
- 心率血压传感器模块: 主要测试了几种松恩电子产品,SON3019A等. 测试效果不令人满意,但不支持二次开发,不集成在我们的设备上.
- 环境传感器和体征传感器I2C接在同一I2C总线,因为I2C硬件地址不同,可以正常读取数据.
- 使用主控器STM32F405RG,64pin的一块芯片
- 用于电源管理芯片TPS6260.3芯片),快速充电管理芯片(BQ24040)
- 还有一些外设,按键,OLED显示屏,SD卡存储器
- 在蓝牙部分,我以前尝试过北欧(Nordic)的nRF基于52832蓝牙芯片的简单实现FreeRTOS蓝牙穿透数据的功能
- 但是,当与我们的可穿戴设备相连时,由于音频数据要求太快,可穿戴设备没有集成.
STM32F405的硬件资源
- 有1MB的flash 和192KB的SRAM
软件部分
- 国内嵌入式操作系统的使用(RT-Thread),基于位图的调度器
- rt-thread基于优先调度和时间片轮转调度共存的调度算法
- 支持具有相同线程优先级的多个线程
- 对于不同优先级的线程,程:即高优先级的线程将立即抢占低优先级的线程
- 同线程优先级的多线程采用时间片旋转的方式
- 用线程控制块表示每个线程的信息
- 非负整数(即无符号整数)表示线程的优先级,优先级越高,相应数量越小
- 系统线程优先级数固定,最多支持256级(32字节数据,每字节8位)
- 按键线程控制开始和停止记录(thread_key)
- 显示电量、CPU利用率、行为数据变化和温湿度传感器数据的显示线程(thread_oled,SPI协议的OLED屏)
- 控制电池充电和ADC采样的电池线程(thread_battery)
- 采集mpu传感器数据6050的线程(thread_mpu6050)
- 收集语音信号的线程(thread_wm8978)
- 收集环境传感器和体征传感器数据的线程(thread_sensors)
- 文本文件保存传感器数据(语音保存).wav,保存行为、环境和体征数据.csv文件)于FAT-FS文件系统中(thread_file)
- 计算语音特征的线程(thread_dsp),计算四个语音特征(短时能量、谱熵、亮度、共振峰)
- 优先级设置: 关键线程优先级最高,
- 传感器读取数据线程第二高,采用时间片轮询的方式,
- 文件写数据SD卡中优先级第三高,
- DSP计算线程特征的线程第四高,
- 显示数据、时间、电量和CPU利用率线程第五高,
- 电源管理线程第6高,主要是ADC采样和监控充电管理芯片I/O;
- 行为传感器数据: (三轴陀螺仪和三轴加速度计,IIC一次读64字节,缓存设置为5K,然后写入缓存满SD卡
- 采集audio音频采集线程(结合DAM实现控制器配置DMA的双buffer机制),一个buffer设置为5K,主要实现录音功能;
- DMA中断时,会向写文件的线程管理发送信号,并将音频数据写入SD卡中
- 光线传感器(bh1750)环境压力和温度传感器(bmp180)和温湿度传感器(si7021)用一个线程收集数据,并在文件中立即收集事件
阅读和写作分离的思想和时间同步(确保同时保存体征、环境和体征、语音文本),使用单独的文件线程编写传感器文件
- 一些技术细节:
- 传统的DMA外设地址寄存器(PAR)、内存地址寄存器(MAR),双缓冲DMA有两个内存地址寄存器(M0AR,M1AR)
- 同时,有一个标志位表示目前正在使用哪个内存地址寄存器MxAR(DMA->SxCR[CT]) //使用语音DMA双缓冲机制
- 也可以通过设置该位置主动切换当前位置MxAR,在RAM两个接收缓冲区,DMA配置为双缓冲,防止数据在处理的时候被DMA改写。
- WM8979只集成了ADC和DAC音频编码器本身没有音频数据传输功能
- 输出采样到的音频数据SD存储和使用卡I2S协议传输音频数据
- I2S总线接口有三个主要信号,但只能实现数据半双工传输,全双工需要扩展数据引脚(一般只有两个引脚)sd和ck)
- SD(serial data): 串行数据线用于发送数据
- WS(word select): 字段选择线,又称帧时钟(LRC)线,表示当前传输数据的声道。WS采样频率等于采样频率(FS)
- CK(serial clock): 串行时钟线,也称为时钟(BCLK),每个数字音频数据对应一个数字音频CK脉冲,其频率为:2采样频率量化位数,2代表左右通道数据
- ext_SD(extern serial data): 扩展串行数据线,接收全双工传输的数据
- 主时钟传输(MCK),256*FS
- I2C相关知识: (I2C需要两个上拉电阻,一般是4.7K)
- I2C的速率: 100Kbits/s(标准模式),4000Kbits(快速模式),3.4Mbits(高速模式)
- I2C总线: 串行数据线SDA,串行时钟线SCL
- 每个接收总线的设备都可以通过唯一的地址和简单的主机/从机关系软件设置地址
- 主机可作为主发送器或主机接收器
- 起始条件: 当SCL线是高电平时,SDA线路从高电平向低电平切换表示起始条件,即沿触发下降
- 停止条件: 当SCL线是高电平时,SDA线路从低电平向高电平切换表示停止条件,即上升沿触发
- 总线空闲状态: SDA和SCL两条信号线都处于高电平,即总线上的所有设备都释放总线,两条信号线各自的上拉电阻拉高电平
- I2C总线端口必须泄漏: 因此需要上拉电阻,上拉电平驱动能力很弱,因此决定其运行不快.
- I2C负载能力为400pF,每个设备的总线接口都有一定的等效电容器
- 数据传输: 发送到SDA每个字节在线必须是8位,每次传输的字节数不受限制
- 每个字节后必须有响应位(即响应位)
- 首先,传输数据的最高位置(MSB)
- 如果机器需要完成一些其他功能(如中断服务程序)才能接受或发送下一个完整的数据字节,则时钟线可以保持低电平,迫使主机进入等待变态
- 准备好接收下一个数据字节并释放时钟线SCL之后,继续传输数据.
- I2C如何读写数据: 假设主机寄存器地址为8位;
- 主机先发起通信,读取command(0x01)以及需要读取的寄存器地址address写入从机;(主机发出写作操作);
- IIC读写非常详细
- 主机首先发送从机的7位地址,并发送读写位(R/W,0代表写作,1代表读取),检查响应,然后是8位数据,然后是响应位,然后继续发送数据直到停止;
- SPI相关知识:
- spi是一种高速,全双工,同样步的通信总线; 一条时钟线(sck), 一条数据输入线(MOSI), 一条数据输出线(MISO), 一条NSS使能线(传输数据时为低电平)
- SPI的Master(主设备)会根据将要交换的数据产生相应的时钟脉冲(Clock Pulse), 时钟脉冲组成了时钟信号
- 时钟信号通过时钟极性(CPOL)和时钟相位(CPHA)控制两个SPI设备间何时数据交换以及何时对接收到的数据进行采样, 来保证数据在两个设备之间是同步传输的
- SPI四种模式: SPI的四种模式通过时钟线的相位和极性来进行选择:
- 模式1: CPOL = 0, CPHA = 0; 总线空闲时SCK为低电平, SPI在SCLK第一个边沿开始采样
- 模式2: CPOL = 0, CPHA = 1; 总线空闲时SCK为低电平, SPI在SCLK第二个边沿开始采样
- 模式3: CPOL = 1, CPHA = 0; 总线空闲时SCK为高电平, SPI在SCLK第一个边沿开始采样
- 模式4: CPOL = 1, CPHA = 1; 总线空闲时SCK为高电平, SPI在SCLK第二个边沿开始采样
- 时钟极性CPOL: 即SPI空闲时, 时钟信号线的电平, CPOL为1时, 空闲时高电平, 0空闲时低电平
- 时钟相位CPHA: 即SPI在SCLK第几个边沿开始采样, 0表示第一个边沿开始采样, 1表示第二个边沿开始采样
- OLED显示屏使用的CPOL = 1, CPHA = 1, 即模式4; 总线空闲高电平, 第二个边沿开始采样, 也就是上升沿采样.
- SPI速率很高, 最高速率大于50Mbps
- 串口是异步通信(因为没有时钟线), SPI是同步通信, I2C是同步通信
串口是双工通信, SPI双工通信, I2C是半双工通信, 因为只有I2C只有一根数据线
- SD总线: 最高能到10Mbps
- USB总线:
- USB1.1 低速模式: 1.5Mbps, 全速模式: 12Mbps
- USB2.0 向下兼容, 增加了高速模式, 最大速率为480Mbps, 高速模式25-480Mbps(bits per second, 比特率, 比特/s, 每秒传送位数, 传输速率常用单位)
- USB3.0 向下兼容, 增加了超高速模式, 理论上可以达到4.8Gbps, 实际中, 也就是高速模式的10倍左右
- 线程间用到的同步和通信机制:
- 同步机制: 互斥量(PV原语), 初始化一个数值S为1, P操作(Proberen-测试的意思)就是对这个值减1, 如果S >= 0, 则改线程继续执行, 否则线程进入等待状态, 进入等待队列等待被唤醒
- V操作(Verhogen)把S的值加1, 如果S > 0, 则该线程继续执行, 否则释放等待队列中第一个等待该信号量的线程.
- 线程通信: 利用事件来进行通信, 具体实现是利用一个
uint32_t
(一个无符号整型)来表示一个事件集合, 一种事件表示一个位 - 该位为1表示事件发生, 该位为0表示事件没有发生, 所以每个事件集合最多容纳32个事件
- 对一个事件对象发送某种事件, 对该事件对象接收某个事件, 对某个事件进行超时等待(在固定时间内没有等待到某个事件将直接返回)
- 本质上是利用了事件机制实现了一个状态机编程
- 异步通信与同步通信
- 同步通信就是需要发送方和接收方有一个时钟, 在同一个时钟下来进行需要数据的传输
- 异步通信发送和接收方有着自己的时钟, 通过起始位和停止位来判断是否有数据, 为了保证数据传输的可靠性, 会有一些校验位
- 用于判断数据是否有效: 如奇偶校验
- 线程优先级的配置问题
- 按键的优先级设置为2;
- 其他功能的实现
- 计算MCU的利用率
- 实现U盘的高速传输(USB2.0)
蓝牙通信方面
- 通信方面, 用过WIFI透传模块, 主要是发送AT指令, 但功耗太高, 超过了100ma, DC-DC的芯片无法满足, 只有换蓝牙的方案,
- 后面换了一块蓝牙芯片nRF52832(一个蓝牙4.0的芯片来作数据传输), 试过蓝牙透传的功能, 传输速率比较慢, 10kb/s左右, 115200波特率
- 如果没有奇偶校验, 就除以10, 如果有奇偶校验就出以11, 波特率115200 = 115200(位/秒) = 11520(字节/秒) 再除以1024等于11.52字节/秒
- 蓝牙协议栈简介
- ATT属性协议层
- 与应用紧密相关的 GAP/GATT 层, GAP 通用访问配置文件层(Generic Access Profile), GATT 通用属性配置文件层(Generic Attribute Profile);
- 通过 SoftDevice(即协议栈,这种方式使得协议栈和用户应用可以单独编译和链接)的 API 软件接口(以 sd_ 开头)调用来实现;
- 低功耗蓝牙协议栈包含两部分共8层:主机(Host)和控制器(Controller)。
- 控制器部分包括:
- 物理层(Physical Layer)
- 链路层(Link Layer)
- 主机控制接口层(Host Controller Interface)
- 主机部分包括:
- L2CAP 逻辑链路控制及自适应协议层(Logical Link Control and Adaptation Protocol)
- 安全管理层(Security Manager)
- ATT 属性协议层(Attribute Protocol)
- GAP 通用访问配置文件层(Generic Access Profile)
- GATT 通用属性配置文件层(Generic Attribute Profile)
- 低功耗蓝牙有两种频道类型:广播频道 3 个,数据频道 37 个,共 40 个频道;
- 最大发射功率为 +10 dBm(10mW),最小发射功率为 -20 dBm(0.01mW);
- 在低功耗蓝牙中,所有的数据块由一个 Profile 或服务所使用的数据库称为特性(characteristic);
- ANT协议;
- 控制器部分包括:
服务器和手机APP通信
- 实现了一个http服务器, 主要包括7个步骤:
- 建立连接: 与客户端建立TCP/IP链接;
- 接受请求: 从socket链接中读取HTTP请求数据;
- 解析请求: 根据HTTP请求报文结构解析请求报文;
- 处理请求: 处理请求, 一般是数据库增、 删、改、查操作;
- 构建响应: 按照HTTP响应报文格式将处理结果构建成响应报文;
- 发送响应: 将响应报文通过socket链接发送给客户端;
- 记录事务: 将上述处理过程作为一个事务记录在日志文件中;
- 基于muduo库实现了一个简单的HTTP服务器, 利用POST和GET方法进行传输数据;
- Json文本进行数据传输;
- JSON解析器和生成器是Github热门开源软件RapidJSON;
- RapidJSON是一个用C++语言开发的高性能JSON解析/生成器,具有解析速度快、资源占用小等优点;
- C++版的Mysql Veson3.2.3, 做数据存储;
- 服务器主要放在阿里云服务器上;
- App发出HTTP请求, 服务器作HTTP响应;
- 处理HTTP请求与生成HTTP响应的程序则是基于muduo网络库框架自行开发的;
- HTTP协议是一个基于请求与响应模式的、无状态、应用层协议,该协议基于TCP传输协议处于七层OSI模型的应用层;
- HTTP报文分为请求报文和响应报文;
- 请求报文是客户端发送给服务器的请求动作,响应报文则是服务器处理请求后发送给客户端的响应行动;
- 解析请求报文时,HTTP服务器会不定期地读取Buffer中的数据;
- 网络连接可能随时都会出现延迟,每当读取Buffer中的数据时,都需要判断请求的完整性,如果不完整则立即返回,直到请求完整才会解析HTTP请求;
- 解析完HTTP请求之后,会根据HTTP的方法(GET/POST等)结合首部以及主体来操作服务器的资源,最终对数据进行增加、删除、变改、查询操作;
- 采用MySQL作为数据库存储App上传的历史数据;
- 使用C/C++语言连接MySQL数据库的方法主要有两种,一个是使用mysql connector库,另一个是使用mysql++库;
Muduo库HTTP程序
- muduo库的安装, 编译与安装
转载于:https://www.cnblogs.com/longjiang-uestc/p/9539465.html