无名飞控

2023-05-16

无名飞控Time.c文件

由于无名飞控主要核心:传感器滤波、姿态解算、惯导、控制等代码在TIME.c里面运行,所以先来分析这个文件。

打开文件第一个函数:

void Timer4_Configuration(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;//结构体变量,这个结构体的成员是定时器的配置寄存器,如果将定时器的基址强制转换为这个结构体指针就可以依靠这个指针操作寄存器
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);//使能或者失能APB1外设时钟
TIM_DeInit(TIM4);//将外设TIM4寄存器重设为缺省值
TIM_TimeBaseStructure.TIM_Period=4000;//TIM_Period设置了在下一个更新事件装入活动的自动重装载寄存器周期的值。它的取值必须在0x0000和0xFFFF之间。
TIM_TimeBaseStructure.TIM_Prescaler= (72 - 1);//设置了用来作为TIM4时钟频率除数的预分频值。它的取值必须在0x0000和0xFFFF之间
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;//设置了时钟分割
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;//TIM向上计数模式
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);//1us*1000=1ms
TIM_ClearFlag(TIM4, TIM_FLAG_Update);
TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE);
TIM_Cmd(TIM4, ENABLE);
}
其中:


IM_ClearFlag(TIM4, TIM_FLAG_Update);// 清除TIM4的待处理标志位

TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE);// 使能或者失能指定的TIM中断, TIM中断源

TIM_Cmd(TIM4, ENABLE);// 使能或者失能TIMx外设


这个函数是初始化TIM4时钟,时钟开始运行后应发中断,从而运行姿态结算和控制代码。

//定义变量赋值

uint8 US_100_Start=0,US_100_Finished=1,US_100_Sampling_Cnt=0,US_100_Retry_Cnt=0;
uint8 ADNS3080_Cnt=0;
uint8 HC_SR04_Cnt=0;
Testime Time4_Delta;//结构体
uint16_t High_Okay_flag=0;
其中
typedef struct
{
  float Last_Time;
  float Now_Time;
  float Time_Delta;
  uint16 Time_Delta_INT;单位ms
}Testime;

 接下来判断中断是否发生

if(TIM_GetITStatus(TIM4,TIM_IT_Update)!=RESET )//检查指定的TIM4中断发生与否
 {    假如中断发生
     Test_Period(&Time4_Delta);//系统调度时间测试器
     NRF24L01_RC();//遥控器查询接收,非中端方式
 /*************加速度计、陀螺仪数字量采集***********/
     GET_MPU_DATA();//1.4ms
其中首先调用了Test_Period来得到现在的时间,上次中断发生时间,时间间隔

void Test_Period(Testime *Time_Lab)
{
   Time_Lab->Last_Time=Time_Lab->Now_Time;
   Time_Lab->Now_Time=(10000*TIME_ISR_CNT
                      +TIM2->CNT/2)/1000.0;单位ms
   Time_Lab->Time_Delta=Time_Lab->Now_Time-Time_Lab->Last_Time;
   Time_Lab->Time_Delta_INT=(uint16)(Time_Lab->Time_Delta);
}

这个函数是有TIME_ISR_CNT,这个量是从TIM2中来,这个量主要是记录现在已经工作了多少0.01S,TIM2->CNT/2是现在又经过了多少微秒,可以从TIM2中看出一点端倪:

void TIM2_Configuration_Cnt(void)
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
    TIM_DeInit(TIM2);
    //TIM_TimeBaseStructure.TIM_Period = 60000;//30ms
    //TIM_TimeBaseStructure.TIM_Period = 20000;//10ms
    TIM_TimeBaseStructure.TIM_Period = 20000;//0.01s,系统运行1S,会计数2000000次,这里数20000即引发中断

    TIM_TimeBaseStructure.TIM_Prescaler = 36-1; //36M/36/2=0.5us,分频36M,
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;系统时钟72M
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

    TIM_ClearFlag(TIM2, TIM_FLAG_Update);
    TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
    TIM_Cmd(TIM2, ENABLE);
}


先不管NRF24L01_RC函数,是 nRF24L01的驱动函数,如果使用自己的接收机的话,这里应该用不着。

nRF24L01是由NORDIC生产的工作在2.4GHz~2.5GHz的ISM 频段的单片无线收发器芯片

进入 GET_MPU_DATA()得到mpu的数据

定义:

void GET_MPU_DATA(void)
{
  //GET_ACC_DATA();
  IMU_Filter();
  GET_GYRO_DATA();
  
}

首先IMU_Filter函数

float X_Origion,Y_Origion,Z_Origion;
void IMU_Filter(void)/*得到加速度数据,并进行低通滤波*/
{
	uint8_t axis;   
        imu.accelRaw[0] = GetData(ACCEL_XOUT_H);//imu结构体
        imu.accelRaw[1] = GetData(ACCEL_YOUT_H);
        imu.accelRaw[2] = GetData(ACCEL_ZOUT_H);
        Acce_Correct_Filter();//对imu.accelRaw进行低通滤波得到数组Acce_Correct
             
        X_Origion=K[0]*(imu.accelRaw[0])-B[0];//经过椭球校正后的三轴加速度量//初值均为0;
        Y_Origion=K[1]*(imu.accelRaw[1])-B[1];
        Z_Origion=K[2]*(imu.accelRaw[2])-B[2];
        /*typedef struct
 {
 float Position[Axis_Num];//位置估计量
 float Speed[Axis_Num];//速度估计量
 float Acceleration[Axis_Num];//加速度估计量
 float Pos_History[Axis_Num][Num];//历史惯导位置
 float Vel_History[Axis_Num][Num];//历史惯导速度
 float Acce_Bias[Axis_Num];//惯导加速度漂移量估计量
 }SINS;
  FilterBefore_NamelessQuad是一个SINS结构体  *///我注释的
        FilterBefore_NamelessQuad.Acceleration[_YAW]=
                      -Sin_Roll* X_Origion
                        + Sin_Pitch *Cos_Roll *Y_Origion
                           + Cos_Pitch * Cos_Roll *Z_Origion;
        FilterBefore_NamelessQuad.Acceleration[_PITCH]=
                   Cos_Yaw* Cos_Roll * X_Origion
                        +(Sin_Pitch*Sin_Roll*Cos_Yaw-Cos_Pitch * Sin_Yaw) * Y_Origion
                          +(Sin_Pitch * Sin_Yaw+Cos_Pitch * Sin_Roll * Cos_Yaw) * Z_Origion;  
        FilterBefore_NamelessQuad.Acceleration[_ROLL]=
                   Sin_Yaw* Cos_Roll * X_Origion
                        +(Sin_Pitch * Sin_Roll * Sin_Yaw +Cos_Pitch * Cos_Yaw) * Y_Origion 
                          + (Cos_Pitch * Sin_Roll * Sin_Yaw - Sin_Pitch * Cos_Yaw) * Z_Origion;  
        
        
        FilterBefore_NamelessQuad.Acceleration[_YAW]*=AcceGravity/AcceMax;
        FilterBefore_NamelessQuad.Acceleration[_YAW]-=AcceGravity;
        FilterBefore_NamelessQuad.Acceleration[_YAW]*=100;//加速度cm/s^2
        FilterBefore_NamelessQuad.Acceleration[_PITCH]*=AcceGravity/AcceMax;
        FilterBefore_NamelessQuad.Acceleration[_PITCH]*=100;//加速度cm/s^2
        FilterBefore_NamelessQuad.Acceleration[_ROLL]*=AcceGravity/AcceMax;
        FilterBefore_NamelessQuad.Acceleration[_ROLL]*=100;//加速度cm/s^2

     
        Acce_Control_Filter();//加速度滤波,用于惯导、加速度控制反馈量再次滤波     
        
	/* 加速度计Butterworth滤波 */
	/* 获取最新x(n) */
	    accButter[0].input[2] =Int_Sort(X_Origion);
        accButter[1].input[2] =Int_Sort(Y_Origion);
        accButter[2].input[2] =Int_Sort(Z_Origion);
	/* Butterworth滤波 */
	for (axis = 0; axis < 3; axis++)
	{
	accButter[axis].output[2] =
                 Int_Sort(b_acc[0] * accButter[axis].input[2] 
                  + b_acc[1] * accButter[axis].input[1] 
                    + b_acc[2] * accButter[axis].input[0] 
                      - a_acc[1] * accButter[axis].output[1] 
                        - a_acc[2] * accButter[axis].output[0]);
		imu.accelFilter[axis] = accButter[axis].output[2];
	}	
	for (axis = 0; axis < 3; axis++)
	{
		/* x(n) 序列保存 */
		accButter[axis].input[0] = accButter[axis].input[1];
		accButter[axis].input[1] = accButter[axis].input[2];
		/* y(n) 序列保存 */
		accButter[axis].output[0] = accButter[axis].output[1];
		accButter[axis].output[1] = accButter[axis].output[2];
	}  
       X_g_av=imu.accelFilter[0];
       Y_g_av=imu.accelFilter[1];
       Z_g_av=imu.accelFilter[2];   
}
对于  imu 是一个 _IMU_Tag 类型的结构体, _IMU_Tag imu;
typedef struct 
{
	float accelRaw[3];	// 加速度计原始数据
	float gyroRaw[3];     // 陀螺仪原始数据
	float accelFilter[3];	// 加速度计滤波后数据
	float gyroFilter[3];	// 陀螺仪滤波后数据
}_IMU_Tag;
接着是gitdata函数,将原始数据赋值给一个16位无符号整形的数
int16_t GetData(uint8_t REG_Address)
{
	uint8_t Hd,Ld;
	Hd=Single_ReadI2C(0xD0,REG_Address);
	Ld=Single_ReadI2C(0xD0,REG_Address+1);
	return (Hd<<8)+Ld; 
}

取完数据后,回到IMU_Filter进入

 Acce_Correct_Filter();butterworth滤波,对imu.accelRaw进行滤波赋值给Acce_Correct

void Acce_Correct_Filter()
{
   Acce_Correct[0]=Int_Sort(LPButterworth(imu.accelRaw[0],
                    &Butter_Buffer_Correct[0],&Butter_1HZ_Parameter_Acce));
   Acce_Correct[1]=Int_Sort(LPButterworth(imu.accelRaw[1]
                    ,&Butter_Buffer_Correct[1],&Butter_1HZ_Parameter_Acce));
   Acce_Correct[2]=Int_Sort(LPButterworth(imu.accelRaw[2]
                    ,&Butter_Buffer_Correct[2],&Butter_1HZ_Parameter_Acce)); 
}

对于Acce_Correct有定义 int16_t Acce_Correct[3]={0};//用于矫正加速度量,截至频率很低

对于int_Sort有定义 #define Int_Sort    (int16_t)

对于LPButterworth,其参数有:

Butter_BufferData Butter_Buffer_Correct[3];

Butter_Parameter Butter_1HZ_Parameter_Acce={

  //250hz---1hz      

  1,   -1.822694925196,    0.837181651256,

  0.003621681514929,0.007243363029857, 0.003621681514929

};  

从名字上推应该是低通Butterworth滤波器定义 


float LPButterworth(float curr_input,Butter_BufferData *Buffer,Butter_Parameter *Parameter)
{   
    /* 加速度计Butterworth滤波 */
	/* 获取最新x(n) */
        static int LPB_Cnt=0;
        Buffer->Input_Butter[2]=curr_input;
        if(LPB_Cnt>=100)
        {
	/* Butterworth滤波 */
        Buffer->Output_Butter[2]=
         Parameter->b[0] * Buffer->Input_Butter[2] 
        +Parameter->b[1] * Buffer->Input_Butter[1]
	+Parameter->b[2] * Buffer->Input_Butter[0] 
        -Parameter->a[1] * Buffer->Output_Butter[1] 
        -Parameter->a[2] * Buffer->Output_Butter[0];
        }
        else
        {
          Buffer->Output_Butter[2]=Buffer->Input_Butter[2];
          LPB_Cnt++;
        }
	/* x(n) 序列保存 */
        Buffer->Input_Butter[0]=Buffer->Input_Butter[1];
        Buffer->Input_Butter[1]=Buffer->Input_Butter[2];
	/* y(n) 序列保存 */
        Buffer->Output_Butter[0]=Buffer->Output_Butter[1];
        Buffer->Output_Butter[1]=Buffer->Output_Butter[2];
        
        
        return Buffer->Output_Butter[2];
}

对imu.accelRaw[i]进行滤波,之后赋给 Acce_Correct[i]

经校正后给I_Origion

        X_Origion=K[0]*(imu.accelRaw[0])-B[0];//经过椭球校正后的三轴加速度量//初值均为0;
        Y_Origion=K[1]*(imu.accelRaw[1])-B[1];
        Z_Origion=K[2]*(imu.accelRaw[2])-B[2];

{ floatK[3]={1.0,1.0,1.0};//标度误差

float B[3]={0,0,0};//零位误差}

坐标系转换,将加速度有地理系转到机体系

FilterBefore_NamelessQuad.Acceleration[_YAW]=
                      -Sin_Roll* X_Origion
                        + Sin_Pitch *Cos_Roll *Y_Origion
                           + Cos_Pitch * Cos_Roll *Z_Origion;
        FilterBefore_NamelessQuad.Acceleration[_PITCH]=
                   Cos_Yaw* Cos_Roll * X_Origion
                        +(Sin_Pitch*Sin_Roll*Cos_Yaw-Cos_Pitch * Sin_Yaw) * Y_Origion
                          +(Sin_Pitch * Sin_Yaw+Cos_Pitch * Sin_Roll * Cos_Yaw) * Z_Origion;  
        FilterBefore_NamelessQuad.Acceleration[_ROLL]=
                   Sin_Yaw* Cos_Roll * X_Origion
                        +(Sin_Pitch * Sin_Roll * Sin_Yaw +Cos_Pitch * Cos_Yaw) * Y_Origion 
                          + (Cos_Pitch * Sin_Roll * Sin_Yaw - Sin_Pitch * Cos_Yaw) * Z_Origion;  

 FilterBefore_NamelessQuad是一个SINS结构体  
  
{
 float Position[Axis_Num];//位置估计量
 float Speed[Axis_Num];//速度估计量
 float Acceleration[Axis_Num];//加速度估计量
 float Pos_History[Axis_Num][Num];//历史惯导位置
 float Vel_History[Axis_Num][Num];//历史惯导速度
 float Acce_Bias[Axis_Num];//惯导加速度漂移量估计量
 }SINS;

继续回到IMU_Filter

FilterBefore_NamelessQuad.Acceleration[_YAW]*=AcceGravity/AcceMax;
        FilterBefore_NamelessQuad.Acceleration[_YAW]-=AcceGravity;
        FilterBefore_NamelessQuad.Acceleration[_YAW]*=100;//加速度cm/s^2
        FilterBefore_NamelessQuad.Acceleration[_PITCH]*=AcceGravity/AcceMax;
        FilterBefore_NamelessQuad.Acceleration[_PITCH]*=100;//加速度cm/s^2
        FilterBefore_NamelessQuad.Acceleration[_ROLL]*=AcceGravity/AcceMax;
        FilterBefore_NamelessQuad.Acceleration[_ROLL]*=100;//加速度cm/s^2//

//把加速度量化处理,也是乘以一个量程

接下来又有:(好像并没有什么卵用)

Acce_Control_Filter();//加速度滤波,用于惯导、加速度控制反馈量再次滤波,对imu.accelRaw[i]进行滤波,之后赋给 Acce_Correct[i]

又有:再次butterworth滤波,对纠正后的数据进行滤波,滤波后数据赋值给I_g_av

         /* 加速度计Butterworth滤波 */

         /* 获取最新x(n) */

         accButter[0].input[2]=Int_Sort(X_Origion);

        accButter[1].input[2]=Int_Sort(Y_Origion);

        accButter[2].input[2]=Int_Sort(Z_Origion);

         /* Butterworth滤波 */

         for (axis = 0; axis < 3; axis++)

         {

         accButter[axis].output[2] =

                 Int_Sort(b_acc[0] *accButter[axis].input[2]

                  + b_acc[1] *accButter[axis].input[1]

                    + b_acc[2] *accButter[axis].input[0]

                      - a_acc[1] *accButter[axis].output[1]

                        - a_acc[2] *accButter[axis].output[0]);

                   imu.accelFilter[axis] =accButter[axis].output[2];

         }       

         for (axis = 0; axis < 3; axis++)

         {

                   /* x(n) 序列保存 */

                   accButter[axis].input[0] =accButter[axis].input[1];

                   accButter[axis].input[1] =accButter[axis].input[2];

                   /* y(n) 序列保存 */

                   accButter[axis].output[0] =accButter[axis].output[1];

                   accButter[axis].output[1] =accButter[axis].output[2];

         } 

       X_g_av=imu.accelFilter[0];

       Y_g_av=imu.accelFilter[1];

       Z_g_av=imu.accelFilter[2];  

}

其中,accButter是一个结构体

struct _ButterWorth2d_Acc_Tag accButter[3] = 
{
	/* input[3] output[3] */
	{0, 0, 0, 0, 0, 0},		// X-axis
	{0, 0, 0, 0, 0, 0},		// Y-axis
	{0, 0, 0, 0, 0, 0},		// Z-axis
};

加速度的数据经过两次滤波,一次是1赫兹的,然后纠偏,转换到机体系,再滤波,这次滤波是15赫兹(程序注释是这样具体什么样再看看)

至此也就得到了加速度数据要取陀螺仪数据

回到GET_MPU_DATA,进入GET_GYRO_DATA();

void GET_GYRO_DATA(void)//角速度低通滤波后用于姿态解算
{
	X_w  = GetData(GYRO_XOUT_H)-X_w_off;
	Y_w  = GetData(GYRO_YOUT_H)-Y_w_off;
	Z_w  = GetData(GYRO_ZOUT_H)-Z_w_off;
        X_w_av=GYRO_LPF(X_w,
                        &Gyro_BufferData[0],
                        &Gyro_Parameter   
                        );
        Y_w_av=GYRO_LPF(Y_w,
                        &Gyro_BufferData[1],
                        &Gyro_Parameter   
                        );
        Z_w_av=GYRO_LPF(Z_w,
                        &Gyro_BufferData[2],
                        &Gyro_Parameter   
                        );  
}

其中:float  X_w_off =0,Y_w_off =0,Z_w_off =0;

和加速度处理类似,将原始数据赋值给一个16位无符号整形的数,减去偏差,然后滤波

对于GYRO_LPF:

float GYRO_LPF(float curr_inputer,
               Butter_BufferData *Buffer,
               Butter_Parameter *Parameter)
{
        /* 加速度计Butterworth滤波 */
	/* 获取最新x(n) */
        Buffer->Input_Butter[2]=curr_inputer;
	/* Butterworth滤波 */
        Buffer->Output_Butter[2]=
         Parameter->b[0] * Buffer->Input_Butter[2] 
        +Parameter->b[1] * Buffer->Input_Butter[1]
	+Parameter->b[2] * Buffer->Input_Butter[0] 
        -Parameter->a[1] * Buffer->Output_Butter[1] 
        -Parameter->a[2] * Buffer->Output_Butter[0];
	/* x(n) 序列保存 */
        Buffer->Input_Butter[0]=Buffer->Input_Butter[1];
        Buffer->Input_Butter[1]=Buffer->Input_Butter[2];
	/* y(n) 序列保存 */
        Buffer->Output_Butter[0]=Buffer->Output_Butter[1];
        Buffer->Output_Butter[1]=Buffer->Output_Butter[2];
        return (Buffer->Output_Butter[2]);
}
其中:Butter_Parameter Gyro_Parameter={
  1,   -1.475480443593,   0.5869195080612,
  0.02785976611714,  0.05571953223427,  0.02785976611714,
};  

Butter_BufferData Gyro_BufferData[3];

就此得到加速度计和陀螺仪数据,也就得到了mpu所有数据

下面回到void TIM4_IRQHandler(void)

根据飞控介绍,飞控使用气压计spl06_01,磁力计IST8310

则应该进入

SPL06_001_StateMachine();
 Get_Mag_IST8310();

磁力计和气压计

#elsedef IMU_BOARD_NC686
      SPL06_001_StateMachine();
      Get_Mag_IST8310();

具体定义

先进入SPL06_001_StateMachine,表面上无输入无输出,但是

uint8 SPL06_001_Offset_Okay=0;
uint8 SPL06_001_Finished=0;
float SPL06_001_Filter_P,SPL06_001_Filter_high;
unsigned int SPL06_001_Cnt=0;
void SPL06_001_StateMachine(void)
{
  user_spl0601_get();
  if(SPL06_001_Cnt<=50)  SPL06_001_Cnt++;
  if(SPL06_001_Cnt==49)
  {
    SPL06_001_Offset_Okay=1;
    High_Okay_flag=1;
    SPL06_001_Offset=pressure;
  }
    
  if(SPL06_001_Offset_Okay==1)//初始气压零点设置完毕
  {
    SPL06_001_Filter_P=pressure;      
    SPL06_001_Filter_high=Get_Altitude_SPL06_001(SPL06_001_Filter_P);
  }

但是它有调用了user_spl0601_get,顾名思义就是得到spl0601的数据,具体什么数据,接着看。

float temperature;
float pressure;
float user_spl0601_get()
{
  static uint16_t spl06_cnt=0;
  spl06_cnt++;
  if(spl06_cnt==1)
  {
  spl0601_get_raw_temp();
  temperature = spl0601_get_temperature();
  }
  else
  {
    spl0601_get_raw_pressure();
    pressure = spl0601_get_pressure();
    spl06_cnt=0;
  }
  return 0;
}
有两句语句

static uint16_t spl06_cnt=0;
 spl06_cnt++;

这两句把spl06_cnt变成1,于是if(spl06_cnt==1)就成立,每次判断都成立,
判断成立就有:

spl0601_get_raw_temp();
 temperature = spl0601_get_temperature();

又调用函数spl0601_get_raw_temp

/*****************************************************************************
 函 数 名  : spl0601_get_raw_temp
 功能描述  : 获取温度的原始值,并转换成32Bits整数
 输入参数  : void  
 输出参数  : 无
 返 回 值  : 
 调用函数  : 
 被调函数  : 
 
 修改历史      :
  1.日    期   : 2015年11月30日
    作    者   : WL
    修改内容   : 新生成函数

*****************************************************************************/
void spl0601_get_raw_temp(void)
{
    uint8 h[3] = {0}; 
    h[0] = spl0601_read(HW_ADR, 0x03);
    h[1] = spl0601_read(HW_ADR, 0x04);
    h[2] = spl0601_read(HW_ADR, 0x05);
    p_spl0601->i32rawTemperature = (int32)h[0]<<16 | (int32)h[1]<<8 | (int32)h[2];
    p_spl0601->i32rawTemperature= (p_spl0601->i32rawTemperature&0x800000) ? (0xFF000000|p_spl0601->i32rawTemperature) : p_spl0601->i32rawTemperature;
}
然后


/*****************************************************************************
 函 数 名  : spl0601_get_temperature
 功能描述  : 在获取原始值的基础上,返回浮点校准后的温度值
 输入参数  : void  
 输出参数  : 无
 返 回 值  : 
 调用函数  : 
 被调函数  : 
 
 修改历史      :
  1.日    期   : 2015年11月30日
    作    者   : WL
    修改内容   : 新生成函数

*****************************************************************************/
float spl0601_get_temperature(void)
{
    float fTCompensate;
    float fTsc;

    fTsc = p_spl0601->i32rawTemperature / (float)p_spl0601->i32kT;
    fTCompensate =  p_spl0601->calib_param.c0 * 0.5 + p_spl0601->calib_param.c1 * fTsc;
    return fTCompensate;
}

总之就此得到了温度,这是气压计啊,为什么得到温度?不应该是压力吗?

接着看 user_spl0601_get结束,下面进入

if(SPL06_001_Cnt<=50)  SPL06_001_Cnt++;
  if(SPL06_001_Cnt==49)
  {
    SPL06_001_Offset_Okay=1;
    High_Okay_flag=1;
    SPL06_001_Offset=pressure;
  }
    
  if(SPL06_001_Offset_Okay==1)//初始气压零点设置完毕
  {
    SPL06_001_Filter_P=pressure;      
    SPL06_001_Filter_high=Get_Altitude_SPL06_001(SPL06_001_Filter_P);
  }
   
}
也就是说SPL06_001_Cnt累加50次后进入到if(SPL06_001_Cnt==49)的判断,取高度




先不管

看看磁力计

Get_Mag_IST8310得到磁力计数据



IST8310 Mag_IST8310;
void Get_Mag_IST8310(void)
{
  static uint16_t IST8310_Sample_Cnt=0;
  float MagTemp[3]={0};
  IST8310_Sample_Cnt++;
  if(IST8310_Sample_Cnt==1)
  {  
  Single_WriteI2C(IST8310_SLAVE_ADDRESS,IST8310_REG_CNTRL1,0x01);//Single Measurement Mode
  }
  else if(IST8310_Sample_Cnt==3)//至少间隔6ms,此处为8ms
  {
    Mag_IST8310.Buf[0]=Single_ReadI2C(IST8310_SLAVE_ADDRESS,0x03);//OUT_X_L_A
    Mag_IST8310.Buf[1]=Single_ReadI2C(IST8310_SLAVE_ADDRESS,0x04);//OUT_X_H_A
    Mag_IST8310.Buf[2]=Single_ReadI2C(IST8310_SLAVE_ADDRESS,0x05);//OUT_Y_L_A
    Mag_IST8310.Buf[3]=Single_ReadI2C(IST8310_SLAVE_ADDRESS,0x06);//OUT_Y_H_A
    Mag_IST8310.Buf[4]=Single_ReadI2C(IST8310_SLAVE_ADDRESS,0x07);//OUT_Z_L_A
    Mag_IST8310.Buf[5]=Single_ReadI2C(IST8310_SLAVE_ADDRESS,0x08);//OUT_Z_H_A
    /*****************合成三轴磁力计数据******************/
    Mag_IST8310.Mag_Data[0]=(Mag_IST8310.Buf[1]<<8)|Mag_IST8310.Buf[0];
    Mag_IST8310.Mag_Data[1]=(Mag_IST8310.Buf[3]<<8)|Mag_IST8310.Buf[2];
    Mag_IST8310.Mag_Data[2]=(Mag_IST8310.Buf[5]<<8)|Mag_IST8310.Buf[4];
    IST8310_Sample_Cnt=0;
  }
#ifdef MAG_REVERSE_SIDE//重新映射磁力计三轴数据
   Mag_IST8310.x = Mag_IST8310.Mag_Data[0];
   Mag_IST8310.y = -Mag_IST8310.Mag_Data[1];
   Mag_IST8310.z = Mag_IST8310.Mag_Data[2];
#else 
   Mag_IST8310.x = Mag_IST8310.Mag_Data[0];
   Mag_IST8310.y = Mag_IST8310.Mag_Data[1];
   Mag_IST8310.z = Mag_IST8310.Mag_Data[2];
#endif
   DataMag.x=Mag_IST8310.x;
   DataMag.y=Mag_IST8310.y;
   DataMag.z=Mag_IST8310.z;
        
   MagTemp[0]=Mag_IST8310.x-Mag_Offset[0];
   MagTemp[1]=Mag_IST8310.y-Mag_Offset[1];
   MagTemp[2]=Mag_IST8310.z-Mag_Offset[2];
   
   
   /************磁力计倾角补偿*****************/
   Mag_IST8310.thx = MagTemp[0] * Cos_Roll+ MagTemp[2] * Sin_Roll;
   Mag_IST8310.thy = MagTemp[0] * Sin_Pitch*Sin_Roll    
                    +MagTemp[1] * Cos_Pitch
                    -MagTemp[2] * Cos_Roll*Sin_Pitch;
   /***********反正切得到磁力计观测角度*********/
   Mag_IST8310.Angle_Mag=atan2(Mag_IST8310.thx,Mag_IST8310.thy)*57.296;
}
磁力计倾角补偿为什么?










本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

无名飞控 的相关文章

  • 用位运算实现两个整数的加减乘除运算

    位运算的思想可以应用到很多地方 xff0c 这里简单的总结一下用位运算来实现整数的四则运算 1 整数加法 int Add int a int b for int i 61 1 i i lt lt 61 1 if b amp i for in
  • 深入理解C/C++数组和指针

    版权所有 xff0c 转载请注明出处 xff0c 谢谢 xff01 http blog csdn net walkinginthewind article details 7044380 C语言中数组和指针是一种很特别的关系 xff0c 首
  • 轻松搞定面试中的链表题目

    版权所有 xff0c 转载请注明出处 xff0c 谢谢 xff01 http blog csdn net walkinginthewind article details 7393134 链表是最基本的数据结构 xff0c 面试官也常常用链
  • 轻松搞定面试中的二叉树题目

    版权所有 xff0c 转载请注明出处 xff0c 谢谢 xff01 http blog csdn net walkinginthewind article details 7518888 树是一种比较重要的数据结构 xff0c 尤其是二叉树
  • 动态内存分配(malloc/free)简单实现--隐式空闲链表

    本文使用隐式空闲链表实现简单的动态内存分配 动态内存分配器维护一个大块区域 xff0c 也就是堆 xff0c 处理动态的内存分配请求 分配器将堆视为一组不同大小的块的集合来维护 xff0c 每个块要么是已分配的 xff0c 要么是空闲的 实
  • 二分查找,你真的掌握了吗?

    版权所有 xff0c 转载请注明出处 xff0c 谢谢 xff01 http blog csdn net walkinginthewind article details 8937978 二分查找 xff0c 最基本的算法之一 xff0c
  • 【谷歌面试题】求数组中两个元素的最小距离

    一个数组 xff0c 含有重复元素 xff0c 给出两个数num1和num2 xff0c 求这两个数字在数组中出现的位置的最小距离 O n 时间复杂度 xff0c O 1 空间复杂度 int minDistance int A int si
  • 进程间通信

    原作者地址不详 摘 要 随着人们对应用程序的要求越来越高 xff0c 单进程应用在许多场合已不能满足人们的要求 编写多进程 多线程程序成为现代程序设计的一个重要特点 xff0c 在多进程程序设计中 xff0c 进程间的通信是不可避免的 Mi
  • 通过能观性分析理解SLAM系统的可观维度。

    目录 1 能观性分析大体理解2 可观性定义3 可观性矩阵 1 能观性分析大体理解 什么是能观性分析 xff1f 能观性分析通过计算可观性矩阵 xff0c 分析它的零空间的秩 xff0c 来分析系统哪些状态维度可观 不可观 可观性矩阵对应系统
  • 百度2014移动研发笔试题目——1013清华版

    一 简答题 1 简述计算机的存储系统分为哪几个层次 xff0c 为什么这样的分层能够提高程序的执行效率 2 浮点数在计算中如何表示 xff0c 如何对浮点数判等 3 简述TCP与UDP协议的差别 xff0c 两者与HTTP的关系 并列举HT
  • 史上最全的ubuntu16.04安装nvidia驱动+cuda9.0+cuDnn7.0

    本文参考了 http www cnblogs com 5211314jackrose p 7081020 html https jingyan baidu com article 4853e1e55679491909f726f4 html
  • 4、ORB-SLAM闭环检测之通过词袋寻找当前关键帧和闭环候选帧之间的匹配

    目录 1 SearchByBoW 2 图解每一步实现原理 2 1 通过词袋模型寻找匹配 2 2 通过旋转直方图来筛除离群点 3 期待您加入 前面 我们已经了解到了sim3的求解流程 具体计算过程中有三步比较重要 1 寻找两关键帧之间的粗匹配
  • 基于Web服务的物联网-WoT(Web of Things)

    当我们谈到智能手机 xff0c 多样性 往往不是问题 xff0c 主流市场不是基于苹果IOS系统的就是谷歌的Android系统 xff0c 但即将到来的物联网浪潮 xff0c 智能对象是否也能这样 xff1f 这就复杂多了 xff0c 当前
  • 如何选择 catkin_make和catkin_make_isolated

    问题 在编译cartographer的代码包的时候 xff0c 会被建议使用catkin make isolated xff0c 为何不使用catkin make呢 xff1f 原因 catkin make was the first sc
  • 基于共享内存的分布式消息学习笔记

    作者 xff1a 深圳自研业务组 jimwu 编辑 xff1a 上海业务组 alenai 目录 xff1a Tbus 简介 Tbus 原理 Tbus 配置与工具 Tbus 简单应用 Tbus 运维应用 为 python 扩展 总结 Tbus
  • 分享一下工作以来我看过计算机书籍

    由于自工作依赖一直专注于linux 下的c c 43 43 编程工作 xff0c 所以 xff0c 我的书籍也大的都是这方 这边书尽管很经典 xff0c 但是我的能力实在有限 xff0c 只把数据结构的那点看了一下 xff0c 其他的 看的
  • 51单片机定时器初值计算详解

    前言 xff1a 本文详细介绍了51单片机学习过程中定时器的初值计算问题以及相关概念 xff0c 力求把每一个学习过程中的可能会遇到的难点说清楚 xff0c 并举相关的例子加以说明 学习完毕 xff0c 又顺手利用刚学到定时器的相关知识写了
  • STM32平台下官方DMP库6.12超详细移植教程

    前记 Motion Driver官方库 xff1a Motion Driver 6 12 STM32工程源码 xff1a STM32F103C8 软件MPU6050 xff08 DMP xff09 MPU6050软件I2C驱动 xff0c
  • STM32F103C8-平衡小车笔记

    STM32F103C8 平衡小车笔记 1 PID的作用 xff08 1 xff09 比例项 xff1a 提高响应速度 xff0c 减小静差 xff08 2 xff09 积分项 xff1a 消除稳态误差 xff08 3 xff09 微分项 x

随机推荐

  • 嵌入式Linux系统开发笔记(十四)

    U Boot环境变量 uboot 中有两个非常重要的环境变量 bootcmd 和 bootargs xff0c bootcmd 和 bootagrs 是采用类似 shell 脚本语言编写的 xff0c 里面有很多的变量引用 xff0c 这些
  • 嵌入式Linux系统开发笔记(十五)

    Linux内核启动验证 5 1 编译内核 span class token comment 清除工程 span span class token comment make distclean span span class token co
  • 基于ROS搭建机器人仿真环境

    别人的发复现及经验 https blog csdn net qq 38620941 article details 125321347 gazebo默认仿真环境 1 gazebo models 是系统下gazebo放置模型库的默认位置 2
  • 嵌入式Linux系统开发笔记(十六)

    根文件系统rootfs启动验证测试 接下来我们使用测试一下前面创建好的根文件系统 rootfs xff0c 测试方法使用 NFS 挂载 6 1 检查是否在Ubuntu主机中安装和开启了NFS服务 xff08 特别注意 xff1a nfs 配
  • 安卓5.0以上7.0以下使用Termux

    参考 xff1a https zhuanlan zhihu com p 400507701 说明 xff1a Termux支持5 0以上的安卓系统 Termux7 3版本之后 xff0c 仅支持7 0以上的安卓系统 1 安装Termux 设
  • 关于DSP的CCS6.0平台下的工程搭建(完全可移植)

    本工程以CCS6 0下新建TMS320F28335工程为例 xff0c 其他系列处理器工程搭建类似 xff0c 参考本例即可 工程搭建用到的F2833x TI官方库文件 下载链接 也可直接参考笔者搭建好CCS6 0的工程 下载链接 所建工程
  • STM32Fxx JTAG/SWD复用功能重映射

    问题描述 xff1a 在实验室调车过程中 xff0c 遇到的一个问题 xff1a 为了每次下载程序方便 xff0c 队员们往往会把 Jlink 插在板子上 xff0c 可是在调车过程中发现 xff0c 有时程序会莫名死掉 xff0c 而同样
  • VS2012编译RTKLIB——GNSS定位开源库

    RTKLIB 开源库 有着强大的 GPS 数据实时和后处理功能 xff0c 由于 笔者的毕业设计中需要对GPS 载波相位观测量进行 RTK 解算 xff0c 故而 xff0c 对 RTKLIB 开源库进行了学习与研究 RTKLIB 提供了很
  • 51单片机串行口波特率计算

    1 工作方式介绍 xff1a 方式 0 xff1a 这种工作方式比较特殊 xff0c 与常见的微型计算机的串行口不同 xff0c 它又叫 同步移位寄存器输出方式 在这种方式下 xff0c 数据从 RXD 端串行输出或输入 xff0c 同步信
  • 数码管显示问题总结

    1 数码管显示原理 我们最常用的是七段式和八段式 LED 数码管 xff0c 八段比七段多了一个小数点 xff0c 其他的基本相同 所谓的八段就是指数码管里有八个小 LED 发光二极管 xff0c 通过控制不同的 LED 的亮灭来显示出不同
  • 单片机与嵌入式linux 比较

    MCU门槛低 xff0c 入门容易 xff0c 但是灵活 xff0c 其实对工程师的软硬件功底要求更高 xff0c 随着半导体的飞速发展 xff0c MCU能实现很多匪夷所思匪夷所思的功能 xff0c 比如 xff0c 使用GPIO模拟1个
  • rtk 精确定位 简介

    RTK又称载波相位差分 xff1a 基准站通过数据链及时将其载波观测量及站坐标信息一同传送给用户站 用户站接收GPS卫星的载波相位与来自基准站的载波相位 xff0c 并组成相位差分观测值进行及时处理 xff0c 能及时给出厘米级的定位结果
  • STM32开发利器:STM32CubeMX

    这篇博客篇幅不长 xff0c 主要是为大家介绍ST公司推出的STM32CubeMX开发工具 xff0c 当成下周更新STM32 10个项目工程的预备篇 xff0c 同时FPGA FPGA 20个例程篇 xff1a 8 SD卡任意地址的读写
  • ROS命名空间

    ROS命令空间是一个很重要的内容 xff0c 官方文档 xff1a http wiki ros org Names 分为三类 xff1a relative xff0c global xff0c private 下边是一个官网给的示例 Nod
  • STM32CubeMX关于添加DSP库的使用

    前言 人生如逆旅 xff0c 我亦是行人 一 介绍 STM32 系列基于专为要求高性能 低成本 低功耗的嵌入式应用专门设计的 ARM Cortex M3 内核 而 DSP 应该是 TMS320 系列 xff0c TMS320 系列 DSP
  • STM32H750VBT6的DSP使用的学习——基于CubeMX

    前言 人生如逆旅 xff0c 我亦是行人 1 STM32H7的DSP功能介绍 xff08 STMicroelectronics xff0c 简称ST xff09 推出新的运算性能创记录的H7系列微控制器 新系列内置STM32平台中存储容量最
  • ROS中激光雷达数据类型传递转换及自定义点云数据类型介绍

    目录 一 ROS中激光雷达数据类型传递转换 xff1b 二 点云数据解析 三 自定义点云数据类型 一 ROS中激光雷达数据类型传递转换 xff1b ROS中涉及激光雷达传递的消息类型有两种 xff0c 一种是针对2D雷达 sensor ms
  • C/C++优秀书籍清单

    转载自 xff1a https www cnblogs com kimiway p 3225767 html 书籍是码农进步的阶梯 读好书 好读书 干一行爱一行 除了工作还有生活 在陪伴家人同时 也不忘提高自己 为更好的生活努力 1 C程序
  • 打印_battery_status.scale

    在px4的姿态控制中 xff0c publish控制量时代码乘以了一个 battery status scale xff0c scale effort by battery status if params bat scale en amp
  • 无名飞控

    无名飞控Time c文件 由于 无名飞控主要核心 xff1a 传感器滤波 姿态解算 惯导 控制等代码在TIME c里面运行 xff0c 所以先来分析这个文件 打开文件第一个函数 xff1a void Timer4 Configuration