A driver for the MMA8451 3-axis Accelerometer.

Committer:
wilminc
Date:
Wed Oct 02 08:29:41 2019 +0000
Revision:
0:f1c020594c48
Child:
1:13c3035afa27
Initial Commit v1.0

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 0:f1c020594c48 5 * @version 1.0
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
wilminc 0:f1c020594c48 36 _i2c->frequency(MMA8451_I2C_CLOCK);
wilminc 0:f1c020594c48 37 init();
wilminc 0:f1c020594c48 38 }
wilminc 0:f1c020594c48 39
wilminc 0:f1c020594c48 40 MMA8451::~MMA8451() {
wilminc 0:f1c020594c48 41
wilminc 0:f1c020594c48 42 }
wilminc 0:f1c020594c48 43
wilminc 0:f1c020594c48 44 bool MMA8451::init() {
wilminc 0:f1c020594c48 45
wilminc 0:f1c020594c48 46 if(id() != 0x1A)
wilminc 0:f1c020594c48 47 return false;
wilminc 0:f1c020594c48 48
wilminc 0:f1c020594c48 49 writeRegister(MMA8451_CTRL_REG2, 0x40); // Trigger soft reset
wilminc 0:f1c020594c48 50 // RST bit in CTRL_REG2 is deasserted when boot is finished
wilminc 0:f1c020594c48 51 uint8_t content;
wilminc 0:f1c020594c48 52 while(!readRegister(MMA8451_CTRL_REG2, &content) && (content & 0x40));
wilminc 0:f1c020594c48 53 writeRegister(MMA8451_CTRL_REG1, 0x01); // Active mode
wilminc 0:f1c020594c48 54 _sens = MMA8451_SENSITIVITY_2G;
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 0:f1c020594c48 106 status |= _i2c->read(_i2cAddr, (char*)data, 1, true);
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 0:f1c020594c48 114 int status = _i2c->write(_i2cAddr, buf, 2, true);
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 0:f1c020594c48 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 0:f1c020594c48 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 0:f1c020594c48 141 uint8_t content = 0;
wilminc 0:f1c020594c48 142 uint8_t mask = 0xFE;
wilminc 0:f1c020594c48 143 if(readRegister(MMA8451_CTRL_REG1, &content))
wilminc 0:f1c020594c48 144 writeRegister(MMA8451_CTRL_REG1, content & mask);
wilminc 0:f1c020594c48 145 }
wilminc 0:f1c020594c48 146
wilminc 0:f1c020594c48 147 void MMA8451::setActiveMode() {
wilminc 0:f1c020594c48 148 uint8_t content = 0;
wilminc 0:f1c020594c48 149 uint8_t mask = 0x01;
wilminc 0:f1c020594c48 150 if(readRegister(MMA8451_CTRL_REG1, &content))
wilminc 0:f1c020594c48 151 writeRegister(MMA8451_CTRL_REG1, content | mask);
wilminc 0:f1c020594c48 152 }
wilminc 0:f1c020594c48 153
wilminc 0:f1c020594c48 154 void MMA8451::setDataRate(mma8451_dataRate_t rate) {
wilminc 0:f1c020594c48 155 uint8_t content = 0;
wilminc 0:f1c020594c48 156 uint8_t mask = (static_cast<uint8_t>(rate) << 3) & 0x38;
wilminc 0:f1c020594c48 157 if(readRegister(MMA8451_CTRL_REG1, &content))
wilminc 0:f1c020594c48 158 writeRegister(MMA8451_CTRL_REG1, content | mask);
wilminc 0:f1c020594c48 159 }
wilminc 0:f1c020594c48 160
wilminc 0:f1c020594c48 161 void MMA8451::setSensitivity(mma8451_sensitivity_t sens) {
wilminc 0:f1c020594c48 162 writeRegister(MMA8451_XYZ_DATA_CFG, sens);
wilminc 0:f1c020594c48 163 _sens = sens;
wilminc 0:f1c020594c48 164 }
wilminc 0:f1c020594c48 165
wilminc 0:f1c020594c48 166