A library to interface with the LSM9DS1 IMU using SPI

Dependents:   LSM9DS1

Files at this revision

API Documentation at this revision

Comitter:
Anaesthetix
Date:
Wed Oct 18 09:22:00 2017 +0000
Commit message:
LSM9DS1 spi library

Changed in this revision

LSM9DS1_SPI.cpp Show annotated file Show diff for this revision Revisions of this file
LSM9DS1_SPI.h Show annotated file Show diff for this revision Revisions of this file
LSM9DS1_SPI_Registers.h Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r dc98084cf6be LSM9DS1_SPI.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LSM9DS1_SPI.cpp	Wed Oct 18 09:22:00 2017 +0000
@@ -0,0 +1,249 @@
+// Written by: Erik van de Coevering 
+
+#include "mbed.h"
+#include "LSM9DS1_SPI.h"
+#include "LSM9DS1_SPI_Registers.h"
+
+lsm9ds1_spi::lsm9ds1_spi(SPI& _spi, PinName _csAG, PinName _csM) : spi(_spi), csAG(_csAG), csM(_csM) {}
+
+unsigned int lsm9ds1_spi::WriteRegAG( uint8_t WriteAddr, uint8_t WriteData)
+{
+      unsigned int temp_val;
+    selectAG();
+    spi.write(WriteAddr);
+    temp_val=spi.write(WriteData);
+    deselectAG();
+    wait_us(5);
+    return temp_val;
+}
+
+unsigned int lsm9ds1_spi::WriteRegM( uint8_t WriteAddr, uint8_t WriteData)
+{
+      unsigned int temp_val;
+    selectM();
+    spi.write(WriteAddr);
+    temp_val=spi.write(WriteData);
+    deselectM();
+    wait_us(5);
+    return temp_val;
+}
+
+unsigned int lsm9ds1_spi::ReadRegAG( uint8_t WriteAddr, uint8_t WriteData)
+{
+        return WriteRegAG(WriteAddr | READ_FLAG, WriteData);
+}
+
+unsigned int lsm9ds1_spi::ReadRegM( uint8_t WriteAddr, uint8_t WriteData)
+{
+        return WriteRegM(WriteAddr | READ_FLAG, WriteData);
+}
+
+void lsm9ds1_spi::ReadRegsAG( uint8_t ReadAddr, uint8_t *ReadBuf, unsigned int Bytes )
+{
+    unsigned int  i = 0;
+
+    selectAG();
+    spi.write(ReadAddr | READ_FLAG);
+    for(i=0; i<Bytes; i++)
+        ReadBuf[i] = spi.write(0x00);
+    deselectAG();
+    //wait_us(50);
+}
+
+void lsm9ds1_spi::ReadRegsM( uint8_t ReadAddr, uint8_t *ReadBuf, unsigned int Bytes )
+{
+    unsigned int  i = 0;
+
+    selectM();
+    spi.write(ReadAddr | READ_FLAG);
+    for(i=0; i<Bytes; i++)
+        ReadBuf[i] = spi.write(0x00);
+    deselectM();
+}
+
+#define LSM_InitRegNumAG 10
+#define LSM_InitRegNumM 6
+
+/*--------------------------------------INIT-----------------------------------------------
+Possible values for BW / FS / ODR:
+
+Gyroscope full-scale setting:
+FS_G_245DPS         
+FS_G_500DPS         
+FS_G_2000DPS
+
+Gyroscope output data rate setting:
+ODR_G_15HZ          
+ODR_G_60HZ          
+ODR_G_119HZ         
+ODR_G_238HZ         
+ODR_G_476HZ         
+ODR_G_952HZ 
+
+Gyro bandwidth dependant on ODR, these freq's are correct for ODR=476Hz or 952Hz. Check datasheet for other ODR's
+BW_G_33HZ           
+BW_G_40HZ           
+BW_G_58HZ
+BW_G_100HZ
+
+Accelerometer full-scale setting:
+FS_A_2G
+FS_A_4G
+FS_A_8G
+FS_A_16G
+
+Magnetometer full-scale setting:
+FS_M_4GAUSS
+FS_M_8GAUSS 
+FS_M_12GAUSS
+FS_M_16GAUSS
+
+
+Set sensitivity according to full-scale settings. Possible values are:
+ACC_SENS_2G         
+ACC_SENS_4G         
+ACC_SENS_8G         
+ACC_SENS_16G        
+GYR_SENS_245DPS     
+GYR_SENS_500DPS     
+GYR_SENS_2000DPS    
+MAG_SENS_4GAUSS     
+MAG_SENS_8GAUSS     
+MAG_SENS_12GAUSS    
+MAG_SENS_16GAUSS    
+*/
+
+
+void lsm9ds1_spi::init() {
+    
+    deselectAG();
+    deselectM();
+    
+    uint8_t LSM_Init_Data[LSM_InitRegNumAG][2] = {
+        {ODR_G_952HZ | FS_G_500DPS | BW_G_100HZ, CTRL_REG1_G},
+        {0x00, CTRL_REG2_G}, // enable FIFO, disable HPF/LPF2 <-- something seems to be wrong with the filters, check datasheet if you want to use them
+        {0x09, CTRL_REG3_G}, // Disable HPF
+        {0x00, ORIENT_CFG_G},
+        {0x38, CTRL_REG4},      //Enable gyro outputs, no latched interrupt
+        {0x38, CTRL_REG5_XL}, //No decimation of accel data, Enable accelerometer outputs
+        {0xC0 | FS_A_2G, CTRL_REG6_XL}, // Accel ODR 952Hz, BW 408 Hz, +-2g
+        {0xC0, CTRL_REG7_XL}, //LP cutoff ODR/9, LPF enabled, HPF bypassed, bypass LPF = 0xC0
+        {0x16, CTRL_REG9},      //Temperature FIFO enabled, I2C disabled, FIFO enabled
+        {0xC0, FIFO_CTRL},      //Continuous mode, overwrite if FIFO is full
+    };
+    
+    uint8_t LSM_Init_DataM[LSM_InitRegNumM][2] = {
+        {0x7C, CTRL_REG1_M}, // Ultra-high performance mode (x & y axis), ODR 80Hz, no temp comp
+        {FS_M_4GAUSS, CTRL_REG2_M}, // FS +- 4 gauss
+        {0x84, CTRL_REG3_M}, // Disable I2C, enable SPI read/write, continuous-conversion mode
+        {0x0C, CTRL_REG4_M}, // Ultra-high performance mode (z-axis)
+        {0x00, CTRL_REG5_M}, // Fast read disabled, continuous update
+        {0x02, INT_CFG_M}, 
+    };
+    spi.format(8,3);
+    spi.frequency(10000000);
+    
+    for(int i=0; i<LSM_InitRegNumAG; i++) {
+        WriteRegAG(LSM_Init_Data[i][1], LSM_Init_Data[i][0]);
+    }
+    
+    for(int i=0; i<LSM_InitRegNumM; i++) {
+        WriteRegM(LSM_Init_DataM[i][1], LSM_Init_DataM[i][0]);
+    }
+    
+    // Sensitivity settings
+    acc_multiplier = ACC_SENS_2G;
+    gyro_multiplier = GYR_SENS_500DPS;
+    mag_multiplier = MAG_SENS_4GAUSS;
+}
+
+void lsm9ds1_spi::read_acc()
+{
+    uint8_t response[6];
+    int16_t bit_data;
+    float data;
+    int i;
+    ReadRegsAG(OUT_X_L_XL,response,6);
+    for(i=0; i<3; i++) {
+        bit_data=((int16_t)response[i*2+1]<<8)|response[i*2];
+        data=(float)bit_data;
+        accelerometer_data[i]=data*acc_multiplier;
+    }
+    
+}
+
+void lsm9ds1_spi::read_gyr()
+{
+    uint8_t response[6];
+    int16_t bit_data;
+    float data;
+    int i;
+    ReadRegsAG(OUT_X_L_G,response,6);
+    for(i=0; i<3; i++) {
+        bit_data=((int16_t)response[i*2+1]<<8)|response[i*2];
+        data=(float)bit_data;
+        gyroscope_data[i]=data*gyro_multiplier;
+    }
+    
+}
+
+float lsm9ds1_spi::read_temp(){
+    uint8_t response[2];
+    int16_t bit_data;
+    float data;
+    ReadRegsAG(OUT_TEMP_L,response,2);
+
+    bit_data=((int16_t)response[1]<<8)|response[0];
+    data=(float)bit_data;
+    data = data/16;
+        return (data+25);
+}
+
+void lsm9ds1_spi::read_mag()
+{
+    uint8_t response[6];
+    int16_t bit_data;
+    float data;
+    int i;
+    ReadRegsM(OUT_X_L_M,response,6);
+    for(i=0; i<3; i++) {
+        bit_data=((int16_t)response[i*2+1]<<8)|response[i*2];
+        data=(float)bit_data;
+        magnetometer_data[i]=data*mag_multiplier;
+    }
+    
+}
+
+void lsm9ds1_spi::read_all()
+{
+        read_acc();
+        read_gyr();
+        read_mag();
+}
+
+unsigned int lsm9ds1_spi::whoami() 
+{
+        return ReadRegAG(WHO_AM_I_XG, 0x00);
+}
+
+unsigned int lsm9ds1_spi::whoamiM() 
+{
+        return ReadRegM(WHO_AM_I_M, 0x00);
+}
+
+void lsm9ds1_spi::selectAG() {
+        csAG = 0;
+}
+
+void lsm9ds1_spi::selectM() {
+        csM = 0;
+}
+
+void lsm9ds1_spi::deselectAG() {
+        csAG = 1;
+}
+
+void lsm9ds1_spi::deselectM() {
+        csM = 1;
+}
+
diff -r 000000000000 -r dc98084cf6be LSM9DS1_SPI.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LSM9DS1_SPI.h	Wed Oct 18 09:22:00 2017 +0000
@@ -0,0 +1,84 @@
+// Written by: Erik van de Coevering 
+
+#ifndef __LSM9DS1_SPI_H__
+#define __LSM9DS1_SPI_H__
+
+#include "mbed.h"
+
+class lsm9ds1_spi
+{
+        SPI& spi;
+        DigitalOut csAG;
+        DigitalOut csM;
+    
+    public:
+        lsm9ds1_spi(SPI& _spi, PinName _csAG, PinName _csM);
+        unsigned int WriteRegAG(uint8_t WriteAddr, uint8_t WriteData);
+        unsigned int WriteRegM(uint8_t WriteAddr, uint8_t WriteData);
+        unsigned int ReadRegAG(uint8_t WriteAddr, uint8_t WriteData);
+        unsigned int ReadRegM(uint8_t WriteAddr, uint8_t WriteData);
+        void ReadRegsAG(uint8_t ReadAddr, uint8_t *ReadBuf, unsigned int Bytes );
+        void ReadRegsM(uint8_t ReadAddr, uint8_t *ReadBuf, unsigned int Bytes );
+    
+        void selectAG();
+        void selectM();
+        void deselectAG();
+        void deselectM();
+    
+        void init();
+        unsigned int whoami();
+        unsigned int whoamiM();
+        float read_temp();      // reads temperature in degrees C
+        void read_acc();        // reads accelerometer in G
+        void read_gyr();        // reads gyroscope in DPS
+        void read_mag();        // reads magnetometer in gauss
+        void read_all();        // reads acc / gyro / magneto
+    
+        float acc_multiplier;
+        float gyro_multiplier;
+        float mag_multiplier;
+        float accelerometer_data[3];
+        float gyroscope_data[3];
+        float magnetometer_data[3];
+    
+};
+
+#define FS_G_245DPS         0x00
+#define FS_G_500DPS         0x08
+#define FS_G_2000DPS        0x18
+#define ODR_G_15HZ          0x20
+#define ODR_G_60HZ          0x40
+#define ODR_G_119HZ         0x60
+#define ODR_G_238HZ         0x80
+#define ODR_G_476HZ         0xA0
+#define ODR_G_952HZ         0xC0
+#define BW_G_33HZ           0x00    // Bandwidth dependant on ODR, these freq's are correct for ODR=476Hz or 952Hz. Check datasheet for other ODR's
+#define BW_G_40HZ           0x01
+#define BW_G_58HZ           0x02
+#define BW_G_100HZ          0x03
+#define FS_A_2G             0x00
+#define FS_A_4G             0x10
+#define FS_A_8G             0x18
+#define FS_A_16G            0x08
+#define FS_M_4GAUSS         0x00
+#define FS_M_8GAUSS         0x20    
+#define FS_M_12GAUSS        0x40
+#define FS_M_16GAUSS        0x60
+
+#define ACC_SENS_2G         0.000061f
+#define ACC_SENS_4G         0.000122f
+#define ACC_SENS_8G         0.000244f
+#define ACC_SENS_16G        0.000732f
+#define GYR_SENS_245DPS     0.00875f
+#define GYR_SENS_500DPS     0.0175f
+#define GYR_SENS_2000DPS    0.07f
+#define MAG_SENS_4GAUSS     0.00014f
+#define MAG_SENS_8GAUSS     0.00029f
+#define MAG_SENS_12GAUSS    0.00043f
+#define MAG_SENS_16GAUSS    0.000732f
+
+#define READ_FLAG 0x80  
+
+#endif
+
+
diff -r 000000000000 -r dc98084cf6be LSM9DS1_SPI_Registers.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LSM9DS1_SPI_Registers.h	Wed Oct 18 09:22:00 2017 +0000
@@ -0,0 +1,113 @@
+/******************************************************************************
+LSM9DS1_Registers.h
+SFE_LSM9DS1 Library - LSM9DS1 Register Map
+Jim Lindblom @ SparkFun Electronics
+Original Creation Date: April 21, 2015
+https://github.com/sparkfun/LSM9DS1_Breakout
+ 
+This file defines all registers internal to the gyro/accel and magnetometer
+devices in the LSM9DS1.
+ 
+Development environment specifics:
+    IDE: Arduino 1.6.0
+    Hardware Platform: Arduino Uno
+    LSM9DS1 Breakout Version: 1.0
+ 
+This code is beerware; if you see me (or any other SparkFun employee) at the
+local, and you've found our code helpful, please buy us a round!
+ 
+Distributed as-is; no warranty is given.
+******************************************************************************/
+ 
+#ifndef __LSM9DS1_Registers_H__
+#define __LSM9DS1_Registers_H__
+ 
+/////////////////////////////////////////
+// LSM9DS1 Accel/Gyro (XL/G) Registers //
+/////////////////////////////////////////
+#define ACT_THS             0x04
+#define ACT_DUR             0x05
+#define INT_GEN_CFG_XL      0x06
+#define INT_GEN_THS_X_XL    0x07
+#define INT_GEN_THS_Y_XL    0x08
+#define INT_GEN_THS_Z_XL    0x09
+#define INT_GEN_DUR_XL      0x0A
+#define REFERENCE_G         0x0B
+#define INT1_CTRL           0x0C
+#define INT2_CTRL           0x0D
+#define WHO_AM_I_XG         0x0F
+#define CTRL_REG1_G         0x10
+#define CTRL_REG2_G         0x11
+#define CTRL_REG3_G         0x12
+#define ORIENT_CFG_G        0x13
+#define INT_GEN_SRC_G       0x14
+#define OUT_TEMP_L          0x15
+#define OUT_TEMP_H          0x16
+#define STATUS_REG_0        0x17
+#define OUT_X_L_G           0x18
+#define OUT_X_H_G           0x19
+#define OUT_Y_L_G           0x1A
+#define OUT_Y_H_G           0x1B
+#define OUT_Z_L_G           0x1C
+#define OUT_Z_H_G           0x1D
+#define CTRL_REG4           0x1E
+#define CTRL_REG5_XL        0x1F
+#define CTRL_REG6_XL        0x20
+#define CTRL_REG7_XL        0x21
+#define CTRL_REG8           0x22
+#define CTRL_REG9           0x23
+#define CTRL_REG10          0x24
+#define INT_GEN_SRC_XL      0x26
+#define STATUS_REG_1        0x27
+#define OUT_X_L_XL          0x28
+#define OUT_X_H_XL          0x29
+#define OUT_Y_L_XL          0x2A
+#define OUT_Y_H_XL          0x2B
+#define OUT_Z_L_XL          0x2C
+#define OUT_Z_H_XL          0x2D
+#define FIFO_CTRL           0x2E
+#define FIFO_SRC            0x2F
+#define INT_GEN_CFG_G       0x30
+#define INT_GEN_THS_XH_G    0x31
+#define INT_GEN_THS_XL_G    0x32
+#define INT_GEN_THS_YH_G    0x33
+#define INT_GEN_THS_YL_G    0x34
+#define INT_GEN_THS_ZH_G    0x35
+#define INT_GEN_THS_ZL_G    0x36
+#define INT_GEN_DUR_G       0x37
+ 
+///////////////////////////////
+// LSM9DS1 Magneto Registers //
+///////////////////////////////
+#define OFFSET_X_REG_L_M    0x05
+#define OFFSET_X_REG_H_M    0x06
+#define OFFSET_Y_REG_L_M    0x07
+#define OFFSET_Y_REG_H_M    0x08
+#define OFFSET_Z_REG_L_M    0x09
+#define OFFSET_Z_REG_H_M    0x0A
+#define WHO_AM_I_M          0x0F
+#define CTRL_REG1_M         0x20
+#define CTRL_REG2_M         0x21
+#define CTRL_REG3_M         0x22
+#define CTRL_REG4_M         0x23
+#define CTRL_REG5_M         0x24
+#define STATUS_REG_M        0x27
+#define OUT_X_L_M           0x28
+#define OUT_X_H_M           0x29
+#define OUT_Y_L_M           0x2A
+#define OUT_Y_H_M           0x2B
+#define OUT_Z_L_M           0x2C
+#define OUT_Z_H_M           0x2D
+#define INT_CFG_M           0x30
+#define INT_SRC_M           0x30
+#define INT_THS_L_M         0x32
+#define INT_THS_H_M         0x33
+ 
+////////////////////////////////
+// LSM9DS1 WHO_AM_I Responses //
+////////////////////////////////
+#define WHO_AM_I_AG_RSP     0x68
+#define WHO_AM_I_M_RSP      0x3D
+ 
+#endif
+