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均比较小,所以此示例并未调用地图接口实现,而是通过直接判断经纬度来决定当前位置。因此实现功能方式类似于公交报站实现方式,所有路径需要提交采集路线,进行路径保存。




审核编辑:刘清


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

    关注

    6078

    文章

    45629

    浏览量

    675420
  • GPS技术
    +关注

    关注

    0

    文章

    26

    浏览量

    10615
  • sram
    +关注

    关注

    6

    文章

    843

    浏览量

    117778
  • STM32F103
    +关注

    关注

    34

    文章

    499

    浏览量

    68359
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    [FRED] FRED的光路和光路历史记录

    用户之后使用诊断工具,如光路追迹路径报告、杂散光报告、图像伪影诊断工具,以及在分析表面中使用射线选择过滤器。 创建/用户线光历史记录文件 此选项保存每条光线的每个交点的坐标数据,可以用于重新绘制选定路径的光线轨迹。通常,这是通
    发表于 05-25 08:23

    数据记录仪(阴极保护专用)阴极保护专用数据记录

    记录
    jf_32253924
    发布于 :2026年04月28日 09:09:16

    高速数字电路回流路径怎么找

    回流路径沿着阻抗最低的路径流动,高频时就是信号线下方的参考平面。
    的头像 发表于 04-11 17:11 1259次阅读
    高速数字电路回流<b class='flag-5'>路径</b>怎么找

    多通道振弦与温度信号采集记录

    记录
    稳控自动化
    发布于 :2026年04月08日 10:14:48

    智慧奔跑,一“码”当先:鸿陆RFID技术如何重塑跑步存取新体验

    跑步,这项曾被视为孤独者修行的运动,如今已科技的力量而焕发新的生机,成为城市人群社交与健康生活的新选择。某专注于场地赛事服务的网络科技公司,创新融合鸿陆RFID技术、5G网络与AI自助终端,将公园绿
    的头像 发表于 03-13 13:52 136次阅读
    智慧奔跑,一“码”当先:鸿陆RFID技术如何重塑<b class='flag-5'>跑步</b>存取新体验

    LAT1171+STM32F745 USART1 Bootloader 失败原因分析与解决

    使用 STM32F745 进行产品开发的时候,出现了使用 STM32CubeProgramer 无法通过 USART1 Bootloader 进行程序升级的问题。为了解决客户的问题,我在 NUCLEO-F746ZG 开发板上,复现了同样的现象,本文针对这个现象,分析了该问
    发表于 01-11 17:33 0次下载

    ESP32 编译过程中 bootloader 配置阶段的 CMake 缓存冲突错误,记录

    CMake 识别的源码路径与缓存中记录的不一致。 错误原因分析 这个错误提示非常明确: CMake 当前尝试使用 D:/v5.5.1/frameworks/esp-idf-v5.5.1 路径
    发表于 12-23 07:07

    电能质量在线监测装置的暂态事件记录的事件记录容量是多少?

    电能质量在线监测装置的暂态事件记录容量分为 事件台账容量 (仅记录事件关键参数)和 波形记录容量 (完整记录事件波形数据)两类,容量大小与设备等级、存储配置密切相关,且普遍支持外部存储
    的头像 发表于 12-10 17:50 1473次阅读
    电能质量在线监测装置的暂态事件<b class='flag-5'>记录</b>的事件<b class='flag-5'>记录</b>容量是多少?

    电源管理芯片在跑步机中的应用

    跑步是一项全民性的健身运动,跑步机作为一种现代化健身器材,已经越来越多地融入到人们的日常生活当中。
    的头像 发表于 09-30 11:40 1927次阅读
    电源管理芯片在<b class='flag-5'>跑步</b>机中的应用

    京东:调用用户行为API分析购买路径,优化页面跳转逻辑

    ​  在电商平台的激烈竞争中, 用户购买路径的流畅性 直接影响转化率。京东通过深度整合用户行为API,构建了完整的购买路径分析体系,显著优化了页面跳转逻辑。以下是关键技术实现路径: 一、用户行为
    的头像 发表于 09-18 14:38 899次阅读
    京东:调用用户行为API分析购买<b class='flag-5'>路径</b>,优化页面跳转逻辑

    STM32CUBEIDE使用UCOS的时候,头文件路径已经添加了,依旧提示未找到路径怎么解决?

    在使用UCOS的时候,头文件路径已经添加了,他依旧提示未找到路径怎么解决
    发表于 07-25 06:28

    【正点原子STM32MP257开发板试用】系统更新

    【正点原子STM32MP257开发板试用】系统更新 本文介绍了正点原子 STM32MP257 开发板实现固件上传与系统更新的主要流程。 项目介绍 前期准备工作包括:官方资料更新记录查询、固件下载
    发表于 06-17 18:35

    言必信_如何选择适合跑步机的电源滤波器

    本文主要介绍了跑步机电源滤波器的作用、选择与使用要点,以及滤波器的插入损耗特性。在选择跑步机电源滤波器时,应考虑电源参数电压、电流、电磁兼容标准要求、插入损耗特性以及安规认证与安全性。
    的头像 发表于 06-09 17:12 971次阅读
    言必信_如何选择适合<b class='flag-5'>跑步</b>机的电源滤波器

    基于STM32的卫星GPS路径记录仪(附完整源代码)实例项目下载

    基于STM32的卫星GPS路径记录仪(附完整源代码)实例项目推荐下载!
    发表于 05-29 21:35

    每周推荐!基于STM32开发项目实例下载(含PCB、原理图、源码等)

    、论文等) 基于STM32的武警哨位联动报警系统设计,支持以太网和WIFI通信(硬件、源码、论文等) 项目实例下载! 4、基于STM32的卫星GPS路径记录仪(附完整源代码) 基
    发表于 05-26 14:01