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:
Thu Oct 17 10:21:37 2013 +0000
Revision:
9:dfb0f6a7a455
Parent:
8:89272163f395
Child:
10:ca9ba7ad4e94
super clean

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
nherriot 1:ef026bf28798 23 Accelerometer_MMA8452::Accelerometer_MMA8452(PinName sda, PinName scl,int frequency) : m_i2c(sda, scl) , m_frequency(frequency)
nherriot 0:bcf2aa85d7f9 24 {
nherriot 0:bcf2aa85d7f9 25 //m_i2c.frequency(m_frequency);
ashleymills 6:f6bde04bf8be 26
ashleymills 6:f6bde04bf8be 27 // setup read and write addresses to avoid duplication
ashleymills 6:f6bde04bf8be 28 _readAddress = (MMA8452_ADDRESS<<1) | 0x01;
ashleymills 6:f6bde04bf8be 29 _writeAddress = (MMA8452_ADDRESS<<1) & 0xFE;
nherriot 0:bcf2aa85d7f9 30 }
nherriot 0:bcf2aa85d7f9 31
nherriot 0:bcf2aa85d7f9 32
nherriot 0:bcf2aa85d7f9 33 // Destroys instance
ashleymills 6:f6bde04bf8be 34 Accelerometer_MMA8452::~Accelerometer_MMA8452()
nherriot 0:bcf2aa85d7f9 35 {
nherriot 0:bcf2aa85d7f9 36
nherriot 0:bcf2aa85d7f9 37 }
nherriot 0:bcf2aa85d7f9 38
nherriot 0:bcf2aa85d7f9 39 // Setting the control register bit 1 to true to activate the MMA8452
nherriot 0:bcf2aa85d7f9 40 int Accelerometer_MMA8452::activate()
nherriot 0:bcf2aa85d7f9 41 {
ashleymills 6:f6bde04bf8be 42 // set control register 1 to active
ashleymills 6:f6bde04bf8be 43 char init[2] = {CTRL_REG_1,ACTIVE};
nherriot 3:ffb0b1650ca2 44
ashleymills 6:f6bde04bf8be 45 // perform write and return error code
ashleymills 6:f6bde04bf8be 46 return m_i2c.write(_writeAddress,init,2);
nherriot 3:ffb0b1650ca2 47 }
nherriot 3:ffb0b1650ca2 48
nherriot 3:ffb0b1650ca2 49
nherriot 5:b3d0abd97e55 50 // 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 51 // resisters from 0x01 to 0x06. When F_READ is '0' then all 6 registers will be read.
nherriot 5:b3d0abd97e55 52
ashleymills 9:dfb0f6a7a455 53 int Accelerometer_MMA8452::get_CTRL_Reg1(int* dst)
ashleymills 9:dfb0f6a7a455 54 {
ashleymills 9:dfb0f6a7a455 55 return read_reg(CTRL_REG_1,dst);
nherriot 5:b3d0abd97e55 56 }
nherriot 5:b3d0abd97e55 57
nherriot 3:ffb0b1650ca2 58 // Setting the control register bit 1 to true to activate the MMA8452
nherriot 3:ffb0b1650ca2 59 int Accelerometer_MMA8452::standby()
nherriot 3:ffb0b1650ca2 60 {
ashleymills 8:89272163f395 61 // set control register 1 to standby
ashleymills 8:89272163f395 62 char init[2] = {CTRL_REG_1,STANDBY};
nherriot 1:ef026bf28798 63
ashleymills 8:89272163f395 64 // write to the register and return the error code
ashleymills 8:89272163f395 65 return m_i2c.write(_writeAddress,init,2);
nherriot 0:bcf2aa85d7f9 66 }
nherriot 0:bcf2aa85d7f9 67
nherriot 0:bcf2aa85d7f9 68
nherriot 3:ffb0b1650ca2 69
nherriot 0:bcf2aa85d7f9 70 // Device initialization
nherriot 0:bcf2aa85d7f9 71 void Accelerometer_MMA8452::init()
nherriot 0:bcf2aa85d7f9 72 {
nherriot 0:bcf2aa85d7f9 73
nherriot 0:bcf2aa85d7f9 74 write_reg(INTSU_STATUS, 0x10); // automatic interrupt after every measurement
nherriot 0:bcf2aa85d7f9 75 write_reg(SR_STATUS, 0x00); // 120 Samples/Second
nherriot 0:bcf2aa85d7f9 76 write_reg(MODE_STATUS, 0x01); // Active Mode
nherriot 0:bcf2aa85d7f9 77
nherriot 0:bcf2aa85d7f9 78 }
nherriot 0:bcf2aa85d7f9 79
nherriot 3:ffb0b1650ca2 80 // Get real time status of device - it can be STANDBY, WAKE or SLEEP
ashleymills 9:dfb0f6a7a455 81 int Accelerometer_MMA8452::get_SystemMode(int *dst)
nherriot 3:ffb0b1650ca2 82 {
ashleymills 9:dfb0f6a7a455 83 return read_reg(SYSMOD,dst);
nherriot 3:ffb0b1650ca2 84 }
nherriot 3:ffb0b1650ca2 85
nherriot 3:ffb0b1650ca2 86
nherriot 3:ffb0b1650ca2 87
nherriot 3:ffb0b1650ca2 88 // Get real time status of device - it can be STANDBY, WAKE or SLEEP
ashleymills 9:dfb0f6a7a455 89 int Accelerometer_MMA8452::get_Status(int* dst)
nherriot 3:ffb0b1650ca2 90 {
ashleymills 9:dfb0f6a7a455 91 return read_reg(STATUS,dst);
nherriot 3:ffb0b1650ca2 92 }
nherriot 3:ffb0b1650ca2 93
nherriot 0:bcf2aa85d7f9 94
nherriot 1:ef026bf28798 95 // Get device ID
ashleymills 9:dfb0f6a7a455 96 int Accelerometer_MMA8452::get_DeviceID(int *dst)
nherriot 1:ef026bf28798 97 {
ashleymills 9:dfb0f6a7a455 98 return read_reg(WHO_AM_I,dst);
nherriot 1:ef026bf28798 99 }
nherriot 1:ef026bf28798 100
nherriot 1:ef026bf28798 101
nherriot 3:ffb0b1650ca2 102 /*
nherriot 3:ffb0b1650ca2 103 // Reads x data
nherriot 3:ffb0b1650ca2 104 int Accelerometer_MMA8452::read_x(int& xaxisLSB)
nherriot 0:bcf2aa85d7f9 105 {
nherriot 3:ffb0b1650ca2 106 char mcu_address = (MMA8452_ADDRESS<<1);
nherriot 3:ffb0b1650ca2 107 m_i2c.start();
nherriot 3:ffb0b1650ca2 108 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 109 {
nherriot 3:ffb0b1650ca2 110 return 1; // we failed to write the mcu address on the bus to initiate dialogue
nherriot 3:ffb0b1650ca2 111 }
nherriot 3:ffb0b1650ca2 112 if( m_i2c.write( OUT_X_MSB) == 0)
nherriot 3:ffb0b1650ca2 113 {
nherriot 3:ffb0b1650ca2 114 return 1; // we failed to write 'X axis LSB' to the chip
nherriot 3:ffb0b1650ca2 115 }
nherriot 3:ffb0b1650ca2 116 m_i2c.start();
nherriot 3:ffb0b1650ca2 117 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 118 {
nherriot 3:ffb0b1650ca2 119 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 120 }
nherriot 3:ffb0b1650ca2 121 xaxisLSB = m_i2c.read(0);
nherriot 3:ffb0b1650ca2 122 m_i2c.stop();
nherriot 3:ffb0b1650ca2 123 return 0;
nherriot 3:ffb0b1650ca2 124 }
nherriot 3:ffb0b1650ca2 125 */
nherriot 0:bcf2aa85d7f9 126
ashleymills 8:89272163f395 127 int Accelerometer_MMA8452::read_raw(char src, char *dst, int len) {
ashleymills 8:89272163f395 128 // this is the register we want to get data from
ashleymills 8:89272163f395 129 char register_address[1];
ashleymills 8:89272163f395 130 register_address[0] = src;
ashleymills 8:89272163f395 131
ashleymills 8:89272163f395 132 if(m_i2c.write(_writeAddress,register_address,1,true) == 0)
ashleymills 8:89272163f395 133 {
ashleymills 8:89272163f395 134 if(m_i2c.read(_readAddress,dst,len)==0)
ashleymills 8:89272163f395 135 {
ashleymills 8:89272163f395 136 return 0;
ashleymills 8:89272163f395 137 }
ashleymills 8:89272163f395 138 }
ashleymills 8:89272163f395 139
ashleymills 8:89272163f395 140 // failure case, zero array and return error
ashleymills 8:89272163f395 141 for(int i=0; i<len; i++) {
ashleymills 8:89272163f395 142 dst[i] = 0x00;
ashleymills 8:89272163f395 143 }
ashleymills 8:89272163f395 144 return 1;
ashleymills 8:89272163f395 145 }
nherriot 3:ffb0b1650ca2 146
nherriot 3:ffb0b1650ca2 147 // Reads x data. This method reads two registers containing the x-axis values from the accelerometer.
nherriot 3:ffb0b1650ca2 148 // It takes a 2 byte char array and copies the register values into the buffer. If it fails the char array
nherriot 3:ffb0b1650ca2 149 // is set to '0'. It returns '0' success '1' fail. This method does nothing to the registers - just returns
nherriot 3:ffb0b1650ca2 150 // the raw data.
nherriot 3:ffb0b1650ca2 151 //int Accelerometer_MMA8452::read_x(int& xaxisLSB)
nherriot 3:ffb0b1650ca2 152 int Accelerometer_MMA8452::read_x_raw(char *xaxis)
ashleymills 8:89272163f395 153 {
ashleymills 9:dfb0f6a7a455 154 return read_raw(OUT_X_MSB,xaxis,2);
nherriot 0:bcf2aa85d7f9 155 }
nherriot 0:bcf2aa85d7f9 156
nherriot 0:bcf2aa85d7f9 157
nherriot 3:ffb0b1650ca2 158 // Reads y data. This method reads two registers containing the x-axis values from the accelerometer.
nherriot 3:ffb0b1650ca2 159 // It takes a 2 byte char array and copies the register values into the buffer. If it fails the char array
nherriot 3:ffb0b1650ca2 160 // is set to '0'. It returns '0' success '1' fail. This method does nothing to the registers - just returns
nherriot 3:ffb0b1650ca2 161 // the raw data.
nherriot 3:ffb0b1650ca2 162
ashleymills 8:89272163f395 163 int Accelerometer_MMA8452::read_y_raw(char *yaxis) {
ashleymills 8:89272163f395 164 return read_raw(OUT_Y_MSB,yaxis,2);
nherriot 3:ffb0b1650ca2 165 }
nherriot 3:ffb0b1650ca2 166
nherriot 0:bcf2aa85d7f9 167
nherriot 3:ffb0b1650ca2 168
nherriot 3:ffb0b1650ca2 169 // Reads z data. This method reads two registers containing the x-axis values from the accelerometer.
nherriot 3:ffb0b1650ca2 170 // It takes a 2 byte char array and copies the register values into the buffer. If it fails the char array
nherriot 3:ffb0b1650ca2 171 // is set to '0'. It returns '0' success '1' fail. This method does nothing to the registers - just returns
nherriot 3:ffb0b1650ca2 172 // the raw data.
nherriot 3:ffb0b1650ca2 173
nherriot 3:ffb0b1650ca2 174 int Accelerometer_MMA8452::read_z_raw(char *zaxis)
nherriot 3:ffb0b1650ca2 175 {
ashleymills 8:89272163f395 176 return read_raw(OUT_Z_MSB,zaxis,2);
nherriot 3:ffb0b1650ca2 177 }
nherriot 0:bcf2aa85d7f9 178
nherriot 0:bcf2aa85d7f9 179
nherriot 0:bcf2aa85d7f9 180
nherriot 0:bcf2aa85d7f9 181 // Reads y data
nherriot 0:bcf2aa85d7f9 182 int Accelerometer_MMA8452::read_y()
nherriot 0:bcf2aa85d7f9 183 {
nherriot 1:ef026bf28798 184 char mcu_address = (MMA8452_ADDRESS <<1);
nherriot 0:bcf2aa85d7f9 185
nherriot 0:bcf2aa85d7f9 186 m_i2c.start(); // Start
nherriot 0:bcf2aa85d7f9 187 m_i2c.write(mcu_address); // A write to device 0x98
nherriot 0:bcf2aa85d7f9 188 m_i2c.write(OUT_Y_MSB); // Register to read
nherriot 0:bcf2aa85d7f9 189 m_i2c.start();
nherriot 0:bcf2aa85d7f9 190 m_i2c.write(mcu_address); // Read from device 0x99
nherriot 1:ef026bf28798 191 int y = m_i2c.read(0); // Read the data
nherriot 0:bcf2aa85d7f9 192 m_i2c.stop();
nherriot 0:bcf2aa85d7f9 193
nherriot 1:ef026bf28798 194 return y;
nherriot 0:bcf2aa85d7f9 195
nherriot 0:bcf2aa85d7f9 196 }
nherriot 0:bcf2aa85d7f9 197
nherriot 0:bcf2aa85d7f9 198
nherriot 0:bcf2aa85d7f9 199 // Reads z data
nherriot 0:bcf2aa85d7f9 200 int Accelerometer_MMA8452::read_z()
nherriot 0:bcf2aa85d7f9 201 {
nherriot 1:ef026bf28798 202 char mcu_address = (MMA8452_ADDRESS <<1);
nherriot 0:bcf2aa85d7f9 203
nherriot 0:bcf2aa85d7f9 204 m_i2c.start(); // Start
nherriot 0:bcf2aa85d7f9 205 m_i2c.write(mcu_address); // A write to device 0x98
nherriot 0:bcf2aa85d7f9 206 m_i2c.write(OUT_Z_MSB); // Register to read
nherriot 0:bcf2aa85d7f9 207 m_i2c.start();
nherriot 0:bcf2aa85d7f9 208 m_i2c.write(mcu_address); // Read from device 0x99
nherriot 1:ef026bf28798 209 int z = m_i2c.read(0); // Read the data
nherriot 0:bcf2aa85d7f9 210 m_i2c.stop();
nherriot 0:bcf2aa85d7f9 211
nherriot 1:ef026bf28798 212 return z;
nherriot 0:bcf2aa85d7f9 213
nherriot 0:bcf2aa85d7f9 214 }
nherriot 0:bcf2aa85d7f9 215
nherriot 0:bcf2aa85d7f9 216
nherriot 0:bcf2aa85d7f9 217 // Reads xyz
nherriot 1:ef026bf28798 218 int Accelerometer_MMA8452::read_xyz(char *x, char *y, char *z)
nherriot 1:ef026bf28798 219 {
nherriot 1:ef026bf28798 220
nherriot 1:ef026bf28798 221
nherriot 1:ef026bf28798 222 char mcu_address = (MMA8452_ADDRESS <<1);
nherriot 1:ef026bf28798 223 char register_buffer[6] ={0,0,0,0,0,0};
nherriot 1:ef026bf28798 224 const char Addr_X = OUT_X_MSB;
nherriot 1:ef026bf28798 225 m_i2c.write(mcu_address); // A write to device 0x98
nherriot 1:ef026bf28798 226 m_i2c.write(MMA8452_ADDRESS, &Addr_X, 1); // Pointer to the OUT_X_MSB register
nherriot 1:ef026bf28798 227
nherriot 1:ef026bf28798 228 if(m_i2c.write(mcu_address,&Addr_X,1) == 0)
nherriot 1:ef026bf28798 229 {
nherriot 1:ef026bf28798 230 if(m_i2c.read(mcu_address,register_buffer,6) == 0)
nherriot 1:ef026bf28798 231 {
nherriot 1:ef026bf28798 232 *x = register_buffer[1];
nherriot 1:ef026bf28798 233 *y = register_buffer[3];
nherriot 1:ef026bf28798 234 *z = register_buffer[5];
nherriot 1:ef026bf28798 235 return 0; // yahoooooo
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 1:ef026bf28798 241 }
nherriot 1:ef026bf28798 242 else
nherriot 1:ef026bf28798 243 {
nherriot 1:ef026bf28798 244 return 1; // failed oh nooo!
nherriot 1:ef026bf28798 245 }
nherriot 0:bcf2aa85d7f9 246
nherriot 1:ef026bf28798 247 }
nherriot 0:bcf2aa85d7f9 248
nherriot 0:bcf2aa85d7f9 249 // Write register (The device must be placed in Standby Mode to change the value of the registers)
nherriot 0:bcf2aa85d7f9 250 void Accelerometer_MMA8452::write_reg(char addr, char data)
nherriot 0:bcf2aa85d7f9 251 {
nherriot 0:bcf2aa85d7f9 252
nherriot 0:bcf2aa85d7f9 253 char cmd[2] = {0, 0};
nherriot 0:bcf2aa85d7f9 254
nherriot 0:bcf2aa85d7f9 255 cmd[0] = MODE_STATUS;
nherriot 0:bcf2aa85d7f9 256 cmd[1] = 0x00; // Standby Mode on
nherriot 0:bcf2aa85d7f9 257 m_i2c.write(MMA8452_ADDRESS, cmd, 2);
nherriot 0:bcf2aa85d7f9 258
nherriot 0:bcf2aa85d7f9 259 cmd[0] = addr;
nherriot 0:bcf2aa85d7f9 260 cmd[1] = data; // New value of the register
nherriot 0:bcf2aa85d7f9 261 m_i2c.write(MMA8452_ADDRESS, cmd, 2);
nherriot 0:bcf2aa85d7f9 262
nherriot 0:bcf2aa85d7f9 263 cmd[0] = MODE_STATUS;
nherriot 0:bcf2aa85d7f9 264 cmd[1] = 0x01; // Active Mode on
nherriot 0:bcf2aa85d7f9 265 m_i2c.write(MMA8452_ADDRESS, cmd, 2);
nherriot 0:bcf2aa85d7f9 266
nherriot 0:bcf2aa85d7f9 267 }
nherriot 0:bcf2aa85d7f9 268
nherriot 0:bcf2aa85d7f9 269
nherriot 0:bcf2aa85d7f9 270
nherriot 0:bcf2aa85d7f9 271 // Read from specified MMA7660FC register
ashleymills 9:dfb0f6a7a455 272 int Accelerometer_MMA8452::read_reg(char addr, int *dst)
nherriot 0:bcf2aa85d7f9 273 {
nherriot 0:bcf2aa85d7f9 274
ashleymills 8:89272163f395 275 m_i2c.start();
ashleymills 8:89272163f395 276 if( m_i2c.write(_writeAddress) == 0)
ashleymills 8:89272163f395 277 {
ashleymills 8:89272163f395 278 return 1; // we failed to write the mcu address on the bus to initiate dialogue
ashleymills 8:89272163f395 279 }
ashleymills 9:dfb0f6a7a455 280 if( m_i2c.write(addr) == 0)
ashleymills 8:89272163f395 281 {
ashleymills 8:89272163f395 282 return 1; // we failed to write 'status' to the chip
ashleymills 8:89272163f395 283 }
ashleymills 8:89272163f395 284 m_i2c.start();
ashleymills 8:89272163f395 285 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 286 {
ashleymills 8:89272163f395 287 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 288 }
ashleymills 9:dfb0f6a7a455 289 *dst = m_i2c.read(0);
ashleymills 8:89272163f395 290 m_i2c.stop();
nherriot 0:bcf2aa85d7f9 291
ashleymills 9:dfb0f6a7a455 292 return 0;
nherriot 0:bcf2aa85d7f9 293
nherriot 0:bcf2aa85d7f9 294 }
nherriot 0:bcf2aa85d7f9 295
nherriot 0:bcf2aa85d7f9 296
nherriot 0:bcf2aa85d7f9 297
nherriot 0:bcf2aa85d7f9 298
nherriot 0:bcf2aa85d7f9 299
nherriot 0:bcf2aa85d7f9 300