A library to interface with the LSM9DS1 IMU using SPI
Revision 0:dc98084cf6be, committed 2017-10-18
- Comitter:
- Anaesthetix
- Date:
- Wed Oct 18 09:22:00 2017 +0000
- Commit message:
- LSM9DS1 spi library
Changed in this revision
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 +