查看: 1420|回复: 0
收起左侧

LSM303AGR姿态传感器 risc-v Sifive learn inventor基础之硬件i2c与LSM303

[复制链接]

  离线 

  • TA的每日心情
    奋斗
    2021-3-3 12:32
  • 签到天数: 10 天

    [LV.3]

    发表于 2020-8-25 15:06:14 | 显示全部楼层 |阅读模式

    有人预言,RISC-V或将是继Intel和Arm之后的第三大主流处理器体系。欢迎访问全球首家只专注于RISC-V单片机行业应用的中文网站

    您需要 登录 才可以下载或查看,没有帐号?立即注册

    x
    本帖最后由 皋陶 于 2020-8-28 21:52 编辑


    本文是第四篇:LSM303AGR姿态传感器 RISC-V Sifive learn inventor基础之硬件i2c与LSM303AGR通信


    这一次用iic简单的读取lsm303的加速度数据,对于中断等不做操作;


    2020 .7.29 优化了数据处理部分的代码。得到的数据更直观。精度是0.1mm


    一,硬件连接

    如图的连接,I2C的两根信号都通过R6,R7上拉,通过这点可知与LSM303的通信波特率是400khz。


    国内芯片技术交流-LSM303AGR姿态传感器 risc-v Sifive learn inventor基础之硬件i2c与LSM303risc-v单片机中文社区(1)



    二,获取数据

    1,使用最新的freedom-e-sdk,freedom-e-sdk GitHub仓库,最新的sdk支持iic和pwm库函数开发,而且提供freertos的模板例程。在此基础上开发iic十分方便。

    2,首先初始化开发板的iic接口,并通过iic接口配置lsm303的寄存器,设置加速度计的工作模式和输出速率(reg1_a寄存器),这里我设置的是普通模式,输出速率为400hz:


    1. //reg1中是reg1_a寄存器的地址及写入的值
    2.         char reg1[2]={0x20,0x77};
    3.         //初始化iic为master 波特率400khz
    4.         metal_i2c_init(i2c, I2C_BAUDRATE, METAL_I2C_MASTER);
    5.         //写控制寄存器reg1_A 普通模式,400hz输出,使能x,y,z轴加速度计
    6.         metal_i2c_write(i2c, ACCELEROMETER_I2C_ADDR, 2,reg1 , METAL_I2C_STOP_ENABLE);
    复制代码


    然后创建一个定时时间为dt的任务,在这个任务里,我们读取lsm303加速度的输出寄存器的高位数据,比较对精度要求不高的话可以忽略低位数据。然后将数据进行积分处理得到速度和路程。这个项目里我不需要y轴数据所以没有读取。


    1. /*
    2. * 由于普通模式有效数据10位,且数据为左对齐,只读取高位寄存器
    3. * 将数据进行积分处理
    4. */
    5. static void prvAccelerTask(void *pvParameters)
    6. {
    7.         TickType_t xNextWakeTime;
    8.          char *  pcMessage = "start accelertask\r\n";
    9.         (void)pvParameters;
    10.         //out_add中的值是加速度计OUT_X_H_A,OUT_Z_H_A寄存器的地址,
    11.         static char out_addr[2]={0x29,0x2d},buff[2]={0};
    12.         //延时时间,同时也是时间的微分dt 单位是ms
    13.         Motor.dt=20;
    14.         xNextWakeTime = xTaskGetTickCount();
    15.         write(STDOUT_FILENO,pcMessage,strlen(pcMessage));

    16.         while(1)
    17.         {

    18.                 //进入临界段,防止通信被打断
    19.                 taskENTER_CRITICAL();
    20.                 //分别读取OUT_X_H_A,OUT_Z_H_A高位寄存器
    21.                 metal_i2c_write(i2c, ACCELEROMETER_I2C_ADDR, 1,out_addr , METAL_I2C_STOP_DISABLE);
    22.                 metal_i2c_read(i2c, ACCELEROMETER_I2C_ADDR, 1,buff , METAL_I2C_STOP_ENABLE);
    23.                 metal_i2c_write(i2c, ACCELEROMETER_I2C_ADDR, 1,&out_addr[1] , METAL_I2C_STOP_DISABLE);
    24.                 metal_i2c_read(i2c, ACCELEROMETER_I2C_ADDR, 1,&buff[1] , METAL_I2C_STOP_ENABLE);
    25.                 //赋值给lsm303对象
    26.                 lsm303.acc_x_raw=buff[0];
    27.                 lsm303.acc_z_raw=buff[1];
    28.                 //对原生数据处理,转化成加速度,速度,位移
    29.                 sensor_data_process();
    30.                 taskEXIT_CRITICAL();
    31.                 write(1,pcMessage,strlen(pcMessage));
    32.                 vTaskDelayUntil( &xNextWakeTime, pdMS_TO_TICKS( Motor.dt ) );
    33.         }
    34. }
    复制代码


    这就是配置的寄存器;


    国内芯片技术交流-LSM303AGR姿态传感器 risc-v Sifive learn inventor基础之硬件i2c与LSM303risc-v单片机中文社区(2)


    我设置的是400hz,所以代码里写入的值是0x77,其实也不必太高,过高会影响精度。


    国内芯片技术交流-LSM303AGR姿态传感器 risc-v Sifive learn inventor基础之硬件i2c与LSM303risc-v单片机中文社区(3)


    以下是不同模式下,输出数据的有效位数,普通模式下,输出10位数据,再看看输出寄存器的描述,大概的意思就是输出的数据是左对齐的二进制补码。那就在处理数据时要解析出原码。至于不了解左对齐是什么的可以点我。


    国内芯片技术交流-LSM303AGR姿态传感器 risc-v Sifive learn inventor基础之硬件i2c与LSM303risc-v单片机中文社区(4)


    国内芯片技术交流-LSM303AGR姿态传感器 risc-v Sifive learn inventor基础之硬件i2c与LSM303risc-v单片机中文社区(5)




    三,处理数据


    上面得到的数据是原始的,原生态无污染的,要加工成加速度数据,也就是单位为m/s^2的数据。要计算实际的加速度,需要乘以一个比例系数,在开发文档称为灵敏度,灵敏度与加速度计工作模式与full scal(缩放)有关,缩放的配置在reg4_a寄存器,默认是0,也就是±2g。所以可知我配置的灵敏度为3.9mg。详细如下图:


    国内芯片技术交流-LSM303AGR姿态传感器 risc-v Sifive learn inventor基础之硬件i2c与LSM303risc-v单片机中文社区(6)


    国内芯片技术交流-LSM303AGR姿态传感器 risc-v Sifive learn inventor基础之硬件i2c与LSM303risc-v单片机中文社区(7)


    因为板子是倾斜约45°放的,所以要得到水平的加速度需要经过直角坐标转换。


    lsm303.acc_x_real=(int)lsm303.acc_x_raw*4*39;乘4是因为普通模式输出10位数据,而我只读了高八位,舍弃了低二位,所以要左移2位,也就是乘4,39就是灵敏度。经过单位换算,得到的加速度单位是100ug


    1. /*
    2. * 处理lsm303读取的数据,获取速度,距离
    3. */
    4. void sensor_data_process()
    5. {
    6.         //如果raw是负数的话需要取绝对值,乘以灵敏度,再将符号返回
    7.         if(lsm303.acc_x_raw&0x80)
    8.         {
    9.                 lsm303.acc_x_raw =-lsm303.acc_x_raw;
    10.                 lsm303.acc_x_real=(int)lsm303.acc_x_raw*4*39;
    11.                 lsm303.acc_x_real=-lsm303.acc_x_real;
    12.         }
    13.         else lsm303.acc_x_real=(int)lsm303.acc_x_raw*4*39;
    14.         if(lsm303.acc_z_raw&0x80)
    15.         {
    16.                 lsm303.acc_z_raw =-lsm303.acc_z_raw;
    17.                 lsm303.acc_z_real=(int)lsm303.acc_z_raw*4*39;
    18.                 lsm303.acc_z_real=-lsm303.acc_z_real;
    19.         }
    20.         else lsm303.acc_z_real=(int)lsm303.acc_z_raw*4*39;

    21.         //x=8112 z=-6552 滤除重力
    22.         lsm303.acc_x_filter=lsm303.acc_x_real-8112;
    23.         lsm303.acc_z_filter=6552+lsm303.acc_z_real;

    24.         //lsm303.acc_x_filter=lsm303.acc_x_filter & ~0x000000ff;
    25.         //lsm303.acc_z_filter=lsm303.acc_z_filter & ~0x000000ff;

    26.         //加速度分解到水平方向  sinθ=2/3 cosθ=3/4
    27.         Motor.acc=(lsm303.acc_x_filter*2/3+lsm303.acc_z_filter*3/4)/100;//cm/s^2

    28.         //加速度,速度积分
    29.         Motor.speed=Motor.speed+Motor.acc*Motor.dt/100;//mm
    30.         Motor.distance=Motor.distance+Motor.speed*Motor.dt/100;//0.1mm

    31. }
    复制代码


    三,小结

    这种简单粗暴的用加速度双重积分出距离其实非常不准确,积分误差会随时间而增加,需要其他方式进行校准。

    国内芯片技术交流-LSM303AGR姿态传感器 risc-v Sifive learn inventor基础之硬件i2c与LSM303risc-v单片机中文社区(8)

    本篇完,感谢关注:RISC-V单片机中文网




    上一篇:漫谈LiteOS-LiteOS SDK支持RISC-V架构
    下一篇:安装riscv的全过程 简单易懂!!
    RISCV作者优文
    全球首家只专注于RISC-V单片机行业应用的中文网站
    回复

    使用道具 举报

    高级模式
    B Color Image Link Quote Code Smilies

    本版积分规则

    关闭

    RISC-V单片机中文网上一条 /2 下一条



    版权及免责声明|RISC-V单片机中文网 |网站地图

    GMT+8, 2024-3-29 01:27 , Processed in 0.475330 second(s), 48 queries .

    快速回复 返回顶部 返回列表