STM32走行軌跡記録に基づく
科学技術の絶え間ない進歩により、電子機器は私たちの日常生活に浸透し続けています。生活水準の向上に伴い、さまざまなフィットネス運動が登場していますが、フィットネス運動は闇雲に行うものではなく、科学的なフィットネス法のみが私たち自身の体力を効果的に向上させることができます。
現在、それぞれのブレスレットと時計の出現により、ユーザーはスマートブレスレットを通じて、日常生活における運動、睡眠、一部の食事などのリアルタイムデータを記録し、これらのデータを携帯電話や平等と同期して、健康を導くことができます。データの役割を通じて人生を生きます。
スマートブレスレットはウェアラブルデバイスとして比較的強力な機能を備えており、その開発には、スマートブレスレットからBluetooth ICへのMCUデータ命令の送信、BluetoothからAPPへのデータ通信プロトコル、APPからアプリへの通信デバッグロジックの実装が含まれます。携帯電話やAPPデータの実現、クラウドサーバーのデータベースアルゴリズム設計などの一連の開発。複数のスポーツモニタリングモードをサポートし、体のさまざまなパフォーマンス指標をリアルタイムでモニタリングできます。
我が国のスマートブレスレット製品が本格的に消費者市場に大規模に参入したのは2012年以降であり、一方で、この時期が4G時代に入ってからは、携帯電話のインテリジェンス化の傾向が加速し、研究と応用が新たな世界を切り開きました。一方で、より実用的な機能も急速に登場しており、ブレスレットは身体的特徴を記録するための単純なツールであるだけでなく、通話、モバイル決済、人体認識、インテリジェントなリマインダー機能、共有機能などを備えており、アプリケーションを大幅に拡大しています。リストバンドの人口。スマートブレスレットを身に着けると、健康、テクノロジー、自信、センスが得られ、典型的なハイテク製品の 1 つとなっています。
STM32に基づくランニングパス記録は主にユーザーの毎日の運動記録に使用され、ランニングパスの設定、ランニングルートの計画、50~80m手前での方向転換のリマインド、ブザーアラームプロンプトの通知、ランニングパスの記録、現在位置を表示し、 ボタンを押す 走行距離を設定します。
- ビデオディスプレイ
GPS測位パスを保存する
1. モジュールの選択
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 の 2 つのアンテナ インターフェイスを備えているため、必要な外部アンテナを選択するのが便利です。
- PPSタイミング出力端子を備えており、クロック同期などの用途に便利です。
2.4 ブザー
ブザー:アクティブブザー
3. 回路設計
3. 物理的な表示
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; i<len; i++)
{
p1=(u8*)strstr((const char *)p,"$BDGSV");
if(!p1)return; //没有查找成功
for(j=0; j<4; j++)
{
posx=GPS_GetCommaOffset(p1,4+j*4);
if(posx!=0XFF)GPS_DecodeInfo->beidou_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 とフラッシュは比較的小さいため、この例ではマップ インターフェイスを呼び出さず、緯度と緯度を判断して現在位置を直接決定します。経度。したがって、この機能を実現する方法は、バス停のアナウンスを実現する方法と同様であり、ルートを収集して保存するには、すべてのルートを送信する必要があります。