赞
踩
本项目中无人机机载PM2.5和温度传感器,并将相关信息无线传送至自研的LABVIEW无人机地面站进行可视化显示与飞行调试。
STM32_270小四轴相对成本便宜,飞机有一定冗余负载能力,且飞控与遥控器源码开源,配合PV3953L1光流激光模块(PMW3901+VL53L1X),可实现室内低空稳定定点悬停,适合无人机二次开发和学习惯导、飞行控制等基本理论,多数本科毕业设计基于该平台都可以快速实现期望功能。
STM32_270小四轴原生链路如下图所示,飞机与遥控之间采用无线NRF24L01通信,遥控器与电脑端上位机采用有线USB通信,
原生固件还预留了多个其他用户接口,如uart、iic、spi、io等接口便于用户二次开发。
上述多个接口也可以根据需求查找原理图和芯片资源手册重新映射资源,如将iic或spi映射为其他uart、IO、ADC等功能。
如下图所示,左上角为串口功能配置,左下为基本飞行数据数据,右上仪表为环境温度、颗粒物含量显示、遥控器剩余电量、飞行器剩余电量,右下角波形图为多个通道的数据波形图表。
部分labview后面板程序如下:
串口通信协议为自定义简单协议,帧头+数据帧方式,识别之后按位进行相关数据解析。
PM2.5传感器采用串口接口传感器,具体协议见商家描述,与四轴串口2连接通信,温度数据使用mems惯性传感器提供的信息,相关解析程序如下:
void Uart2_Receive_Prepare(u8 data)
{
static u8 _data_len = 0,_data_cnt = 0,state = 0,data1 = 0,data2 = 0;
if(state==0&&data==0xFF)//帧头1
{
state=1;
Uart2_RxBuffer[0]=data;
}
else if(state==1&&data==0x18)//帧头2
{
state=2;
Uart2_RxBuffer[1]=data;
_data_len = 5;
_data_cnt = 0;
}
else if(state==2&&_data_len>0)
{
_data_len--;
Uart2_RxBuffer[2+_data_cnt++]=data;
if(_data_len==0)
{
data1=Uart2_RxBuffer[3];
data2=Uart2_RxBuffer[4];
PM25_Data=data1*100+data2;//获取得到PM25数据
state = 0;
}
}
else state = 0;
}
四轴向遥控器发送相关数据程序如下:
void ANO_DT_Data_Exchange(void) //飞机发送数据到遥控器,遥控再上传到上位机,4ms调用一次
{
if(Send_Check)//接收回验,上位机发送的数据在飞机端计算校验后反馈发送至上位机,上位机判断是否发送成功(用于上位机状态反馈)
{
Send_Check = 0;
ANO_DT_Send_Data(data_to_send, 7);
}
else if(f.send_pid) //上位机请求获取PID参数标志位
{
cnt++;
switch(cnt)
{
case 1: ANO_DT_Send_PID(1,pidRateX.kp*1000,pidRateX.ki*1000,pidRateX.kd*1000,
pidRateY.kp*1000,pidRateY.ki*1000,pidRateY.kd*1000,
pidRateZ.kp*1000,pidRateZ.ki*1000,pidRateZ.kd*1000);
break;
case 2: ANO_DT_Send_PID(2,pidRoll.kp*1000,pidRoll.ki*1000,pidRoll.kd*1000,
pidPitch.kp*1000,pidPitch.ki*1000,pidPitch.kd*1000,
pidYaw.kp*1000,pidYaw.ki*1000,pidYaw.kd*1000);
break;
case 3: ANO_DT_Send_PID(3,pidHeightRate.kp*1000,pidHeightRate.ki*1000,pidHeightRate.kd*1000,
pidHeightHigh.kp*1000,pidHeightHigh.ki*1000,pidHeightHigh.kd*1000,
Flow_SpeedPid_x.kp*1000,Flow_SpeedPid_x.ki*1000,Flow_SpeedPid_x.kd*1000);
break;
case 4: ANO_DT_Send_PID(4,Flow_PosPid_x.kp*1000,Flow_PosPid_x.ki*1000,Flow_PosPid_x.kd*1000,
Flow_SpeedPid_y.kp*1000,Flow_SpeedPid_y.ki*1000,Flow_SpeedPid_y.kd*1000,
Flow_PosPid_y.kp*1000,Flow_PosPid_y.ki*1000,Flow_PosPid_y.kd*1000);
cnt = 0; f.send_pid = 0;
break;
}
}
else if(f.send_version) //上位机请求获取飞机固件版本
{
f.send_version = 0;
//ANO_DT_Send_Version(1,ANO_Param.hardware,ANO_Param.software,510,0);
}
else //常规消息自动发送
{
cnt++;
switch(cnt)
{
case 1: ANO_DT_Send_Status(-Angle.roll,Angle.pitch,-Angle.yaw,
mini.flow_High,
ALL_flag.slock_flag,ALL_flag.unlock); // 飞控状态
break;
case 2: ANO_DT_Send_Senser(MPU6050.accX,MPU6050.accY,MPU6050.accZ, // 陀螺仪加速度数据
MPU6050.gyroX,MPU6050.gyroY,MPU6050.gyroZ, // 陀螺仪角度数据
mini.flow_x_iOUT,mini.flow_y_iOUT , mini.qual); // 光流原使数据
break;
case 3: ANO_DT_Send_RCData(Remote.thr,Remote.yaw,Remote.roll,Remote.pitch,
Remote.AUX1,Remote.AUX2,Remote.AUX3,Remote.AUX4,
NRF_SSI,Remote.AUX6); // 遥控器通道数据
break;
case 4: ANO_DT_Send_Power(voltage/10,Remote.AUX5,1,NRF_SSI,
test_flag,set_flag); //电压
break;
case 5: ANO_DT_Send_Senser2(temperature*100,PM25_Data);
break;
case 6: ANO_DT_Send_speed(pixel_flow.loc_x,pixel_flow.loc_y,
FlightData.High.bara_height); //光流模块数据
cnt = 0;
break;
/*send drone feedback data*/
}
}
}
使用串口+DMA方式发送数据至LABVIEW地面站,部分程序如下所示:
void DMA_Send_StateMachine(void)
{//DMA数据发送
/*
temperature 4 放大10倍 0~999
PM25_Data 5 放大100倍 0~9999
Show.X ROLL 4 正负三位数,放大10 -90~90
Show.Y PITCH 4
Show.Z YAW 4 -180~180
Battery_Rc 4 放大100倍 0~500
Battery_Fly 4 放大100倍 0~500
*/
Vcan_Buff.Head=0x4D49;\\ "I"+"M"识别帧头
/***************************************************************************************************************************/
send_data_temp=limit(temperature,0,999);
if(send_data_temp>0)Vcan_Buff.DataBuf[DMA_SEND_CNT++]='+';
else
{
send_data_temp=-send_data_temp;
Vcan_Buff.DataBuf[DMA_SEND_CNT++]='-';
}
send_bai=send_data_temp/100;
send_shi=send_data_temp%100/10;
send_ge=send_data_temp%100%10;
Vcan_Buff.DataBuf[DMA_SEND_CNT++]=send_bai+0x30;
Vcan_Buff.DataBuf[DMA_SEND_CNT++]=send_shi+0x30;
Vcan_Buff.DataBuf[DMA_SEND_CNT++]=send_ge+0x30;
/***************************************************************************************************************************/
send_data_temp=limit(PM25_Data,0,9999);
if(send_data_temp>0)Vcan_Buff.DataBuf[DMA_SEND_CNT++]='+';
else
{
send_data_temp=-send_data_temp;
Vcan_Buff.DataBuf[DMA_SEND_CNT++]='-';
}
send_qian=send_data_temp/1000;
send_bai=send_data_temp%1000/100;
send_shi=send_data_temp%100/10;
send_ge=send_data_temp%100%10;
Vcan_Buff.DataBuf[DMA_SEND_CNT++]=send_qian+0x30;
Vcan_Buff.DataBuf[DMA_SEND_CNT++]=send_bai+0x30;
Vcan_Buff.DataBuf[DMA_SEND_CNT++]=send_shi+0x30;
Vcan_Buff.DataBuf[DMA_SEND_CNT++]=send_ge+0x30;
/***************************************************************************************************************************/
send_data_temp=limit(Show.X,-999,999);
if(send_data_temp>0)Vcan_Buff.DataBuf[DMA_SEND_CNT++]='+';
else
{
send_data_temp=-send_data_temp;
Vcan_Buff.DataBuf[DMA_SEND_CNT++]='-';
}
send_bai=send_data_temp/100;
send_shi=send_data_temp%100/10;
send_ge=send_data_temp%100%10;
Vcan_Buff.DataBuf[DMA_SEND_CNT++]=send_bai+0x30;
Vcan_Buff.DataBuf[DMA_SEND_CNT++]=send_shi+0x30;
Vcan_Buff.DataBuf[DMA_SEND_CNT++]=send_ge+0x30;
/***************************************************************************************************************************/
send_data_temp=limit(Show.Y,-999,999);
if(send_data_temp>0)Vcan_Buff.DataBuf[DMA_SEND_CNT++]='+';
else
{
send_data_temp=-send_data_temp;
Vcan_Buff.DataBuf[DMA_SEND_CNT++]='-';
}
send_bai=send_data_temp/100;
send_shi=send_data_temp%100/10;
send_ge=send_data_temp%100%10;
Vcan_Buff.DataBuf[DMA_SEND_CNT++]=send_bai+0x30;
Vcan_Buff.DataBuf[DMA_SEND_CNT++]=send_shi+0x30;
Vcan_Buff.DataBuf[DMA_SEND_CNT++]=send_ge+0x30;
/***************************************************************************************************************************/
send_data_temp=limit(Show.Z/10,-999,999);
if(send_data_temp>0)Vcan_Buff.DataBuf[DMA_SEND_CNT++]='+';
else
{
send_data_temp=-send_data_temp;
Vcan_Buff.DataBuf[DMA_SEND_CNT++]='-';
}
send_bai=send_data_temp/100;
send_shi=send_data_temp%100/10;
send_ge=send_data_temp%100%10;
Vcan_Buff.DataBuf[DMA_SEND_CNT++]=send_bai+0x30;
Vcan_Buff.DataBuf[DMA_SEND_CNT++]=send_shi+0x30;
Vcan_Buff.DataBuf[DMA_SEND_CNT++]=send_ge+0x30;
/***************************************************************************************************************************/
send_data_temp=limit(Show.Battery_Rc,0,999);
if(send_data_temp>0)Vcan_Buff.DataBuf[DMA_SEND_CNT++]='+';
else
{
send_data_temp=-send_data_temp;
Vcan_Buff.DataBuf[DMA_SEND_CNT++]='-';
}
send_bai=send_data_temp/100;
send_shi=send_data_temp%100/10;
send_ge=send_data_temp%100%10;
Vcan_Buff.DataBuf[DMA_SEND_CNT++]=send_bai+0x30;
Vcan_Buff.DataBuf[DMA_SEND_CNT++]=send_shi+0x30;
Vcan_Buff.DataBuf[DMA_SEND_CNT++]=send_ge+0x30;
/***************************************************************************************************************************/
send_data_temp=limit(Show.Battery_Fly,0,999);
if(send_data_temp>0)Vcan_Buff.DataBuf[DMA_SEND_CNT++]='+';
else
{
send_data_temp=-send_data_temp;
Vcan_Buff.DataBuf[DMA_SEND_CNT++]='-';
}
send_bai=send_data_temp/100;
send_shi=send_data_temp%100/10;
send_ge=send_data_temp%100%10;
Vcan_Buff.DataBuf[DMA_SEND_CNT++]=send_bai+0x30;
Vcan_Buff.DataBuf[DMA_SEND_CNT++]=send_shi+0x30;
Vcan_Buff.DataBuf[DMA_SEND_CNT++]=send_ge+0x30;
/***************************************************************************************************************************/
/***************************************************************************************************************************/
// for(u8 i=0;i<18;i++)Vcan_Buff.DataBuf[DMA_SEND_CNT++]=0;
Vcan_Buff.DataBuf[DMA_SEND_CNT++]=0x0D; // 30
Vcan_Buff.DataBuf[DMA_SEND_CNT++]=0x0A; // 31
/***************************************************************************************************************************/
Quad_DMA1_USART1_SEND((u32)(&Vcan_Buff),sizeof(Vcan_Buff));
DMA_SEND_CNT=0;
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。