Arduino与LSM9DS1九轴传感器模块的驱动详解

文章目录

  • 一、简介
  • 产品参数
  • LSM9DS1模块引脚说明
  • 使用说明
  • 引脚接线
  • 代码
  • 实验现象
  • 一、简介

    LSM9DS1是一个包含3D数字线性加速度传感器、3D数字角速率传感器和3D数字磁传感器的系统。
    LSM9DS1的线性加速度满刻度为±2g/±4g/±8/±16g,磁场满刻度为±4/±8/土12/土16高斯,角速率为±245/±500/±2000dpso,LSM9DS1包括支持标准和快速模式(100kHz和400 kHz)的I2C串行总线接口和SPI串行标准接口。磁性、加速度计和陀螺仪感应可单独启用或设置为断电模式,以实现智能电源管理。

    产品参数

    工作电压:3.3V
    工作温度:-40~85℃
    储存温度:-40~125℃
    通信接口:I2C/SPI接口

    LSM9DS1模块引脚说明

    GND:地
    VDD:电源正
    SDA:I2C串行数据线
    SPI串行数据输入
    SCL:I2C串行时钟线
    SPI串行时钟端口
    SDO_AG:用于加速度计和陀螺仪的SPI串行数据输出(SDO)
    用于加速度计和陀螺仪设备I2C协议器件地址的选择位
    SDO_M:磁强计的SPI串行数据输出
    磁强计I2C模式下器件地址的选择位
    CS_AG:加速度计和陀螺仪的I2C/SPI模式选择
    1:SPI空闲模式/12C通信启用
    0:SPI通信模式/I2C禁用
    CS_M: 磁强计I2C/SPI模式选择
    1:SPI空闲模式/12C通信启用
    0:SPI通信模式/I2C禁用
    RDY: 磁传感器数据准备就绪
    INTM:磁传感器中断
    INT1:加速度计和陀螺仪中断1
    INT2:加速度计和陀螺仪中断2
    DEN:加速度计和陀螺仪数据启用

    使用说明

    在I2C模式下,模块的I2C器件地址由SDO引脚决定
    当SDO_AG引脚为低电平时,模块加速度计和陀螺仪的I2C器件地址为1101010x(x为读写控制位)
    当SDO_AG引脚为高电平时,模块加速度计和陀螺仪的I2C器件地址为1101011x(x为读写控制位)
    当SDO_M、SDO_AG引脚为低电平时,模块磁强计的I2C器件地址为0011100x(x为读写控制位)
    当SD0_M引脚为高电平、SDO_AG引脚为低电平时,模块磁强计的I2C器件地址为0011110x(x为读写控制位)详情请参照下表:

    SPI模式有几个相关的读写控制寄存器,SPI读写协议如下图:



    本文将使用SPI接口实现数据通信。

    引脚接线

    LSM9DS1 ——— Arduino
    CS_AG ————- 9
    CS_M ————- 10
    SDO_AG ———– 12
    SDO_M ———— 12 (tied to SDO_AG)
    SCL ————– 13
    SDA ————– 11
    VDD ————– 3.3V
    GND ————– GND

    代码

    #include <Wire.h>
    #include <SPI.h>
    #include <SparkFunLSM9DS1.h>
    
    //
    // LSM9DS1 Library Init //
    //
    // Use the LSM9DS1 class to create an object. [imu] can be
    // named anything, we'll refer to that throught the sketch.
    LSM9DS1 imu;
    
    ///
    // Example SPI Setup //
    ///
    // Define the pins used for our SPI chip selects. We're
    // using hardware SPI, so other signal pins are set in stone.
    #define LSM9DS1_M_CS	10 // Can be any digital pin
    #define LSM9DS1_AG_CS	9  // Can be any other digital pin
    
    
    // Sketch Output Settings //
    
    #define PRINT_CALCULATED
    //#define PRINT_RAW
    #define PRINT_SPEED 250 // 250 ms between prints
    
    // Earth's magnetic field varies by location. Add or subtract 
    // a declination to get a more accurate heading. Calculate 
    // your's here:
    // http://www.ngdc.noaa.gov/geomag-web/#declination
    #define DECLINATION -8.58 // Declination (degrees) in Boulder, CO.
    
    void setup() 
    {
      Serial.begin(115200);
      
      // Before initializing the IMU, there are a few settings
      // we may need to adjust. Use the settings struct to set
      // the device's communication mode and addresses:
      imu.settings.device.commInterface = IMU_MODE_SPI;
      imu.settings.device.mAddress = LSM9DS1_M_CS;
      imu.settings.device.agAddress = LSM9DS1_AG_CS;
      // The above lines will only take effect AFTER calling
      // imu.begin(), which verifies communication with the IMU
      // and turns it on.
      if (!imu.begin())
      {
        Serial.println("Failed to communicate with LSM9DS1.");
        Serial.println("Double-check wiring.");
        Serial.println("Default settings in this sketch will " \
                      "work for an out of the box LSM9DS1 " \
                      "Breakout, but may need to be modified " \
                      "if the board jumpers are.");
        while (1)
          ;
      }
    }
    
    void loop()
    {
      printGyro();  // Print "G: gx, gy, gz"
      printAccel(); // Print "A: ax, ay, az"
      printMag();   // Print "M: mx, my, mz"
      
      // Print the heading and orientation for fun!
      // Call print attitude. The LSM9DS1's magnetometer x and y
      // axes are opposite to the accelerometer, so my and mx are
      // substituted for each other.
      printAttitude(imu.ax, imu.ay, imu.az, -imu.my, -imu.mx, imu.mz);
      Serial.println();
      
      delay(PRINT_SPEED);
    }
    
    void printGyro()
    {
      // To read from the gyroscope, you must first call the
      // readGyro() function. When this exits, it'll update the
      // gx, gy, and gz variables with the most current data.
      imu.readGyro();
      
      // Now we can use the gx, gy, and gz variables as we please.
      // Either print them as raw ADC values, or calculated in DPS.
      Serial.print("G: ");
    #ifdef PRINT_CALCULATED
      // If you want to print calculated values, you can use the
      // calcGyro helper function to convert a raw ADC value to
      // DPS. Give the function the value that you want to convert.
      Serial.print(imu.calcGyro(imu.gx), 2);
      Serial.print(", ");
      Serial.print(imu.calcGyro(imu.gy), 2);
      Serial.print(", ");
      Serial.println(imu.calcGyro(imu.gz), 2);
    #elif defined PRINT_RAW
      Serial.print(imu.gx);
      Serial.print(", ");
      Serial.print(imu.gy);
      Serial.print(", ");
      Serial.println(imu.gz);
    #endif
    }
    
    void printAccel()
    {
      // To read from the accelerometer, you must first call the
      // readAccel() function. When this exits, it'll update the
      // ax, ay, and az variables with the most current data.
      imu.readAccel();
      
      // Now we can use the ax, ay, and az variables as we please.
      // Either print them as raw ADC values, or calculated in g's.
      Serial.print("A: ");
    #ifdef PRINT_CALCULATED
      // If you want to print calculated values, you can use the
      // calcAccel helper function to convert a raw ADC value to
      // g's. Give the function the value that you want to convert.
      Serial.print(imu.calcAccel(imu.ax), 2);
      Serial.print(", ");
      Serial.print(imu.calcAccel(imu.ay), 2);
      Serial.print(", ");
      Serial.println(imu.calcAccel(imu.az), 2);
    #elif defined PRINT_RAW 
      Serial.print(imu.ax);
      Serial.print(", ");
      Serial.print(imu.ay);
      Serial.print(", ");
      Serial.println(imu.az);
    #endif
    
    }
    
    void printMag()
    {
      // To read from the magnetometer, you must first call the
      // readMag() function. When this exits, it'll update the
      // mx, my, and mz variables with the most current data.
      imu.readMag();
      
      // Now we can use the mx, my, and mz variables as we please.
      // Either print them as raw ADC values, or calculated in Gauss.
      Serial.print("M: ");
    #ifdef PRINT_CALCULATED
      // If you want to print calculated values, you can use the
      // calcMag helper function to convert a raw ADC value to
      // Gauss. Give the function the value that you want to convert.
      Serial.print(imu.calcMag(imu.mx), 2);
      Serial.print(", ");
      Serial.print(imu.calcMag(imu.my), 2);
      Serial.print(", ");
      Serial.println(imu.calcMag(imu.mz), 2);
    #elif defined PRINT_RAW
      Serial.print(imu.mx);
      Serial.print(", ");
      Serial.print(imu.my);
      Serial.print(", ");
      Serial.println(imu.mz);
    #endif
    }
    
    // Calculate pitch, roll, and heading.
    // Pitch/roll calculations take from this app note:
    // http://cache.freescale.com/files/sensors/doc/app_note/AN3461.pdf?fpsp=1
    // Heading calculations taken from this app note:
    // http://www51.honeywell.com/aero/common/documents/myaerospacecatalog-documents/Defense_Brochures-documents/Magnetic__Literature_Application_notes-documents/AN203_Compass_Heading_Using_Magnetometers.pdf
    void printAttitude(
    float ax, float ay, float az, float mx, float my, float mz)
    {
      float roll = atan2(ay, az);
      float pitch = atan2(-ax, sqrt(ay * ay + az * az));
      
      float heading;
      if (my == 0)
        heading = (mx < 0) ? 180.0 : 0;
      else
        heading = atan2(mx, my);
        
      heading -= DECLINATION * PI / 180;
      
      if (heading > PI) heading -= (2 * PI);
      else if (heading < -PI) heading += (2 * PI);
      else if (heading < 0) heading += 2 * PI;
      
      // Convert everything from radians to degrees:
      heading *= 180.0 / PI;
      pitch *= 180.0 / PI;
      roll  *= 180.0 / PI;
      
      Serial.print("Pitch, Roll: ");
      Serial.print(pitch, 2);
      Serial.print(", ");
      Serial.println(roll, 2);
      Serial.print("Heading: "); Serial.println(heading, 2);
    

    实验现象

    作者:优信电子

    物联沃分享整理
    物联沃-IOTWORD物联网 » Arduino与LSM9DS1九轴传感器模块的驱动详解

    发表回复