【随手笔记】三轴传感器

模组知识之三轴

1. 名词释义

请问什么是三轴,什么是6轴
请问什么是加速度,陀螺仪,罗盘

  • 三轴加速度

三轴加速度传感器是加速度传感器中用来测量空间加速度的传感器,即测量物体在空间中速度变化的快慢,三轴加速度传感器与单轴、两轴加速度传感器在测量原理上没有差别,他们的主要差别在于测量的维度不同,三轴加速度传感器主要是将空间加速度在X、Y、Z三个轴上进行分解,在一定的技术上三个单轴就可以变成一个三轴

先看下加速度计和陀螺仪的区别

测量类型:加速度计测量线性运动(直线运动),而陀螺仪测量旋转运动。
数据输出:加速度计输出的是加速度,单位通常是米/秒²;
陀螺仪输出的是角速度,单位通常是度/秒或弧度/秒。

(加速度的单位在国际单位制(SI)中是 米每二次方秒(meter per second squared),通常写作 m/s² 或者 m·s⁻²。这个单位用来衡量速度随时间变化的速率,即物体的速度每秒钟增加或减少多少米每秒。
加速度是一个矢量量,它不仅有大小,还有方向。加速度的方向与引起速度变化的力的方向一致。例如,在直线运动中,如果一个物体的速度在增加,那么它的加速度方向就与它的运动方向相同;反之,如果速度在减小,则加速度方向与运动方向相反)

应用:虽然两者都被用于确定设备的方向,
但加速度计更常用于测量设备的倾斜(如智能手机的屏幕方向),
而陀螺仪更常用于测量设备的转动(如无人机的航向)

通常来讲,所谓的几轴传感器,一般是泛指:加速度计(ACCELEROMETER)、陀螺仪(GYROSCOPE)、电子罗盘(COMPASS),这三类传感器

  • 加速度:可以感知任意方向上的加速度,通过测量组件在某个轴向的受力情况来得到结果,表现形式为轴向的加速度大小和方向(X、Y、Z)
  • 陀螺仪:通过测量自身的旋转运动状态(角速度),判断出设备当前运动状态(向前、向后、向左、向右、向上、向下),不能判断出设备的方位(东、西、南、北)。
  • 电子罗盘:可以测量出当前设备与东、南、西、北四个方向上的夹角。有时候还会见到,一些设备标注装备了:磁力计(Magnetic、M-Sensor),磁力计作用和电子罗盘差不多,都是利用并测量地球磁场的传感器,磁力计测量数据之后需要自己读数,电子罗盘则进一步把测量后的结果显示出来。
    6轴传感器:通常由多种3轴传感器组合而成,3轴加速度计+3轴陀螺仪

9轴传感器:就是3轴加速度计+3轴陀螺仪+3轴电子罗盘,通过欧拉角加四元数数据融合后的组合,在飞行器上是广泛应用的。

举个例子来说:当日常佩戴装备加速度计、陀螺仪、电子罗盘的智能穿戴设备时,相当于:加速计知道“我们开始运动了(监测运动中加速度)”,陀螺仪知道“我们在何时转了个身(监测运动中角速度)”、磁力计则知道“我们是运动的具体方向(监测运动方位:东南西北)”。

  • 加速度:检测物体的加速度,判断倾角(三轴加速度计的原理能够用来测量角度)
  • 陀螺仪:检测物体的运行方向
  • 电子罗盘:检测物体的世界方位

参考链接:

[学习IMU](MEMS 三轴加速计、三轴陀螺仪、三轴磁力计)6轴IMU+磁力计,9轴传感器讲解

加速计和陀螺仪的区别
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
介于其测量角度的工作原理三轴加速度计无法测量偏航角
可测量俯仰角和横滚角
在这里插入图片描述

2. 三轴模组ADXL35

在这里插入图片描述
在这里插入图片描述
参考链接
ADXL345传感器介绍

使用IIC通讯

请看使用数据手册

  • ADXL345自动调节功耗,与输出数据速率成比例

  • 数据读取方式IIC

  • ALT ADDRESS引脚处于高电平,器件的7位I2C地址是0x1D,随后为R/W位。这转化为
    0x3A写入,0x3B读取。

  • 通过ALT ADDRESS引脚(引脚12)接地,可以选择备用I2C地址0x53(随后为R/W位)。

  • 这转化为0xA6写入,0xA7读取
    在这里插入图片描述
    IIC通讯的时序

  • ADXL345为驱动中断提供两个输出引脚:INT1和INT2。
    这两个中断引脚都是推挽低阻抗引脚,其输出规格如表
    1 3所 示 。 中 断 引 脚 默 认 配 置 为 高 电 平 有 效 。 设 置
    DATA_FORMAT寄存器(地址0x31)中的INT_INVERT
    位,可以更改为低电平有效。所有功能都可以同时使


每一个寄存器的研究设置是一个力气活

3.代码参考

/*
* 初始化: 角度测量+阀值触发活动中断
* /
rt_err_t triaxial_init(rt_device_t dev)
{
    uint8_t init_read =0;
     //打开
     ADXL345_HIGH;
     TRIAX_SCL_HIGH;
     TRIAX_SDA_HIGH;

     rt_thread_mdelay(1000);

     user_iic_init_extend(&iic_ctl_triaxial);

     user_read_byte_extend(&iic_ctl_triaxial, ADXL345_ADDR, ADXL345_START, &init_read);
     LOG_OUT("triaxial_init=[%x]\r\n", init_read);
     if(init_read == 0xE5)
     {
         LOG_OUT("triaxial ok\r\n");
     }

     user_write_byte_extend(&iic_ctl_triaxial, ADXL345_ADDR, 0x2E,0x00);   //禁用中断

     user_write_byte_extend(&iic_ctl_triaxial, ADXL345_ADDR, 0x1E,0x00);   //X 偏移量 根据测试传感器的状态写入
     user_write_byte_extend(&iic_ctl_triaxial, ADXL345_ADDR, 0x1F,0x00);   //Y 偏移量 根据测试传感器的状态写入
     user_write_byte_extend(&iic_ctl_triaxial, ADXL345_ADDR, 0x20,0x00);   //Z 偏移量 根据测试传感器的状态写入

     user_write_byte_extend(&iic_ctl_triaxial, ADXL345_ADDR, 0x1D,0x10);   //敲击阀值
     user_write_byte_extend(&iic_ctl_triaxial, ADXL345_ADDR, 0x21,0x00);   //持续时间
     user_write_byte_extend(&iic_ctl_triaxial, ADXL345_ADDR, 0x22,0x00);   //开始延迟
     user_write_byte_extend(&iic_ctl_triaxial, ADXL345_ADDR, 0x23,0x00);   //敲击窗口

     user_write_byte_extend(&iic_ctl_triaxial, ADXL345_ADDR, 0x24,0x0A);   //活动阀值
     user_write_byte_extend(&iic_ctl_triaxial, ADXL345_ADDR, 0x25,0x05);   //静止阀值
     user_write_byte_extend(&iic_ctl_triaxial, ADXL345_ADDR, 0x26,0x01);   //进入静止时间
     user_write_byte_extend(&iic_ctl_triaxial, ADXL345_ADDR, 0x27,0xFF);   //三轴参与

     user_write_byte_extend(&iic_ctl_triaxial, ADXL345_ADDR, 0x28,0x05);   //自由落体阀值
     user_write_byte_extend(&iic_ctl_triaxial, ADXL345_ADDR, 0x29,0x14);   //自由落体时间

     user_write_byte_extend(&iic_ctl_triaxial, ADXL345_ADDR, 0x2A,0x00);   //抑制双击检测

     user_write_byte_extend(&iic_ctl_triaxial, ADXL345_ADDR, 0x2C,0x0A);   //标准默认速率
     user_write_byte_extend(&iic_ctl_triaxial, ADXL345_ADDR, 0x2D,0x08);   //测量不休眠

     user_write_byte_extend(&iic_ctl_triaxial, ADXL345_ADDR, 0x31,0x0B);   //测量范围,正负16g,13位模式
     user_write_byte_extend(&iic_ctl_triaxial, ADXL345_ADDR, 0x38,0xA0);   //流

     user_write_byte_extend(&iic_ctl_triaxial, ADXL345_ADDR, 0x2F,0xEF);   //使能中断引脚
     user_write_byte_extend(&iic_ctl_triaxial, ADXL345_ADDR, 0x2E,0x93);   //使能中断

 //    设置参数查看
 //    uint8_t data_read =0;
 //    for(uint8_t t=29; t<58; t++)
 //    {
 //        user_read_byte_extend(&iic_ctl_triaxial, ADXL345_ADDR, t, &data_read);
 //        LOG_OUT("%x=%x\r\n", t, data_read);
 //    }


    return RT_EOK;
}
/*
* 数据读取
* /
rt_size_t triaxial_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
{
    LOG_OUT("triaxial_read\r\n");

//  int a[3][4];
//  定义了一个 3 行 4 列的二维数组

    triaxial_init(NULL);

    uint8_t data_buff[6] = {0};
    int16_t data_xyz[ADXL345_BUFF_ROW][ADXL345_BUFF_COL] = {0};

    uint8_t irq_flag = 0;
    int data_x = 0;
    int data_y = 0;
    int data_z = 0;
    uint8_t shake_flag = 0;
    uint8_t *data_p = buffer;

    rt_thread_mdelay(100);

    user_read_byte_extend(&iic_ctl_triaxial, ADXL345_ADDR, 0x30, &irq_flag);
    LOG_OUT("irq_flag=%x\r\n", irq_flag);

    for(uint8_t t=0; t<ADXL345_BUFF_ROW; t++)
    {

        user_iic_read_byte_more_extend(&iic_ctl_triaxial, ADXL345_ADDR, ADXL345_ADDR_X1, data_buff, 6);

        //LOG_OUT("%x %x %x %x %x %x\r\n", data_buff[0], data_buff[1], data_buff[2], data_buff[3], data_buff[4], data_buff[5]);

        data_xyz[t][0] = data_buff[0] | data_buff[1]<<8;
        data_xyz[t][1] = data_buff[2] | data_buff[3]<<8;
        data_xyz[t][2] = data_buff[4] | data_buff[5]<<8;

        if(data_xyz[t][0] < 0)
            data_xyz[t][0] = -data_xyz[t][0];

        if(data_xyz[t][1] < 0)
            data_xyz[t][1] = -data_xyz[t][1];

        if(data_xyz[t][2] < 0)
            data_xyz[t][2] = -data_xyz[t][2];

        LOG_OUT("x=%d y=%d z=%d\r\n", data_xyz[t][0], data_xyz[t][1], data_xyz[t][2]);
        rt_thread_mdelay(15);
    }
    user_read_byte_extend(&iic_ctl_triaxial, ADXL345_ADDR, 0x30, &irq_flag);
    LOG_OUT("irq_flag=%x\r\n", irq_flag);
    rt_thread_mdelay(500);

    if(TRIAX_READ == GPIO_PIN_SET)
    {
        LOG_OUT(">>> INT1=HIGH\r\n");
        shake_flag = 1;
    }
    else
    {
        LOG_OUT(">>> INT1=LOW\r\n");
        shake_flag = 0;
    }

    user_read_byte_extend(&iic_ctl_triaxial, ADXL345_ADDR, 0x30, &irq_flag);
    LOG_OUT("irq_flag=%x\r\n", irq_flag);

    //关闭
    ADXL345_LOW;
    TRIAX_SCL_LOW;
    TRIAX_SDA_LOW;

    for(uint8_t t=0; t<ADXL345_BUFF_ROW; t++)
    {
        data_x += data_xyz[t][0];
        data_y += data_xyz[t][1];
        data_z += data_xyz[t][2];
    }
    data_x = data_x / ADXL345_BUFF_ROW;
    data_y = data_y / ADXL345_BUFF_ROW;
    data_z = data_z / ADXL345_BUFF_ROW;

    LOG_OUT("average x=%d y=%d z=%d\r\n", data_x, data_y, data_z);

    data_x = sqrt(data_y*data_y + data_z*data_z)/data_x;
    data_x = atan(data_x)*180/3.14;
    data_x = 90 - data_x;

    data_y = sqrt(data_x*data_x + data_z*data_z)/data_y;
    data_y = atan(data_y)*180/3.14;
    data_y = 90 - data_y;

    data_z = sqrt(data_x*data_x + data_y*data_y)/data_z;
    data_z = atan(data_z)*180/3.14;
    data_z = 90 - data_z;

    LOG_OUT("ret angle:x=%d y=%d z=%d\r\n", data_x, data_y, data_z);

    *data_p = data_x&0xFF;
    *(data_p+1) = data_y&0xFF;
    *(data_p+2) = data_z&0xFF;
    *(data_p+3) = shake_flag;

    return RT_EOK;


}

在这里插入图片描述
注意0x30寄存器,读取数据后数据位清零

4. 角度计算

在这里插入图片描述

pitch是俯仰角,是“点头“,(在固定翼飞机中则由升降舵舵机控制)

yaw是偏航角,是‘摇头’,(在固定翼飞机中则由方向舵舵机控制)

roll是旋转角,是“翻滚”,(在固定翼飞机中则由副翼舵机控制)
换算角度
ax =  atan(sqrt(y*y+z*z)/x)*180/3.14;
ay =  atan(sqrt(x*x+z*z)/y)*180/3.14;
az =  atan(sqrt(x*x+y*y)/z)*180/3.14

 dev=sqrt( x*x+y*y)/(z);//分母是谁,就是谁的倾角
 dev=atan(dev)*180/3.1416;
 sprintf(str," qj %3.2f",dev)
	角度转换参考
    LOG_OUT("average x=%d y=%d z=%d\r\n", data_x, data_y, data_z);

    data_x = sqrt(data_y*data_y + data_z*data_z)/data_x;
    data_x = atan(data_x)*180/3.14;
    data_x = 90 - data_x;

    data_y = sqrt(data_x*data_x + data_z*data_z)/data_y;
    data_y = atan(data_y)*180/3.14;
    data_y = 90 - data_y;

    data_z = sqrt(data_x*data_x + data_y*data_y)/data_z;
    data_z = atan(data_z)*180/3.14;
    data_z = 90 - data_z;

    LOG_OUT("ret angle:x=%d y=%d z=%d\r\n", data_x, data_y, data_z);

分享链接
【嵌入式模块芯片开发】ADXL345的优化精确测量和角度计算(中断单次测量、卡尔曼滤波)

shineblink ADXL345传感器测量三轴加速度/倾斜角

ADXL345加速度计使用心得(带中断唤醒)

在这里插入图片描述

基于STM32CubeMX ADXL345传感器经验分享

ADXL345测量角度

STM32——库函数版——ADXL345驱动程序

/*******************************************************************************
* 函 数 名 : ADXL345_Get_Angle
* 函数功能 : 得到角度
* 输    入 : x,y,z:x,y,z方向的重力加速度分量(不需要单位,直接数值即可)
             dir:要获得的角度.0,与Z轴的角度;1,与X轴的角度;2,与Y轴的角度.
* 输    出 : 无
* 返 回 值 :返回值:角度值.单位0.1°.
*******************************************************************************/
short ADXL345_Get_Angle(float x,float y,float z,u8 dir)
{
	float temp;
 	float res=0;     //res得到的是弧度值,需要将其转换为角度值也就是*180/3.14
	switch(dir)
	{
		case 0:        //与自然Z轴的角度
 			temp=sqrt((x*x+y*y))/z;
 			res=atan(temp);
 			break;
		case 1:       //与自然X轴的角度
 			temp=x/sqrt((y*y+z*z));
 			res=atan(temp);
 			break;
 		case 2:        //与自然Y轴的角度
 			temp=y/sqrt((x*x+z*z));
 			res=atan(temp);
 			break;
 	}
	return res*180/3.14*10;      //乘以10是为了取一位小数,角度精确到0.1°所以要乘以10
}

  • 关于角度的计算网上的资料很多,详细介绍的很少,慢慢整理
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值