锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

四旋翼无人机光流定位和激光定高2(2中含原代码)

时间:2022-11-09 23:30:01 位移传感器pa1c

四旋翼无人机光流定位原代码:

通常,我们购买以下光流模块GL9306

串口输出模块光流数据,格式如下:

串口读取代码如下:

usart.h

#ifndef __USART1_H
#define __USART1_H

#include "stm32f10x.h"
#include

extern void USART1_SendByte(const int8_t *Data,uint8_t len);
extern void USART3_SendByte(const int8_t *Data,uint8_t len);
extern void USART1_Config(void);
extern void USART3_Config(void);

extern int fputc(int ch, FILE *f);

extern void USART1_setBaudRate(uint32_t baudRate);

#endif /* __USART1_H */

usart.c

#include "usart.h"

// 改写光流定位 串口通讯
// 接线方式 光流模块TX - stm32 PA10 RX

void USART1_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure1;
USART_InitTypeDef USART_InitStructure1;
NVIC_InitTypeDef NVIC_InitStructure1;
/* 配置串口1 (USART1) 时钟*/

/*" 第1步:打开GPIO和USART部件的时钟 "*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE );//| RCC_APB2Periph_AFIO, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);

/* Configure the NVIC Preemption Priority Bits */


/* 中断串口1 */
NVIC_InitStructure1.NVIC_IRQChannel = USART1_IRQn; //USART1 串口1全局中断
NVIC_InitStructure1.NVIC_IRQChannelPreemptionPriority = 1.//抢占优先级1
NVIC_InitStructure1.NVIC_IRQChannelSubPriority = 1; //子优先级1
/*IRQ通道使能*/
NVIC_InitStructure1.NVIC_IRQChannelCmd = ENABLE;
/*根据NVIC_InitStruct初始化外设中指定的参数NVIC寄存器USART1*/
NVIC_Init(&NVIC_InitStructure1);

/*串口GPIO端口配置*/
/* 配置串口1 (USART1 Tx (PA.09))*/
GPIO_InitStructure1.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure1.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure1.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure1);

/* 配置串口1 USART1 Rx (PA.10)*/
GPIO_InitStructure1.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure1.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure1);


//USART 初始化设置
USART_InitStructure1.USART_BaudRate =19200./串口波特率
USART_InitStructure1.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
USART_InitStructure1.USART_StopBits = USART_StopBits_1;//一个停止位
USART_InitStructure1.USART_Parity = USART_Parity_No;///无奇偶校准位
USART_InitStructure1.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
USART_InitStructure1.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式
USART_Init(USART1, &USART_InitStructure1);

USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//打开中断

USART_Cmd(USART1, ENABLE); //使能串口
}

/**************************实现函数**********************************************
*功 能: usart发送一个字节
*********************************************************************************/
void usart1_send(u8 data)
{
USART1->DR = data;
while((USART1->SR&0x40)==0);
}
/**************************************************************************
函数功能:串口1初始化
入口参数:pclk2:PCLK2 时钟频率(Mhz) bound:波特率
返回 值:无
**************************************************************************/
void uart1_init(u32pclk2,u32 bound)
{       
float temp;
    u16 mantissa;
    u16 fraction;       
    temp=(float)(pclk2*1000000)/(bound*16);//得到USARTDIV
    mantissa=temp;                 //得到整数部分
    fraction=(temp-mantissa)*16; //得到小数部分     
  mantissa<<=4;
    mantissa+=fraction; 
    RCC->APB2ENR|=1<<0;    //开启辅助时钟
    RCC->APB2ENR|=1<<3;   //使能PORTB口时钟  
    RCC->APB1ENR|=1<<18;  //使能串口时钟 
    GPIOB->CRH&=0XFFFF0FFF; 
    GPIOB->CRH|=0X00008000;//IO状态设置
    GPIOB->ODR|=1<<10;     

    RCC->APB1RSTR|=1<<18;   //复位串口1
    RCC->APB1RSTR&=~(1<<18);//停止复位              
    //波特率设置
     USART1->BRR=mantissa; // 波特率设置     
    USART1->CR1|=0X200C;  //1位停止,无校验位.
    //使能接收中断
    USART1->CR1|=1<<8;    //PE中断使能
    USART1->CR1|=1<<5;    //接收缓冲区非空中断使能            
//    MY_NVIC_Init(0,0,USART1_IRQn,1);//组2,最低优先级 
}

/**************************************************************************
函数功能:串口3接收中断
入口参数:无
返回  值:无
**************************************************************************/
int USART1_IRQHandler(void)
{    
    
    static u8 RxBuffer[32];
    static u8 _data_cnt = 0;
    static u8 state = 0;
    u8 data;
    u8 sum = 0;
    if(USART1->SR&(1<<5))//接收到数据
    {  
        
        USART1->SR&=~(1<<0);//清除中断标志位
        data=USART1->DR;
    switch(state)
    {
        case 0:
            if(data==0xFE)
            {
                state=1;
                RxBuffer[_data_cnt++]=data;
            }else state = 0;
        break;
            
        case 1:
            if(data==0x04)
            {
                state=2;
                RxBuffer[_data_cnt++]=data;
            }else state = 0;
        break;
            
        case 2:
            RxBuffer[_data_cnt++]=data;
        
            if(_data_cnt==9)
            {
                state = 0;
                _data_cnt = 0;
                
                sum =  (RxBuffer[2] + RxBuffer[3] + RxBuffer[4] + RxBuffer[5]);
                
                if((0xAA == data) && (sum == RxBuffer[6])) //和校验
                {
                    count_temp++;
                    
                    //读原始数据
                    Flow_Pitch = ( (s16)(*(RxBuffer+3)<<8)|*(RxBuffer+2) );
                    Flow_Roll  = ( (s16)(*(RxBuffer+5)<<8)|*(RxBuffer+4) );
                                        
                    //累积求位移
                    Flow_Pitch_i += Flow_Pitch;
                    Flow_Roll_i  += Flow_Roll;
                if(count_temp>400)
                          { 
                                                   Flag_USART3=1;                        
                               X_Flow_Pitch_i+= Flow_Pitch_i/(8200.0f/(this_Final_Distance*1.0f));//this_Final_Distance为实际高度
                     Y_Flow_Roll_i += Flow_Roll_i /(8200.0f/(this_Final_Distance*1.0f));//this_Final_Distance为实际高度                
                           
                                               Flow_Pitch_i=0;//使用完后清零,防止高度提升时位移发生变化
                                 Flow_Roll_i =0;//使用完后清零,防止高度提升时位移发生变化 
                    }    
                }
            }
        break;
            
        default:
            state = 0;
            _data_cnt = 0;
        break;
    }

        
   }
     return 0;    
         
}

//

 无人机控制部分代码如下:

//调试时 real_height=400 ,this_Final_Distance暂时赋值为500,即0.5米的高度
     real_height=400;
         this_Final_Distance=450;
        //*************************************姿态角补偿光流*****************************************************//            
        //光流定位
        Roll=Angle.roll;  //赋给测量值    即姿态模块取得的实时角度
        Pitch=Angle.pitch;
        
         if(Flag_USART3==1)  //串口1读到光流数据
                     {
                                  Flag_USART3 = 0;             

                                 Y_change = tan( (Roll -Roll_Y)  *angle_to_rad );
                               X_change = tan( (Pitch-Pitch_X) *angle_to_rad );
                                              
                                       Pitch_ang_x += ( X_change- Pitch_ang_x ) *0.3f;//低通滤波  因为光流数据的输出滞后于 实时欧拉角的输出,所以补偿
                                     Roll_ang_y  += ( Y_change- Roll_ang_y  ) *0.3f;//低通滤波
                                     if(real_height<=800)Mag=0.130f;
                                         else Mag=0.126f;
                                       
                                                         X_Flow_Pitch_i_final = X_Flow_Pitch_i - (Pitch_ang_x * this_Final_Distance * Mag );                 
                                       Y_Flow_Roll_i_final  = Y_Flow_Roll_i  - (Roll_ang_y  * this_Final_Distance * Mag ); 
                                                                
                                   PK1= X_Flow_Pitch_i_final - last_X_Flow_Pitch_i ;
                                       PK2= Y_Flow_Roll_i_final  - last_Y_Flow_Roll_i  ;
                                       
                                        last_X_Flow_Pitch_i = X_Flow_Pitch_i_final;    
                                   last_Y_Flow_Roll_i  = Y_Flow_Roll_i_final;
                        
                                             velocity_X =  PK1 / 0.005f ;
                                     velocity_Y =  PK2 / 0.005f ;
                                                                        
                                                   if( velocity_X>+150 ) velocity_X=+150;
                     if( velocity_Y>+150 ) velocity_Y=+150;
                     if( velocity_X<-150 ) velocity_X=-150;
                     if( velocity_Y<-150 ) velocity_Y=-150;        
                     
                     

                     //*********************************摇杆控制-平行Roll\Pitch轴向的位置**************************************//
                    
           
                
                                 
                                    X_Yaogan=pidPitch.desired /4.0f;      //pidPitch.desired为遥杆值
                           Y_Yaogan=pidRoll.desired/4.0f;    
                   
                                     
                                                                  
        } 
        
//***********************************光流定点位置环******************************************************//
                                     
                               
                         if(X_Yaogan!=0)  
                                                {position_X=0;X_POSITION=X_Flow_Pitch_i_final;}
                      else
                                                position_X = Move_X_position (X_POSITION,X_Flow_Pitch_i_final);
             
                      if(Y_Yaogan!=0) 
                                                {position_Y=0;Y_POSITION=Y_Flow_Roll_i_final;}                                    
                        else
                                                position_Y = Move_Y_position (Y_POSITION,Y_Flow_Roll_i_final);
                                           
                               if(position_X>+40)position_X=+40;
                         if(position_X<-40)position_X=-40;
                         if(position_Y>+40)position_Y=+40;
                         if(position_Y<-40)position_Y=-40;          
                                   
                                        
//************************************光流定点速度环*****************************************************//        
            if(real_height<350)
            {
                if(X_Yaogan>30)X_Yaogan=30;
                    if(Y_Yaogan>30)Y_Yaogan=30;
                    if(X_Yaogan<-30)X_Yaogan=-30;
                    if(Y_Yaogan<-30)Y_Yaogan=-30;
            }
      if(real_height<200)
            {
                    X_Yaogan=0;
                    Y_Yaogan=0;
                
            }            
            MOVE_X = Move_X_velocity (velocity_X,X_Yaogan-position_X);
                              
            MOVE_Y = Move_Y_velocity (velocity_Y,Y_Yaogan-position_Y);
                              
                     if(MOVE_X>+6)   MOVE_X=+6;
                   
                       if(MOVE_X<-6)MOVE_X=-6;
                    
                     if(MOVE_Y>+6)MOVE_Y=+6;
                 
                       if(MOVE_Y<-6)MOVE_Y=-6;     
        
    
        //说明:在你的无人机控制部分叠加 光流量   MOVE_X,MOVE_Y即可,例如下面两句代码
        //    pidPitch.measured = Angle.pitch+MOVE_X; //   外环测量值  单位:角度  叠加 光流量          //      MOVE_X
        //  pidRoll.measured = Angle.roll+MOVE_Y;   //叠加 光流量MOVE_Y

     
    /    


//需要用到的光流函数

//********************************光流定点速度环****************************************************************//
float Move_X_velocity (float Gyro,float Target)
{     
     static float Bias,Last_Bias,Pwm,Integral_bias;
     Bias=Gyro-Target; //计算偏差
     if(Bias>150)Bias=150;
     if(Bias<-150)Bias=-150;
     if(real_height>10)Integral_bias+=Bias;     //求出偏差的积分
     if(Integral_bias>7000)Integral_bias=7000;
     if(Integral_bias<-7000)Integral_bias=-7000;
     Pwm=move_KP*Bias/1000+move_KI*Integral_bias/70000+move_KD*(Bias-Last_Bias)/1000; //位置式PID控制器
     Last_Bias=Bias;
           if(Flag_Stop==1)Integral_bias=0,Pwm=0,Bias=0,Last_Bias=0;    
     return Pwm;         //增量输出
}
float Move_Y_velocity (float Gyro,float Target)
{     
     static float Bias,Last_Bias,Pwm,Integral_bias;
     Bias=Gyro-Target; //计算偏差
     if(Bias>150)Bias=150;
     if(Bias<-150)Bias=-150;
     if(real_height>10)Integral_bias+=Bias;     //求出偏差的积分
     if(Integral_bias>7000)Integral_bias=7000;
     if(Integral_bias<-7000)Integral_bias=-7000;
     Pwm=move_KP*Bias/1000+move_KI*Integral_bias/70000+move_KD*(Bias-Last_Bias)/1000; //位置式PID控制器
     Last_Bias=Bias;
           if(Flag_Stop==1)Integral_bias=0,Pwm=0,Bias=0,Last_Bias=0;    
     return Pwm;         //增量输出
}
//********************************光流定点位置环****************************************************************//
float Move_X_position (float Gyro,float Target)
{     
    static float Position_PWM,Last_Position,Position_Bias,Position_Differential;
    static float Position_Least;
      Position_Least = Target-Gyro;             //===获取偏差
          Position_Bias *=0.8;           
          Position_Bias += Position_Least*0.2;                 //===一阶低通滤波器  
    Position_Differential = Position_Bias-Last_Position;  //===获取偏差变化率
    Last_Position = Position_Bias; //保存上一次的偏差
    Position_PWM = Position_Bias*Position_Kp + Position_Differential*Position_Kd/10; //===位置控制     
if(Flag_Stop==1)Position_Bias=0,Position_Differential=0,Position_Least=0,Last_Position=0,Position_PWM=0;        
    return Position_PWM;         //增量输出
}
float Move_Y_position (float Gyro,float Target)
{     
    static float Position_PWM,Last_Position,Position_Bias,Position_Differential;
    static float Position_Least;
      Position_Least =Target-Gyro;                          //===获取偏差
          Position_Bias *=0.8;           
          Position_Bias += Position_Least*0.2;                  //===一阶低通滤波器  
    Position_Differential = Position_Bias-Last_Position;  //===获取偏差变化率
    Last_Position = Position_Bias; //保存上一次的偏差
    Position_PWM = Position_Bias*Position_Kp + Position_Differential*Position_Kd/10; //===位置控制     
if(Flag_Stop==1)Position_Bias=0,Position_Differential=0,Position_Least=0,Last_Position=0,Position_PWM=0;    
    return Position_PWM;        //增量输出
}


/

锐单商城拥有海量元器件数据手册IC替代型号,打造电子元器件IC百科大全!

相关文章