基于STM32跑步路徑記錄
隨著科技不斷進(jìn)步,電子化設(shè)備不斷進(jìn)入涌入我們的日常生活。生活水平的提高,各項(xiàng)健身運(yùn)動(dòng)應(yīng)運(yùn)而生,然后,健身運(yùn)動(dòng)不能盲目進(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)動(dòng)監(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)用打開了另一個(gè)世界。另一方面是更多實(shí)用性功能快速出現(xiàn),手環(huán)不僅僅是用來記錄身體特征的單純工具,同時(shí)也可以滿足通話、移動(dòng)支付、人體識(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、板載可充電電子,可加速熱啟動(dòng)搜星過程
默認(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)星信號(hào)即可返回衛(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)星編號(hào)
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;//切換到下一個(gè)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 移動(dòng)速度獲取
/*
函數(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);//獲取移動(dòng)速度
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("移動(dòng)速度:%.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)注
6074文章
45451瀏覽量
667015 -
GPS技術(shù)
+關(guān)注
關(guān)注
0文章
26瀏覽量
10581 -
sram
+關(guān)注
關(guān)注
6文章
814瀏覽量
117332 -
STM32F103
+關(guān)注
關(guān)注
34文章
493瀏覽量
67403
發(fā)布評(píng)論請(qǐng)先 登錄
LAT1171+STM32F745 USART1 Bootloader 失敗原因分析與解決
ESP32 編譯過程中 bootloader 配置階段的 CMake 緩存沖突錯(cuò)誤,記錄
電能質(zhì)量在線監(jiān)測裝置的暫態(tài)事件記錄的事件記錄容量是多少?
電源管理芯片在跑步機(jī)中的應(yīng)用
京東:調(diào)用用戶行為API分析購買路徑,優(yōu)化頁面跳轉(zhuǎn)邏輯
STM32CUBEIDE使用UCOS的時(shí)候,頭文件路徑已經(jīng)添加了,依舊提示未找到路徑怎么解決?
智能路徑調(diào)度:AI驅(qū)動(dòng)負(fù)載均衡的異常路徑治理實(shí)踐
【正點(diǎn)原子STM32MP257開發(fā)板試用】系統(tǒng)更新
AGV小車中的動(dòng)態(tài)路徑規(guī)劃算法揭秘
言必信_(tái)如何選擇適合跑步機(jī)的電源濾波器
基于STM32的衛(wèi)星GPS路徑記錄儀(附完整源代碼)實(shí)例項(xiàng)目下載
每周推薦!基于STM32開發(fā)項(xiàng)目實(shí)例下載(含PCB、原理圖、源碼等)
基于STM32的衛(wèi)星GPS路徑記錄儀(附完整源代碼)
FRED的光路和光路歷史記錄
基于STM32跑步路徑記錄
評(píng)論