Subversion Repositories libLSM9DS1

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.   This file is part of the Arduino_LSM9DS1 library.
  3.   Copyright (c) 2019 Arduino SA. All rights reserved.
  4.  
  5.   This library is free software; you can redistribute it and/or
  6.   modify it under the terms of the GNU Lesser General Public
  7.   License as published by the Free Software Foundation; either
  8.   version 2.1 of the License, or (at your option) any later version.
  9.  
  10.   This library is distributed in the hope that it will be useful,
  11.   but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.   Lesser General Public License for more details.
  14.  
  15.   You should have received a copy of the GNU Lesser General Public
  16.   License along with this library; if not, write to the Free Software
  17.   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  18. */
  19.  
  20. #include "libLSM9DS1/LSM9DS1.h"
  21.  
  22. #define LSM9DS1_ADDRESS            0x6b
  23.  
  24. #define LSM9DS1_WHO_AM_I           0x0f
  25. #define LSM9DS1_CTRL_REG1_G        0x10
  26. #define LSM9DS1_STATUS_REG         0x17
  27. #define LSM9DS1_OUT_X_G            0x18
  28. #define LSM9DS1_CTRL_REG6_XL       0x20
  29. #define LSM9DS1_CTRL_REG8          0x22
  30. #define LSM9DS1_OUT_X_XL           0x28
  31.  
  32. // magnetometer
  33. #define LSM9DS1_ADDRESS_M          0x1e
  34.  
  35. #define LSM9DS1_CTRL_REG1_M        0x20
  36. #define LSM9DS1_CTRL_REG2_M        0x21
  37. #define LSM9DS1_CTRL_REG3_M        0x22
  38. #define LSM9DS1_STATUS_REG_M       0x27
  39. #define LSM9DS1_OUT_X_L_M          0x28
  40.  
  41. LSM9DS1Class::LSM9DS1Class(I2C_HandleTypeDef* i2c) :
  42.   continuousMode(false), _i2c(i2c)
  43. {
  44. }
  45.  
  46. LSM9DS1Class::~LSM9DS1Class()
  47. {
  48. }
  49.  
  50. int LSM9DS1Class::begin()
  51. {
  52.  
  53.   // reset
  54.   writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG8, 0x05);
  55.   writeRegister(LSM9DS1_ADDRESS_M, LSM9DS1_CTRL_REG2_M, 0x0c);
  56.  
  57.   HAL_Delay(10);
  58.  
  59.  
  60.   if (readRegister(LSM9DS1_ADDRESS, LSM9DS1_WHO_AM_I) != 0x68) {
  61.     end();
  62.  
  63.     return 0;
  64.   }
  65.  
  66.   if (readRegister(LSM9DS1_ADDRESS_M, LSM9DS1_WHO_AM_I) != 0x3d) {
  67.     end();
  68.  
  69.     return 0;
  70.   }
  71.  
  72.   writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G, 0x78); // 119 Hz, 2000 dps, 16 Hz BW
  73.   writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL, 0x70); // 119 Hz, 4g
  74.  
  75.   writeRegister(LSM9DS1_ADDRESS_M, LSM9DS1_CTRL_REG1_M, 0xb4); // Temperature compensation enable, medium performance, 20 Hz
  76.   writeRegister(LSM9DS1_ADDRESS_M, LSM9DS1_CTRL_REG2_M, 0x00); // 4 gauss
  77.   writeRegister(LSM9DS1_ADDRESS_M, LSM9DS1_CTRL_REG3_M, 0x00); // Continuous conversion mode
  78.  
  79.   return 1;
  80. }
  81.  
  82. void LSM9DS1Class::setContinuousMode() {
  83.   // Enable FIFO (see docs https://www.st.com/resource/en/datasheet/DM00103319.pdf)
  84.   writeRegister(LSM9DS1_ADDRESS, 0x23, 0x02);
  85.   // Set continuous mode
  86.   writeRegister(LSM9DS1_ADDRESS, 0x2E, 0xC0);
  87.  
  88.   continuousMode = true;
  89. }
  90.  
  91. void LSM9DS1Class::setOneShotMode() {
  92.   // Disable FIFO (see docs https://www.st.com/resource/en/datasheet/DM00103319.pdf)
  93.   writeRegister(LSM9DS1_ADDRESS, 0x23, 0x00);
  94.   // Disable continuous mode
  95.   writeRegister(LSM9DS1_ADDRESS, 0x2E, 0x00);
  96.  
  97.   continuousMode = false;
  98. }
  99.  
  100. void LSM9DS1Class::end()
  101. {
  102.   writeRegister(LSM9DS1_ADDRESS_M, LSM9DS1_CTRL_REG3_M, 0x03);
  103.   writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG1_G, 0x00);
  104.   writeRegister(LSM9DS1_ADDRESS, LSM9DS1_CTRL_REG6_XL, 0x00);
  105.  
  106. }
  107.  
  108. int LSM9DS1Class::readAcceleration(float& x, float& y, float& z)
  109. {
  110.   int16_t data[3];
  111.  
  112.   if (!readRegisters(LSM9DS1_ADDRESS, LSM9DS1_OUT_X_XL, (uint8_t*)data, sizeof(data))) {
  113.     x = NAN;
  114.     y = NAN;
  115.     z = NAN;
  116.  
  117.     return 0;
  118.   }
  119.  
  120.   x = data[0] * 4.0 / 32768.0;
  121.   y = data[1] * 4.0 / 32768.0;
  122.   z = data[2] * 4.0 / 32768.0;
  123.  
  124.   return 1;
  125. }
  126.  
  127. int LSM9DS1Class::accelerationAvailable()
  128. {
  129.   if (continuousMode) {
  130.     // Read FIFO_SRC. If any of the rightmost 8 bits have a value, there is data.
  131.     if (readRegister(LSM9DS1_ADDRESS, 0x2F) & 63) {
  132.       return 1;
  133.     }
  134.   } else {
  135.     if (readRegister(LSM9DS1_ADDRESS, LSM9DS1_STATUS_REG) & 0x01) {
  136.       return 1;
  137.     }
  138.   }
  139.  
  140.   return 0;
  141. }
  142.  
  143. float LSM9DS1Class::accelerationSampleRate()
  144. {
  145.   return 119.0F;
  146. }
  147.  
  148. int LSM9DS1Class::readGyroscope(float& x, float& y, float& z)
  149. {
  150.   int16_t data[3];
  151.  
  152.   if (!readRegisters(LSM9DS1_ADDRESS, LSM9DS1_OUT_X_G, (uint8_t*)data, sizeof(data))) {
  153.     x = NAN;
  154.     y = NAN;
  155.     z = NAN;
  156.  
  157.     return 0;
  158.   }
  159.  
  160.   x = data[0] * 2000.0 / 32768.0;
  161.   y = data[1] * 2000.0 / 32768.0;
  162.   z = data[2] * 2000.0 / 32768.0;
  163.  
  164.   return 1;
  165. }
  166.  
  167. int LSM9DS1Class::gyroscopeAvailable()
  168. {
  169.   if (readRegister(LSM9DS1_ADDRESS, LSM9DS1_STATUS_REG) & 0x02) {
  170.     return 1;
  171.   }
  172.  
  173.   return 0;
  174. }
  175.  
  176. float LSM9DS1Class::gyroscopeSampleRate()
  177. {
  178.   return 119.0F;
  179. }
  180.  
  181. int LSM9DS1Class::readMagneticField(float& x, float& y, float& z)
  182. {
  183.   int16_t data[3];
  184.  
  185.   if (!readRegisters(LSM9DS1_ADDRESS_M, LSM9DS1_OUT_X_L_M, (uint8_t*)data, sizeof(data))) {
  186.     x = NAN;
  187.     y = NAN;
  188.     z = NAN;
  189.  
  190.     return 0;
  191.   }
  192.  
  193.   x = data[0] * 4.0 * 100.0 / 32768.0;
  194.   y = data[1] * 4.0 * 100.0 / 32768.0;
  195.   z = data[2] * 4.0 * 100.0 / 32768.0;
  196.  
  197.   return 1;
  198. }
  199.  
  200. int LSM9DS1Class::magneticFieldAvailable()
  201. {
  202.   if (readRegister(LSM9DS1_ADDRESS_M, LSM9DS1_STATUS_REG_M) & 0x08) {
  203.     return 1;
  204.   }
  205.  
  206.   return 0;
  207. }
  208.  
  209. float LSM9DS1Class::magneticFieldSampleRate()
  210. {
  211.   return 20.0;
  212. }
  213.  
  214. int LSM9DS1Class::readRegister(uint8_t slaveAddress, uint8_t address)
  215. {
  216.   uint8_t c;
  217.   HAL_StatusTypeDef st =  HAL_I2C_Mem_Read(_i2c, slaveAddress<<1, address, 1, &c, 1, 10000);
  218.  
  219.    return c;
  220. }
  221.  
  222. int LSM9DS1Class::readRegisters(uint8_t slaveAddress, uint8_t address, uint8_t* data, size_t length)
  223. {
  224.   HAL_StatusTypeDef st =  HAL_I2C_Mem_Read(_i2c, slaveAddress<<1, address, 1, data, length, 10000);
  225.   return st == HAL_OK ? 1 : 0;
  226. }
  227.  
  228. int LSM9DS1Class::writeRegister(uint8_t slaveAddress, uint8_t address, uint8_t value)
  229. {
  230.   uint8_t c= value;
  231.   HAL_StatusTypeDef st = HAL_I2C_Mem_Write (_i2c, slaveAddress << 1, address, 1,
  232.                                             &c, 1, 10000);
  233.  
  234.   return st == HAL_OK ? 1 : 0;
  235. }
  236.  
  237.