Library for driving the MMA8452 accelerometer over I2C

Dependents:   MMA8452_Test MMA8452_Demo Dualing_Tanks IMU-Controlled_MP3_Player ... more

Here is a simple example:

#include "mbed.h"
#include "MMA8452.h"

int main() {
   Serial pc(USBTX,USBRX);
   pc.baud(115200);
   double x = 0, y = 0, z = 0;

   MMA8452 acc(p28, p27, 40000);
   acc.setBitDepth(MMA8452::BIT_DEPTH_12);
   acc.setDynamicRange(MMA8452::DYNAMIC_RANGE_4G);
   acc.setDataRate(MMA8452::RATE_100);
   
   while(1) {
      if(!acc.isXYZReady()) {
         wait(0.01);
         continue;
      }
      acc.readXYZGravity(&x,&y,&z);
      pc.printf("Gravities: %lf %lf %lf\r\n",x,y,z);
   }
}

An easy way to test that this actually works is to run the loop above and hold the MMA8452 parallel to the ground along the respective axis (and upsidedown in each axis). You will see 1G on the respective axis and 0G on the others.

Committer:
ashleymills
Date:
Tue Mar 04 11:14:34 2014 +0000
Revision:
10:ca9ba7ad4e94
Parent:
9:dfb0f6a7a455
Child:
11:dfd1e0afcb7b
Some minor changes

Who changed what in which revision?

UserRevisionLine numberNew contents of line
nherriot 0:bcf2aa85d7f9 1 // Author: Nicholas Herriot
nherriot 0:bcf2aa85d7f9 2 /* Copyright (c) 2013 Vodafone, MIT License
nherriot 0:bcf2aa85d7f9 3 *
nherriot 0:bcf2aa85d7f9 4 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
nherriot 0:bcf2aa85d7f9 5 * and associated documentation files (the "Software"), to deal in the Software without restriction,
nherriot 0:bcf2aa85d7f9 6 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
nherriot 0:bcf2aa85d7f9 7 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
nherriot 0:bcf2aa85d7f9 8 * furnished to do so, subject to the following conditions:
nherriot 0:bcf2aa85d7f9 9 *
nherriot 0:bcf2aa85d7f9 10 * The above copyright notice and this permission notice shall be included in all copies or
nherriot 0:bcf2aa85d7f9 11 * substantial portions of the Software.
nherriot 0:bcf2aa85d7f9 12 *
nherriot 0:bcf2aa85d7f9 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
nherriot 0:bcf2aa85d7f9 14 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
nherriot 0:bcf2aa85d7f9 15 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
nherriot 0:bcf2aa85d7f9 16 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
nherriot 0:bcf2aa85d7f9 17 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
nherriot 0:bcf2aa85d7f9 18 */
nherriot 0:bcf2aa85d7f9 19
nherriot 0:bcf2aa85d7f9 20 # include "MMA8452.h"
nherriot 0:bcf2aa85d7f9 21
nherriot 0:bcf2aa85d7f9 22 // Connect module at I2C address using I2C port pins sda and scl
ashleymills 10:ca9ba7ad4e94 23 MMA8452::MMA8452(PinName sda, PinName scl,int frequency) : m_i2c(sda, scl) , m_frequency(frequency) {
nherriot 0:bcf2aa85d7f9 24 //m_i2c.frequency(m_frequency);
ashleymills 6:f6bde04bf8be 25
ashleymills 6:f6bde04bf8be 26 // setup read and write addresses to avoid duplication
ashleymills 6:f6bde04bf8be 27 _readAddress = (MMA8452_ADDRESS<<1) | 0x01;
ashleymills 6:f6bde04bf8be 28 _writeAddress = (MMA8452_ADDRESS<<1) & 0xFE;
nherriot 0:bcf2aa85d7f9 29 }
nherriot 0:bcf2aa85d7f9 30
nherriot 0:bcf2aa85d7f9 31
nherriot 0:bcf2aa85d7f9 32 // Destroys instance
ashleymills 10:ca9ba7ad4e94 33 MMA8452::~MMA8452() {}
nherriot 0:bcf2aa85d7f9 34
nherriot 0:bcf2aa85d7f9 35 // Setting the control register bit 1 to true to activate the MMA8452
ashleymills 10:ca9ba7ad4e94 36 int MMA8452::activate() {
ashleymills 6:f6bde04bf8be 37 // set control register 1 to active
ashleymills 6:f6bde04bf8be 38 char init[2] = {CTRL_REG_1,ACTIVE};
nherriot 3:ffb0b1650ca2 39
ashleymills 6:f6bde04bf8be 40 // perform write and return error code
ashleymills 6:f6bde04bf8be 41 return m_i2c.write(_writeAddress,init,2);
nherriot 3:ffb0b1650ca2 42 }
nherriot 3:ffb0b1650ca2 43
nherriot 3:ffb0b1650ca2 44
nherriot 5:b3d0abd97e55 45 // Get 'Fast Read Mode' called F_READ. If bit 1 is set '1' then F_READ is active. Fast read will skip LSB when reading xyz
nherriot 5:b3d0abd97e55 46 // resisters from 0x01 to 0x06. When F_READ is '0' then all 6 registers will be read.
nherriot 5:b3d0abd97e55 47
ashleymills 10:ca9ba7ad4e94 48 int MMA8452::get_CTRL_Reg1(int* dst)
ashleymills 9:dfb0f6a7a455 49 {
ashleymills 10:ca9ba7ad4e94 50 return readRegister(CTRL_REG_1,dst);
nherriot 5:b3d0abd97e55 51 }
nherriot 5:b3d0abd97e55 52
nherriot 3:ffb0b1650ca2 53 // Setting the control register bit 1 to true to activate the MMA8452
ashleymills 10:ca9ba7ad4e94 54 int MMA8452::standby()
nherriot 3:ffb0b1650ca2 55 {
ashleymills 8:89272163f395 56 // set control register 1 to standby
ashleymills 8:89272163f395 57 char init[2] = {CTRL_REG_1,STANDBY};
nherriot 1:ef026bf28798 58
ashleymills 8:89272163f395 59 // write to the register and return the error code
ashleymills 8:89272163f395 60 return m_i2c.write(_writeAddress,init,2);
nherriot 0:bcf2aa85d7f9 61 }
nherriot 0:bcf2aa85d7f9 62
nherriot 0:bcf2aa85d7f9 63
nherriot 3:ffb0b1650ca2 64
nherriot 0:bcf2aa85d7f9 65 // Device initialization
ashleymills 10:ca9ba7ad4e94 66 void MMA8452::init()
nherriot 0:bcf2aa85d7f9 67 {
nherriot 0:bcf2aa85d7f9 68
ashleymills 10:ca9ba7ad4e94 69 writeRegister(INTSU_STATUS, 0x10); // automatic interrupt after every measurement
ashleymills 10:ca9ba7ad4e94 70 writeRegister(SR_STATUS, 0x00); // 120 Samples/Second
ashleymills 10:ca9ba7ad4e94 71 writeRegister(MODE_STATUS, 0x01); // Active Mode
nherriot 0:bcf2aa85d7f9 72
nherriot 0:bcf2aa85d7f9 73 }
nherriot 0:bcf2aa85d7f9 74
nherriot 3:ffb0b1650ca2 75 // Get real time status of device - it can be STANDBY, WAKE or SLEEP
ashleymills 10:ca9ba7ad4e94 76 int MMA8452::getSystemMode(int *dst)
nherriot 3:ffb0b1650ca2 77 {
ashleymills 10:ca9ba7ad4e94 78 return readRegister(SYSMOD,dst);
nherriot 3:ffb0b1650ca2 79 }
nherriot 3:ffb0b1650ca2 80
nherriot 3:ffb0b1650ca2 81
nherriot 3:ffb0b1650ca2 82
nherriot 3:ffb0b1650ca2 83 // Get real time status of device - it can be STANDBY, WAKE or SLEEP
ashleymills 10:ca9ba7ad4e94 84 int MMA8452::getStatus(int* dst)
nherriot 3:ffb0b1650ca2 85 {
ashleymills 10:ca9ba7ad4e94 86 return readRegister(STATUS,dst);
nherriot 3:ffb0b1650ca2 87 }
nherriot 3:ffb0b1650ca2 88
nherriot 0:bcf2aa85d7f9 89
nherriot 1:ef026bf28798 90 // Get device ID
ashleymills 10:ca9ba7ad4e94 91 int MMA8452::getDeviceID(int *dst)
nherriot 1:ef026bf28798 92 {
ashleymills 10:ca9ba7ad4e94 93 return readRegister(WHO_AM_I,dst);
nherriot 1:ef026bf28798 94 }
nherriot 1:ef026bf28798 95
nherriot 1:ef026bf28798 96
nherriot 3:ffb0b1650ca2 97 /*
nherriot 3:ffb0b1650ca2 98 // Reads x data
ashleymills 10:ca9ba7ad4e94 99 int MMA8452::read_x(int& xaxisLSB)
nherriot 0:bcf2aa85d7f9 100 {
nherriot 3:ffb0b1650ca2 101 char mcu_address = (MMA8452_ADDRESS<<1);
nherriot 3:ffb0b1650ca2 102 m_i2c.start();
nherriot 3:ffb0b1650ca2 103 if( m_i2c.write( mcu_address & 0xFE) == 0) // just good practice to force bit 1 to a '0' by ANDing with 0xFE
nherriot 3:ffb0b1650ca2 104 {
nherriot 3:ffb0b1650ca2 105 return 1; // we failed to write the mcu address on the bus to initiate dialogue
nherriot 3:ffb0b1650ca2 106 }
nherriot 3:ffb0b1650ca2 107 if( m_i2c.write( OUT_X_MSB) == 0)
nherriot 3:ffb0b1650ca2 108 {
nherriot 3:ffb0b1650ca2 109 return 1; // we failed to write 'X axis LSB' to the chip
nherriot 3:ffb0b1650ca2 110 }
nherriot 3:ffb0b1650ca2 111 m_i2c.start();
nherriot 3:ffb0b1650ca2 112 if( m_i2c.write( mcu_address | 0x01) == 0) // this is asking to read the slave mcu address - even though it's a 'write' method!!! Crap API...
nherriot 3:ffb0b1650ca2 113 {
nherriot 3:ffb0b1650ca2 114 return 1; // we failed to request a read from that mcu - this really is just writing the mcu vaule on the bus
nherriot 3:ffb0b1650ca2 115 }
nherriot 3:ffb0b1650ca2 116 xaxisLSB = m_i2c.read(0);
nherriot 3:ffb0b1650ca2 117 m_i2c.stop();
nherriot 3:ffb0b1650ca2 118 return 0;
nherriot 3:ffb0b1650ca2 119 }
nherriot 3:ffb0b1650ca2 120 */
nherriot 0:bcf2aa85d7f9 121
ashleymills 10:ca9ba7ad4e94 122 int MMA8452::readRaw(char src, char *dst, int len) {
ashleymills 8:89272163f395 123 // this is the register we want to get data from
ashleymills 8:89272163f395 124 char register_address[1];
ashleymills 8:89272163f395 125 register_address[0] = src;
ashleymills 8:89272163f395 126
ashleymills 8:89272163f395 127 if(m_i2c.write(_writeAddress,register_address,1,true) == 0)
ashleymills 8:89272163f395 128 {
ashleymills 8:89272163f395 129 if(m_i2c.read(_readAddress,dst,len)==0)
ashleymills 8:89272163f395 130 {
ashleymills 8:89272163f395 131 return 0;
ashleymills 8:89272163f395 132 }
ashleymills 8:89272163f395 133 }
ashleymills 8:89272163f395 134
ashleymills 8:89272163f395 135 // failure case, zero array and return error
ashleymills 8:89272163f395 136 for(int i=0; i<len; i++) {
ashleymills 8:89272163f395 137 dst[i] = 0x00;
ashleymills 8:89272163f395 138 }
ashleymills 8:89272163f395 139 return 1;
ashleymills 8:89272163f395 140 }
nherriot 3:ffb0b1650ca2 141
nherriot 3:ffb0b1650ca2 142 // Reads x data. This method reads two registers containing the x-axis values from the accelerometer.
nherriot 3:ffb0b1650ca2 143 // It takes a 2 byte char array and copies the register values into the buffer. If it fails the char array
nherriot 3:ffb0b1650ca2 144 // is set to '0'. It returns '0' success '1' fail. This method does nothing to the registers - just returns
nherriot 3:ffb0b1650ca2 145 // the raw data.
ashleymills 10:ca9ba7ad4e94 146 //int MMA8452::read_x(int& xaxisLSB)
ashleymills 10:ca9ba7ad4e94 147 int MMA8452::readRawX(char *xaxis)
ashleymills 8:89272163f395 148 {
ashleymills 10:ca9ba7ad4e94 149 return readRaw(OUT_X_MSB,xaxis,2);
nherriot 0:bcf2aa85d7f9 150 }
nherriot 0:bcf2aa85d7f9 151
nherriot 0:bcf2aa85d7f9 152
nherriot 3:ffb0b1650ca2 153 // Reads y data. This method reads two registers containing the x-axis values from the accelerometer.
nherriot 3:ffb0b1650ca2 154 // It takes a 2 byte char array and copies the register values into the buffer. If it fails the char array
nherriot 3:ffb0b1650ca2 155 // is set to '0'. It returns '0' success '1' fail. This method does nothing to the registers - just returns
nherriot 3:ffb0b1650ca2 156 // the raw data.
nherriot 3:ffb0b1650ca2 157
ashleymills 10:ca9ba7ad4e94 158 int MMA8452::readRawY(char *yaxis) {
ashleymills 10:ca9ba7ad4e94 159 return readRaw(OUT_Y_MSB,yaxis,2);
nherriot 3:ffb0b1650ca2 160 }
nherriot 3:ffb0b1650ca2 161
nherriot 0:bcf2aa85d7f9 162
nherriot 3:ffb0b1650ca2 163
nherriot 3:ffb0b1650ca2 164 // Reads z data. This method reads two registers containing the x-axis values from the accelerometer.
nherriot 3:ffb0b1650ca2 165 // It takes a 2 byte char array and copies the register values into the buffer. If it fails the char array
nherriot 3:ffb0b1650ca2 166 // is set to '0'. It returns '0' success '1' fail. This method does nothing to the registers - just returns
nherriot 3:ffb0b1650ca2 167 // the raw data.
nherriot 3:ffb0b1650ca2 168
ashleymills 10:ca9ba7ad4e94 169 int MMA8452::readRawZ(char *zaxis)
nherriot 3:ffb0b1650ca2 170 {
ashleymills 10:ca9ba7ad4e94 171 return readRaw(OUT_Z_MSB,zaxis,2);
nherriot 3:ffb0b1650ca2 172 }
nherriot 0:bcf2aa85d7f9 173
nherriot 0:bcf2aa85d7f9 174
nherriot 0:bcf2aa85d7f9 175
nherriot 0:bcf2aa85d7f9 176 // Reads y data
ashleymills 10:ca9ba7ad4e94 177 int MMA8452::read_y()
nherriot 0:bcf2aa85d7f9 178 {
nherriot 1:ef026bf28798 179 char mcu_address = (MMA8452_ADDRESS <<1);
nherriot 0:bcf2aa85d7f9 180
nherriot 0:bcf2aa85d7f9 181 m_i2c.start(); // Start
nherriot 0:bcf2aa85d7f9 182 m_i2c.write(mcu_address); // A write to device 0x98
nherriot 0:bcf2aa85d7f9 183 m_i2c.write(OUT_Y_MSB); // Register to read
nherriot 0:bcf2aa85d7f9 184 m_i2c.start();
nherriot 0:bcf2aa85d7f9 185 m_i2c.write(mcu_address); // Read from device 0x99
nherriot 1:ef026bf28798 186 int y = m_i2c.read(0); // Read the data
nherriot 0:bcf2aa85d7f9 187 m_i2c.stop();
nherriot 0:bcf2aa85d7f9 188
nherriot 1:ef026bf28798 189 return y;
nherriot 0:bcf2aa85d7f9 190
nherriot 0:bcf2aa85d7f9 191 }
nherriot 0:bcf2aa85d7f9 192
nherriot 0:bcf2aa85d7f9 193
nherriot 0:bcf2aa85d7f9 194 // Reads z data
ashleymills 10:ca9ba7ad4e94 195 int MMA8452::read_z()
nherriot 0:bcf2aa85d7f9 196 {
nherriot 1:ef026bf28798 197 char mcu_address = (MMA8452_ADDRESS <<1);
nherriot 0:bcf2aa85d7f9 198
nherriot 0:bcf2aa85d7f9 199 m_i2c.start(); // Start
nherriot 0:bcf2aa85d7f9 200 m_i2c.write(mcu_address); // A write to device 0x98
nherriot 0:bcf2aa85d7f9 201 m_i2c.write(OUT_Z_MSB); // Register to read
nherriot 0:bcf2aa85d7f9 202 m_i2c.start();
nherriot 0:bcf2aa85d7f9 203 m_i2c.write(mcu_address); // Read from device 0x99
nherriot 1:ef026bf28798 204 int z = m_i2c.read(0); // Read the data
nherriot 0:bcf2aa85d7f9 205 m_i2c.stop();
nherriot 0:bcf2aa85d7f9 206
nherriot 1:ef026bf28798 207 return z;
nherriot 0:bcf2aa85d7f9 208
nherriot 0:bcf2aa85d7f9 209 }
nherriot 0:bcf2aa85d7f9 210
nherriot 0:bcf2aa85d7f9 211
nherriot 0:bcf2aa85d7f9 212 // Reads xyz
ashleymills 10:ca9ba7ad4e94 213 int MMA8452::readRawXYZ(char *x, char *y, char *z)
nherriot 1:ef026bf28798 214 {
nherriot 1:ef026bf28798 215
nherriot 1:ef026bf28798 216
nherriot 1:ef026bf28798 217 char mcu_address = (MMA8452_ADDRESS <<1);
nherriot 1:ef026bf28798 218 char register_buffer[6] ={0,0,0,0,0,0};
nherriot 1:ef026bf28798 219 const char Addr_X = OUT_X_MSB;
nherriot 1:ef026bf28798 220 m_i2c.write(mcu_address); // A write to device 0x98
nherriot 1:ef026bf28798 221 m_i2c.write(MMA8452_ADDRESS, &Addr_X, 1); // Pointer to the OUT_X_MSB register
nherriot 1:ef026bf28798 222
nherriot 1:ef026bf28798 223 if(m_i2c.write(mcu_address,&Addr_X,1) == 0)
nherriot 1:ef026bf28798 224 {
nherriot 1:ef026bf28798 225 if(m_i2c.read(mcu_address,register_buffer,6) == 0)
nherriot 1:ef026bf28798 226 {
nherriot 1:ef026bf28798 227 *x = register_buffer[1];
nherriot 1:ef026bf28798 228 *y = register_buffer[3];
nherriot 1:ef026bf28798 229 *z = register_buffer[5];
nherriot 1:ef026bf28798 230 return 0; // yahoooooo
nherriot 1:ef026bf28798 231 }
nherriot 1:ef026bf28798 232 else
nherriot 1:ef026bf28798 233 {
nherriot 1:ef026bf28798 234 return 1; // failed oh nooo!
nherriot 1:ef026bf28798 235 }
nherriot 1:ef026bf28798 236 }
nherriot 1:ef026bf28798 237 else
nherriot 1:ef026bf28798 238 {
nherriot 1:ef026bf28798 239 return 1; // failed oh nooo!
nherriot 1:ef026bf28798 240 }
nherriot 0:bcf2aa85d7f9 241
nherriot 1:ef026bf28798 242 }
nherriot 0:bcf2aa85d7f9 243
nherriot 0:bcf2aa85d7f9 244 // Write register (The device must be placed in Standby Mode to change the value of the registers)
ashleymills 10:ca9ba7ad4e94 245 void MMA8452::writeRegister(char addr, char data)
nherriot 0:bcf2aa85d7f9 246 {
nherriot 0:bcf2aa85d7f9 247
nherriot 0:bcf2aa85d7f9 248 char cmd[2] = {0, 0};
nherriot 0:bcf2aa85d7f9 249
nherriot 0:bcf2aa85d7f9 250 cmd[0] = MODE_STATUS;
nherriot 0:bcf2aa85d7f9 251 cmd[1] = 0x00; // Standby Mode on
nherriot 0:bcf2aa85d7f9 252 m_i2c.write(MMA8452_ADDRESS, cmd, 2);
nherriot 0:bcf2aa85d7f9 253
nherriot 0:bcf2aa85d7f9 254 cmd[0] = addr;
nherriot 0:bcf2aa85d7f9 255 cmd[1] = data; // New value of the register
nherriot 0:bcf2aa85d7f9 256 m_i2c.write(MMA8452_ADDRESS, cmd, 2);
nherriot 0:bcf2aa85d7f9 257
nherriot 0:bcf2aa85d7f9 258 cmd[0] = MODE_STATUS;
nherriot 0:bcf2aa85d7f9 259 cmd[1] = 0x01; // Active Mode on
nherriot 0:bcf2aa85d7f9 260 m_i2c.write(MMA8452_ADDRESS, cmd, 2);
nherriot 0:bcf2aa85d7f9 261
nherriot 0:bcf2aa85d7f9 262 }
nherriot 0:bcf2aa85d7f9 263
nherriot 0:bcf2aa85d7f9 264 // Read from specified MMA7660FC register
ashleymills 10:ca9ba7ad4e94 265 int MMA8452::readRegister(char addr, int *dst)
nherriot 0:bcf2aa85d7f9 266 {
nherriot 0:bcf2aa85d7f9 267
ashleymills 8:89272163f395 268 m_i2c.start();
ashleymills 8:89272163f395 269 if( m_i2c.write(_writeAddress) == 0)
ashleymills 8:89272163f395 270 {
ashleymills 8:89272163f395 271 return 1; // we failed to write the mcu address on the bus to initiate dialogue
ashleymills 8:89272163f395 272 }
ashleymills 9:dfb0f6a7a455 273 if( m_i2c.write(addr) == 0)
ashleymills 8:89272163f395 274 {
ashleymills 8:89272163f395 275 return 1; // we failed to write 'status' to the chip
ashleymills 8:89272163f395 276 }
ashleymills 8:89272163f395 277 m_i2c.start();
ashleymills 8:89272163f395 278 if( m_i2c.write(_readAddress) == 0) // this is asking to read the slave mcu address - even though it's a 'write' method!!! Crap API...
ashleymills 8:89272163f395 279 {
ashleymills 8:89272163f395 280 return 1; // we failed to request a read from that mcu - this really is just writing the mcu vaule on the bus
ashleymills 8:89272163f395 281 }
ashleymills 9:dfb0f6a7a455 282 *dst = m_i2c.read(0);
ashleymills 8:89272163f395 283 m_i2c.stop();
nherriot 0:bcf2aa85d7f9 284
ashleymills 9:dfb0f6a7a455 285 return 0;
nherriot 0:bcf2aa85d7f9 286
nherriot 0:bcf2aa85d7f9 287 }