基于STM32跑步路徑記錄
隨著科技不斷進(jìn)步,電子化設(shè)備不斷進(jìn)入涌入我們的日常生活。生活水平的提高,各項(xiàng)健身運(yùn)動應(yīng)運(yùn)而生,然后,健身運(yùn)動不能盲目進(jìn)行,科學(xué)的健身方式才能有效的提升我們自身的身體素質(zhì)。
現(xiàn)如今各自手環(huán)手表的出現(xiàn), 通過智能手環(huán),用戶可以記錄日常生活中的鍛煉、睡眠、部分還有飲食等實(shí)時(shí)數(shù)據(jù),并將這些數(shù)據(jù)與手機(jī)、平等同步,起到通過數(shù)據(jù)指導(dǎo)健康生活的作用。
智能手環(huán)作為可穿戴設(shè)備,其功能還是比較強(qiáng)大的,其開發(fā)涉及智能手環(huán)MCU數(shù)據(jù)指令到藍(lán)牙IC的傳輸、藍(lán)牙到APP的數(shù)據(jù)通信協(xié)議、APP到手機(jī)內(nèi)部的通信調(diào)試邏輯實(shí)現(xiàn)、APP數(shù)據(jù)到云端服務(wù)器的數(shù)據(jù)庫算法設(shè)計(jì)等一系列的開發(fā)。支持多種運(yùn)動監(jiān)控模式,可以實(shí)時(shí)監(jiān)控身體的各項(xiàng)性能指標(biāo)。
我國智能手環(huán)產(chǎn)品真正大范圍進(jìn)入消費(fèi)市場是在2012年以后,一方面是這一時(shí)期步入4G時(shí)代以后手機(jī)智能化趨勢加快,與手機(jī)一樣具備數(shù)據(jù)分享的智能手環(huán)的出現(xiàn)給智能手環(huán)的研究和應(yīng)用打開了另一個世界。另一方面是更多實(shí)用性功能快速出現(xiàn),手環(huán)不僅僅是用來記錄身體特征的單純工具,同時(shí)也可以滿足通話、移動支付、人體識別、智能提醒功能以及分享功能,極大的擴(kuò)寬了手環(huán)的應(yīng)用人群。佩戴智能手環(huán)帶來健康、科技、自信有品位的良好感受,成為了高科技產(chǎn)品的典型之一。
??基于STM32的跑步路記錄主要用于記錄用戶在日常身體鍛煉中,可設(shè)置跑步路徑,跑步路線規(guī)劃,在50~80m前提醒拐彎,蜂鳴器報(bào)警提示;記錄跑步路徑,顯示當(dāng)前位置,通過按鍵設(shè)置跑步距離。
2.模塊選型
2.1 主控MCU:STM32F103C8最小系統(tǒng)板
??STM32最小系統(tǒng)板:STM32系統(tǒng)板
2.2 OLED顯示屏:0.96寸SPI/IIC接口
??顯示屏幕:OLED屏幕
2.3 GPS定位模塊
GPS定位:GPS模塊 北斗模塊 雙模定位 ATGM336H
支持北斗/GPS/GLONASS衛(wèi)星系統(tǒng)
支持3.3V-5V供電,可以方便接入3.3V或者5V單片機(jī)系統(tǒng)3、板載可充電電子,可加速熱啟動搜星過程
默認(rèn)波特率9600,波特率可設(shè)置
TTL電平UART接口,用戶連接單片機(jī)的串口TTL電平或者USB-TTL模塊測試。
帶有SMA和 IPEX兩種天線接口,方便選擇自己需要的外置天線。
帶有PPS授時(shí)輸出引腳,方便做時(shí)鐘同步等應(yīng)用。
2.4 蜂鳴器
??蜂鳴器:有源蜂鳴器
4.實(shí)物展示
4.軟件設(shè)計(jì)
4.1 GPS定位信息獲取
??ATGM336H采用串口協(xié)議,直接接上電源,在空曠的地方只要接收到衛(wèi)星信號即可返回衛(wèi)星定位數(shù)據(jù)。
/* 函數(shù)功能:分析BDGSV信息 函數(shù)參數(shù):GPS_DecodeInfo:nmea信息結(jié)構(gòu)體 buf:接收到的GPS數(shù)據(jù)緩沖區(qū)首地址 */ 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的條數(shù) posx=GPS_GetCommaOffset(p1,3); //得到可見北斗衛(wèi)星總數(shù) 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); //得到衛(wèi)星編號 else break; posx=GPS_GetCommaOffset(p1,5+j*4); if(posx!=0XFF)GPS_DecodeInfo->beidou_slmsg[slx].beidou_eledeg=GPS_StrtoNum(p1+posx,&dx);//得到衛(wèi)星仰角 else break; posx=GPS_GetCommaOffset(p1,6+j*4); if(posx!=0XFF)GPS_DecodeInfo->beidou_slmsg[slx].beidou_azideg=GPS_StrtoNum(p1+posx,&dx);//得到衛(wèi)星方位角 else break; posx=GPS_GetCommaOffset(p1,7+j*4); if(posx!=0XFF)GPS_DecodeInfo->beidou_slmsg[slx].beidou_sn=GPS_StrtoNum(p1+posx,&dx); //得到衛(wèi)星信噪比 else break; slx++; } p=p1+1;//切換到下一個BDGSV信息 } }
4.2 衛(wèi)星數(shù)量獲取
/* 函數(shù)功能:分析GNGGA信息 函數(shù)參數(shù): GPS_DecodeInfo:nmea信息結(jié)構(gòu)體 buf:接收到的GPS數(shù)據(jù)緩沖區(qū)首地址 */ 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狀態(tài) if(posx!=0XFF)GPS_DecodeInfo->gpssta=GPS_StrtoNum(p1+posx,&dx); posx=GPS_GetCommaOffset(p1,7); //得到用于定位的衛(wèi)星數(shù) 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 移動速度獲取
/* 函數(shù)功能:分析GNVTG信息 函數(shù)參數(shù):GPS_DecodeInfo:nmea信息結(jié)構(gòu)體 buf:接收到的GPS數(shù)據(jù)緩沖區(qū)首地址 */ 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); //確保擴(kuò)大1000倍 } }
4.4 主函數(shù)
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數(shù)據(jù)) TIMx_Init(TIM2,72,20000);//定時(shí)20ms,用定時(shí)器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();//更新數(shù)據(jù)到屏幕 } else if(key==2)//確認(rèn) { BEEP=1; if(y==16)distance=400; else if(y==32)distance=1000; else if(y==48)distance=2000; OLED_RefreshGram();//更新數(shù)據(jù)到屏幕 DelayMs(50); BEEP=0; DelayMs(200); break; } DelayMs(1); time++; if(time>=50) { time=0; OLED_RefreshGram();//更新數(shù)據(jù)到屏幕 LED1=!LED1; } } y=60; while(1) { if(usart2_flag)//獲取GPS數(shù)據(jù) { 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);//獲取衛(wèi)星數(shù)量 GPS_GNVTG_InfoGet(&GPS_DecodeInfo,usart2_rx_buff);//獲取移動速度 GPS_GNRMC_InfoGet(&GPS_DecodeInfo,usart2_rx_buff);//獲取經(jīng)緯度 printf("衛(wèi)星數(shù)量: %d\r\n",GPS_DecodeInfo.posslnum); E_data=GPS_DecodeInfo.longitude; N_data=GPS_DecodeInfo.latitude; printf("經(jīng)度:%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)//衛(wèi)星數(shù)量超過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();//更新數(shù)據(jù)到屏幕 } }
5.注意事項(xiàng)
??由于采用的是STM32F103實(shí)現(xiàn)本功能,該CPU主頻僅有72MHZ,SRAM和flash均比較小,所以此示例并未調(diào)用地圖接口實(shí)現(xiàn),而是通過直接判斷經(jīng)緯度來決定當(dāng)前位置。因此實(shí)現(xiàn)功能方式類似于公交報(bào)站實(shí)現(xiàn)方式,所有路徑需要提交采集路線,進(jìn)行路徑保存。
審核編輯:劉清
-
單片機(jī)
+關(guān)注
關(guān)注
6030文章
44498瀏覽量
632155 -
GPS技術(shù)
+關(guān)注
關(guān)注
0文章
26瀏覽量
10240 -
sram
+關(guān)注
關(guān)注
6文章
762瀏覽量
114596 -
STM32F103
+關(guān)注
關(guān)注
33文章
475瀏覽量
63422
發(fā)布評論請先 登錄
相關(guān)推薦
評論