A driver for the MMA8451 3-axis Accelerometer.

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?

UserRevisionLine numberNew 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*)&reg, 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*)&reg, 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 }