匿名四轴上位机使用手册
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;i3+i]=data[i]; //复制数据 for(i=0;i 3;i++)send_buf[len+3]+=send_buf[i]; //计算校验和 for(i=0;i 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>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;i3+i]=data[i]; //复制数据 for(i=0;i 3;i++)send_buf[len+3]+=send_buf[i]; //计算校验和 for(i=0;i 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); } }