├── .github ├── ISSUE_TEMPLATE │ ├── bug-report-or-feature-request.md │ └── config.yml └── workflows │ └── ci.yaml ├── .gitignore ├── .gitlab-ci.yml ├── LICENSE.txt ├── LSM6.cpp ├── LSM6.h ├── README.md ├── examples └── Serial │ └── Serial.ino ├── keywords.txt └── library.properties /.github/ISSUE_TEMPLATE/bug-report-or-feature-request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report or feature request 3 | about: Did you find a specific bug in the code for this project? Do you want to request 4 | a new feature? Please open an issue! 5 | title: '' 6 | labels: '' 7 | assignees: '' 8 | 9 | --- 10 | 11 | 12 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Pololu Forum 4 | url: https://forum.pololu.com/ 5 | about: Do you need help getting started? Can't get this code to work at all? Having problems with electronics? Please post on our forum! 6 | -------------------------------------------------------------------------------- /.github/workflows/ci.yaml: -------------------------------------------------------------------------------- 1 | name: "CI" 2 | on: 3 | pull_request: 4 | push: 5 | jobs: 6 | ci: 7 | runs-on: ubuntu-20.04 8 | steps: 9 | - name: Checkout this repository 10 | uses: actions/checkout@v2.3.4 11 | - name: Cache for arduino-ci 12 | uses: actions/cache@v2.1.3 13 | with: 14 | path: | 15 | ~/.arduino15 16 | key: ${{ runner.os }}-arduino 17 | - name: Install nix 18 | uses: cachix/install-nix-action@v12 19 | - run: nix-shell -I nixpkgs=channel:nixpkgs-unstable -p arduino-ci --run "arduino-ci" 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /docs/ 2 | /out/ 3 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | image: $CI_REGISTRY_IMAGE/nixos/nix:2.3.6 2 | 3 | stages: 4 | - ci 5 | 6 | ci: 7 | stage: ci 8 | tags: 9 | - nix 10 | script: 11 | - nix-shell -I nixpkgs=channel:nixpkgs-unstable -p arduino-ci --run "arduino-ci" 12 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016-2022 Pololu Corporation (www.pololu.com) 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /LSM6.cpp: -------------------------------------------------------------------------------- 1 | #include "LSM6.h" 2 | #include 3 | #include 4 | 5 | // Defines //////////////////////////////////////////////////////////////// 6 | 7 | // The Arduino two-wire interface uses a 7-bit number for the address, 8 | // and sets the last bit correctly based on reads and writes 9 | #define DS33_SA0_HIGH_ADDRESS 0b1101011 10 | #define DS33_SA0_LOW_ADDRESS 0b1101010 11 | #define DSO_SA0_HIGH_ADDRESS 0b1101011 12 | #define DSO_SA0_LOW_ADDRESS 0b1101010 13 | 14 | #define TEST_REG_ERROR -1 15 | 16 | #define DS33_WHO_ID 0x69 17 | #define DSO_WHO_ID 0x6C 18 | 19 | // Constructors //////////////////////////////////////////////////////////////// 20 | 21 | LSM6::LSM6() 22 | #if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_TWOWIRE) 23 | : bus(&Wire) 24 | #else 25 | : bus(nullptr) 26 | #endif 27 | , _device(device_auto) 28 | { 29 | } 30 | 31 | // Public Methods ////////////////////////////////////////////////////////////// 32 | 33 | bool LSM6::init(deviceType device, sa0State sa0) 34 | { 35 | // perform auto-detection unless device type and SA0 state were both specified 36 | if (device == device_auto || sa0 == sa0_auto) 37 | { 38 | // check for LSM6DS33 if device is unidentified or was specified to be this type 39 | if (device == device_auto || device == device_DS33) 40 | { 41 | // check SA0 high address unless SA0 was specified to be low 42 | if (sa0 != sa0_low && testReg(DS33_SA0_HIGH_ADDRESS, WHO_AM_I) == DS33_WHO_ID) 43 | { 44 | sa0 = sa0_high; 45 | device = device_DS33; 46 | } 47 | // check SA0 low address unless SA0 was specified to be high 48 | else if (sa0 != sa0_high && testReg(DS33_SA0_LOW_ADDRESS, WHO_AM_I) == DS33_WHO_ID) 49 | { 50 | sa0 = sa0_low; 51 | device = device_DS33; 52 | } 53 | } 54 | 55 | // check for LSM6DSO if device is unidentified or was specified to be this type 56 | if (device == device_auto || device == device_DSO) 57 | { 58 | // check SA0 high address unless SA0 was specified to be low 59 | if (sa0 != sa0_low && testReg(DSO_SA0_HIGH_ADDRESS, WHO_AM_I) == DSO_WHO_ID) 60 | { 61 | sa0 = sa0_high; 62 | device = device_DSO; 63 | } 64 | // check SA0 low address unless SA0 was specified to be high 65 | else if (sa0 != sa0_high && testReg(DSO_SA0_LOW_ADDRESS, WHO_AM_I) == DSO_WHO_ID) 66 | { 67 | sa0 = sa0_low; 68 | device = device_DSO; 69 | } 70 | } 71 | 72 | // make sure device and SA0 were successfully detected; otherwise, indicate failure 73 | if (device == device_auto || sa0 == sa0_auto) 74 | { 75 | return false; 76 | } 77 | } 78 | 79 | _device = device; 80 | 81 | switch (device) 82 | { 83 | case device_DS33: 84 | address = (sa0 == sa0_high) ? DS33_SA0_HIGH_ADDRESS : DS33_SA0_LOW_ADDRESS; 85 | break; 86 | 87 | case device_DSO: 88 | address = (sa0 == sa0_high) ? DSO_SA0_HIGH_ADDRESS : DSO_SA0_LOW_ADDRESS; 89 | break; 90 | 91 | default: 92 | return false; // this should not ever happen 93 | } 94 | 95 | return true; 96 | } 97 | 98 | /* 99 | Enables the LSM6's accelerometer and gyro. Also: 100 | - Sets sensor full scales (gain) to default power-on values, which are 101 | +/- 2 g for accelerometer and 245 dps for gyro 102 | - Selects 1.66 kHz (high performance) ODR (output data rate) for accelerometer 103 | and 1.66 kHz (high performance) ODR for gyro. (These are the ODR settings for 104 | which the electrical characteristics are specified in the LSM6DS33 datasheet.) 105 | - Enables automatic increment of register address during multiple byte access 106 | Note that this function will also reset other settings controlled by 107 | the registers it writes to. 108 | */ 109 | void LSM6::enableDefault() 110 | { 111 | if (_device == device_DS33 || _device == device_DSO) 112 | { 113 | // Accelerometer 114 | 115 | // 0x80 = 0b10000000 116 | // ODR = 1000 (1.66 kHz (high performance)); FS_XL = 00 (+/-2 g full scale) 117 | writeReg(CTRL1_XL, 0x80); 118 | 119 | // Gyro 120 | 121 | // 0x80 = 0b010000000 122 | // ODR = 1000 (1.66 kHz (high performance)); FS_G = 00 (245 dps for DS33, 250 dps for DSO) 123 | writeReg(CTRL2_G, 0x80); 124 | 125 | // Common 126 | 127 | // 0x04 = 0b00000100 128 | // IF_INC = 1 (automatically increment register address) 129 | writeReg(CTRL3_C, 0x04); 130 | } 131 | } 132 | 133 | void LSM6::writeReg(uint8_t reg, uint8_t value) 134 | { 135 | bus->beginTransmission(address); 136 | bus->write(reg); 137 | bus->write(value); 138 | last_status = bus->endTransmission(); 139 | } 140 | 141 | uint8_t LSM6::readReg(uint8_t reg) 142 | { 143 | uint8_t value; 144 | 145 | bus->beginTransmission(address); 146 | bus->write(reg); 147 | last_status = bus->endTransmission(); 148 | 149 | bus->requestFrom(address, (uint8_t)1); 150 | value = bus->read(); 151 | 152 | return value; 153 | } 154 | 155 | // Reads the 3 accelerometer channels and stores them in vector a 156 | void LSM6::readAcc() 157 | { 158 | bus->beginTransmission(address); 159 | // automatic increment of register address is enabled by default (IF_INC in CTRL3_C) 160 | bus->write(OUTX_L_XL); 161 | bus->endTransmission(); 162 | 163 | bus->requestFrom(address, (uint8_t)6); 164 | uint8_t xla = bus->read(); 165 | uint8_t xha = bus->read(); 166 | uint8_t yla = bus->read(); 167 | uint8_t yha = bus->read(); 168 | uint8_t zla = bus->read(); 169 | uint8_t zha = bus->read(); 170 | 171 | // combine high and low bytes 172 | a.x = (int16_t)(xha << 8 | xla); 173 | a.y = (int16_t)(yha << 8 | yla); 174 | a.z = (int16_t)(zha << 8 | zla); 175 | } 176 | 177 | // Reads the 3 gyro channels and stores them in vector g 178 | void LSM6::readGyro() 179 | { 180 | bus->beginTransmission(address); 181 | // automatic increment of register address is enabled by default (IF_INC in CTRL3_C) 182 | bus->write(OUTX_L_G); 183 | bus->endTransmission(); 184 | 185 | bus->requestFrom(address, (uint8_t)6); 186 | uint8_t xlg = bus->read(); 187 | uint8_t xhg = bus->read(); 188 | uint8_t ylg = bus->read(); 189 | uint8_t yhg = bus->read(); 190 | uint8_t zlg = bus->read(); 191 | uint8_t zhg = bus->read(); 192 | 193 | // combine high and low bytes 194 | g.x = (int16_t)(xhg << 8 | xlg); 195 | g.y = (int16_t)(yhg << 8 | ylg); 196 | g.z = (int16_t)(zhg << 8 | zlg); 197 | } 198 | 199 | // Reads all 6 channels of the LSM6 and stores them in the object variables 200 | void LSM6::read() 201 | { 202 | readAcc(); 203 | readGyro(); 204 | } 205 | 206 | void LSM6::vector_normalize(vector *a) 207 | { 208 | float mag = sqrt(vector_dot(a, a)); 209 | a->x /= mag; 210 | a->y /= mag; 211 | a->z /= mag; 212 | } 213 | 214 | // Private Methods ////////////////////////////////////////////////////////////// 215 | 216 | int16_t LSM6::testReg(uint8_t address, regAddr reg) 217 | { 218 | bus->beginTransmission(address); 219 | bus->write((uint8_t)reg); 220 | if (bus->endTransmission() != 0) 221 | { 222 | return TEST_REG_ERROR; 223 | } 224 | 225 | bus->requestFrom(address, (uint8_t)1); 226 | if (bus->available()) 227 | { 228 | return bus->read(); 229 | } 230 | else 231 | { 232 | return TEST_REG_ERROR; 233 | } 234 | } -------------------------------------------------------------------------------- /LSM6.h: -------------------------------------------------------------------------------- 1 | #ifndef LSM6_h 2 | #define LSM6_h 3 | 4 | #include 5 | #include 6 | 7 | class LSM6 8 | { 9 | public: 10 | template struct vector 11 | { 12 | T x, y, z; 13 | }; 14 | 15 | enum deviceType { device_DS33, device_DSO, device_auto }; 16 | enum sa0State { sa0_low, sa0_high, sa0_auto }; 17 | 18 | // register addresses 19 | enum regAddr 20 | { 21 | FUNC_CFG_ACCESS = 0x01, 22 | 23 | // This register conflicts with a register in the ESP32 with the same 24 | // name. We call it DSO_PIN_CTRL to work around this problem, but we'll 25 | // also define PIN_CTRL for use on other platforms. 26 | DSO_PIN_CTRL = 0x02, // DSO 27 | #ifndef PIN_CTRL 28 | PIN_CTRL = 0x02, // DSO 29 | #endif 30 | 31 | DS33_FIFO_CTRL1 = 0x06, // DS33 32 | DS33_FIFO_CTRL2 = 0x07, // DS33 33 | DS33_FIFO_CTRL3 = 0x08, // DS33 34 | DS33_FIFO_CTRL4 = 0x09, // DS33 35 | DS33_FIFO_CTRL5 = 0x0A, // DS33 36 | 37 | DSO_FIFO_CTRL1 = 0x07, // DSO 38 | DSO_FIFO_CTRL2 = 0x08, // DSO 39 | DSO_FIFO_CTRL3 = 0x09, // DSO 40 | DSO_FIFO_CTRL4 = 0x0A, // DSO 41 | 42 | ORIENT_CFG_G = 0x0B, // DS33 43 | COUNTER_BDR_REG1 = 0x0B, // DSO 44 | COUNTER_BDR_REG2 = 0x0C, // DSO 45 | INT1_CTRL = 0x0D, 46 | INT2_CTRL = 0x0E, 47 | WHO_AM_I = 0x0F, 48 | CTRL1_XL = 0x10, 49 | CTRL2_G = 0x11, 50 | CTRL3_C = 0x12, 51 | CTRL4_C = 0x13, 52 | CTRL5_C = 0x14, 53 | CTRL6_C = 0x15, 54 | CTRL7_G = 0x16, 55 | CTRL8_XL = 0x17, 56 | CTRL9_XL = 0x18, 57 | CTRL10_C = 0x19, 58 | ALL_INT_SRC = 0x1A, // DSO 59 | WAKE_UP_SRC = 0x1B, 60 | TAP_SRC = 0x1C, 61 | D6D_SRC = 0x1D, 62 | STATUS_REG = 0x1E, 63 | STATUS_SPIAux = 0x1E, // DSO 64 | 65 | OUT_TEMP_L = 0x20, 66 | OUT_TEMP_H = 0x21, 67 | OUTX_L_G = 0x22, 68 | OUTX_H_G = 0x23, 69 | OUTY_L_G = 0x24, 70 | OUTY_H_G = 0x25, 71 | OUTZ_L_G = 0x26, 72 | OUTZ_H_G = 0x27, 73 | OUTX_L_XL = 0x28, // DS33 74 | OUTX_H_XL = 0x29, // DS33 75 | OUTY_L_XL = 0x2A, // DS33 76 | OUTY_H_XL = 0x2B, // DS33 77 | OUTZ_L_XL = 0x2C, // DS33 78 | OUTZ_H_XL = 0x2D, // DS33 79 | OUTX_L_A = 0x28, // DSO 80 | OUTX_H_A = 0x29, // DSO 81 | OUTY_L_A = 0x2A, // DSO 82 | OUTY_H_A = 0x2B, // DSO 83 | OUTZ_L_A = 0x2C, // DSO 84 | OUTZ_H_A = 0x2D, // DSO 85 | 86 | EMB_FUNC_STATUS_MAINPAGE = 0x35, // DSO 87 | FSM_STATUS_A_MAINPAGE = 0x36, // DSO 88 | FSM_STATUS_B_MAINPAGE = 0x37, // DSO 89 | 90 | STATUS_MASTER_MAINPAGE = 0x39, // DSO 91 | 92 | FIFO_STATUS1 = 0x3A, 93 | FIFO_STATUS2 = 0x3B, 94 | FIFO_STATUS3 = 0x3C, // DS33 95 | FIFO_STATUS4 = 0x3D, // DS33 96 | FIFO_DATA_OUT_L = 0x3E, // DS33 97 | FIFO_DATA_OUT_H = 0x3F, // DS33 98 | TIMESTAMP0_REG = 0x40, // DS33 99 | TIMESTAMP1_REG = 0x41, // DS33 100 | TIMESTAMP2_REG = 0x42, // DS33 101 | TIMESTAMP0 = 0x40, // DSO 102 | TIMESTAMP1 = 0x41, // DSO 103 | TIMESTAMP2 = 0x42, // DSO 104 | TIMESTAMP3 = 0x43, // DSO 105 | 106 | STEP_TIMESTAMP_L = 0x49, // DS33 107 | STEP_TIMESTAMP_H = 0x4A, // DS33 108 | DS33_STEP_COUNTER_L = 0x4B, // DS33 (DSO version in embedded functions regs) 109 | DS33_STEP_COUNTER_H = 0x4C, // DS33 110 | 111 | FUNC_SRC = 0x53, // DS33 112 | 113 | TAP_CFG0 = 0x56, // DSO 114 | TAP_CFG1 = 0x57, // DSO 115 | TAP_CFG2 = 0x58, // DSO 116 | TAP_CFG = 0x58, // DS33 117 | TAP_THS_6D = 0x59, 118 | INT_DUR2 = 0x5A, 119 | WAKE_UP_THS = 0x5B, 120 | WAKE_UP_DUR = 0x5C, 121 | FREE_FALL = 0x5D, 122 | MD1_CFG = 0x5E, 123 | MD2_CFG = 0x5F, 124 | 125 | I3C_BUS_AVB = 0x62, // DSO 126 | INTERNAL_FREQ_FINE = 0x63, // DSO 127 | 128 | INT_OIS = 0x6F, // DSO 129 | CTRL1_OIS = 0x70, // DSO 130 | CTRL2_OIS = 0x71, // DSO 131 | CTRL3_OIS = 0x72, // DSO 132 | X_OFS_USR = 0x73, // DSO 133 | Y_OFS_USR = 0x74, // DSO 134 | Z_OFS_USR = 0x75, // DSO 135 | FIFO_DATA_OUT_TAG = 0x78, // DSO 136 | FIFO_DATA_OUT_X_L = 0x79, // DSO 137 | FIFO_DATA_OUT_X_H = 0x7A, // DSO 138 | FIFO_DATA_OUT_Y_L = 0x7B, // DSO 139 | FIFO_DATA_OUT_Y_H = 0x7C, // DSO 140 | FIFO_DATA_OUT_Z_L = 0x7D, // DSO 141 | FIFO_DATA_OUT_Z_H = 0x7E, // DSO 142 | 143 | // LSM6DSO embedded functions registers 144 | 145 | PAGE_SEL = 0x02, 146 | 147 | EMB_FUNC_EN_A = 0x04, 148 | EMB_FUNC_EN_B = 0x05, 149 | 150 | PAGE_ADDRESS = 0x08, 151 | PAGE_VALUE = 0x09, 152 | EMB_FUNC_INT1 = 0x0A, 153 | FSM_INT1_A = 0x0B, 154 | FSM_INT1_B = 0x0C, 155 | 156 | EMB_FUNC_INT2 = 0x0E, 157 | FSM_INT2_A = 0x0F, 158 | FSM_INT2_B = 0x10, 159 | 160 | EMB_FUNC_STATUS = 0x12, 161 | FSM_STATUS_A = 0x13, 162 | FSM_STATUS_B = 0x14, 163 | 164 | PAGE_RW = 0x17, 165 | 166 | EMB_FUNC_FIFO_CFG = 0x44, 167 | 168 | FSM_ENABLE_A = 0x46, 169 | FSM_ENABLE_B = 0x47, 170 | FSM_LONG_COUNTER_L = 0x48, 171 | FSM_LONG_COUNTER_H = 0x49, 172 | FSM_LONG_COUNTER_CLEAR = 0x4A, 173 | 174 | FSM_OUTS1 = 0x4C, 175 | FSM_OUTS2 = 0x4D, 176 | FSM_OUTS3 = 0x4E, 177 | FSM_OUTS4 = 0x4F, 178 | FSM_OUTS5 = 0x50, 179 | FSM_OUTS6 = 0x51, 180 | FSM_OUTS7 = 0x52, 181 | FSM_OUTS8 = 0x53, 182 | FSM_OUTS9 = 0x54, 183 | FSM_OUTS10 = 0x55, 184 | FSM_OUTS11 = 0x56, 185 | FSM_OUTS12 = 0x57, 186 | FSM_OUTS13 = 0x58, 187 | FSM_OUTS14 = 0x59, 188 | FSM_OUTS15 = 0x5A, 189 | FSM_OUTS16 = 0x5B, 190 | 191 | EMB_FUNC_ODR_CFG_B = 0x5F, 192 | 193 | DSO_STEP_COUNTER_L = 0x62, 194 | DSO_STEP_COUNTER_H = 0x63, 195 | EMB_FUNC_SRC = 0x64, 196 | 197 | EMB_FUNC_INIT_A = 0x66, 198 | EMB_FUNC_INIT_B = 0x67, 199 | 200 | // LSM6DSO embedded advanced features registers, page 0 201 | 202 | MAG_SENSITIVITY_L = 0xBA, 203 | MAG_SENSITIVITY_H = 0xBB, 204 | 205 | MAG_OFFX_L = 0xC0, 206 | MAG_OFFX_H = 0xC1, 207 | MAG_OFFY_L = 0xC2, 208 | MAG_OFFY_H = 0xC3, 209 | MAG_OFFZ_L = 0xC4, 210 | MAG_OFFZ_H = 0xC5, 211 | MAG_SI_XX_L = 0xC6, 212 | MAG_SI_XX_H = 0xC7, 213 | MAG_SI_XY_L = 0xC8, 214 | MAG_SI_XY_H = 0xC9, 215 | MAG_SI_XZ_L = 0xCA, 216 | MAG_SI_XZ_H = 0xCB, 217 | MAG_SI_YY_L = 0xCC, 218 | MAG_SI_YY_H = 0xCD, 219 | MAG_SI_YZ_L = 0xCE, 220 | MAG_SI_YZ_H = 0xCF, 221 | MAG_SI_ZZ_L = 0xD0, 222 | MAG_SI_ZZ_H = 0xD1, 223 | 224 | MAG_CFG_A = 0xD4, 225 | MAG_CFG_B = 0xD5, 226 | 227 | // LSM6DSO embedded advanced features registers, page 1 228 | 229 | FSM_LC_TIMEOUT_L = 0x7A, 230 | FSM_LC_TIMEOUT_H = 0x7B, 231 | FSM_PROGRAMS = 0x7C, 232 | 233 | FSM_START_ADD_L = 0x7E, 234 | FSM_START_ADD_H = 0x7F, 235 | 236 | PEDO_CMD_REG = 0x83, 237 | PEDO_DEB_STEPS_CONF = 0x84, 238 | 239 | PEDO_SC_DELTAT_L = 0xD0, 240 | PEDO_SC_DELTAT_H = 0xD1, 241 | 242 | // LSM6DSO sensor hub registers 243 | 244 | SENSOR_HUB_1 = 0x02, 245 | SENSOR_HUB_2 = 0x03, 246 | SENSOR_HUB_3 = 0x04, 247 | SENSOR_HUB_4 = 0x05, 248 | SENSOR_HUB_5 = 0x06, 249 | SENSOR_HUB_6 = 0x07, 250 | SENSOR_HUB_7 = 0x08, 251 | SENSOR_HUB_8 = 0x09, 252 | SENSOR_HUB_9 = 0x0A, 253 | SENSOR_HUB_10 = 0x0B, 254 | SENSOR_HUB_11 = 0x0C, 255 | SENSOR_HUB_12 = 0x0D, 256 | SENSOR_HUB_13 = 0x0E, 257 | SENSOR_HUB_14 = 0x0F, 258 | SENSOR_HUB_15 = 0x10, 259 | SENSOR_HUB_16 = 0x11, 260 | SENSOR_HUB_17 = 0x12, 261 | SENSOR_HUB_18 = 0x13, 262 | MASTER_CONFIG = 0x14, 263 | SLV0_ADD = 0x15, 264 | SLV0_SUBADD = 0x16, 265 | SLV0_CONFIG = 0x17, 266 | SLV1_ADD = 0x18, 267 | SLV1_SUBADD = 0x19, 268 | SLV1_CONFIG = 0x1A, 269 | SLV2_ADD = 0x1B, 270 | SLV2_SUBADD = 0x1C, 271 | SLV2_CONFIG = 0x1D, 272 | SLV3_ADD = 0x1E, 273 | SLV3_SUBADD = 0x1F, 274 | SLV3_CONFIG = 0x20, 275 | DATAWRITE_SLV0 = 0x21, 276 | STATUS_MASTER = 0x22, 277 | }; 278 | 279 | vector a; // accelerometer readings 280 | vector g; // gyro readings 281 | 282 | uint8_t last_status; // status of last I2C transmission 283 | 284 | LSM6(); 285 | 286 | void setBus(TwoWire * bus) { this->bus = bus; } 287 | TwoWire * getBus() { return bus; } 288 | 289 | bool init(deviceType device = device_auto, sa0State sa0 = sa0_auto); 290 | deviceType getDeviceType() { return _device; } 291 | 292 | void enableDefault(); 293 | 294 | void writeReg(uint8_t reg, uint8_t value); 295 | uint8_t readReg(uint8_t reg); 296 | 297 | void readAcc(); 298 | void readGyro(); 299 | void read(); 300 | 301 | // vector functions 302 | template static void vector_cross(const vector *a, const vector *b, vector *out); 303 | template static float vector_dot(const vector *a, const vector *b); 304 | static void vector_normalize(vector *a); 305 | 306 | private: 307 | TwoWire * bus; 308 | deviceType _device; // chip type 309 | uint8_t address; 310 | 311 | int16_t testReg(uint8_t address, regAddr reg); 312 | }; 313 | 314 | 315 | template void LSM6::vector_cross(const vector *a, const vector *b, vector *out) 316 | { 317 | out->x = (a->y * b->z) - (a->z * b->y); 318 | out->y = (a->z * b->x) - (a->x * b->z); 319 | out->z = (a->x * b->y) - (a->y * b->x); 320 | } 321 | 322 | template float LSM6::vector_dot(const vector *a, const vector *b) 323 | { 324 | return (a->x * b->x) + (a->y * b->y) + (a->z * b->z); 325 | } 326 | 327 | #endif -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LSM6 library for Arduino 2 | [www.pololu.com](https://www.pololu.com/) 3 | 4 | ## Summary 5 | 6 | This is a library for the Arduino IDE that helps interface with ST's LSM6DS33 and LSM6DSO 3D accelerometer and gyro ICs on Pololu boards. It makes it simple to configure the LSM6 and read the raw accelerometer and gyro data from these boards: 7 | 8 | * [LSM6DSO 3D accelerometer and gyro carrier](https://www.pololu.com/product/2798) 9 | * [LSM6DS33 3D accelerometer and gyro carrier](https://www.pololu.com/product/2736) 10 | * [MinIMU-9 v6 (LSM6DSO and LIS3MDL carrier)](https://www.pololu.com/product/2862) 11 | * [AltIMU-10 v6 (LSM6DSO, LIS3MDL, and LPS22DF Carrier)](https://www.pololu.com/product/2863) 12 | * [MinIMU-9 v5 (LSM6DS33 and LIS3MDL carrier)](https://www.pololu.com/product/2738) 13 | * [AltIMU-9 v5 (LSM6DS33, LIS3MDL, and LPS25H carrier)](https://www.pololu.com/product/2739) 14 | 15 | ## Supported platforms 16 | 17 | This library is designed to work with the Arduino IDE versions 1.6.x or later; we have not tested it with earlier versions. This library should support any Arduino-compatible board, including the [Pololu A-Star 32U4 controllers](https://www.pololu.com/category/149/a-star-programmable-controllers). 18 | 19 | ## Getting started 20 | 21 | ### Hardware 22 | 23 | An LSM6 carrier can be purchased from Pololu's website. Before continuing, careful reading of the product page as well as the chip datasheet and application note is recommended. 24 | 25 | Make the following connections between the Arduino and the LSM6 board: 26 | 27 | #### 5V Arduino boards 28 | 29 | (including Arduino Uno, Leonardo, Mega; Pololu A-Star 32U4) 30 | 31 | Arduino LSM6 board 32 | ------- ---------- 33 | 5V - VIN 34 | GND - GND 35 | SDA - SDA 36 | SCL - SCL 37 | 38 | #### 3.3V Arduino boards 39 | 40 | (including Arduino Due) 41 | 42 | Arduino LSM6 board 43 | ------- ---------- 44 | 3V3 - VIN 45 | GND - GND 46 | SDA - SDA 47 | SCL - SCL 48 | 49 | ### Software 50 | 51 | If you are using version 1.6.2 or later of the [Arduino software (IDE)](http://www.arduino.cc/en/Main/Software), you can use the Library Manager to install this library: 52 | 53 | 1. In the Arduino IDE, open the "Sketch" menu, select "Include Library", then "Manage Libraries...". 54 | 2. Search for "LSM6". 55 | 3. Click the LSM6 entry in the list. 56 | 4. Click "Install". 57 | 58 | If this does not work, you can manually install the library: 59 | 60 | 1. Download the [latest release archive from GitHub](https://github.com/pololu/lsm6-arduino/releases) and decompress it. 61 | 2. Rename the folder "lsm6-arduino-master" to "LSM6". 62 | 3. Move the "LSM6" folder into the "libraries" directory inside your Arduino sketchbook directory. You can view your sketchbook location by opening the "File" menu and selecting "Preferences" in the Arduino IDE. If there is not already a "libraries" folder in that location, you should make the folder yourself. 63 | 4. After installing the library, restart the Arduino IDE. 64 | 65 | ## Examples 66 | 67 | An example sketch is available that shows how to use the library. You can access it from the Arduino IDE by opening the "File" menu, selecting "Examples", and then selecting "LSM6". If you cannot find the example, the library was probably installed incorrectly and you should retry the installation instructions above. 68 | 69 | ## Library reference 70 | 71 | * `vector a`
72 | The last values read from the accelerometer. 73 | 74 | * `vector g`
75 | The last values read from the gyro. 76 | 77 | * `uint8_t last_status`
78 | The status of the last I²C write transmission. See the [`Wire.endTransmission()` documentation](http://arduino.cc/en/Reference/WireEndTransmission) for return values. 79 | 80 | * `LSM6()`
81 | Constructor. 82 | 83 | * `void setBus(TwoWire * bus)`
84 | Configures this object to use the specified I²C bus. `bus` should be a pointer to a `TwoWire` object; the default bus is `Wire`, which is typically the first or only I²C bus on an Arduino. If your Arduino has more than one I²C bus and you have the VL53L0X connected to the second bus, which is typically called `Wire1`, you can call `sensor.setBus(&Wire1);`. 85 | 86 | * `TwoWire * getBus()`
87 | Returns a pointer to the I²C bus this object is using. 88 | 89 | * `bool init(deviceType device, sa0State sa0)`
90 | Initializes the library with the device being used (`device_DS33` or `device_auto`) and the state of the SA0 pin (`sa0_low`, `sa0_high`, or `sa0_auto`), which determines the least significant bit of the I²C slave address. Constants for these arguments are defined in LSM6.h. Both of these arguments are optional; if they are not specified, the library will try to automatically detect the device address. A boolean is returned indicating whether the type of LSM6 device was successfully determined (if necessary). 91 | 92 | * `void getDeviceType()`
93 | Returns the device type specified to or detected by `init()`. 94 | 95 | * `void enableDefault()`
96 | Turns on the accelerometer and gyro and enables a consistent set of default settings. 97 | 98 | This function will reset the accelerometer to ±2 g full scale and the gyro to ±245 dps. See the comments in LSM6.cpp for a full explanation of the settings. 99 | 100 | * `void writeReg(uint8_t reg, uint8_t value)`
101 | Writes a sensor register with the given value. 102 | 103 | Register address constants are defined by the regAddr enumeration type in LSM6.h.
104 | Example use: `imu.writeReg(LSM6::CTRL1_XL, 0x80);` 105 | 106 | * `uint8_t readReg(uint8_t reg)`
107 | Reads a sensor register and returns the value read. 108 | 109 | * `void readAcc()`
110 | Takes a reading from the accelerometer and stores the values in the vector `a`. Conversion of the readings to units of g depends on the accelerometer's selected gain (full scale setting). 111 | 112 | * `void readGyro()`
113 | Takes a reading from the gyro and stores the values in the vector `g`. Conversion of the readings to units of dps (degrees per second) depends on the gyro's selected gain (full scale setting). 114 | 115 | * `void read()`
116 | Takes a reading from both the accelerometer and gyro and stores the values in the vectors `a` and `g`. 117 | 118 | ## Version history 119 | 120 | * 2.0.1 (2022-10-14): Renamed PIN_CTRL to DSO_PIN_CTRL to work around a naming conflict with the ESP32. The original name can still be used on other platforms. 121 | * 2.0.0 (2022-09-02): Added support for LSM6DSO and support for alternative I²C buses. Removed timeout functionality that did not work as intended. 122 | * 1.0.0 (2016-01-19): Original release. 123 | -------------------------------------------------------------------------------- /examples/Serial/Serial.ino: -------------------------------------------------------------------------------- 1 | /* 2 | The sensor outputs provided by the library are the raw 3 | 16-bit values obtained by concatenating the 8-bit high and 4 | low accelerometer and gyro data registers. They can be 5 | converted to units of g and dps (degrees per second) using 6 | the conversion factors specified in the datasheet for your 7 | particular device and full scale setting (gain). 8 | 9 | Example: An LSM6DS33 gives an accelerometer Z axis reading 10 | of 16276 with its default full scale setting of +/- 2 g. The 11 | LA_So specification in the LSM6DS33 datasheet (page 15) 12 | states a conversion factor of 0.061 mg/LSB (least 13 | significant bit) at this FS setting, so the raw reading of 14 | 16276 corresponds to 16276 * 0.061 = 992.8 mg = 0.9928 g. 15 | */ 16 | 17 | #include 18 | #include 19 | 20 | LSM6 imu; 21 | 22 | char report[80]; 23 | 24 | void setup() 25 | { 26 | Serial.begin(9600); 27 | Wire.begin(); 28 | 29 | if (!imu.init()) 30 | { 31 | Serial.println("Failed to detect and initialize IMU!"); 32 | while (1); 33 | } 34 | imu.enableDefault(); 35 | } 36 | 37 | void loop() 38 | { 39 | imu.read(); 40 | 41 | snprintf(report, sizeof(report), "A: %6d %6d %6d G: %6d %6d %6d", 42 | imu.a.x, imu.a.y, imu.a.z, 43 | imu.g.x, imu.g.y, imu.g.z); 44 | Serial.println(report); 45 | 46 | delay(100); 47 | } 48 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | LSM6 KEYWORD1 2 | 3 | setBus KEYWORD2 4 | getBus KEYWORD2 5 | init KEYWORD2 6 | getDeviceType KEYWORD2 7 | enableDefault KEYWORD2 8 | writeReg KEYWORD2 9 | readReg KEYWORD2 10 | readAcc KEYWORD2 11 | readGyro KEYWORD2 12 | read KEYWORD2 13 | vector_cross KEYWORD2 14 | vector_dot KEYWORD2 15 | vector_normalize KEYWORD2 16 | 17 | device_DS33 LITERAL1 18 | device_DSO LITERAL1 19 | device_auto LITERAL1 20 | sa0_low LITERAL1 21 | sa0_high LITERAL1 22 | sa0_auto LITERAL1 23 | 24 | FUNC_CFG_ACCESS LITERAL1 25 | DSO_PIN_CTRL LITERAL1 26 | PIN_CTRL LITERAL1 27 | DS33_FIFO_CTRL1 LITERAL1 28 | DS33_FIFO_CTRL2 LITERAL1 29 | DS33_FIFO_CTRL3 LITERAL1 30 | DS33_FIFO_CTRL4 LITERAL1 31 | DS33_FIFO_CTRL5 LITERAL1 32 | DSO_FIFO_CTRL1 LITERAL1 33 | DSO_FIFO_CTRL2 LITERAL1 34 | DSO_FIFO_CTRL3 LITERAL1 35 | DSO_FIFO_CTRL4 LITERAL1 36 | ORIENT_CFG_G LITERAL1 37 | COUNTER_BDR_REG1 LITERAL1 38 | COUNTER_BDR_REG2 LITERAL1 39 | INT1_CTRL LITERAL1 40 | INT2_CTRL LITERAL1 41 | WHO_AM_I LITERAL1 42 | CTRL1_XL LITERAL1 43 | CTRL2_G LITERAL1 44 | CTRL3_C LITERAL1 45 | CTRL4_C LITERAL1 46 | CTRL5_C LITERAL1 47 | CTRL6_C LITERAL1 48 | CTRL7_G LITERAL1 49 | CTRL8_XL LITERAL1 50 | CTRL9_XL LITERAL1 51 | CTRL10_C LITERAL1 52 | ALL_INT_SRC LITERAL1 53 | WAKE_UP_SRC LITERAL1 54 | TAP_SRC LITERAL1 55 | D6D_SRC LITERAL1 56 | STATUS_REG LITERAL1 57 | STATUS_SPIAux LITERAL1 58 | OUT_TEMP_L LITERAL1 59 | OUT_TEMP_H LITERAL1 60 | OUTX_L_G LITERAL1 61 | OUTX_H_G LITERAL1 62 | OUTY_L_G LITERAL1 63 | OUTY_H_G LITERAL1 64 | OUTZ_L_G LITERAL1 65 | OUTZ_H_G LITERAL1 66 | OUTX_L_XL LITERAL1 67 | OUTX_H_XL LITERAL1 68 | OUTY_L_XL LITERAL1 69 | OUTY_H_XL LITERAL1 70 | OUTZ_L_XL LITERAL1 71 | OUTZ_H_XL LITERAL1 72 | OUTX_L_A LITERAL1 73 | OUTX_H_A LITERAL1 74 | OUTY_L_A LITERAL1 75 | OUTY_H_A LITERAL1 76 | OUTZ_L_A LITERAL1 77 | OUTZ_H_A LITERAL1 78 | EMB_FUNC_STATUS_MAINPAGE LITERAL1 79 | FSM_STATUS_A_MAINPAGE LITERAL1 80 | FSM_STATUS_B_MAINPAGE LITERAL1 81 | STATUS_MASTER_MAINPAGE LITERAL1 82 | FIFO_STATUS1 LITERAL1 83 | FIFO_STATUS2 LITERAL1 84 | FIFO_STATUS3 LITERAL1 85 | FIFO_STATUS4 LITERAL1 86 | FIFO_DATA_OUT_L LITERAL1 87 | FIFO_DATA_OUT_H LITERAL1 88 | TIMESTAMP0_REG LITERAL1 89 | TIMESTAMP1_REG LITERAL1 90 | TIMESTAMP2_REG LITERAL1 91 | TIMESTAMP0 LITERAL1 92 | TIMESTAMP1 LITERAL1 93 | TIMESTAMP2 LITERAL1 94 | TIMESTAMP3 LITERAL1 95 | STEP_TIMESTAMP_L LITERAL1 96 | STEP_TIMESTAMP_H LITERAL1 97 | DS33_STEP_COUNTER_L LITERAL1 98 | DS33_STEP_COUNTER_H LITERAL1 99 | FUNC_SRC LITERAL1 100 | TAP_CFG0 LITERAL1 101 | TAP_CFG1 LITERAL1 102 | TAP_CFG2 LITERAL1 103 | TAP_CFG LITERAL1 104 | TAP_THS_6D LITERAL1 105 | INT_DUR2 LITERAL1 106 | WAKE_UP_THS LITERAL1 107 | WAKE_UP_DUR LITERAL1 108 | FREE_FALL LITERAL1 109 | MD1_CFG LITERAL1 110 | MD2_CFG LITERAL1 111 | I3C_BUS_AVB LITERAL1 112 | INTERNAL_FREQ_FINE LITERAL1 113 | INT_OIS LITERAL1 114 | CTRL1_OIS LITERAL1 115 | CTRL2_OIS LITERAL1 116 | CTRL3_OIS LITERAL1 117 | X_OFS_USR LITERAL1 118 | Y_OFS_USR LITERAL1 119 | Z_OFS_USR LITERAL1 120 | FIFO_DATA_OUT_TAG LITERAL1 121 | FIFO_DATA_OUT_X_L LITERAL1 122 | FIFO_DATA_OUT_X_H LITERAL1 123 | FIFO_DATA_OUT_Y_L LITERAL1 124 | FIFO_DATA_OUT_Y_H LITERAL1 125 | FIFO_DATA_OUT_Z_L LITERAL1 126 | FIFO_DATA_OUT_Z_H LITERAL1 127 | PAGE_SEL LITERAL1 128 | EMB_FUNC_EN_A LITERAL1 129 | EMB_FUNC_EN_B LITERAL1 130 | PAGE_ADDRESS LITERAL1 131 | PAGE_VALUE LITERAL1 132 | EMB_FUNC_INT1 LITERAL1 133 | FSM_INT1_A LITERAL1 134 | FSM_INT1_B LITERAL1 135 | EMB_FUNC_INT2 LITERAL1 136 | FSM_INT2_A LITERAL1 137 | FSM_INT2_B LITERAL1 138 | EMB_FUNC_STATUS LITERAL1 139 | FSM_STATUS_A LITERAL1 140 | FSM_STATUS_B LITERAL1 141 | PAGE_RW LITERAL1 142 | EMB_FUNC_FIFO_CFG LITERAL1 143 | FSM_ENABLE_A LITERAL1 144 | FSM_ENABLE_B LITERAL1 145 | FSM_LONG_COUNTER_L LITERAL1 146 | FSM_LONG_COUNTER_H LITERAL1 147 | FSM_LONG_COUNTER_CLEAR LITERAL1 148 | FSM_OUTS1 LITERAL1 149 | FSM_OUTS2 LITERAL1 150 | FSM_OUTS3 LITERAL1 151 | FSM_OUTS4 LITERAL1 152 | FSM_OUTS5 LITERAL1 153 | FSM_OUTS6 LITERAL1 154 | FSM_OUTS7 LITERAL1 155 | FSM_OUTS8 LITERAL1 156 | FSM_OUTS9 LITERAL1 157 | FSM_OUTS10 LITERAL1 158 | FSM_OUTS11 LITERAL1 159 | FSM_OUTS12 LITERAL1 160 | FSM_OUTS13 LITERAL1 161 | FSM_OUTS14 LITERAL1 162 | FSM_OUTS15 LITERAL1 163 | FSM_OUTS16 LITERAL1 164 | EMB_FUNC_ODR_CFG_B LITERAL1 165 | DSO_STEP_COUNTER_L LITERAL1 166 | DSO_STEP_COUNTER_H LITERAL1 167 | EMB_FUNC_SRC LITERAL1 168 | EMB_FUNC_INIT_A LITERAL1 169 | EMB_FUNC_INIT_B LITERAL1 170 | MAG_SENSITIVITY_L LITERAL1 171 | MAG_SENSITIVITY_H LITERAL1 172 | MAG_OFFX_L LITERAL1 173 | MAG_OFFX_H LITERAL1 174 | MAG_OFFY_L LITERAL1 175 | MAG_OFFY_H LITERAL1 176 | MAG_OFFZ_L LITERAL1 177 | MAG_OFFZ_H LITERAL1 178 | MAG_SI_XX_L LITERAL1 179 | MAG_SI_XX_H LITERAL1 180 | MAG_SI_XY_L LITERAL1 181 | MAG_SI_XY_H LITERAL1 182 | MAG_SI_XZ_L LITERAL1 183 | MAG_SI_XZ_H LITERAL1 184 | MAG_SI_YY_L LITERAL1 185 | MAG_SI_YY_H LITERAL1 186 | MAG_SI_YZ_L LITERAL1 187 | MAG_SI_YZ_H LITERAL1 188 | MAG_SI_ZZ_L LITERAL1 189 | MAG_SI_ZZ_H LITERAL1 190 | MAG_CFG_A LITERAL1 191 | MAG_CFG_B LITERAL1 192 | FSM_LC_TIMEOUT_L LITERAL1 193 | FSM_LC_TIMEOUT_H LITERAL1 194 | FSM_PROGRAMS LITERAL1 195 | FSM_START_ADD_L LITERAL1 196 | FSM_START_ADD_H LITERAL1 197 | PEDO_CMD_REG LITERAL1 198 | PEDO_DEB_STEPS_CONF LITERAL1 199 | PEDO_SC_DELTAT_L LITERAL1 200 | PEDO_SC_DELTAT_H LITERAL1 201 | SENSOR_HUB_1 LITERAL1 202 | SENSOR_HUB_2 LITERAL1 203 | SENSOR_HUB_3 LITERAL1 204 | SENSOR_HUB_4 LITERAL1 205 | SENSOR_HUB_5 LITERAL1 206 | SENSOR_HUB_6 LITERAL1 207 | SENSOR_HUB_7 LITERAL1 208 | SENSOR_HUB_8 LITERAL1 209 | SENSOR_HUB_9 LITERAL1 210 | SENSOR_HUB_10 LITERAL1 211 | SENSOR_HUB_11 LITERAL1 212 | SENSOR_HUB_12 LITERAL1 213 | SENSOR_HUB_13 LITERAL1 214 | SENSOR_HUB_14 LITERAL1 215 | SENSOR_HUB_15 LITERAL1 216 | SENSOR_HUB_16 LITERAL1 217 | SENSOR_HUB_17 LITERAL1 218 | SENSOR_HUB_18 LITERAL1 219 | MASTER_CONFIG LITERAL1 220 | SLV0_ADD LITERAL1 221 | SLV0_SUBADD LITERAL1 222 | SLV0_CONFIG LITERAL1 223 | SLV1_ADD LITERAL1 224 | SLV1_SUBADD LITERAL1 225 | SLV1_CONFIG LITERAL1 226 | SLV2_ADD LITERAL1 227 | SLV2_SUBADD LITERAL1 228 | SLV2_CONFIG LITERAL1 229 | SLV3_ADD LITERAL1 230 | SLV3_SUBADD LITERAL1 231 | SLV3_CONFIG LITERAL1 232 | DATAWRITE_SLV0 LITERAL1 233 | STATUS_MASTER LITERAL1 -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=LSM6 2 | version=2.0.1 3 | author=Pololu 4 | maintainer=Pololu 5 | sentence=LSM6 accelerometer and gyro library 6 | paragraph=This is a library for the Arduino IDE that helps interface with ST's LSM6DSO and LSM6DS33 accelerometer and gyro ICs. 7 | category=Sensors 8 | url=https://github.com/pololu/lsm6-arduino 9 | architectures=* 10 | --------------------------------------------------------------------------------