Details | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line |
|---|---|---|---|
| 1 | mjames | 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 |