/ Adafruit_LIS331.cpp
Adafruit_LIS331.cpp
1 /*! 2 * @file Adafruit_LIS331.cpp 3 */ 4 5 #include "Arduino.h" 6 7 #include <Adafruit_LIS331.h> 8 #include <Wire.h> 9 10 /*! 11 * @brief Instantiates a new LIS331 class in I2C 12 * @param TheWire 13 * optional wire object 14 */ 15 Adafruit_LIS331::Adafruit_LIS331(TwoWire *TheWire) {} 16 17 /*! 18 * @brief Instantiates a new LIS331 class using hardware SPI 19 * @param cspin 20 * number of CSPIN (Chip Select) 21 * @param *theSPI 22 * optional parameter contains spi object 23 */ 24 Adafruit_LIS331::Adafruit_LIS331(int8_t cspin, SPIClass *theSPI) {} 25 26 /*! 27 * @brief Instantiates a new LIS331 class using software SPI 28 * @param cspin 29 * number of CSPIN (Chip Select) 30 * @param mosipin 31 * number of pin used for MOSI (Master Out Slave In)) 32 * @param misopin 33 * number of pin used for MISO (Master In Slave Out) 34 * @param sckpin 35 * number of pin used for CLK (clock pin) 36 */ 37 Adafruit_LIS331::Adafruit_LIS331(int8_t cspin, int8_t mosipin, int8_t misopin, 38 int8_t sckpin) {} 39 40 /*! 41 * @brief Get Device ID from LIS331_REG_WHOAMI 42 * @return WHO AM I value 43 */ 44 uint8_t Adafruit_LIS331::getDeviceID(void) { 45 Adafruit_BusIO_Register _chip_id = Adafruit_BusIO_Register( 46 i2c_dev, spi_dev, ADDRBIT8_HIGH_TOREAD, LIS331_REG_WHOAMI, 1); 47 48 return _chip_id.read(); 49 } 50 51 /*! 52 * @brief Reads x y z values at once 53 */ 54 void Adafruit_LIS331::read(void) { 55 56 uint8_t register_address = LIS331_REG_OUT_X_L; 57 if (i2c_dev) { 58 register_address |= 0x80; // set [7] for auto-increment 59 } else { 60 register_address |= 0x40; // set [6] for auto-increment 61 register_address |= 0x80; // set [7] for read 62 } 63 64 Adafruit_BusIO_Register xl_data = Adafruit_BusIO_Register( 65 i2c_dev, spi_dev, ADDRBIT8_HIGH_TOREAD, register_address, 6); 66 67 uint8_t buffer[6]; 68 xl_data.read(buffer, 6); 69 70 x = buffer[0]; 71 x |= ((uint16_t)buffer[1]) << 8; 72 y = buffer[2]; 73 y |= ((uint16_t)buffer[3]) << 8; 74 z = buffer[4]; 75 z |= ((uint16_t)buffer[5]) << 8; 76 77 _scaleValues(); 78 } 79 80 /** 81 * @brief Setup the INT1 or INT2 pin to trigger when new data is ready 82 * 83 * @param irqnum The interrupt number/pin to configure 84 * @param activelow The polarity of the pin. true: active low false: active high 85 * @param opendrain The pinmode for the given interrupt pin. true: open drain. 86 * Connects to GND when activated false: push-pull: connects to VCC when 87 * activated 88 * @return true 89 * @return false 90 */ 91 bool Adafruit_LIS331::configIntDataReady(uint8_t irqnum, bool activelow, 92 bool opendrain) { 93 Adafruit_BusIO_Register ctrl3_reg = Adafruit_BusIO_Register( 94 i2c_dev, spi_dev, ADDRBIT8_HIGH_TOREAD, LIS331_REG_CTRL3, 1); 95 96 Adafruit_BusIO_RegisterBits opendrain_and_polarity_bits = 97 Adafruit_BusIO_RegisterBits(&ctrl3_reg, 2, 6); 98 Adafruit_BusIO_RegisterBits int1_bits = 99 Adafruit_BusIO_RegisterBits(&ctrl3_reg, 2, 0); 100 Adafruit_BusIO_RegisterBits int2_bits = 101 Adafruit_BusIO_RegisterBits(&ctrl3_reg, 2, 3); 102 opendrain_and_polarity_bits.write((activelow << 1) | (opendrain)); 103 104 if (irqnum == 1) { 105 int1_bits.write(0b10); 106 int2_bits.write(0); 107 } else { 108 int2_bits.write(0b10); 109 int1_bits.write(0); 110 } 111 } 112 113 /**************************************************************************/ 114 /*! 115 @brief Enables the high pass filter and/or slope filter 116 @param filter_enabled Whether to enable the slope filter (see datasheet) 117 @param cutoff The frequency below which signals will be filtered out 118 @param use_reference Selects if the reference value set by `setReference` 119 should be used 120 121 See section **4** of the LIS331DLH application note for more information 122 123 https://www.st.com/content/ccc/resource/technical/document/application_note/b5/8e/58/69/cb/87/45/55/CD00215823.pdf/files/CD00215823.pdf/jcr:content/translations/en.CD00215823.pdf 124 */ 125 void Adafruit_LIS331::enableHighPassFilter(bool filter_enabled, 126 lis331_hpf_cutoff_t cutoff, 127 bool use_reference) { 128 Adafruit_BusIO_Register ctrl2_reg = Adafruit_BusIO_Register( 129 i2c_dev, spi_dev, ADDRBIT8_HIGH_TOREAD, LIS331_REG_CTRL2); 130 131 Adafruit_BusIO_RegisterBits HPF_mode = 132 Adafruit_BusIO_RegisterBits(&ctrl2_reg, 1, 5); 133 134 Adafruit_BusIO_RegisterBits HPF_internal_filter_en = 135 Adafruit_BusIO_RegisterBits(&ctrl2_reg, 1, 4); 136 137 Adafruit_BusIO_RegisterBits HPF_cuttoff = 138 Adafruit_BusIO_RegisterBits(&ctrl2_reg, 2, 0); 139 140 if (filter_enabled) { 141 HPF_mode.write(use_reference); 142 HPF_cuttoff.write(cutoff); 143 } 144 HPF_internal_filter_en.write(filter_enabled); 145 } 146 147 /** 148 * @brief Set the reference value to offset measurements when using the 149 High-pass filter. 150 * 151 * @param reference The offset amount. The conversion of `reference` to milli-g 152 depends on the selected range: 153 * 154 * * Full scale Reference mode LSB value (mg) 155 6g/100g ~16mg 156 12g/200g ~31mg 157 24g/400g ~63mg 158 */ 159 void Adafruit_LIS331::setHPFReference(int8_t reference) { 160 Adafruit_BusIO_Register reference_reg = Adafruit_BusIO_Register( 161 i2c_dev, spi_dev, ADDRBIT8_HIGH_TOREAD, LIS331_REG_REFERENCE); 162 reference_reg.write(reference); 163 } 164 /** 165 * @brief Gets the current high-pass filter reference/offset 166 * @return int8_t The current reference value. 167 * See `enableHighPassFilter` and `setHPFReference` for more information. 168 */ 169 int8_t Adafruit_LIS331::getHPFReference(void) { 170 Adafruit_BusIO_Register reference_reg = Adafruit_BusIO_Register( 171 i2c_dev, spi_dev, ADDRBIT8_HIGH_TOREAD, LIS331_REG_REFERENCE); 172 return reference_reg.read(); 173 } 174 175 /** 176 * @brief Zero the measurement offsets while the high-pass filter is enabled 177 when not using a reference. 178 * 179 * See `enableHighPassFilter` and `setHPFReference` for more information. 180 */ 181 void Adafruit_LIS331::HPFReset(void) { 182 Adafruit_BusIO_Register reference_reset_reg = Adafruit_BusIO_Register( 183 i2c_dev, spi_dev, ADDRBIT8_HIGH_TOREAD, LIS331_REG_HP_FILTER_RESET); 184 reference_reset_reg.read(); 185 } 186 187 /** 188 * @brief Scale the acceleration measuremets from their raw value to milli-g 189 * depending on the current measurement range 190 * 191 */ 192 void Adafruit_LIS331::_scaleValues(void) {} 193 194 /** 195 * @brief Set the measurement range for the sensor 196 * 197 * @param range The measurement range to set 198 */ 199 void Adafruit_LIS331::writeRange(uint8_t range) { 200 201 Adafruit_BusIO_Register _ctrl4 = Adafruit_BusIO_Register( 202 i2c_dev, spi_dev, ADDRBIT8_HIGH_TOREAD, LIS331_REG_CTRL4, 1); 203 204 Adafruit_BusIO_RegisterBits range_bits = 205 Adafruit_BusIO_RegisterBits(&_ctrl4, 2, 4); 206 range_bits.write(range); 207 delay(15); // delay to let new setting settle 208 } 209 210 /** 211 * @brief Get the measurement range 212 * 213 * @return uint8_t The measurement range 214 */ 215 uint8_t Adafruit_LIS331::readRange(void) { 216 Adafruit_BusIO_Register _ctrl4 = Adafruit_BusIO_Register( 217 i2c_dev, spi_dev, ADDRBIT8_HIGH_TOREAD, LIS331_REG_CTRL4, 1); 218 219 Adafruit_BusIO_RegisterBits range_bits = 220 Adafruit_BusIO_RegisterBits(&_ctrl4, 2, 4); 221 222 return (uint8_t)range_bits.read(); 223 } 224 225 /******** Power mode, data rate, and Low-pass filter methods ***********/ 226 /*! 227 * @brief Sets the data rate for the LIS331 (affects power consumption) 228 * @param data_rate The new data rate to set. 229 */ 230 void Adafruit_LIS331::setDataRate(lis331_data_rate_t data_rate) { 231 int8_t dr_value = 0; 232 int8_t pm_value = 0; 233 234 lis331_mode_t new_mode = getMode(data_rate); 235 Adafruit_BusIO_Register _ctrl1 = Adafruit_BusIO_Register( 236 i2c_dev, spi_dev, ADDRBIT8_HIGH_TOREAD, LIS331_REG_CTRL1, 1); 237 Adafruit_BusIO_RegisterBits pm_bits = 238 Adafruit_BusIO_RegisterBits(&_ctrl1, 3, 5); 239 240 switch (new_mode) { 241 case LIS331_MODE_SHUTDOWN: 242 break; 243 244 case LIS331_MODE_LOW_POWER: // ODR bits are in CTRL1[7:5] (PM) 245 pm_value = ((data_rate & 0x1C)) >> 2; 246 break; 247 248 case LIS331_MODE_NORMAL: // ODR bits are in CTRL1[4:3] (DR) 249 pm_value = ((data_rate & 0x1C)) >> 2; 250 dr_value = (data_rate & 0x7); 251 252 // only Normal mode uses DR to set ODR, so we can set it here 253 Adafruit_BusIO_RegisterBits dr_bits = 254 Adafruit_BusIO_RegisterBits(&_ctrl1, 2, 3); 255 dr_bits.write(dr_value); 256 break; 257 } 258 259 pm_bits.write(pm_value); 260 } 261 262 /*! 263 * @brief Gets the data rate for the LIS331 (affects power consumption) 264 * @return Returns Data Rate value 265 */ 266 lis331_data_rate_t Adafruit_LIS331::getDataRate(void) { 267 Adafruit_BusIO_Register _ctrl1 = Adafruit_BusIO_Register( 268 i2c_dev, spi_dev, ADDRBIT8_HIGH_TOREAD, LIS331_REG_CTRL1, 1); 269 Adafruit_BusIO_RegisterBits pm_dr_bits = 270 Adafruit_BusIO_RegisterBits(&_ctrl1, 5, 3); 271 return (lis331_data_rate_t)pm_dr_bits.read(); 272 } 273 274 /** 275 * @brief Return the current power mode from the current data rate 276 * @return lis331_mode_t The currently set power mode 277 */ 278 lis331_mode_t Adafruit_LIS331::getMode(void) { 279 lis331_data_rate_t current_rate = getDataRate(); 280 return getMode(current_rate); 281 } 282 283 /** 284 * @brief Return the current power mode from a given data rate value 285 * 286 * @param data_rate The `lis331_data_rate_t` to return the `lis331_mode_t` for 287 * @return lis331_mode_t 288 */ 289 lis331_mode_t Adafruit_LIS331::getMode(lis331_data_rate_t data_rate) { 290 uint8_t pm_value = (data_rate & 0x1C) >> 2; 291 if (pm_value >= LIS331_MODE_LOW_POWER) { 292 return LIS331_MODE_LOW_POWER; 293 } 294 return (lis331_mode_t)pm_value; 295 } 296 /** 297 * @brief Set the Low Pass Filter cutoff frequency. Useful for removing high 298 * frequency noise while sensing orientation using the acceleration from 299 * gravity. 300 * 301 * **Will not work** when sensor is **in Normal mode** because the LPF cutoff 302 * bits are used to set the ODR while in Normal mode. 303 * 304 * @param cutoff The frequency above which signals will be ignored. 305 * @returns true: success false: cuttoff frequency was not set because the 306 */ 307 bool Adafruit_LIS331::setLPFCutoff(lis331_lpf_cutoff_t cutoff) { 308 309 lis331_mode_t current_mode = getMode(); 310 if (current_mode == LIS331_MODE_NORMAL) { 311 return false; 312 } 313 Adafruit_BusIO_Register _ctrl1 = Adafruit_BusIO_Register( 314 i2c_dev, spi_dev, ADDRBIT8_HIGH_TOREAD, LIS331_REG_CTRL1, 1); 315 Adafruit_BusIO_RegisterBits data_rate_bits = 316 Adafruit_BusIO_RegisterBits(&_ctrl1, 2, 3); // including LPen bit 317 318 data_rate_bits.write(cutoff); 319 return true; 320 } 321 322 /************************************************************************/ 323 /*! 324 * @brief Gets the most recent sensor event 325 * @param *event 326 * sensor event that we want to read 327 * @return true if successful 328 */ 329 bool Adafruit_LIS331::getEvent(sensors_event_t *event) { 330 /* Clear the event */ 331 memset(event, 0, sizeof(sensors_event_t)); 332 333 event->version = sizeof(sensors_event_t); 334 event->sensor_id = _sensorID; 335 event->type = SENSOR_TYPE_ACCELEROMETER; 336 event->timestamp = 0; 337 338 read(); 339 340 event->acceleration.x = x_g * SENSORS_GRAVITY_STANDARD; 341 event->acceleration.y = y_g * SENSORS_GRAVITY_STANDARD; 342 event->acceleration.z = z_g * SENSORS_GRAVITY_STANDARD; 343 344 return true; 345 } 346 347 /*! 348 * @brief Gets the sensor_t data 349 * @param *sensor 350 * sensor that we want to write data into 351 */ 352 void Adafruit_LIS331::getSensor(sensor_t *sensor) { 353 /* Clear the sensor_t object */ 354 memset(sensor, 0, sizeof(sensor_t)); 355 356 /* Insert the sensor name in the fixed length char array */ 357 strncpy(sensor->name, "LIS331", sizeof(sensor->name) - 1); 358 sensor->name[sizeof(sensor->name) - 1] = 0; 359 sensor->version = 1; 360 sensor->sensor_id = _sensorID; 361 sensor->type = SENSOR_TYPE_ACCELEROMETER; 362 sensor->min_delay = 0; 363 sensor->max_value = 0; 364 sensor->min_value = 0; 365 sensor->resolution = 0; 366 }