A driver for the MMA8451 3-axis Accelerometer.
MMA8451.cpp@1:13c3035afa27, 2019-10-14 (annotated)
- Committer:
- wilminc
- Date:
- Mon Oct 14 02:35:05 2019 +0000
- Revision:
- 1:13c3035afa27
- Parent:
- 0:f1c020594c48
v1.1
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
wilminc | 0:f1c020594c48 | 1 | /** |
wilminc | 0:f1c020594c48 | 2 | * @file MMA8451.cpp |
wilminc | 0:f1c020594c48 | 3 | * @brief Driver for the MMA8451 3-axis Accelerometer |
wilminc | 0:f1c020594c48 | 4 | * @author Wilmin Ceballos (wceballos) |
wilminc | 1:13c3035afa27 | 5 | * @version 1.1 |
wilminc | 0:f1c020594c48 | 6 | * @copyright MIT License |
wilminc | 0:f1c020594c48 | 7 | * |
wilminc | 0:f1c020594c48 | 8 | * Copyright (c) 2019 Wilmin Ceballos |
wilminc | 0:f1c020594c48 | 9 | * |
wilminc | 0:f1c020594c48 | 10 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
wilminc | 0:f1c020594c48 | 11 | * of this software and associated documentation files (the "Software"), to deal |
wilminc | 0:f1c020594c48 | 12 | * in the Software without restriction, including without limitation the rights |
wilminc | 0:f1c020594c48 | 13 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
wilminc | 0:f1c020594c48 | 14 | * copies of the Software, and to permit persons to whom the Software is |
wilminc | 0:f1c020594c48 | 15 | * furnished to do so, subject to the following conditions: |
wilminc | 0:f1c020594c48 | 16 | * |
wilminc | 0:f1c020594c48 | 17 | * The above copyright notice and this permission notice shall be included in all |
wilminc | 0:f1c020594c48 | 18 | * copies or substantial portions of the Software. |
wilminc | 0:f1c020594c48 | 19 | * |
wilminc | 0:f1c020594c48 | 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
wilminc | 0:f1c020594c48 | 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
wilminc | 0:f1c020594c48 | 22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
wilminc | 0:f1c020594c48 | 23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
wilminc | 0:f1c020594c48 | 24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
wilminc | 0:f1c020594c48 | 25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
wilminc | 0:f1c020594c48 | 26 | * SOFTWARE. |
wilminc | 0:f1c020594c48 | 27 | * |
wilminc | 0:f1c020594c48 | 28 | */ |
wilminc | 0:f1c020594c48 | 29 | |
wilminc | 0:f1c020594c48 | 30 | #include "MMA8451.h" |
wilminc | 0:f1c020594c48 | 31 | |
wilminc | 0:f1c020594c48 | 32 | MMA8451::MMA8451(I2C &i2c, uint8_t i2cAddr) { |
wilminc | 0:f1c020594c48 | 33 | _i2c = &i2c; |
wilminc | 0:f1c020594c48 | 34 | _i2cAddr = static_cast<uint8_t>(i2cAddr) << 1; |
wilminc | 0:f1c020594c48 | 35 | _i2c->frequency(MMA8451_I2C_CLOCK); |
wilminc | 0:f1c020594c48 | 36 | } |
wilminc | 0:f1c020594c48 | 37 | |
wilminc | 0:f1c020594c48 | 38 | MMA8451::~MMA8451() { |
wilminc | 0:f1c020594c48 | 39 | |
wilminc | 0:f1c020594c48 | 40 | } |
wilminc | 0:f1c020594c48 | 41 | |
wilminc | 0:f1c020594c48 | 42 | bool MMA8451::init() { |
wilminc | 0:f1c020594c48 | 43 | |
wilminc | 0:f1c020594c48 | 44 | if(id() != 0x1A) |
wilminc | 0:f1c020594c48 | 45 | return false; |
wilminc | 0:f1c020594c48 | 46 | |
wilminc | 0:f1c020594c48 | 47 | writeRegister(MMA8451_CTRL_REG2, 0x40); // Trigger soft reset |
wilminc | 0:f1c020594c48 | 48 | // RST bit in CTRL_REG2 is deasserted when boot is finished |
wilminc | 1:13c3035afa27 | 49 | uint8_t ctrlReg2 = 0; |
wilminc | 1:13c3035afa27 | 50 | do { |
wilminc | 1:13c3035afa27 | 51 | readRegister(MMA8451_CTRL_REG2, &ctrlReg2); |
wilminc | 1:13c3035afa27 | 52 | } while(ctrlReg2 & 0x40); |
wilminc | 1:13c3035afa27 | 53 | setActiveMode(); |
wilminc | 1:13c3035afa27 | 54 | _sens = MMA8451_SENSITIVITY_2G; // This is the default after reset |
wilminc | 0:f1c020594c48 | 55 | |
wilminc | 0:f1c020594c48 | 56 | return true; |
wilminc | 0:f1c020594c48 | 57 | } |
wilminc | 0:f1c020594c48 | 58 | |
wilminc | 0:f1c020594c48 | 59 | void MMA8451::getXYZ() { |
wilminc | 0:f1c020594c48 | 60 | char ibuf[6] = {0}; // Incoming data |
wilminc | 0:f1c020594c48 | 61 | char baseReg = MMA8451_OUT_X_MSB; |
wilminc | 0:f1c020594c48 | 62 | |
wilminc | 0:f1c020594c48 | 63 | _i2c->write(_i2cAddr, &baseReg, 1, true); |
wilminc | 0:f1c020594c48 | 64 | _i2c->read(_i2cAddr, ibuf, 6, true); |
wilminc | 0:f1c020594c48 | 65 | |
wilminc | 0:f1c020594c48 | 66 | // Data is 14 bits -> 0b00DDDDDD_DDDDDDDD |
wilminc | 0:f1c020594c48 | 67 | int16_t x_int = (static_cast<int16_t>(ibuf[0]))<<8 | ibuf[1]; x_int>>=2; |
wilminc | 0:f1c020594c48 | 68 | int16_t y_int = (static_cast<int16_t>(ibuf[2]))<<8 | ibuf[3]; y_int>>=2; |
wilminc | 0:f1c020594c48 | 69 | int16_t z_int = (static_cast<int16_t>(ibuf[4]))<<8 | ibuf[5]; z_int>>=2; |
wilminc | 0:f1c020594c48 | 70 | |
wilminc | 0:f1c020594c48 | 71 | int16_t div = 1; |
wilminc | 0:f1c020594c48 | 72 | if(_sens == MMA8451_SENSITIVITY_2G) |
wilminc | 0:f1c020594c48 | 73 | div = 4096; |
wilminc | 0:f1c020594c48 | 74 | else if(_sens == MMA8451_SENSITIVITY_4G) |
wilminc | 0:f1c020594c48 | 75 | div = 2048; |
wilminc | 0:f1c020594c48 | 76 | else if(_sens == MMA8451_SENSITIVITY_8G) |
wilminc | 0:f1c020594c48 | 77 | div = 1024; |
wilminc | 0:f1c020594c48 | 78 | |
wilminc | 0:f1c020594c48 | 79 | x = static_cast<float>(x_int) / div; |
wilminc | 0:f1c020594c48 | 80 | y = static_cast<float>(y_int) / div; |
wilminc | 0:f1c020594c48 | 81 | z = static_cast<float>(z_int) / div; |
wilminc | 0:f1c020594c48 | 82 | } |
wilminc | 0:f1c020594c48 | 83 | |
wilminc | 0:f1c020594c48 | 84 | float MMA8451::getX() { |
wilminc | 0:f1c020594c48 | 85 | x = _readAxis(MMA8451_OUT_X_MSB); |
wilminc | 0:f1c020594c48 | 86 | return x; |
wilminc | 0:f1c020594c48 | 87 | } |
wilminc | 0:f1c020594c48 | 88 | |
wilminc | 0:f1c020594c48 | 89 | float MMA8451::getY() { |
wilminc | 0:f1c020594c48 | 90 | y = _readAxis(MMA8451_OUT_Y_MSB); |
wilminc | 0:f1c020594c48 | 91 | return y; |
wilminc | 0:f1c020594c48 | 92 | } |
wilminc | 0:f1c020594c48 | 93 | |
wilminc | 0:f1c020594c48 | 94 | float MMA8451::getZ() { |
wilminc | 0:f1c020594c48 | 95 | z = _readAxis(MMA8451_OUT_Z_MSB); |
wilminc | 0:f1c020594c48 | 96 | return z; |
wilminc | 0:f1c020594c48 | 97 | } |
wilminc | 0:f1c020594c48 | 98 | |
wilminc | 0:f1c020594c48 | 99 | uint8_t MMA8451::id() { |
wilminc | 0:f1c020594c48 | 100 | readRegister(MMA8451_WHO_AM_I, &_whoami); |
wilminc | 0:f1c020594c48 | 101 | return _whoami; |
wilminc | 0:f1c020594c48 | 102 | } |
wilminc | 0:f1c020594c48 | 103 | |
wilminc | 0:f1c020594c48 | 104 | bool MMA8451::readRegister(uint8_t reg, uint8_t *data) { |
wilminc | 0:f1c020594c48 | 105 | int status = _i2c->write(_i2cAddr, (char*)®, 1, true); |
wilminc | 1:13c3035afa27 | 106 | status |= _i2c->read(_i2cAddr, (char*)data, 1, false); |
wilminc | 0:f1c020594c48 | 107 | if(status != 0) |
wilminc | 0:f1c020594c48 | 108 | return false; |
wilminc | 0:f1c020594c48 | 109 | return true; |
wilminc | 0:f1c020594c48 | 110 | } |
wilminc | 0:f1c020594c48 | 111 | |
wilminc | 0:f1c020594c48 | 112 | bool MMA8451::writeRegister(uint8_t reg, uint8_t data) { |
wilminc | 0:f1c020594c48 | 113 | char buf[2] = {reg, data}; |
wilminc | 1:13c3035afa27 | 114 | int status = _i2c->write(_i2cAddr, buf, 2, false); |
wilminc | 0:f1c020594c48 | 115 | if(status != 0) |
wilminc | 0:f1c020594c48 | 116 | return false; |
wilminc | 0:f1c020594c48 | 117 | return true; |
wilminc | 0:f1c020594c48 | 118 | } |
wilminc | 0:f1c020594c48 | 119 | |
wilminc | 0:f1c020594c48 | 120 | float MMA8451::_readAxis(uint8_t reg) { |
wilminc | 0:f1c020594c48 | 121 | char buf[2] = {0}; // Incoming data |
wilminc | 1:13c3035afa27 | 122 | |
wilminc | 0:f1c020594c48 | 123 | _i2c->write(_i2cAddr, (char*)®, 1, true); |
wilminc | 0:f1c020594c48 | 124 | _i2c->read(_i2cAddr, buf, 2, true); |
wilminc | 0:f1c020594c48 | 125 | |
wilminc | 0:f1c020594c48 | 126 | // Data is 14 bits -> 0b00DDDDDD_DDDDDDDD |
wilminc | 0:f1c020594c48 | 127 | int16_t axisData = (static_cast<int16_t>(buf[0]))<<8 | buf[1]; axisData>>=2; |
wilminc | 0:f1c020594c48 | 128 | |
wilminc | 0:f1c020594c48 | 129 | int16_t div = 1; |
wilminc | 0:f1c020594c48 | 130 | if(_sens == MMA8451_SENSITIVITY_2G) |
wilminc | 0:f1c020594c48 | 131 | div = 4096; |
wilminc | 0:f1c020594c48 | 132 | else if(_sens == MMA8451_SENSITIVITY_4G) |
wilminc | 0:f1c020594c48 | 133 | div = 2048; |
wilminc | 0:f1c020594c48 | 134 | else if(_sens == MMA8451_SENSITIVITY_8G) |
wilminc | 0:f1c020594c48 | 135 | div = 1024; |
wilminc | 1:13c3035afa27 | 136 | |
wilminc | 0:f1c020594c48 | 137 | return (static_cast<float>(axisData) / div); |
wilminc | 0:f1c020594c48 | 138 | } |
wilminc | 0:f1c020594c48 | 139 | |
wilminc | 0:f1c020594c48 | 140 | void MMA8451::setStandbyMode() { |
wilminc | 1:13c3035afa27 | 141 | uint8_t ctrlReg1; |
wilminc | 1:13c3035afa27 | 142 | const uint8_t ACTIVE_MASK = 0x01; |
wilminc | 1:13c3035afa27 | 143 | readRegister(MMA8451_CTRL_REG1, &ctrlReg1); |
wilminc | 1:13c3035afa27 | 144 | writeRegister(MMA8451_CTRL_REG1, (ctrlReg1 & ~ACTIVE_MASK)); |
wilminc | 0:f1c020594c48 | 145 | } |
wilminc | 0:f1c020594c48 | 146 | |
wilminc | 0:f1c020594c48 | 147 | void MMA8451::setActiveMode() { |
wilminc | 1:13c3035afa27 | 148 | uint8_t ctrlReg1; |
wilminc | 1:13c3035afa27 | 149 | const uint8_t ACTIVE_MASK = 0x01; |
wilminc | 1:13c3035afa27 | 150 | readRegister(MMA8451_CTRL_REG1, &ctrlReg1); |
wilminc | 1:13c3035afa27 | 151 | writeRegister(MMA8451_CTRL_REG1, (ctrlReg1 | ACTIVE_MASK)); |
wilminc | 0:f1c020594c48 | 152 | } |
wilminc | 0:f1c020594c48 | 153 | |
wilminc | 0:f1c020594c48 | 154 | void MMA8451::setDataRate(mma8451_dataRate_t rate) { |
wilminc | 1:13c3035afa27 | 155 | uint8_t ctrlReg1; |
wilminc | 1:13c3035afa27 | 156 | const uint8_t DR_MASK = 0x38; |
wilminc | 1:13c3035afa27 | 157 | uint8_t dataRate = static_cast<uint8_t>(rate) << 3; |
wilminc | 1:13c3035afa27 | 158 | |
wilminc | 1:13c3035afa27 | 159 | setStandbyMode(); |
wilminc | 1:13c3035afa27 | 160 | readRegister(MMA8451_CTRL_REG1, &ctrlReg1); |
wilminc | 1:13c3035afa27 | 161 | writeRegister(MMA8451_CTRL_REG1, (ctrlReg1 & ~DR_MASK)); |
wilminc | 1:13c3035afa27 | 162 | writeRegister(MMA8451_CTRL_REG1, (ctrlReg1 | dataRate)); |
wilminc | 1:13c3035afa27 | 163 | setActiveMode(); |
wilminc | 0:f1c020594c48 | 164 | } |
wilminc | 0:f1c020594c48 | 165 | |
wilminc | 0:f1c020594c48 | 166 | void MMA8451::setSensitivity(mma8451_sensitivity_t sens) { |
wilminc | 1:13c3035afa27 | 167 | uint8_t dataCfgReg = 0; |
wilminc | 1:13c3035afa27 | 168 | const uint8_t FS_MASK = 0x03; |
wilminc | 1:13c3035afa27 | 169 | |
wilminc | 1:13c3035afa27 | 170 | setStandbyMode(); |
wilminc | 1:13c3035afa27 | 171 | readRegister(MMA8451_XYZ_DATA_CFG, &dataCfgReg); |
wilminc | 1:13c3035afa27 | 172 | writeRegister(MMA8451_XYZ_DATA_CFG, (dataCfgReg & ~FS_MASK)); |
wilminc | 1:13c3035afa27 | 173 | writeRegister(MMA8451_XYZ_DATA_CFG, (dataCfgReg | sens)); |
wilminc | 1:13c3035afa27 | 174 | setActiveMode(); |
wilminc | 0:f1c020594c48 | 175 | _sens = sens; |
wilminc | 0:f1c020594c48 | 176 | } |