匿名四軸上位機使用手冊
1、串口功能
軟件界面
串口功能和串口助手等軟件功能類似,設置也差不多。
1.設置接收格式、端口、波特率即可。
2.打開基本收碼功能。
3.打開串口。
4.測試:
2、高級收碼
高級收碼設置選項卡:
1.1-10對應0XA1-0XAA,我們只需要按定義幀設置即可,我這里使用0XA2,選擇2,並打開開關。
2.因為我需要查看的有三個數據,pitch,roll,yaw,並為float類型,所以如此設置。
3.最后打開高級收碼功能,如果你需要實時查看上傳的數據可以打開收碼顯示。
4.打開串口。
5.測試:
3、波形顯示
波形顯示功能需要在高級收碼的功能上做修改。
波形顯示設置選項卡如下:
1.1-20序號對應的是波形序號,也就是說最多能指定顯示20個波形,我們這里有pitch,roll,yaw三個波形,所以設置1,2,3。
2.設置第一個波形1,它來源於數據幀2的第一位。
3.設置第一個波形2,它來源於數據幀2的第二位。
4.設置第一個波形3,它來源於數據幀2的第三位。
5.打開數據校驗,數據顯示。
6.打開波形顯示。
7.在波形顯示頁面勾上前三個即可:
8.打開串口。
9.測試:
4、飛控狀態
使用到此功能再補充。
5、上傳數據的單片機程序
以下為上傳三個角度的代碼,串口初始化等略過:
void usart1_send_char(u8 c) { while((USART1->SR&0X40)==0);//等待上一次發送完畢 USART1->DR=c; } //fun:功能字. 0XA0~0XAF //data:數據緩存區,最多28字節!! //len:data區有效數據個數 void usart1_niming_report(u8 fun,u8*data,u8 len) { u8 send_buf[32]; u8 i; if(len>28)return; //最多28字節數據 send_buf[len+3]=0; //校驗數置零 send_buf[0]=0X88; //幀頭 send_buf[1]=fun; //功能字 send_buf[2]=len; //數據長度 for(i=0;i<len;i++)send_buf[3+i]=data[i]; //復制數據 for(i=0;i<len+3;i++)send_buf[len+3]+=send_buf[i]; //計算校驗和 for(i=0;i<len+4;i++)usart1_send_char(send_buf[i]); //發送數據到串口1 } void mpu6050_send_data(float pitch,float roll,float yaw) { u8 tbuf[16]; unsigned char *p; p=(unsigned char *)&pitch; tbuf[0]=(unsigned char)(*(p+3)); tbuf[1]=(unsigned char)(*(p+2)); tbuf[2]=(unsigned char)(*(p+1)); tbuf[3]=(unsigned char)(*(p+0)); p=(unsigned char *)&roll; tbuf[4]=(unsigned char)(*(p+3)); tbuf[5]=(unsigned char)(*(p+2)); tbuf[6]=(unsigned char)(*(p+1)); tbuf[7]=(unsigned char)(*(p+0)); p=(unsigned char *)&yaw; tbuf[8]=(unsigned char)(*(p+3)); tbuf[9]=(unsigned char)(*(p+2)); tbuf[10]=(unsigned char)(*(p+1)); tbuf[11]=(unsigned char)(*(p+0)); usart1_niming_report(0XA2,tbuf,12);//自定義幀,0XA2 }
注意:最后一個函數把float拆成四個字節發送(由於串口只能一個字節一個字節的發送),用指針獲得float型變量的首地址,然后強制轉換為unsigned char型,地址逐漸加大把float的四個字節分別發出即可。
6、更多參考
匿名四軸上位機視頻教程:https://v.youku.com/v_show/id_XNTkzNDkxNTU2.html
另外在個人的無人機中使用如下:
/********************************************************************************* * 文件名 :main.c * 描述 :無人機 * 實驗平台: STM32開發板 * 庫版本 :ST3.5.0 * 作者 : 零 **********************************************************************************/ #include "stm32f10x.h" #include "pwm_output.h" #include "key.h" #include "delay.h" #include "QDTFT_demo.h" #include "led.h" #include "Lcd_Driver.h" #include "mpu6050.h" #include "inv_mpu.h" #include "inv_mpu_dmp_motion_driver.h" #include "usart.h" #include "delay.h" #include "misc.h" #include "GUI.h" #include "pid_1.h" #include "math.h" #include "control.h" #include "string.h" #include "usmart.h" #include "stm32f10x_usart.h" /************************************************/ //串口1發送1個字符 //c:要發送的字符 void usart1_send_char(u8 c) { while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET); //循環發送,直到發送完畢 USART_SendData(USART1,c); } /* //傳送數據給匿名四軸上位機軟件(V2.6版本) //fun:功能字. 0XA0~0XAF //data:數據緩存區,最多28字節!! //len:data區有效數據個數 void usart1_niming_report(u8 fun,u8*data,u8 len) { u8 send_buf[32]; u8 i; if(len>28)return; //最多28字節數據 send_buf[len+3]=0; //校驗數置零 send_buf[0]=0X88; //幀頭 send_buf[1]=fun; //功能字 send_buf[2]=len; //數據長度 for(i=0;i<len;i++)send_buf[3+i]=data[i]; //復制數據 for(i=0;i<len+3;i++)send_buf[len+3]+=send_buf[i]; //計算校驗和 for(i=0;i<len+4;i++)usart1_send_char(send_buf[i]); //發送數據到串口1 } //if(report)mpu6050_send_data(aacx,aacy,aacz,gyrox,gyroy,gyroz);//用自定義幀發送加速度和陀螺儀原始數據 //if(report)usart1_report_imu(aacx,aacy,aacz,gyrox,gyroy,gyroz,(int)(roll*100),(int)(pitch*100),(int)(yaw*10)); //發送加速度傳感器數據和陀螺儀數據 //aacx,aacy,aacz:x,y,z三個方向上面的加速度值 //gyrox,gyroy,gyroz:x,y,z三個方向上面的陀螺儀值 void mpu6050_send_data(short aacx,short aacy,short aacz,short gyrox,short gyroy,short gyroz) { u8 tbuf[12]; tbuf[0]=(aacx>>8)&0XFF; tbuf[1]=aacx&0XFF; tbuf[2]=(aacy>>8)&0XFF; tbuf[3]=aacy&0XFF; tbuf[4]=(aacz>>8)&0XFF; tbuf[5]=aacz&0XFF; tbuf[6]=(gyrox>>8)&0XFF; tbuf[7]=gyrox&0XFF; tbuf[8]=(gyroy>>8)&0XFF; tbuf[9]=gyroy&0XFF; tbuf[10]=(gyroz>>8)&0XFF; tbuf[11]=gyroz&0XFF; usart1_niming_report(0XA1,tbuf,12);//自定義幀,0XA1 } //通過串口1上報結算后的姿態數據給電腦 //aacx,aacy,aacz:x,y,z三個方向上面的加速度值 //gyrox,gyroy,gyroz:x,y,z三個方向上面的陀螺儀值 //roll:橫滾角.單位0.01度。 -18000 -> 18000 對應 -180.00 -> 180.00度 //pitch:俯仰角.單位 0.01度。-9000 - 9000 對應 -90.00 -> 90.00 度 //yaw:航向角.單位為0.1度 0 -> 3600 對應 0 -> 360.0度 void usart1_report_imu(short aacx,short aacy,short aacz,short gyrox,short gyroy,short gyroz,short roll,short pitch,short yaw) { u8 tbuf[28]; u8 i; for(i=0;i<28;i++)tbuf[i]=0;//清0 tbuf[0]=(aacx>>8)&0XFF; tbuf[1]=aacx&0XFF; tbuf[2]=(aacy>>8)&0XFF; tbuf[3]=aacy&0XFF; tbuf[4]=(aacz>>8)&0XFF; tbuf[5]=aacz&0XFF; tbuf[6]=(gyrox>>8)&0XFF; tbuf[7]=gyrox&0XFF; tbuf[8]=(gyroy>>8)&0XFF; tbuf[9]=gyroy&0XFF; tbuf[10]=(gyroz>>8)&0XFF; tbuf[11]=gyroz&0XFF; tbuf[18]=(roll>>8)&0XFF; tbuf[19]=roll&0XFF; tbuf[20]=(pitch>>8)&0XFF; tbuf[21]=pitch&0XFF; tbuf[22]=(yaw>>8)&0XFF; tbuf[23]=yaw&0XFF; usart1_niming_report(0XAF,tbuf,28);//飛控顯示幀,0XAF } ************************************************/ //fun:功能字. 0XA0~0XAF //data:數據緩存區,最多28字節!! //len:data區有效數據個數 void usart1_niming_report(u8 fun,u8*data,u8 len) { u8 send_buf[32]; u8 i; if(len>28)return; //最多28字節數據 send_buf[len+3]=0; //校驗數置零 send_buf[0]=0X88; //幀頭 send_buf[1]=fun; //功能字 send_buf[2]=len; //數據長度 for(i=0;i<len;i++)send_buf[3+i]=data[i]; //復制數據 for(i=0;i<len+3;i++)send_buf[len+3]+=send_buf[i]; //計算校驗和 for(i=0;i<len+4;i++)usart1_send_char(send_buf[i]); //發送數據到串口1 } void mpu6050_send_data(float pitch,float roll,float yaw) { u8 tbuf[16]; unsigned char *p; p=(unsigned char *)&pitch; tbuf[0]=(unsigned char)(*(p+3)); tbuf[1]=(unsigned char)(*(p+2)); tbuf[2]=(unsigned char)(*(p+1)); tbuf[3]=(unsigned char)(*(p+0)); p=(unsigned char *)&roll; tbuf[4]=(unsigned char)(*(p+3)); tbuf[5]=(unsigned char)(*(p+2)); tbuf[6]=(unsigned char)(*(p+1)); tbuf[7]=(unsigned char)(*(p+0)); p=(unsigned char *)&yaw; tbuf[8]=(unsigned char)(*(p+3)); tbuf[9]=(unsigned char)(*(p+2)); tbuf[10]=(unsigned char)(*(p+1)); tbuf[11]=(unsigned char)(*(p+0)); usart1_niming_report(0XA2,tbuf,12);//自定義幀,0XA2 } u16 pwm1=2000,pwm2=2000,pwm3=2000,pwm4=2000; /************************************************/ /* * 函數名:main * 描述 :主函數 * 輸入 :無 * 輸出 :無 */ int main(void) { u8 report=1; //默認開啟上報 u8 res; u8 test[20]; u8 temp_value[20]; //存儲陀螺儀的臨時值 u8 temp_value2[20]; //存儲pwm輸出的臨時值 u8 t=0; u8 key; //按鍵值 u8 key_status=0; //按鍵狀態 u8 keystatus=0; //按鍵s4的狀態值 float temp; float pitch,roll,yaw; //歐拉角 short aacx,aacy,aacz; //加速度傳感器原始數據 short gyrox,gyroy,gyroz; //陀螺儀原始數據 int Motor1=0; //電機1輸出 int Motor2=0; //電機2輸出 int Motor3=0; //電機3輸出 int Motor4=0; //電機4輸出 float Pitch; float Roll; float Yaw; PIDx_init(); PIDy_init(); PIDz_init(); pitch_init(); roll_init(); yaw_init(); NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //設置NVIC中斷分組2:2位搶占優先級,2位響應優先級 delay_init(); KEY_Init(); uart_init(500000); //初始化串口 usmart_dev.init(72); //初始化USMART pwm_init();/* TIM3 PWM波輸出初始化,並使能TIM3 PWM輸出 */ Lcd_Init(); LCD_LED_SET;//通過IO控制背光亮 Lcd_Clear(GRAY0); delay_ms(1000); MPU_Init(); //初始化MPU6050 Gui_DrawFont_GBK16(25,30,YELLOW,GRAY0,"Start check"); while(mpu_dmp_init())Gui_DrawFont_GBK16(16,50,YELLOW,GRAY0,"MPU6050 Error"); Gui_DrawFont_GBK16(25,50,YELLOW,GRAY0,"MPU6050 OK"); Lcd_Clear(GRAY0); Gui_DrawFont_GBK16(25,30,YELLOW,GRAY0,"S3->shuju"); Gui_DrawFont_GBK16(25,50,BLUE,GRAY0,"S4->PWM"); while (1){ if(keystatus!=1&&key!=2) key=KEY_Scan(0); //得到鍵值 if(key) { switch(key) { case KEY0_PRES: // { Lcd_Clear(GRAY0); Gui_DrawFont_GBK16(25,30,YELLOW,GRAY0,"M1: "); Gui_DrawFont_GBK16(25,50,BLUE,GRAY0,"M2: "); Gui_DrawFont_GBK16(25,70,RED,GRAY0, "M3: "); Gui_DrawFont_GBK16(25,90,BLUE,GRAY0,"M4: "); while (1) { key = KEY_Scan(1); if (key) switch(key) { case KEY1_PRES: key_status=1; break; } if(key_status==1) break; //有沒有更新值,有更新新的值就會繼續往下執行 if(mpu_dmp_get_data(&pitch,&roll,&yaw)==0) { /* MPU_Get_Accelerometer(&aacx,&aacy,&aacz); //得到加速度傳感器數據 MPU_Get_Gyroscope(&gyrox,&gyroy,&gyroz); //得到陀螺儀數據 */ Pitch = PIDx_out_realize(pitch); Roll = PIDy_out_realize(roll); Yaw = PIDz_out_realize(yaw); //Pitch +=PIDx_inner_realize(pitch); //Roll +=PIDy_inner_realize(roll); //Yaw +=PIDz_inner_realize(yaw); //Motor1 = (int)(2200 - Pitch + Roll - Yaw); //Motor2 = (int)(2200 + Pitch + Roll + Yaw); //Motor3 = (int)(2200 + Pitch - Roll - Yaw); //Motor4 = (int)(2200 - Pitch - Roll + Yaw); Motor1 = (int)(2500 + Pitch - Roll); Motor2 = (int)(2500 + Pitch + Roll); Motor3 = (int)(2500 - Pitch + Roll); Motor4 = (int)(2500 - Pitch - Roll); //TIM_SetCompare1(TIM3,Motor4);// //TIM_SetCompare2(TIM3,Motor1);// //TIM_SetCompare3(TIM3,Motor2);// //TIM_SetCompare4(TIM3,Motor3);// if(t%1==0) { sprintf(temp_value2,"%4d",Motor4); Gui_DrawFont_GBK16(50,30,BLUE,GRAY0,temp_value2); sprintf(temp_value2,"%4d",Motor1); Gui_DrawFont_GBK16(50,50,BLUE,GRAY0,temp_value2); sprintf(temp_value2,"%4d",Motor2); Gui_DrawFont_GBK16(50,70,BLUE,GRAY0,temp_value2); sprintf(temp_value2,"%4d",Motor3); Gui_DrawFont_GBK16(50,90,BLUE,GRAY0,temp_value2); if(report)mpu6050_send_data(pitch,roll,yaw);//用自定義幀發送加速度和陀螺儀原始數據 //if(report)usart1_report_imu(aacx,aacy,aacz,gyrox,gyroy,gyroz,(int)(roll*100),(int)(pitch*100),(int)(yaw*10)); } } t++; } key_status=0; } case KEY1_PRES: // { keystatus = 0; Lcd_Clear(GRAY0); Gui_DrawFont_GBK16(25,50,BLUE,GRAY0,"Pitch: .C"); Gui_DrawFont_GBK16(25,70,RED,GRAY0, "Roll: .C"); Gui_DrawFont_GBK16(25,90,BLUE,GRAY0,"Yaw : .C"); while(1){ key = KEY_Scan(0); if (key) switch(key) { case KEY0_PRES: key_status=1; break; } if(key_status==1) break; if(mpu_dmp_get_data(&pitch,&roll,&yaw)==0) { //MPU_Get_Accelerometer(&aacx,&aacy,&aacz); //得到加速度傳感器數據 //MPU_Get_Gyroscope(&gyrox,&gyroy,&gyroz); //得到陀螺儀數據 Pitch = PIDx_out_realize(pitch); Roll = PIDy_out_realize(roll); Yaw = PIDz_out_realize(yaw); //Pitch +=PIDx_inner_realize(pitch); //Roll +=PIDy_inner_realize(roll); //Yaw +=PIDz_inner_realize(yaw); //Motor1 = (int)(2200 - Pitch + Roll - Yaw); //Motor2 = (int)(2200 + Pitch + Roll + Yaw); //Motor3 = (int)(2200 + Pitch - Roll - Yaw); //Motor4 = (int)(2200 - Pitch - Roll + Yaw); Motor1 = (int)(2500 + Pitch - Roll); Motor2 = (int)(2500 + Pitch + Roll); Motor3 = (int)(2500 - Pitch + Roll); Motor4 = (int)(2500 - Pitch - Roll); //TIM_SetCompare1(TIM3,Motor4);// //TIM_SetCompare2(TIM3,Motor1);// //TIM_SetCompare3(TIM3,Motor2);// //TIM_SetCompare4(TIM3,Motor3);// temp=pitch; if(temp<0) { Gui_DrawFont_GBK16(10,50,BLUE,GRAY0,"-"); temp=-temp; //轉為正數 }else Gui_DrawFont_GBK16(10,50,BLUE,GRAY0," ");//去掉負號 sprintf(temp_value,"%.2f",temp); Gui_DrawFont_GBK16(70,50,BLUE,GRAY0,temp_value); temp=roll; if(temp<0) { Gui_DrawFont_GBK16(10,70,BLUE,GRAY0,"-"); temp=-temp; //轉為正數 }else Gui_DrawFont_GBK16(10,70,BLUE,GRAY0," ");//去掉負號 sprintf(temp_value,"%.2f",temp); Gui_DrawFont_GBK16(65,70,BLUE,GRAY0,temp_value); temp=yaw; //z軸 if(temp<0) { Gui_DrawFont_GBK16(10,90,BLUE,GRAY0,"-"); temp=-temp; //轉為正數 }else Gui_DrawFont_GBK16(10,90,BLUE,GRAY0," ");//去掉負號 sprintf(temp_value,"%.2f",temp); Gui_DrawFont_GBK16(65,90,BLUE,GRAY0,temp_value); } if(report)mpu6050_send_data(pitch,roll,yaw);//用自定義幀發送加速度和陀螺儀原始數據 //if(report)usart1_report_imu(aacx,aacy,aacz,gyrox,gyroy,gyroz,(int)(roll*100),(int)(pitch*100),(int)(yaw*10)); } key_status=0; keystatus=1; } case KEY2_PRES: // break; case KEY3_PRES: // break; case KEY4_PRES: // break; } }else delay_ms(10); } }