0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

基于STM32跑步路径记录

嵌入式技术 来源:嵌入式技术 作者:嵌入式技术 2022-09-18 09:30 次阅读

基于STM32跑步路径记录

随着科技不断进步,电子化设备不断进入涌入我们的日常生活。生活水平的提高,各项健身运动应运而生,然后,健身运动不能盲目进行,科学的健身方式才能有效的提升我们自身的身体素质。

现如今各自手环手表的出现, 通过智能手环,用户可以记录日常生活中的锻炼、睡眠、部分还有饮食等实时数据,并将这些数据与手机、平等同步,起到通过数据指导健康生活的作用。

智能手环作为可穿戴设备,其功能还是比较强大的,其开发涉及智能手环MCU数据指令到蓝牙IC的传输、蓝牙到APP的数据通信协议、APP到手机内部的通信调试逻辑实现、APP数据到云端服务器的数据库算法设计等一系列的开发。支持多种运动监控模式,可以实时监控身体的各项性能指标。

我国智能手环产品真正大范围进入消费市场是在2012年以后,一方面是这一时期步入4G时代以后手机智能化趋势加快,与手机一样具备数据分享的智能手环的出现给智能手环的研究和应用打开了另一个世界。另一方面是更多实用性功能快速出现,手环不仅仅是用来记录身体特征的单纯工具,同时也可以满足通话、移动支付、人体识别、智能提醒功能以及分享功能,极大的扩宽了手环的应用人群。佩戴智能手环带来健康、科技、自信有品位的良好感受,成为了高科技产品的典型之一。

  基于STM32的跑步路记录主要用于记录用户在日常身体锻炼中,可设置跑步路径,跑步路线规划,在50~80m前提醒拐弯,蜂鸣器报警提示;记录跑步路径,显示当前位置,通过按键设置跑步距离。

2.模块选型

2.1 主控MCU:STM32F103C8最小系统板

  STM32最小系统板:STM32系统板

pYYBAGMl1VqAadOtAALXCNzhAsY724.png#pic_center

2.2 OLED显示屏:0.96寸SPI/IIC接口

  显示屏幕:OLED屏幕

poYBAGMl1VqAeYm6AAG1S6bL93A707.png#pic_center

2.3 GPS定位模块

GPS定位:GPS模块 北斗模块 双模定位 ATGM336H

pYYBAGMl1VqADX-SAAGLWKsdK4I204.png#pic_center

支持北斗/GPS/GLONASS卫星系统

支持3.3V-5V供电,可以方便接入3.3V或者5V单片机系统3、板载可充电电子,可加速热启动搜星过程

默认波特率9600,波特率可设置

TTL电平UART接口,用户连接单片机的串口TTL电平或者USB-TTL模块测试。

带有SMA和 IPEX两种天线接口,方便选择自己需要的外置天线。

带有PPS授时输出引脚,方便做时钟同步等应用。

poYBAGMl1VuAcSN1AAJWRsuDDFA662.png#pic_centerpYYBAGMl1VuALeEnAAOOC8U2fBs276.png#pic_center

2.4 蜂鸣器

  蜂鸣器:有源蜂鸣器

poYBAGMl1VuANwshAAHuk9Zbvm0921.png#pic_center

3.电路设计

poYBAGMl1VyAJQlhAAGj2YUgI74662.png#pic_center

4.实物展示

pYYBAGMl1VyAPjb8AAYQaG5owXc416.png#pic_centerpoYBAGMl1V2AbU4tAAbxna4FSIQ113.png#pic_center

4.软件设计

4.1 GPS定位信息获取

  ATGM336H采用串口协议,直接接上电源,在空旷的地方只要接收到卫星信号即可返回卫星定位数据。

pYYBAGMl1V2AQhWMAARi-lW3NT4103.png#pic_center

/*
函数功能:分析BDGSV信息
函数参数:GPS_DecodeInfo:nmea信息结构体
		  buf:接收到的GPS数据缓冲区首地址
*/
void GPS_BDGSV_InfoGet(GPS_Msg *GPS_DecodeInfo,u8 *buf)
{
	u8 *p,*p1,dx;
	u8 len,i,j,slx=0;
	u8 posx;
	p=buf;
	p1=(u8*)strstr((const char *)p,"$BDGSV");
	if(!p1)return; //没有查找成功
	len=p1[7]-'0';								//得到BDGSV的条数
	posx=GPS_GetCommaOffset(p1,3); 					//得到可见北斗卫星总数
	if(posx!=0XFF)GPS_DecodeInfo->beidou_svnum=GPS_StrtoNum(p1+posx,&dx);
	for(i=0; ibeidou_slmsg[slx].beidou_num=GPS_StrtoNum(p1+posx,&dx);	//得到卫星编号
			else break;
			posx=GPS_GetCommaOffset(p1,5+j*4);
			if(posx!=0XFF)GPS_DecodeInfo->beidou_slmsg[slx].beidou_eledeg=GPS_StrtoNum(p1+posx,&dx);//得到卫星仰角 
			else break;
			posx=GPS_GetCommaOffset(p1,6+j*4);
			if(posx!=0XFF)GPS_DecodeInfo->beidou_slmsg[slx].beidou_azideg=GPS_StrtoNum(p1+posx,&dx);//得到卫星方位角
			else break;
			posx=GPS_GetCommaOffset(p1,7+j*4);
			if(posx!=0XFF)GPS_DecodeInfo->beidou_slmsg[slx].beidou_sn=GPS_StrtoNum(p1+posx,&dx);	//得到卫星信噪比
			else break;
			slx++;
		}
		p=p1+1;//切换到下一个BDGSV信息
	}
}


4.2 卫星数量获取

/*
函数功能:分析GNGGA信息
函数参数:
		GPS_DecodeInfo:nmea信息结构体
		buf:接收到的GPS数据缓冲区首地址
*/
void GPS_GNGGA_InfoGet(GPS_Msg *GPS_DecodeInfo,u8 *buf)
{
	u8 *p1,dx;
	u8 posx;
	p1=(u8*)strstr((const char *)buf,"$GNGGA");
	if(!p1)return; //没有查找成功
	posx=GPS_GetCommaOffset(p1,6);								//得到GPS状态
	if(posx!=0XFF)GPS_DecodeInfo->gpssta=GPS_StrtoNum(p1+posx,&dx);
	posx=GPS_GetCommaOffset(p1,7);								//得到用于定位的卫星数
	if(posx!=0XFF)GPS_DecodeInfo->posslnum=GPS_StrtoNum(p1+posx,&dx);
	posx=GPS_GetCommaOffset(p1,9);								//得到海拔高度
	if(posx!=0XFF)GPS_DecodeInfo->altitude=GPS_StrtoNum(p1+posx,&dx);
}

4.3 移动速度获取

/*
函数功能:分析GNVTG信息
函数参数:GPS_DecodeInfo:nmea信息结构体
		  buf:接收到的GPS数据缓冲区首地址
*/

void GPS_GNVTG_InfoGet(GPS_Msg *GPS_DecodeInfo,u8 *buf)
{
	u8 *p1,dx;
	u8 posx;
	p1=(u8*)strstr((const char *)buf,"$GNVTG");
	if(!p1)return; //没有查找成功
	posx=GPS_GetCommaOffset(p1,7);								//得到地面速率
	if(posx!=0XFF)
	{
		GPS_DecodeInfo->speed=GPS_StrtoNum(p1+posx,&dx);
		if(dx<3)GPS_DecodeInfo->speed*=GPS_GetPow(10,3-dx);	 	 		//确保扩大1000倍
	}
}

4.4 主函数

int main()
{
  u8 key;
  char buff[100];
	u32 E_data=0,E_data2=0,N_data=0,N_data2=0;
	LEDInit();
  KEYInit();
  Beep_Init();
	USARTx_Init(USART1,115200);
	USARTx_Init(USART2,9600);//串口3初始化(接收GPS数据)
  TIMx_Init(TIM2,72,20000);//定时20ms,用定时器2辅助usart1接收
	TIMx_Init(TIM3,72,20000);
	USARTx_Sendstr(USART1,"串口1初始化成功\r\n");
	OLED_Init();//OLED初始化
  u8 x=5;
  u8 y=16;
  u8 stat=0xff;
  u8 stat2=0;
  u16 time=0;
  u16 distance=400;
AA:
  while(1)
  {
    /*距离选择*/
    OLED_ClearGram();
    OLED_Display_Font(32,0,16,2);
    OLED_Display_Font(32+16,0,16,3);
    OLED_Display_Font(32+16*2,0,16,4);
    OLED_Display_Font(32+16*3,0,16,5);
    OLED_Display_str(24,16,16,(u8 *)"400 M");
    OLED_Display_str(24,16*2,16,(u8 *)"1000 M");
    OLED_Display_str(24,16*3,16,(u8 *)"2000 M");
    OLED_Display_str(128-30,y,16,(u8 *)"<--");
    key=GetKeyVual(1);
    if(key==1)//距离选择
    {
      if(y<48)y+=16;
      else y=16;   
      OLED_RefreshGram();//更新数据到屏幕
    }
    else if(key==2)//确认
    {
      BEEP=1;
      if(y==16)distance=400;
      else if(y==32)distance=1000;
      else if(y==48)distance=2000;
      OLED_RefreshGram();//更新数据到屏幕
      DelayMs(50);
      BEEP=0;
      DelayMs(200);
      break;
    }
    DelayMs(1);
    time++;
    if(time>=50)
    {
      time=0;
      OLED_RefreshGram();//更新数据到屏幕
      LED1=!LED1;
    }
  }
  y=60;
  while(1)
  {
		if(usart2_flag)//获取GPS数据
		{
			usart2_rx_buff[usart2_cnt]='\0';
			//printf("%s\r\n",usart2_rx_buff);
			usart2_flag=0;
			usart2_cnt=0;
			GPS_GNGGA_InfoGet(&GPS_DecodeInfo,usart2_rx_buff);//获取卫星数量
      GPS_GNVTG_InfoGet(&GPS_DecodeInfo,usart2_rx_buff);//获取移动速度
      GPS_GNRMC_InfoGet(&GPS_DecodeInfo,usart2_rx_buff);//获取经纬度		
			printf("卫星数量: %d\r\n",GPS_DecodeInfo.posslnum);
			E_data=GPS_DecodeInfo.longitude;
			N_data=GPS_DecodeInfo.latitude;
			printf("经度:%c,%d \r\n",GPS_DecodeInfo.ewhemi,E_data);
			printf("纬度:%c,%d\r\n",GPS_DecodeInfo.nshemi,N_data);		
      printf("移动速度:%.1f. km/h\r\n",GPS_DecodeInfo.speed/1000.0);
    }
    if(GPS_DecodeInfo.posslnum>=3 && stat2==0)//卫星数量超过3颗开始定位
    {
      printf("stat2==%d\n",stat2);
      BEEP=1;
      DelayMs(1000);
      BEEP=0;
      stat2=1;
      
    }
    key=GetKeyVual(1);
    if(key==1 && stat2==1)//开始
    {
      LED1=!LED1;
      stat=0;
      x=5;
      y=60;
    }
    else if(key==2)//退出
    {
      LED3=LED2=1;
      LED1=!LED1;
      stat=0xff;
      stat2=0;
      y=16;
      goto AA;//重新选择距离
    }
    OLED_ClearGram();
    OLED_Display_Font(15,35,16,2);
    OLED_Display_Font(15+16,35,16,3);
    snprintf(buff,sizeof(buff),":%d M",distance);
    OLED_Display_str(15+16*2,35,16,(u8 *)buff);
    OLED_Display_Font(15,15,16,0);
    OLED_Display_Font(15+16,15,16,1);
    //snprintf(buff,sizeof(buff),":%.fkm/h",GPS_DecodeInfo.speed/1000.0);
    snprintf(buff,sizeof(buff),":%.fkm/h",GPS_DecodeInfo.speed/1000.0);
    OLED_Display_str(15+16*2,15,16,(u8 *)buff);
    OLED_DrawRectangle(5, 5, 124, 60);
    OLED_DrawRectangle(4, 4, 125, 61);
    gui_circle(x, y,1,3,1);
    if(stat==0)
    {
      if(N_data-N_data2>=4)
      {
        x+=2;
        N_data2=N_data;
      }
    }
    else if(stat==1)
    {
      if(N_data-N_data2>=2 || N_data2-N_data>=2)
      {
        N_data2=N_data;
        y--;
      }
    }
    else if(stat==2)
    {
      if(N_data2-N_data>=3)
      {
        N_data2=N_data;
        x-=2;
      }
    }
    else if(stat==3)
    {
      if(N_data-N_data2>=3 || N_data2-N_data>=3)
      {
        N_data2=N_data;
        y+=2;
      }
    }
    if(x>=124 && y==60)
    {
      x=124;
      stat=1;
    }
    else if(y==5 && x>=124)
    {
      x=124;
      stat=2;
    }
    else if(x<=5 && y==5)
    {
      x=5;
      stat=3;
    }
    else if(x==5 && y>=60 && (stat==3 || stat==4))
    {
      BEEP=1;
      DelayMs(100);
      BEEP=0;
      stat=4;
      LED1=LED2=1;
      LED3=!LED3;
      y=60;
      x=5;
      
    }
    if(time>=20)
    {
      time=0;
      if(stat==0xff)
      {
        LED3=LED2=1;
        LED1=!LED1;
      }
      else if(stat<=3)
      {
        LED1=LED3=1;
        LED2=!LED2;
      }
    }
    DelayMs(1);
    time++;
    OLED_RefreshGram();//更新数据到屏幕
  }
}

5.注意事项

  由于采用的是STM32F103实现本功能,该CPU主频仅有72MHZ,SRAM和flash均比较小,所以此示例并未调用地图接口实现,而是通过直接判断经纬度来决定当前位置。因此实现功能方式类似于公交报站实现方式,所有路径需要提交采集路线,进行路径保存。




审核编辑:刘清


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 单片机
    +关注

    关注

    5998

    文章

    43956

    浏览量

    620674
  • GPS技术
    +关注

    关注

    0

    文章

    26

    浏览量

    10174
  • sram
    +关注

    关注

    6

    文章

    742

    浏览量

    113890
  • STM32F103
    +关注

    关注

    33

    文章

    474

    浏览量

    62561
收藏 人收藏

    评论

    相关推荐

    更改stm32cubemx固件包下载路径后不能下载固件包,为什么?

    更改stm32cubemx固件包下载路径后不能下载固件包
    发表于 04-08 06:24

    STM32CubeMx生成工程后下次再打开,Project Manager就不能修改工程名和保存路径了怎么解决?

    STM32CubeMx生成工程后下次再打开,Project Manager就不能修改工程名和保存路径了,有什么办法解决吗?
    发表于 04-02 08:27

    求问电子设计自学路径

    新手小白也想自己做出小车、小电视甚至小机器人等等有意思的项目,有C语言基础并且对stm32有了一丁点基础的了解,但是硬件、电路设计以及更高阶的程序语言仍然一窍不通。请问自学路径是怎么样的(硬件和软件)?如何从0开始入门呢?如果有推荐的网课或者书籍,那就更好啦!谢谢各位大佬
    发表于 03-23 21:42

    WT2605C-32N语音芯片:跑步机音乐新搭档,畅享健康奔跑旋律

    在现代健身领域,唯创知音的WT2605C-32N蓝牙音频MP3音乐解码语音芯片IC作为音乐解码的新搭档,为跑步机带来了更为智能、富有音乐节奏的健康奔跑体验,引领跑步健身的新时代。1.蓝牙连接,自由
    的头像 发表于 12-13 09:19 177次阅读
    WT2605C-32N语音芯片:<b class='flag-5'>跑步</b>机音乐新搭档,畅享健康奔跑旋律

    Matlab中如何绘制最优路径

    绘制最优路径 从目标点开始,依次根据节点及父节点回推规划的路径直至起点,要注意tree结构体中parent的长度比child要小1。最后将规划的路径显示在figure中。 %% 绘制最优路径
    的头像 发表于 11-24 16:34 307次阅读
    Matlab中如何绘制最优<b class='flag-5'>路径</b>

    全局路径规划RRT算法原理

    无人驾驶路径规划 众所周知,无人驾驶大致可以分为三个方面的工作:感知,决策及控制。 路径规划是感知和控制之间的决策阶段,主要目的是考虑到车辆动力学、机动能力以及相应规则和道路边界条件下,为车辆提供
    的头像 发表于 11-24 15:57 415次阅读

    什么是信号回流路径

    什么是信号回流路径? 信号回流路径,也称为信号返回路径,是指电子系统中信号从输出端返回到输入端的路径。在一个电路或系统中,信号在经过各种组件和部件的作用后,可能会反射、散射、干扰等,形
    的头像 发表于 11-24 14:44 813次阅读

    基于ARM WinCE的跑步机控制器设计

    电子发烧友网站提供《基于ARM WinCE的跑步机控制器设计.pdf》资料免费下载
    发表于 10-12 10:34 0次下载
    基于ARM WinCE的<b class='flag-5'>跑步</b>机控制器设计

    FPGA设计存在的4类时序路径

    命令set_multicycle_path常用来约束放松路径的约束。通常情况下,这种路径具有一个典型的特征:数据多个周期翻转一次,如下图所示。因此,我们把这种路径称为多周期路径(FPG
    的头像 发表于 09-14 09:05 526次阅读
    FPGA设计存在的4类时序<b class='flag-5'>路径</b>

    跑步机CE认证ASTM F 2115-12标准测试流程

    测试跑步
    jf_68417261
    发布于 :2023年08月09日 17:13:15

    详解时序路径的相关概念

    reg2reg路径约束的对象是源寄存器(时序路径的起点)和目的寄存器(时序路径的终点)都在FPGA内部的路径
    的头像 发表于 06-26 14:28 662次阅读
    详解时序<b class='flag-5'>路径</b>的相关概念

    FPGA时序分析之关键路径

    关键路径通常是指同步逻辑电路中,组合逻辑时延最大的路径(这里我认为还需要加上布线的延迟),也就是说关键路径是对设计性能起决定性影响的时序路径
    发表于 06-21 14:14 1351次阅读
    FPGA时序分析之关键<b class='flag-5'>路径</b>

    FPGA时序约束之伪路径和多周期路径

    前面几篇FPGA时序约束进阶篇,介绍了常用主时钟约束、衍生时钟约束、时钟分组约束的设置,接下来介绍一下常用的另外两个时序约束语法“伪路径”和“多周期路径”。
    发表于 06-12 17:33 978次阅读

    CS1262让跑步健康测量更精准

    “如果你想强壮,跑步吧如果你想健美,跑步吧如果你想聪明,跑步吧”——古希腊格言跑步是一种生活方式,也是一门艺术。2020年,美国癌症协会(ACS)公布预防癌症的运动与饮食指南,指出成人
    的头像 发表于 06-12 10:16 601次阅读
    CS1262让<b class='flag-5'>跑步</b>健康测量更精准