STM32_270四旋翼无人机机载PM2.5+温度传感器采集监测环境数据毕业设计

本贴为基于STM32_270四旋翼无人机的毕业设计二次开发经验贴。

方案描述

本项目中无人机机载PM2.5温度传感器,并将相关信息无线传送至自研的LABVIEW无人机地面站进行可视化显示与飞行调试。
STM32_270小四轴相对成本便宜,飞机有一定冗余负载能力,且飞控与遥控器源码开源,配合PV3953L1光流激光模块(PMW3901+VL53L1X),可实现室内低空稳定定点悬停,适合无人机二次开发和学习惯导、飞行控制等基本理论,多数本科毕业设计基于该平台都可以快速实现期望功能。

四轴通信链路设计

STM32_270小四轴原生链路如下图所示,飞机与遥控之间采用无线NRF24L01通信,遥控器与电脑端上位机采用有线USB通信,
在这里插入图片描述
原生固件还预留了多个其他用户接口,如uart、iic、spi、io等接口便于用户二次开发。
在这里插入图片描述
上述多个接口也可以根据需求查找原理图和芯片资源手册重新映射资源,如将iic或spi映射为其他uart、IO、ADC等功能。

LABVIEW无人机地面站设计

如下图所示,左上角为串口功能配置,左下为基本飞行数据数据,右上仪表为环境温度、颗粒物含量显示、遥控器剩余电量、飞行器剩余电量,右下角波形图为多个通道的数据波形图表。
在这里插入图片描述
部分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;
}

小四轴资料下载链接
提取码:mpdp
如有问题评论区留言,或加q209518616
祝好!
完整资料包下载链接

  • 12
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

amusen.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值