Xavier's Blog

做更美好的自己

基于KL46的计步器设计

pedometer

引言

如今的生活水平越来越高,很多人都开始关注自己的健康问题。与此同时,随着可穿戴设备的产生发展而逐渐衍生出来的可穿戴健康设备得到了长足的发展和进步。可穿戴健康设备得到越来越多的人的青睐,计步器作为一种新型可穿戴健康设备在社会上逐渐流行。

计步器是一种对日常锻炼行为进行可量化观测的可穿戴健康设备,可以计算人们行走的步数,估计行走距离、消耗的能量以及运动的时间,方便人们随时监控自己的健身强度、运动水平和新陈代谢。本设计采用MKL46Z256VLH4为主控芯片,三轴加速度计MMA8652FC进行数据采集,将数据输入到计步算法中算出有效步数,进而求出行走距离、消耗能量和运动时间。本设计还增加了温湿度采集模块对运动环境进行温湿度测量使运动者更好的知道环境是否适合运动。

总体设计描述

本设计利用三轴加速度传感器获取佩戴者运动时身体在三个轴的加速度分量,通过滤波算法和计步算法分析获取步数,配合佩戴者的身高、体重、步距等信息,换算得到行走距离和消耗的能量,并将相关信息显示在段码LCD屏上。利用本设计的按键可快捷地控制屏幕显示相应信息。温湿度传感器采集到环境的温湿度参数后也可将环境的温湿度变化显示在段码LCD屏上。当佩戴者的特征信息和运动数据确定后,其储存到微控制器的内部Flash中,保证信息在系统掉电后不丢失,并可以通过按键查看三天的运动数据。

硬件上选用了功耗极低,处理数据能力较强的MKL46Z128VLH4微控制器作为主控芯片。计步传感器采用了分辨率高、反应速度快、功耗低的MMA8652FC三轴加速度传感器。考虑到温度和湿度对科学的运动有较大的关系,我们采用温湿度传感DHT11采集数据并显示在屏幕上。电源是计步器能够正常稳定工作的前提,应采用小巧,更换方便和续航能力强的电源,所以本设计采用了CR2032作为电源。用户数据要能稳定的存储在计步器中。计步器要有人性化的输入输出接口。总体设计框图如图所示。

为了提供友好的界面显示,方便人机交互,我们采用的段式LCD除了提供基本的数字字符,还提供了箭头标示,结合标签,让用户在使用的过程中得到更多的信息。本设计的主屏幕箭头的功能标示如图所示。

功能简介

本次设计完成的计步器以飞思卡尔Kinetis系列KL46为控制核心,具有的主要功能如下:

  • 能够记录佩戴者本次运动的有效步数、时间和距离;
  • 能够计算运动消耗的能量;
  • 能够对三天的数据进行统计和存储;
  • 时钟显示;
  • 温湿度显示;
  • 简单的人机交互。

主要技术指标

基于Kinetis系列KL46的计步器的主要技术指标如下:

  • 精准记录行走步数、时间和距离,换算出所消耗的能量,实现灵敏度可调;
  • 能够显示当天和前三天的行走步数、时间和距离,提供用户信息设置功能;
  • 计步精度在95%以上;
  • 存储用户信息,保证掉电不丢失;
  • 整机工作电流低于2毫安。

主要技术分析

计步器的设计涉及的知识面比较广泛,主要有三轴加速度传感器、I2C协议、计步算法、段式LCD、低功耗设计、数据存储。

三轴加速度传感器

随着加速度传感器的工艺逐渐成熟,测量精度也逐渐提高,功耗已达到微安级别。本设计选用的飞思卡尔MMA8652FC加速度传感器具有灵活的、用户可编程的嵌入式功能,使用I2C协议与主机通讯,编程简单。该加速度传感器具有12位数字输出,保证了精度,量程±2g/±4g /±8g可选,满足检测人体运动状态的需求。MMA8652FC拥有一个集成的32级FIFO,可用于储存数据,利用此特性可以将主机处理负荷降至最低,从而降低系统总功耗。在本设计中我们采用了±2g的量程和200Hz的采样频率。

显而易见,无论用户如何携带计步器,至少有一个轴具有相对较大的周期性加速度变化。因此只要做好峰值检测和设定好加速度阈值即可判断目标是否在跑动,如图是MMA8652Q在不同姿态X、Y、Z重力输出。综上,可以实现灵敏度可控。

I2C协议

主控芯片MKL46Z128VLH4提供了I2C接口,无需模拟I2C通讯。在硬件上,二线制的I2C串行总线使得各IC只需最简单的连接,而且总线接口都集成在IC中,不需另加总线接口电路,从而简化省去了电路板。上的大量走线,降低设计的难度,提高可靠性。I2C双向数据传输位速率在标准模式下可达100Kb/s,快速模式下可达400Kb/s,高速模式下可达3.4Mb/s,完全满足加速度传感器与主机的通讯要求。

计步算法

在可用于分析跑步和步行的特征当中,我们选择“加速度”作为相关参数。跑步个体(及其相关轴)的运动包括三个分量,分别是前向(“滚动”)、竖向(“偏航”)和侧向(“俯仰”),如图所示。

步行时人的步伐分解如图所示。无论如何穿戴计步器和做何种运动(跑步,散步,快走等),总有至少一个轴具有相对较大的周期性加速度变化,因此可以通过阈值检测和针对所有三个轴上的加速度的动态阈值决策算法来检测单位步行或跑步周期。

从一名跑步者测得的X、Y和Z轴加速度的典型图样。从图可以看出只有一个轴的变化波形振幅较大(假设为X轴),另外两个轴加速度变化波形振幅较小(假设为Y、Z轴)。Y、Z轴波形特征不明显,无法与扰动的波形区分开;X轴的加速度变化最为明显,振幅较大,特征明显。故先不考虑Y、Z轴的加速度曲线,只分析X轴。

在对X轴上的数据进行峰值检测之前,我们首先要去除其上的扰动波形(毛刺),以达到更高的准确度。为此,可以设计滤波器对X轴上的数据进行滤波。采用滑动平均滤波算法处理过后的波形和原先波形的对比如图所示。

从可以看出,进过滑动平均滤波算法处理后的波形几乎不存在毛刺,效果理想,为阈值检测的实现带来了方便,结合对所有三个轴上的加速度的动态阈值决策算法,可以较为准确地识别出步行或跑步的步数。在计步算法中我们还加入了时间窗口用来判断通过计步的步数是否有效,进一步增加了计步的准确性。

低功耗

本设计采用基于Cortex-M0+内核的微控制器MKL46Z128VLH4具有多个灵活的低功率模式,I2C、ADC、DAC、LP定时器和DMA等功能支持低功耗模式运行,无需唤醒内核。所选用的三轴数字加速度传感器在低功耗模式是电流为7μA,正常工作电流在30μA左右。另外,所选用的段式LCD功耗极低,正常工作电流在μA级别。总体而言,本设计可以实现整机电流在1~2mA的低功耗计步器。如图所示为低功耗模式转换示意图,我们在待机状态下选择VLPS这种深度睡眠模式,可以获得极低功耗。

数据存储

本设计使用的主控芯片MKL46Z128VLH4内部拥有128KB的Flash,可用于存储代码和用户数据。由于本设计的程序不算复杂,程序运行过程所需的缓存不大,初步估计总共所需的存储空间不超过128KB,可以在片内Flash分配出约4KB左右的空间用来存储用户数据,无需外扩,不仅降低了系统功耗,而且节约成本,降低设计的复杂度。另外,考虑到Flash只能按页擦写,而EEPROM可以按位擦写,更为节省空间,并且可擦写的次数远比Flash多,故我们用Flash模拟EEPROM来存储数据。

硬件整体设计

为尽可能的降低功耗,可只引出使用到的一些端口,未使用的资源一律不引出。对于功耗高的模块,可通过一个IO口控制P沟道MOS管的通断,从而控制对模块的供电。为方便调试程序,预留SWD和UART接口。

为了实现监控计步器的工作状态,确保计步器正常工作,同时为了直观的快捷的观测传感器数据,本设计增加了UART接口作为系统的调试接口。可以在线调试仿真和用串口打印信息,并以写好驱动可直接调用printf函数。如图所示为SWD接口与UART接口。

段码LCD屏为1/4DUTY,1/3BIAS,驱动电压为3.0V。工程中配的驱动文件能驱动任何一段,并配有详细注释。其段码如图所示。

软件整体设计

设计思路

本次设计主要有5个功能,即计步算法的实现,Flash存储运动数据,温湿度传感器的实现,按键的实现,及人机界面的设计。首先上电之后,主界面显示当前时间和温湿度。之后设置个人参数,输入性别、步长、体重。随后切换界面,进入计步状态,加速度计正常工作,实时显示当前步数、距离和消耗的热量。计步完成后,可以将信息存储起来,下次上电之后可以调出该信息,计步器可记录三天的运动信息。在没有按键按下一段时间内系统关屏以降低功耗,在加速度计不工作时且没有其他操作,系统经过一段时间自动进入低功耗模式。本项目软件部分采用模块化设计的思想,把系统分为七个模块,然后每个模块对外留出接口,方便其他模块与其通信,每个模块之间无不干扰,相对独立。

设计流程图

图为主程序流程图。首先初始化系统时钟、配置SLCD的初始界面,以及加速度传感器、温湿度传感器、Flash和个人信息配置等初始化工作。然后进入任务循环,根据当前的按键操作调用相应的功能函数,如若在主界面,则正常显示日期、时间,环境的温湿度;要开始运动,则使加速度传感器处于激活状态,并开始计步;若要存储运动信息,则调用Flash读写函数。最后若一段时间没有使用计步器,则系统进入低功耗状态,传感器暂停工作,并切断液晶屏的电源。此时,可通过按键解除低功耗模式,使得计步器正常工作。

软件开发环境

Keil4.5开发环境

Keil工程文件夹含义如图所示。

软件实现

温湿度传感器数据的程序设计

程序清单1  温湿度采集
uint_8 DHT_ReadTempHumi()
{
   uint_8 i=0,check_value=0;
   GPIO_PinConfig(HW_GPIOD, 7, kOutput);      /*配置PTD7为输出                                                */
   GPIO_WriteBit(HW_GPIOD, 7, 0);             /*拉低数据线大于18ms发送开始信号                                   */
   DelayMs(20);
   GPIO_PinConfig(HW_GPIOD, 7, kInput);       /*释放数据线,用于检测低电平的应答信号                              */
   DelayUs(20);                               /*延时20-40us,等待一段时间后检测应答信号,应答信号是从机拉低数据线80us */
   if((GPIO_ReadBit(HW_GPIOD, 7))!=0) {       /*检测应答信号,应答信号是低电平                                   */
       return ERROR;                          /*没应答信号                                                    */
   } else {
       while((GPIO_ReadBit(HW_GPIOD, 7))==0); /*有应答信号,等待应答信号结束                                     */
       while((GPIO_ReadBit(HW_GPIOD, 7))!=0);
       for(i=0;i<4;i++)                       /*读出湿,温度值                                                 */
       {
           value_array=DHT11_ReadValue();
           if(status==ERROR) {                /*调用ReadValue()读数据出错会设定status为ERROR                    */
               return ERROR;
           }
           if(i!=4) {                         /*读出的最后一个值是校验值不需要加上去                              */
              check_value+=value_array;       /*读出的五字节数据中的前四字节数据和等于第五字节数据表示成功            */
           }
       }
       if(check_value==value_array[4]) {      /*在没用发生函数调用失败时进行校验                                 */
           g_temp_humi[0]=value_array[0];     /*湿度                                                         */
           g_temp_humi[1]=value_array[2];     /*温度                                                         */
           return OK;                         /*正确读出DHT11输出的数据                                        */
       } else {
           return ERROR;                      /*没有读出DHT11输出的数据                                        */
       }
   }
}

数据缓冲区的程序设计

要实现计步算法,必须将三轴加速度传感器三个轴的历史数据存储在一个数据缓冲区中。这样在当新的数据到来时,会舍掉最后面的数据。同时这个数据缓冲区始终更新当前的数据特征,如最大值,最小值,基值,上限阈值,下线阈值等。如程序清单2所示。

程序清单2  计步器的数据缓冲区
int16_t DateBufferX[10] ={0};  /*滑动平均值滤波缓冲区        */
int16_t DateBufferY[10] ={0};
int16_t DateBufferZ[10] ={0};

int16_t X_Max =-2048,X_Min = +2047,X_Base = 0,X_UpLimit = 0,X_DownLimit =0,X_Data[64],X_MaxMark = 0,X_MinMark = 0; /*参数初值*/
int16_t Y_Max =-2048,Y_Min = +2047,Y_Base = 0,Y_UpLimit = 0,Y_DownLimit =0,Y_Data[64],Y_MaxMark = 0,Y_MinMark = 0;
int16_t Z_Max = -2048,Z_Min= +2047,Z_Base = 0,Z_UpLimit = 0,Z_DownLimit = 0,Z_Data[64],Z_MaxMark =0,Z_MinMark = 0;

获取数据的程序设计

每当数据准备好,触发外部中断。如程序清单3所示。

程序清单3  计步器外部中断服务程序
void PORTA_IRQHandler(void)
{
    uint_8 accel_data[192]; //
    int16_t temp;
    uint_8 int_source;
    uint_8 j,k;
    //清中断标志位
    PORTA_PCR13 |= PORT_PCR_ISF_MASK;                                                       // Clear the interrupt flag
    int_source = I2C_ReadRegister(MMA8652_I2C_ADDRESS,INT_SOURCE_REG);
    if(int_source & SRC_FIFO_MASK)                                                          // FIFO中断标志
    {
       I2C_ReadMultiRegisters(MMA8652_I2C_ADDRESS, OUT_X_MSB_REG, 192,accel_data); //
        k=0;
        for(i_M = 0;i_M < 32; i_M++)
        {
            for(j =0;j < 3; j++)
            {
                temp = accel_data[k] <<8;
                temp |= accel_data[k+1];
                temp = temp / 16;
                ucdate[j]=temp;
                k += 2;
            }
             CountStep();
        }
}

滤波算法的程序设计

本设计采样各类人群在行走和跑步过程中的运动数据,通过上位机显示波形,并模拟滤波算法,分析得到最适合本设计的滤波算法是滑动平均值滤波算法,采样点为10个。程序清单4给出了核心程序。

程序清单4  计步器滤波算法部分程序
for (i = 0; i < SaveTime.Count - 10; i++)
{
    temp = 0;
   for (j =i; j < i + 10; j++) {
        temp+= SaveDataX[j];
    }
   SaveDataX2 = temp / 10
}

计步算法的程序设计

缓冲区数据经过滤波算法后,得到了比较理想的波形曲线。计步算法分为两步:第一、选择波动最大的那个方向的数据,实现动态阈值,如程序清单5所示;第二、采用迟滞比较算法实现计步,并更新步数,如程序清单6所示。

程序清单5  更新加速度传感器数据阈值
X_Base      = (X_Max + X_Min) / 2; 
Y_Base      = (Y_Max + Y_Min) / 2;
Z_Base      = (Z_Max + Z_Min) / 2;
X_UpLimit   = (X_Base + X_Max * 2) / 3;
Y_UpLimit   = (Y_Base + Y_Max * 2) / 3;
Z_UpLimit   = (Z_Base + Z_Max * 2) / 3;
X_DownLimit = (X_Base +X_Min * 2) / 3;
Y_DownLimit = (Y_Base +Y_Min * 2) / 3;
Z_DownLimit = (Z_Base +Z_Min * 2) / 3;
程序清单6 迟滞比较算法
if((Z_Data[m] >Z_UpLimit) && StepLimitFlag == 0) {
           StepLimitFlag = 1;
}
if((Z_Data[m] < Z_DownLimit)&& StepLimitFlag ==1) {
            StepLimitFlag = 0;
            StepCount++;
}

Flash存储的程序设计

Flash管理的程序流程图如图所示。首先进行Flash初始化,读取Flash中3个扇区的首地址下的4个字节数据,得到当前Flash存储空间的活动扇区。之后,在当前活动扇区中查找当前活动地址,保存索引。整个初始化过程是Flash管理最重要的部分。完成后循环更新Flash管理信息,实现动态的地址分配。 Flash管理结构体如程序清单7所示。

程序清单7  Flash管理
// Flash控制器宏定义,内部使用
#define CCIF    (1<<7)
#define ACCERR  (1<<5)
#define FPVIOL  (1<<4)
#define MGSTAT0(1<<0)

//Flash命令宏定义,内部使用
#define RD1SEC    0x01  // 读整个扇区
#define PGMCHK    0x02  // 写入检查
#define RDRSRC    0x03  // 读目标数据
#define PGM4      0x06  // 写入长字
#define ERSBLK    0x08  // 擦除整块Flash
#define ERSSCR    0x09  // 擦除Flash扇区
#define RD1ALL    0x40  // 读所有的块
#define RDONCE    0x41  // 只读一次
#define PGMONCE   0x43  // 只写一次
#define ERSALL    0x44  // 擦除所有块
#define VFYKEY    0x45  // 验证后门访问钥匙

实现低功耗的程序设计

KL46Z系列微控制器共有十种工作模式,分别是两种Run模式,两种Sleep模式,六种Deep Sleep模式。在这八种睡眠模式中,各自的功耗不同,唤醒条件,唤醒所需时间,均不相同,工作电流在174nA至7mA不等。用户可根据实际需求配置和切换微控制器的工作模式。本系统选择了功耗较低的Deep Sleep中唤醒方式最灵活的VLPS(Very Low Power Stop)模式,作为低功耗的实现模式。如图所示。

转载请注明:Xavier’s Blog » 基于KL46的计步器设计