基于STM32跑步路徑記錄
隨著科技不斷進步,電子化設備不斷進入涌入我們的日常生活。生活水平的提高,各項健身運動應運而生,然后,健身運動不能盲目進行,科學的健身方式才能有效的提升我們自身的身體素質。
現如今各自手環手表的出現, 通過智能手環,用戶可以記錄日常生活中的鍛煉、睡眠、部分還有飲食等實時數據,并將這些數據與手機、平等同步,起到通過數據指導健康生活的作用。
智能手環作為可穿戴設備,其功能還是比較強大的,其開發涉及智能手環MCU數據指令到藍牙IC的傳輸、藍牙到APP的數據通信協議、APP到手機內部的通信調試邏輯實現、APP數據到云端服務器的數據庫算法設計等一系列的開發。支持多種運動監控模式,可以實時監控身體的各項性能指標。
我國智能手環產品真正大范圍進入消費市場是在2012年以后,一方面是這一時期步入4G時代以后手機智能化趨勢加快,與手機一樣具備數據分享的智能手環的出現給智能手環的研究和應用打開了另一個世界。另一方面是更多實用性功能快速出現,手環不僅僅是用來記錄身體特征的單純工具,同時也可以滿足通話、移動支付、人體識別、智能提醒功能以及分享功能,極大的擴寬了手環的應用人群。佩戴智能手環帶來健康、科技、自信有品位的良好感受,成為了高科技產品的典型之一。
??基于STM32的跑步路記錄主要用于記錄用戶在日常身體鍛煉中,可設置跑步路徑,跑步路線規劃,在50~80m前提醒拐彎,蜂鳴器報警提示;記錄跑步路徑,顯示當前位置,通過按鍵設置跑步距離。
2.模塊選型
2.1 主控MCU:STM32F103C8最小系統板
??STM32最小系統板:STM32系統板
2.2 OLED顯示屏:0.96寸SPI/IIC接口
??顯示屏幕:OLED屏幕
2.3 GPS定位模塊
GPS定位:GPS模塊 北斗模塊 雙模定位 ATGM336H
支持北斗/GPS/GLONASS衛星系統
支持3.3V-5V供電,可以方便接入3.3V或者5V單片機系統3、板載可充電電子,可加速熱啟動搜星過程
默認波特率9600,波特率可設置
TTL電平UART接口,用戶連接單片機的串口TTL電平或者USB-TTL模塊測試。
帶有SMA和 IPEX兩種天線接口,方便選擇自己需要的外置天線。
帶有PPS授時輸出引腳,方便做時鐘同步等應用。
2.4 蜂鳴器
??蜂鳴器:有源蜂鳴器
3.電路設計
4.實物展示
4.軟件設計
4.1 GPS定位信息獲取
??ATGM336H采用串口協議,直接接上電源,在空曠的地方只要接收到衛星信號即可返回衛星定位數據。
/* 函數功能:分析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均比較小,所以此示例并未調用地圖接口實現,而是通過直接判斷經緯度來決定當前位置。因此實現功能方式類似于公交報站實現方式,所有路徑需要提交采集路線,進行路徑保存。
審核編輯:劉清
-
單片機
+關注
關注
6035文章
44553瀏覽量
634727 -
GPS技術
+關注
關注
0文章
26瀏覽量
10257 -
sram
+關注
關注
6文章
767瀏覽量
114677 -
STM32F103
+關注
關注
33文章
477瀏覽量
63603
發布評論請先 登錄
相關推薦
評論