匿名四轴【任务一(1000Hz)之读取传感器】

//为什么讲上面的呢因为下面有GetSysTime_us函数,
//返回结果值是value就是我们的记录的时间
//看到1000你应该就明白了每1ms执行一次
u32 test_dT_1000hz[3],test_rT[6];
static void Loop_1000Hz(void)	//1ms执行一次
{
	test_dT_1000hz[0] = test_dT_1000hz[1];
	test_rT[3] = test_dT_1000hz[1] = GetSysTime_us ();
    //记录当前的时间,并将存储的时间存储在test_rT[3],
    //test_dT_1000hz[1]中
    //这样我们再看上面就是把上次存储的时间存储在test_dT_1000hz[0]
    //总的来说
    //test_dT_1000hz[0]上一次时间
    //test_dT_1000hz[1]这次的时间
	test_dT_1000hz[2] = (u32)(test_dT_1000hz[1] - test_dT_1000hz[0]) ;
    //test_dT_1000hz[2]记录这次时间与上一次时间的差值
    
	/*传感器数据读取*/
	Fc_Sensor_Get();
	
	/*惯性传感器数据准备*/
	Sensor_Data_Prepare(1);
	
	/*姿态解算更新*/
	IMU_Update_Task(1);
	
	/*获取WC_Z加速度*/
	WCZ_Acc_Get_Task();
	WCXY_Acc_Get_Task();
	
	/*飞行状态任务*/
	Flight_State_Task(1,CH_N);
	
	/*开关状态任务*/
	Swtich_State_Task(1);
	
	/*光流融合数据准备任务*/
	ANO_OF_Data_Prepare_Task(0.001f);


	/*数传数据交换*/
	ANO_DT_Data_Exchange();

	test_rT[4]= GetSysTime_us ();
	test_rT[5] = (u32)(test_rT[4] - test_rT[3]) ;	
}

读取传感器数据

u16 test_time_cnt;
void Fc_Sensor_Get()//1ms
{
	static u8 cnt;
    /*
    在主函数中flag.start_ok = All_Init();
    //进行所有设备的初始化,并将初始化结果保存
    初始化成功返回1,其实看过All_Init()知道无论什么时候都返回的是1,
    也就说只要函数All_Init()运行过	  
    不管传感器存不存在start_ok都为1
    */
	if(flag.start_ok)//All_Init运行过就为1
	{
		/*读取陀螺仪加速度计数据*/
		Drv_Icm20602_Read();
		cnt ++;
		cnt %= 20;
        //每一次读取数据cnt都实现+1操作,
        //当加到20实现下面的电子罗盘磁力计数据读取和气压计数据读取
        //这样实现了20ms读取电子罗盘磁力计和气压计读取
		if(cnt==0)
		{
			/*读取电子罗盘磁力计数据*/
			Drv_AK8975_Read();
			/*读取气压计数据*/
			baro_height = (s32)Drv_Spl0601_Read();
            //baro_height指的是气压高度
		}
	}	
	test_time_cnt++;
}
陀螺仪读数
u8 mpu_buffer[14];
void Drv_Icm20602_Read()
{
    //#define MPUREG_ACCEL_XOUT_H                     0x3B
	icm20602_readbuf(MPUREG_ACCEL_XOUT_H,14,mpu_buffer);//mpu_buffer用来接收收到的数据
	ICM_Get_Data();
}

icm20602

/*
	陀螺仪数据读取,我们采取的陀螺仪 ICM20602是INVENSENSE一款产品
	INVENSENSE生产MPU6050,其操作和ICM20602差不多
	这里的data是mpu_buffer,length=14,reg = 0X3B
*/
static void icm20602_readbuf(u8 reg, u8 length, u8 *data)
{
	icm20602_enable(1);
    //通过设置CS信号来达到使能和失能,CS即片选信号当有多个芯片接在一条总线上
    //可以通过片选信号来实现对应芯片工作
	Drv_SPI2_RW(reg|0x80);
    //写数据和读数据
	Drv_SPI2_Receive(data,length);
    //接收函数
	icm20602_enable(0);
}
//接下来我们来具体看一下上面提到的两个函数
//接收函数 发送0然后将接收到的数存储在mpu_buffer中,一共十四次,
//正好填满mpu_buffer[14]
void Drv_SPI2_Receive(uint8_t *pData, uint16_t Size)
{
    for(uint16_t i=0; i<Size; i++)
    {
        pData[i] = Drv_SPI2_RW(0);
    }
}
//发一个数据然后返回接收到的数据
u8 Dcrv_SPI2_RW(u8 dat)
{
    while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);
    SPI_I2S_SendData(SPI2, dat);
    while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);
    return SPI_I2S_ReceiveData(SPI2);
}

到此我们可以看懂icm20602_readbuf函数了但是我们还来看一下icm20602_writebyte函数日后可能会用到

//显然经过上面readbuf讲解看着部分代码要显得容易得多
static u8 icm20602_writebyte(u8 reg, u8 data)
{
    u8 status;
    icm20602_enable(1);
    status = Drv_SPI2_RW(reg);//发送reg数据接收返回值给status
    Drv_SPI2_RW(data);//发送data数据
    icm20602_enable(0);
    return status;
}
//这一部分代码我们后续用到再进行讲解
ICM_Get_Data
enum
{
	X = 0,
	Y = 1,
	Z = 2,
	VEC_XYZ,//3
};
//看到这里可能有些人有点慌了,不要急
//enum是C语言提供的一种枚举类型,这里的枚举是没有typename的,
//作用类似于define
void ICM_Get_Data()
{
    //typedef int16_t s16;
	s16 temp[2][3];
	//	/*读取buffer原始数据*/
  //还记得mpu_buffer[14]就是Drv_Icm20602_Read读取的数据存储的方法,
  //这里我们知道了原来读出来的是原始数据temp是16位数据,
  //收到的都是8位数据,收到的数据2个8位表示一个16位数据,
  //这两个8位合在一起才有意义,
  //单单一个8位只能表示一个数的低八位和高八位,
  //我们接受到的数据前一个数据表示高八位
	temp[0][X] = (s16)((((u16)mpu_buffer[0]) << 8) | mpu_buffer[1]);
    //>>1;// + 2 *sensor.Tempreature_C;// + 5 *sensor.Tempreature_C;
	temp[0][Y] = (s16)((((u16)mpu_buffer[2]) << 8) | mpu_buffer[3]);
    //>>1;// + 2 *sensor.Tempreature_C;// + 5 *sensor.Tempreature_C;
	temp[0][Z] = (s16)((((u16)mpu_buffer[4]) << 8) | mpu_buffer[5]);
    //>>1;// + 4 *sensor.Tempreature_C;// + 7 *sensor.Tempreature_C;
	temp[1][X] = (s16)((((u16)mpu_buffer[ 8]) << 8) | mpu_buffer[ 9]) ;
	temp[1][Y] = (s16)((((u16)mpu_buffer[10]) << 8) | mpu_buffer[11]) ;
	temp[1][Z] = (s16)((((u16)mpu_buffer[12]) << 8) | mpu_buffer[13]) ;
    
//十轴陀螺仪返回温度没有什么问题
sensor.Tempreature = ((((int16_t)mpu_buffer[6]) << 8) | mpu_buffer[7]); //tempreature

/*icm20602温度*/
//这个应该是温度的计算,应该再陀螺仪手册中有讲到温度二点换算公式
//senor指的应该是传感器的意思,包括陀螺仪,气压计,罗盘磁力计
sensor.Tempreature_C = sensor.Tempreature/326.8f + 25 
//sensor.Tempreature/340.0f + 36.5f;
//读出的sensor.Tempreature为原始的温度数据值,
//sensor.Tempreature_C为换算后的摄氏度
//调整物理坐标轴与软件坐标轴方向定义一致
//这里的ACC表示加速度,看来陀螺仪很好,读出来的直接是处理好的数据
sensor.Acc_Original[X] = temp[0][X];
sensor.Acc_Original[Y] = temp[0][Y];
sensor.Acc_Original[Z] = temp[0][Z];
//这里的Gyro网上说的就是陀螺仪,暂时不清楚什么意思,
//可能要到拿到芯片资料才知道了
sensor.Gyro_Original[X] = temp[1][X];
sensor.Gyro_Original[Y] = temp[1][Y];
sensor.Gyro_Original[Z] = temp[1][Z];
}
//这边的sensor和下面提到的_sensor_st是同一个东西
typedef struct 
{
	u8 acc_CALIBRATE;
	u8 gyr_CALIBRATE;
	u8 acc_z_auto_CALIBRATE;
	
	s16 Acc_Original[VEC_XYZ];
	s16 Gyro_Original[VEC_XYZ];
	
	s16 Acc[VEC_XYZ];
	s32 Acc_cmss[VEC_XYZ];
	float Gyro[VEC_XYZ];
	float Gyro_deg[VEC_XYZ];
	float Gyro_rad[VEC_XYZ];

	s16 Tempreature;//出来的原始温度
	float Tempreature_C;//出来的摄氏度
}_sensor_st;

如果有错误,希望再评论区指出
好了代码先到这,后续代码还会继续讲解
排版不加,见谅

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
匿名科创四轴同款传感器方案设计ICM20602+AK8975+SPL06-001 电赛必备!!! 四轴必备!!! 四轴起飞时,发出触发信号使导航模块开始工作,同时读取ICM20602的加速度计、陀螺仪数据,对数据卡尔曼滤波后姿态解算,对角度与角速度采取串级PID调节。 控制系统算法设计主要有ICM20602滤波算法,姿态解算算法、串级PID控制算法和定高部分控制算法。碍于篇幅所限,下面介绍最重要的串级PID控制算法和定高部分控制算法。 地理坐标系中重力的水平分量为零,仅用三轴陀螺仪和三轴加速度计无法计算出航向角,由于巡线机器人保持稳定飞行只需要横滚角(roll)和俯仰角(pitch),所以四元数转换成欧拉角。 定高控制算法采用的是增量式PID控制,定高控制的输出最后与姿态控制的输出叠加到四个电机的控制中。数据滤波使用的是低通滤波,采用近三次的平均值。为了防止姿态对激光测距的影响及减小高度控制对姿态控制的干扰使用欧拉角来校正高度值,即Hight=(float)Hight*(cos(roll)* cos(pitch))。将四元数转换后的欧拉角与陀螺仪测出来的角速度进行串级PID控制,其中欧拉角作为外环,角速度作为内环。外环的PID以及内环的PD设定值为测试数据值。由于内环的角速度控制不需要无静差,所以内环采用PD控制,为防止测量的误差造成较大影响,外环积分需要限幅。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值