聚丰项目 > 四轴无人机姿态调整系统

四轴无人机姿态调整系统

随着信息技术的高速发展,以传感器为应用的物联网(IoT)得到了前所未有的发展, 物联网产品应用广泛,市场规模巨大。主流传感器中,又以位置、流量、气体、湿度等传感器备受市场青睐。 本项目是借助 IDT ZMID5201STKIT开发套件,利用ZMID520xMROT36001 Rotary Application Module模块,将无人机飞行过程中的飞行方向偏移角发送给MCU,经过MCU解析后,发送到NRF2401。通过NRF2401无线数据传输,最终将数据发送到手持设备上,可直观的观察到无人机姿态偏斜方向。 该项目的无人机具有一定的使用价值,可在科教、娱乐等领域应用,在工业、民用安防、智慧城市建设方面具有一定的应用价值,市场前景广阔,在未来商业应用方面潜力巨大。

llzhang llzhang

7 喜欢这个项目
团队介绍

llzhang llzhang

团队成员

刘听强 硬件工程师

项目简介
随着信息技术的高速发展,以传感器为应用的物联网(IoT)得到了前所未有的发展, 物联网产品应用广泛,市场规模巨大。主流传感器中,又以位置、流量、气体、湿度等传感器备受市场青睐。 本项目是借助 IDT ZMID5201STKIT开发套件,利用ZMID520xMROT36001 Rotary Application Module模块,将无人机飞行过程中的飞行方向偏移角发送给MCU,经过MCU解析后,发送到NRF2401。通过NRF2401无线数据传输,最终将数据发送到手持设备上,可直观的观察到无人机姿态偏斜方向。 该项目的无人机具有一定的使用价值,可在科教、娱乐等领域应用,在工业、民用安防、智慧城市建设方面具有一定的应用价值,市场前景广阔,在未来商业应用方面潜力巨大。
硬件说明

1、主控芯片:STM32F103C8T6作为主控MCU,STM32F103C8T6采用

Corex-M3内核,工作频率可达到72MHz,20KB SRAM,共3个定时器和3个USART。48个LQFP引脚足够外围电路使用。如下图所示。

image.png

图1 主控芯片

 

2、电源部分:供电方案采用先升压再降压的方案,由于第一次使用1S的锂离子电池,给四个空心杯进行空载供电的时候,四轴启动是没有问题的。但是如果四个空心杯都带上负载,如果瞬间提速到满速,那么电池输出电压拉低到3V以下,如果不采用升压方案,直接用电池给LDO供电,那LDO就会失效。所以通过升压再降压后给单片机系统供电是一个可行的方案,如下图所示。


image.png

图2 升压电路部分

image.png

图3 降压电路部分

 

 

3、传感器部分:MPU6050六轴传感器芯片通过数据滤波处理把三轴陀螺仪数据和三轴加速度数据以及ZMID520xMROT36001 Rotary Application Module角度偏移数据引入MCU进行IMU姿态解算,如下图所示。

image.png

图4 陀螺仪

4、四轴空心杯:无人机能否平稳操控,主要在四个电机上,空心杯选的好,对应姿态的稳定有较大的帮助。当然了驱动电机的MOS管上、陀螺仪上、PCB对四轴最终的效果也起到关键的作用。电机的频率,会才生干扰的频率点,会使无人机振动较大不好控制。另外就是同一批次的电机性能差异很大,导致PID调节的输出差异很大,最终会影响MOS管的寿命、电机寿命。空心杯电机使用SI2302这款MOS管进行驱动,这是非常常见的一款MOS管,便宜又好用。如下图所示。

image.png

图5 空心杯(前)

       5、射频部分:采用NRF2401,这是一块常用芯片,性能也是可以的,无线发射可以做到7dB,加上发射和接收端都采用陶瓷天线,可以达到50m的通讯距离。如果加上AP,那达到100米应该没有问题。通过两个低成本的0欧电

对电源进行了单点接地,防止电机回路的电流波动串进射频回路对射频造成干扰。

image.png

图7  射频部分

 

6、灯光模块:采用3个SOT23-3封装的MOS管进行开关控制,与MCU隔离电源。

7、遥控器电路:采用传统的DBUS遥控器反向电路。


软件说明

1、无线射频传输部分代码:

 

/**********************************************************************

配置NRF2401为RX模式,准备开始接收数据

***********************************************************************/

void RX_Mode(void)

{

       CE_LOW;                                                                                     //拉低CE,进入待机模式,准备开始往NRF2401中的寄存器中写入数据

      

       SPI_Write_Byte(WRITE_REG_CMD + CONFIG, 0x0f);        //配置为接收模式

       SPI_Write_Byte(WRITE_REG_CMD + STATUS, 0x7e);      //写0111 xxxx 给STATUS,清除所有中断标志,防止一进入接收模式就触发中断

      

       CE_HIGH;                                                                                   //拉高CE,准备接受从外部发送过来的数据

}

 

/**********************************************************************

从NRF2401的RX的FIFO中读取一组数据包

输入参数rx_buf:FIFO中读取到的数据的保存区域首地址

***********************************************************************/

void NRF2401_ReceivePacket(u8* rx_buf)

{

       CE_LOW;

       SPI_Read_Buf(RD_RX_PLOAD,rx_buf,RX_PLOAD_WIDTH);      //从RX端的FIFO中读取数据,并存入指定的区域,注意:读取完FIFO中的数据后,NRF2401会自动清除其中的数据

       SPI_Write_Byte(FLUSH_RX,0xff);                       //清除接收FIFO

       CE_HIGH;                                                                                              //重新拉高CE,让其重新处于接收模式,准备接收下一个数据

}

 

/**********************************************************************

配置NRF2401为TX模式,并发送一个数据包

输入参数tfbuf:即将要发送出去的数据区首地址

***********************************************************************/

void NRF2401_SendPacket(u8* tfbuf)

{

       CE_LOW;                                                                                                                //拉低CE,进入待机模式,准备开始往NRF2401中的寄存器中写入数据

      

//     SPI_Write_Buf(WRITE_REG_CMD + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH);    //装载接收端地址,由于这里只有一个通道通讯,不用改变接收端的NRF2401的接收通道地址,所以,这句可以注释掉

       SPI_Write_Buf(WR_TX_PLOAD, tfbuf, TX_PLOAD_WIDTH);                   //将数据写入TX端的FIFO中,写入的个数与TX_PLOAD_WIDTH设置值相同

      

       SPI_Write_Byte(WRITE_REG_CMD + CONFIG, 0x0e);                            //将NRF2401配置成发射模式

       SPI_Write_Byte(WRITE_REG_CMD + STATUS, 0x7e);                      //写0111 xxxx 给STATUS,清除所有中断标志,防止一进入发射模式就触发中断

      

       CE_HIGH;                                                                                           //拉高CE,准备发射TX端FIFO中的数据

      

       delay_ms(1);                                                                                //CE拉高后,需要延迟至少130us

}


void WaitFlY_Connection(void)

{

       static u8 cnt = 0,preaddr;

       ConnectingDisplay();//断线连接状态显示

       while(1)

       {

              if(FLY_Connect_OK)

              {

                     cnt = 0;

                     if(preaddr != TX_ADDRESS[TX_ADR_WIDTH-1])

                     {

                            PID_WriteFlash(); 

                           

//                          printf("Address save :%d preaddr:%d\r\n",TX_ADDRESS[4],preaddr);

                     }

//                   printf("Fly connect OK!!!\r\n");

                     return;

              }else if(cnt++ < 10)

              {

                     PID_ReadFlash();                    //读取上一次保存的飞机的NRF2401地址

                     preaddr = TX_ADDRESS[TX_ADR_WIDTH-1];

                     NRF2401_Config();

                     delay_ms(50);

//                   printf("Flash read NRF2401addr:%d\r\n",TX_ADDRESS[4]);

              }

              else

              {

                     TX_ADDRESS[TX_ADR_WIDTH-1]++ ;

                     RX_ADDRESS[TX_ADR_WIDTH-1]++ ;

                     if(TX_ADDRESS[TX_ADR_WIDTH-1]>AddrMax && RX_ADDRESS[TX_ADR_WIDTH-1]>AddrMax)

                     {

                            TX_ADDRESS[TX_ADR_WIDTH-1] = 0x00;

                            RX_ADDRESS[TX_ADR_WIDTH-1] = 0x00;

                     }

                     SPI_Write_Buf(WRITE_REG_CMD + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH);       

                     SPI_Write_Buf(WRITE_REG_CMD + RX_ADDR_P0, RX_ADDRESS, RX_ADR_WIDTH);

                     delay_ms(100);

              }

              if(ADC_CALIBRATOR_OK)

              {

                     OLED_ShowString(byte(2),line4,"Calibration",8);

              }

              else

              {

                     OLED_ShowString(byte(2),line4,"Connecting...",8);

              }

       }

}

void ReconnectionFly(void)

{

       if(Reconnection_flag)

       {

              ConnectingDisplay();

              if(FLY_Connect_OK)        //遥控已重新连接

              {

                     Display_init();

                     Reconnection_flag = 0;  //断线重连标志复位            

                     return;

              }

              NRF2401_Config();

       }

}

 

image.png

图8 无线射频传输部分代码

 

2、手持终端显示部分代码:

void ButtonCMDDisplay(void)

{

      

       if(GET_FLAG(FLY_ENABLE))

       {

              OLED_ShowString(byte(11),line4,"Nolink",6);

       }else

       {

              OLED_ShowString(byte(11),line4,"Link  ",6);

       }

       SenserOffsetDisplay();

       WiFiOnOffDisplay();

       ModeSelectDisplay();

}

 

void ConnectingDisplay(void)

{

       OLED_Clear();

       OLED_ShowCHinese(1,line1,WiFi,0); //信号强度

       OLED_ShowString(byte(3)+4,line1," IDT_Fly",8); //大赛名

       OLED_ShowCHinese7x7(121,line1,BATT,0); //电池图标

       OLED_ShowString(111,line1,"%",6); //

       OLED_ShowNum(108,line2,0,2,6); //电池电压比例

      } 

}

image.png


 

图9 无线射频传输部分代码


演示效果

四轴无人机下方为自制的指南针,用来定位起飞前的方向。南针放在四轴无人机下方,为了防止电机风力而引起的摆动。

无人机起飞、平衡性并不理想,主要还是在数据传输部分,不能及时将传感器发送的数据,进行其实的处理去调整无人机的姿态。但是是MPU6050还是ZMID520xMROT传输的数据,都能显示在RGB LED屏上。


 

image.png


                                                                                      图9 正面图

 

image.png

                                                                                     图10 背面图

 

image.png


                                                                                    图11 连接图


附件

(0.55 MB)下载

评论区(0 )