/* * Author: Jon Trulson * Copyright (c) 2015 Intel Corporation. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #pragma once #include #include #include #define H3LIS331DL_I2C_BUS 0 #define H3LIS331DL_DEFAULT_I2C_ADDR 0x18 namespace upm { /** * @brief H3LIS331DL I2C Accelerometer (400g) library * @defgroup h3lis331dl libupm-h3lis331dl * @ingroup seeed i2c accelerometer */ /** * @library h3lis331dl * @sensor h3lis331dl * @comname H3LIS331DL 3-Axis Digital Accelerometer * @altname Grove 3-Axis Digital Accelerometer (400g) * @type accelerometer * @man seeed * @web http://www.seeedstudio.com/depot/Grove-3Axis-Digital-Accelerometer400g-p-1897.html * @con i2c * * @brief API for the H3LIS331DL-based Grove 3-Axis Digital Accelerometer (400g) * * This is a high-performance, high-range accelerometer for extreme applications. * * @image html h3lis331dl.jpg * @snippet h3lis331dl.cxx Interesting */ class H3LIS331DL { public: /** * H3LIS331DL registers */ typedef enum { // Reserved bytes must not be written into as they contain // factory calibration data. Changing those values may lead to // improper functioning of the device. // 0x00-0x0E reserved REG_WHOAMI = 0x0f, // 0x10-0x1f reserved REG_REG1 = 0x20, REG_REG2 = 0x21, REG_REG3 = 0x22, REG_REG4 = 0x23, REG_REG5 = 0x24, REG_HP_FILTER_RESET = 0x25, REG_REFERENCE = 0x26, REG_STATUS = 0x27, REG_OUT_X_L = 0x28, REG_OUT_X_H = 0x29, REG_OUT_Y_L = 0x2a, REG_OUT_Y_H = 0x2b, REG_OUT_Z_L = 0x2c, REG_OUT_Z_H = 0x2d, // 0x2e, 0x2f reserved REG_INT1_CFG = 0x30, REG_INT1_SRC = 0x31, REG_INT1_THS = 0x32, REG_INT1_DUR = 0x33, REG_INT2_CFG = 0x34, REG_INT2_SRC = 0x35, REG_INT2_THS = 0x36, REG_INT2_DUR = 0x37, // 0x38-0x3f reserved } H3LIS331DL_REG_T; /** * REG1 bits */ typedef enum { REG1_XEN = 0x01, // X-axis enable REG1_YEN = 0x02, REG1_ZEN = 0x04, REG1_DR0 = 0x08, // data rate REG1_DR1 = 0x10, REG1_DR_SHIFT = 3, // DR shift REG1_PM0 = 0x20, // power mode REG1_PM1 = 0x40, REG1_PM2 = 0x80, REG1_PM_SHIFT = 5 } REG1_BITS_T; /** * REG1 DR (output rate) bits */ typedef enum { DR_50_37 = 0x0, // 50Hz output with 37Hz LPF cutoff DR_100_74 = 0x1, DR_400_292 = 0x2, DR_1000_780 = 0x3 } DR_BITS_T; /** * REG1 PM (power mode) bits */ typedef enum { PM_POWERDWN = 0x0, PM_NORMAL = 0x1, PM_LP05 = 0x2, // .5 updates/sec PM_LP1 = 0x3, // 1 update/sec PM_LP2 = 0x4, PM_LP5 = 0x5, PM_LP10 = 0x6 } PM_BITS_T; /** * REG2 bits */ typedef enum { REG2_HPCF0 = 0x01, REG2_HPCF1 = 0x02, REG2_HPCF_SHIFT = 0, REG2_HPEN1 = 0x04, REG2_HPEN2 = 0x08, REG2_FDS = 0x10, REG2_HPM0 = 0x20, REG2_HPM1 = 0x40, REG2_HPM_SHIFT = 5, REG2_BOOT = 0x80 } REG2_BITS_T; /** * REG2 HPCF (high-pass cutoff frequency) bits */ typedef enum { HPCF_8 = 0x0, HPCF_16 = 0x1, HPCF_32 = 0x2, HPCF_64 = 0x3, } HPCF_BITS_T; /** * REG2 HPM (high-pass filter mode) bits */ typedef enum { HPM_NORMAL0 = 0x0, HPM_REF = 0x1, HPM_NORMAL1 = 0x2 } HPM_BITS_T; /** * REG3 bits */ typedef enum { REG3_I1_CFG0 = 0x01, REG3_I1_CFG1 = 0x02, REG3_I1_CFG_SHIFT = 0, REG3_LIR1 = 0x04, REG3_I2_CFG0 = 0x08, REG3_I2_CFG1 = 0x10, REG3_I2_CFG_SHIFT = 3, REG3_LIR2 = 0x20, REG3_PP_OD = 0x40, REG3_IHL = 0x80 } REG3_BITS_T; /** * REG3 I1/I2 PAD control bits */ typedef enum { I_SRC = 0x0, // INT source I_OR = 0x1, // INT1 OR INT2 source I_DR = 0x2, // Data Ready I_BOOTING = 0x3 // Boot is running } I_CFG_BITS_T; /** * REG4 bits */ typedef enum { REG4_SIM = 0x01, // SPI 4 or 3 wire // bits 01,02,04 reserved REG4_FS0 = 0x10, REG4_FS1 = 0x20, REG4_FS_SHIFT = 4, REG4_BLE = 0x40, // big/little-endian REG4_BDU = 0x80 // Block data update } REG4_BITS_T; /** * REG4 FS (full scale) bits */ typedef enum { FS_100 = 0x0, // 100g scale FS_200 = 0x1, // 200g scale FS_400 = 0x3 // 400g scale } FS_BITS_T; /** * REG5 TURNON (sleep to wake) bits */ typedef enum { REG5_TURNON0 = 0x01, // turn-on mode for sleep-to-wake REG5_TURNON1 = 0x02 // bits 04-80 reserved } REG5_BITS_T; /** * STATUS bits */ typedef enum { STATUS_XDA = 0x01, // X data available STATUS_YDA = 0x02, STATUS_ZDA = 0x04, STATUS_ZYXDA = 0x08, // X, Y, and Z data available STATUS_XOR = 0x10, // X overrun STATUS_YOR = 0x20, STATUS_ZOR = 0x40, STATUS_ZYXOR = 0x80 // X, Y, and Z data overrun } STATUS_BITS_T; /** * INT1/INT2 CFG bits */ typedef enum { INT_CFG_XLIE = 0x01, // enable intr on low X event INT_CFG_XHIE = 0x02, // enable intr on high X event INT_CFG_YLIE = 0x04, INT_CFG_YHIE = 0x08, INT_CFG_ZLIE = 0x10, INT_CFG_ZHIE = 0x20, // 0x40 reserved INT_CFG_AOI = 0x80 // AND or OR combination or intrs } INT_CFG_BITS_T; /** * INT1/INT2 SRC bits */ typedef enum { INT_SRC_XL = 0x01, // X low intr event INT_SRC_XH = 0x02, // X high intr event INT_SRC_YL = 0x04, INT_SRC_YH = 0x08, INT_SRC_ZL = 0x10, INT_SRC_ZH = 0x20, INT_SRC_IA = 0x40 // Interrupt generated (active) // 0x80 reserved } INT_SRC_BITS_T; /** * H3LIS331DL constructor * * @param bus I2C bus to use * @param address Address for this device */ H3LIS331DL(int bus, uint8_t address = H3LIS331DL_DEFAULT_I2C_ADDR); /** * H3LIS331DL destructor */ ~H3LIS331DL(); /** * Sets up initial values and starts operation * * @param odr Data rate: one of the DR_BITS_T values * @param pm Power mode: one of the PM_BITS_T values * @param fs FullScale: one of the FS_BITS_T values * @return True if successful */ bool init(DR_BITS_T odr=DR_50_37, PM_BITS_T pm=PM_NORMAL, FS_BITS_T fs=FS_100); /** * Reads and returns the chip ID (WHO_AM_I register) * * @return True if successful */ uint8_t getChipID(); /** * Sets the output data rate * * @param One of the DR_BITS_T values * @return True if successful */ bool setDataRate(DR_BITS_T odr); /** * Sets the power mode * * @param One of the PM_BITS_T values * @return True if successful */ bool setPowerMode(PM_BITS_T pm); /** * Enables one or more of the 3 axes. The argument is a bitmask * composed of REG1_XEN, REG1_YEN, and/or REG1_ZEN corresponding to * the axes you want enabled. * * @param axisEnable Bitmask of axes to enable * (REG1_XEN | REG1_YEN | REG1_ZEN) * @return True if successful */ bool enableAxis(uint8_t axisEnable); /** * Sets the scaling factor to 100g, 200g, or 400g * * @param fs One of the FS_BITS_T values * @return True if successful */ bool setFullScale(FS_BITS_T fs); /** * Sets a high-pass cutoff filter * * @param val One of the HPCF_BITS_T values * @return True if successful */ bool setHPCF(HPCF_BITS_T val); /** * Sets a high-pass filter mode * * @param val One of the HPM_BITS_T values * @return True if successful */ bool setHPM(HPM_BITS_T val); /** * Boots the device. Booting the device causes internal flash * calibration values to be reloaded into the visible registers * in case they have been corrupted. This function * returns when the booting is complete. * * @return True if successful */ bool boot(); /** * Enables a high-pass filter for interrupt 1 source * * @param enable True to enable the filter, false otherwise * @return True if successful */ bool enableHPF1(bool enable); /** * Enables a high-pass filter for interrupt 2 source * * @param enable True to enable the filter, false otherwise * @return True if successful */ bool enableHPF2(bool enable); /** * Enables filtered data selection * * @param enable True to enable, false otherwise * @return True if successful */ bool enableFDS(bool enable); /** * Sets interrupts to be active low instead of high * * @param enable True to enable, false otherwise * @return True if successful */ bool setInterruptActiveLow(bool enable); /** * Sets an interrupt output mode to open drain rather than push/pull * * @param enable True to enable, false otherwise * @return True if successful */ bool setInterruptOpenDrain(bool enable); /** * Enables interrupt 1 latch * * @param enable True to enable, false otherwise * @return True if successful */ bool setInterrupt1Latch(bool enable); /** * Enables interrupt 2 latch * * @param enable True to enable, false otherwise * @return True if successful */ bool setInterrupt2Latch(bool enable); /** * Sets the interrupt 1 pad configuration * * @param val One fo the I_CFG_BITS_T values * @return True if successful */ bool setInterrupt1PadConfig(I_CFG_BITS_T val); /** * Sets the interrupt 2 pad configuration * * @param val One fo the I_CFG_BITS_T values * @return True if successful */ bool setInterrupt2PadConfig(I_CFG_BITS_T val); /** * Enables block data update. When enabled, low/high output * registers are not updated until both low and high values have * been read. * * @param enable True to enable, false otherwise * @return True if successful */ bool enableBDU(bool enable); /** * Enables big-endian output for 16b reads * * @param enable True to enable, false otherwise * @return True if successful */ bool enableBLE(bool enable); /** * Enables sleep-to-wake functionality * * @param enable True to enable, false otherwise * @return True if successful */ bool enableSleepToWake(bool enable); /** * Returns the contents of the REG_STATUS register * * @return Contents of the REG_STATUS register */ uint8_t getStatus(); /** * Sets up the interrupt 1 config register * * @param val Bitmask of desired INT_CFG_BITS_T bits * @return True if successful */ bool setInterrupt1Config(uint8_t val); /** * Sets up the interrupt 2 config register * * @param val Bitmask of desired INT_CFG_BITS_T bits * @return True if successful */ bool setInterrupt2Config(uint8_t val); /** * Sets up the interrupt 1 source register * * @param val Bitmask of desired INT_SRC_BITS_T bits * @return True if successful */ bool setInterrupt1Source(uint8_t val); /** * Sets up the interrupt 2 source register * * @param val Bitmask of desired INT_SRC_BITS_T bits * @return True if successful */ bool setInterrupt2Source(uint8_t val); /** * Sets up the interrupt 1 threshold register * * @param val Threshhold to set * @return True if successful */ bool setInterrupt1Threshold(uint8_t val); /** * Sets up the interrupt 2 threshold register * * @param val Threshhold to set * @return True if successful */ bool setInterrupt2Threshold(uint8_t val); /** * Sets up the interrupt 1 duration register * * @param val Duration to set * @return True if successful */ bool setInterrupt1Duration(uint8_t val); /** * Sets up the interrupt 2 duration register * * @param val Duration to set * @return True if successful */ bool setInterrupt2Duration(uint8_t val); /** * Reads the sensor and stores current values internally */ void update(); /** * Sets adjustment offsets for each of the axes. This can be used * for calibration. The values supplied here are subtracted * from the axis data read from the device. * * @param adjX Amount by which to correct the X-axis measurement * @param adjY Amount by which to correct the Y-axis measurement * @param adjZ Amount by which to correct the Z-axis measurement */ void setAdjustmentOffsets(int adjX, int adjY, int adjZ); /** * Gets acceleration values for each of the axes * * @param aX Returned X-axis acceleration * @param aY Returned Y-axis acceleration * @param aZ Returned Z-axis acceleration */ void getAcceleration(float *aX, float *aY, float *aZ); /** * Gets raw axis values * * @param x Returned raw X-axis value * @param y Returned raw Y-axis value * @param z Returned raw Z-axis value */ void getRawXYZ(int *x, int *y, int *z); /** * Gets adjusted axis values * * @param x Returned X-axis value * @param y Returned Y-axis value * @param z Returned Z-axis value */ void getXYZ(int *x, int *y, int *z); #ifdef SWIGJAVA /** * Gets acceleration values for each of the axes * * @return Array containing X, Y, Z acceleration values */ float *getAcceleration(); /** * Gets raw axis values * * @return Array containing X, Y, Z raw values */ int *getRawXYZ(); /** * Gets adjusted axis values * * @return Array containing X, Y, Z adjusted axis values */ int *getXYZ(); #endif /** * Provides public access to the MRAA I2C context of the class for * direct user access * * @return Reference to the class I2C context */ mraa::I2c& i2cContext() { return m_i2c; }; protected: int16_t m_rawX, m_rawY, m_rawZ; int16_t m_adjX, m_adjY, m_adjZ; mraa::I2c m_i2c; private: uint8_t m_addr; }; }