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:
Wed Mar 05 16:47:13 2014 +0000
Revision:
16:d6dde2318edc
Parent:
15:7620a11149b8
Child:
17:6e4232c421c0
Added data ready query commands for each independent axes.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ashleymills 15:7620a11149b8 1 #pragma once
ashleymills 15:7620a11149b8 2
ashleymills 14:0602b45ca70f 3 // Authors: Ashley Mills, Nicholas Herriot
nherriot 0:bcf2aa85d7f9 4 /* Copyright (c) 2013 Vodafone, MIT License
nherriot 0:bcf2aa85d7f9 5 *
nherriot 0:bcf2aa85d7f9 6 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
nherriot 0:bcf2aa85d7f9 7 * and associated documentation files (the "Software"), to deal in the Software without restriction,
nherriot 0:bcf2aa85d7f9 8 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
nherriot 0:bcf2aa85d7f9 9 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
nherriot 0:bcf2aa85d7f9 10 * furnished to do so, subject to the following conditions:
nherriot 0:bcf2aa85d7f9 11 *
nherriot 0:bcf2aa85d7f9 12 * The above copyright notice and this permission notice shall be included in all copies or
nherriot 0:bcf2aa85d7f9 13 * substantial portions of the Software.
nherriot 0:bcf2aa85d7f9 14 *
nherriot 0:bcf2aa85d7f9 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
nherriot 0:bcf2aa85d7f9 16 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
nherriot 0:bcf2aa85d7f9 17 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
nherriot 0:bcf2aa85d7f9 18 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
nherriot 0:bcf2aa85d7f9 19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
nherriot 0:bcf2aa85d7f9 20 */
nherriot 0:bcf2aa85d7f9 21
nherriot 0:bcf2aa85d7f9 22 // the SparkFun breakout board defaults to 1, set to 0 if SA0 jumper on the bottom of the board is set
nherriot 0:bcf2aa85d7f9 23 // see the Table 10. I2C Device Address Sequence in Freescale MMA8452Q pdf
nherriot 0:bcf2aa85d7f9 24
ashleymills 11:dfd1e0afcb7b 25
ashleymills 11:dfd1e0afcb7b 26 #define DBG(...) pc.printf(__VA_ARGS__); pc.printf("\r\n");
ashleymills 11:dfd1e0afcb7b 27 #define DBGX(...) pc.print(__VA_ARGS__);
nherriot 0:bcf2aa85d7f9 28
ashleymills 15:7620a11149b8 29 #include "mbed.h"
nherriot 0:bcf2aa85d7f9 30
nherriot 0:bcf2aa85d7f9 31 // More info on MCU Master address can be found on section 5.10.1 of http://www.freescale.com/webapp/sps/site/prod_summary.jsp?code=MMA8452Q
nherriot 0:bcf2aa85d7f9 32 #define SA0 1
nherriot 0:bcf2aa85d7f9 33 #if SA0
ashleymills 11:dfd1e0afcb7b 34 #define MMA8452_ADDRESS 0x3A // 0x1D<<1 // SA0 is high, 0x1C if low -
nherriot 0:bcf2aa85d7f9 35 #else
ashleymills 11:dfd1e0afcb7b 36 #define MMA8452_ADDRESS 0x38 // 0x1C<<1
nherriot 0:bcf2aa85d7f9 37 #endif
nherriot 0:bcf2aa85d7f9 38
nherriot 0:bcf2aa85d7f9 39 // Register descriptions found in section 6 of pdf
ashleymills 12:172540ff6b8b 40 #define MMA8452_STATUS 0x00 // Type 'read' : Status of the data registers
ashleymills 12:172540ff6b8b 41 #define MMA8452_OUT_X_MSB 0x01 // Type 'read' : x axis - MSB of 2 byte sample
ashleymills 12:172540ff6b8b 42 #define MMA8452_OUT_X_LSB 0x02 // Type 'read' : x axis - LSB of 2 byte sample
ashleymills 12:172540ff6b8b 43 #define MMA8452_OUT_Y_MSB 0x03 // Type 'read' : y axis - MSB of 2 byte sample
ashleymills 12:172540ff6b8b 44 #define MMA8452_OUT_Y_LSB 0x04 // Type 'read' : y axis - LSB of 2 byte sample
ashleymills 12:172540ff6b8b 45 #define MMA8452_OUT_Z_MSB 0x05 // Type 'read' : z axis - MSB of 2 byte sample
ashleymills 12:172540ff6b8b 46 #define MMA8452_OUT_Z_LSB 0x06 // Type 'read' : z axis - LSB of 2 byte sample
nherriot 0:bcf2aa85d7f9 47
ashleymills 12:172540ff6b8b 48 // register definitions
ashleymills 12:172540ff6b8b 49 #define MMA8452_XYZ_DATA_CFG 0x0E
ashleymills 12:172540ff6b8b 50
ashleymills 12:172540ff6b8b 51 #define MMA8452_SYSMOD 0x0B // Type 'read' : This tells you if device is active, sleep or standy 0x00=STANDBY 0x01=WAKE 0x02=SLEEP
ashleymills 12:172540ff6b8b 52 #define MMA8452_WHO_AM_I 0x0D // Type 'read' : This should return the device id of 0x2A
nherriot 0:bcf2aa85d7f9 53
ashleymills 12:172540ff6b8b 54 #define MMA8452_PL_STATUS 0x10 // Type 'read' : This shows portrait landscape mode orientation
ashleymills 12:172540ff6b8b 55 #define MMA8452_PL_CFG 0x11 // Type 'read/write' : This allows portrait landscape configuration
ashleymills 12:172540ff6b8b 56 #define MMA8452_PL_COUNT 0x12 // Type 'read' : This is the portraint landscape debounce counter
ashleymills 12:172540ff6b8b 57 #define MMA8452_PL_BF_ZCOMP 0x13 // Type 'read' :
ashleymills 12:172540ff6b8b 58 #define MMA8452_PL_THS_REG 0x14 // Type 'read' :
nherriot 0:bcf2aa85d7f9 59
ashleymills 12:172540ff6b8b 60 #define MMA8452_FF_MT_CFG 0X15 // Type 'read/write' : Freefaul motion functional block configuration
ashleymills 12:172540ff6b8b 61 #define MMA8452_FF_MT_SRC 0X16 // Type 'read' : Freefaul motion event source register
ashleymills 12:172540ff6b8b 62 #define MMA8452_FF_MT_THS 0X17 // Type 'read' : Freefaul motion threshold register
ashleymills 12:172540ff6b8b 63 #define MMA8452_FF_COUNT 0X18 // Type 'read' : Freefaul motion debouce counter
nherriot 0:bcf2aa85d7f9 64
ashleymills 12:172540ff6b8b 65 #define MMA8452_ASLP_COUNT 0x29 // Type 'read/write' : Counter settings for auto sleep
ashleymills 12:172540ff6b8b 66 #define MMA8452_CTRL_REG_1 0x2A // Type 'read/write' :
ashleymills 12:172540ff6b8b 67 #define MMA8452_CTRL_REG_2 0x2B // Type 'read/write' :
ashleymills 12:172540ff6b8b 68 #define MMA8452_CTRL_REG_3 0x2C // Type 'read/write' :
ashleymills 12:172540ff6b8b 69 #define MMA8452_CTRL_REG_4 0x2D // Type 'read/write' :
ashleymills 12:172540ff6b8b 70 #define MMA8452_CTRL_REG_5 0x2E // Type 'read/write' :
nherriot 0:bcf2aa85d7f9 71
nherriot 3:ffb0b1650ca2 72 // Defined in table 13 of the Freescale PDF
ashleymills 12:172540ff6b8b 73 /// xxx these all need to have better names
nherriot 3:ffb0b1650ca2 74 #define STANDBY 0x00 // State value returned after a SYSMOD request, it can be in state STANDBY, WAKE or SLEEP
nherriot 3:ffb0b1650ca2 75 #define WAKE 0x01 // State value returned after a SYSMOD request, it can be in state STANDBY, WAKE or SLEEP
nherriot 3:ffb0b1650ca2 76 #define SLEEP 0x02 // State value returned after a SYSMOD request, it can be in state STANDBY, WAKE or SLEEP
nherriot 3:ffb0b1650ca2 77 #define ACTIVE 0x01 // Stage value returned and set in Control Register 1, it can be STANDBY=00, or ACTIVE=01
nherriot 0:bcf2aa85d7f9 78
nherriot 0:bcf2aa85d7f9 79 #define TILT_STATUS 0x03 // Tilt Status (Read only)
nherriot 0:bcf2aa85d7f9 80 #define SRST_STATUS 0x04 // Sample Rate Status Register (Read only)
nherriot 0:bcf2aa85d7f9 81 #define SPCNT_STATUS 0x05 // Sleep Count Register (Read/Write)
nherriot 0:bcf2aa85d7f9 82 #define INTSU_STATUS 0x06 // Interrupt Setup Register
nherriot 0:bcf2aa85d7f9 83 #define MODE_STATUS 0x07 // Mode Register (Read/Write)
nherriot 0:bcf2aa85d7f9 84 #define SR_STATUS 0x08 // Auto-Wake and Active Mode Portrait/Landscape Samples per Seconds Register (Read/Write)
nherriot 0:bcf2aa85d7f9 85 #define PDET_STATUS 0x09 // Tap/Pulse Detection Register (Read/Write)
nherriot 0:bcf2aa85d7f9 86 #define PD_STATUS 0xA // Tap/Pulse Debounce Count Register (Read/Write)
nherriot 0:bcf2aa85d7f9 87
ashleymills 12:172540ff6b8b 88 // masks for enabling/disabling standby
ashleymills 11:dfd1e0afcb7b 89 #define MMA8452_ACTIVE_MASK 0x01
ashleymills 11:dfd1e0afcb7b 90 #define MMA8452_STANDBY_MASK 0xFE
ashleymills 11:dfd1e0afcb7b 91
ashleymills 12:172540ff6b8b 92 // mask for dynamic range reading and writing
ashleymills 11:dfd1e0afcb7b 93 #define MMA8452_DYNAMIC_RANGE_MASK 0xFC
ashleymills 11:dfd1e0afcb7b 94
ashleymills 12:172540ff6b8b 95 // mask and shift for data rate reading and writing
ashleymills 11:dfd1e0afcb7b 96 #define MMA8452_DATA_RATE_MASK 0xC7
ashleymills 11:dfd1e0afcb7b 97 #define MMA8452_DATA_RATE_MASK_SHIFT 0x03
ashleymills 11:dfd1e0afcb7b 98
ashleymills 12:172540ff6b8b 99 // mask and shift for general reading and writing
ashleymills 11:dfd1e0afcb7b 100 #define MMA8452_WRITE_MASK 0xFE
ashleymills 11:dfd1e0afcb7b 101 #define MMA8452_READ_MASK 0x01
ashleymills 11:dfd1e0afcb7b 102
ashleymills 12:172540ff6b8b 103 // mask and shift for bit depth reading and writing
ashleymills 11:dfd1e0afcb7b 104 #define MMA8452_BIT_DEPTH_MASK 0xFD
ashleymills 11:dfd1e0afcb7b 105 #define MMA8452_BIT_DEPTH_MASK_SHIFT 0x01
ashleymills 12:172540ff6b8b 106
ashleymills 12:172540ff6b8b 107 // status masks and shifts
ashleymills 12:172540ff6b8b 108 #define MMA8452_STATUS_ZYXDR_MASK 0x08
ashleymills 16:d6dde2318edc 109 #define MMA8452_STATUS_ZDR_MASK 0x04
ashleymills 16:d6dde2318edc 110 #define MMA8452_STATUS_YDR_MASK 0x02
ashleymills 16:d6dde2318edc 111 #define MMA8452_STATUS_XDR_MASK 0x01
ashleymills 11:dfd1e0afcb7b 112
ashleymills 10:ca9ba7ad4e94 113 class MMA8452
nherriot 0:bcf2aa85d7f9 114 {
nherriot 0:bcf2aa85d7f9 115 public:
ashleymills 10:ca9ba7ad4e94 116
ashleymills 11:dfd1e0afcb7b 117 enum DynamicRange {
ashleymills 11:dfd1e0afcb7b 118 DYNAMIC_RANGE_2G=0x00,
ashleymills 11:dfd1e0afcb7b 119 DYNAMIC_RANGE_4G,
ashleymills 11:dfd1e0afcb7b 120 DYNAMIC_RANGE_8G,
ashleymills 11:dfd1e0afcb7b 121 DYNAMIC_RANGE_UNKNOWN
ashleymills 10:ca9ba7ad4e94 122 };
nherriot 0:bcf2aa85d7f9 123
ashleymills 10:ca9ba7ad4e94 124 enum BitDepth {
ashleymills 11:dfd1e0afcb7b 125 BIT_DEPTH_12=0x00,
ashleymills 12:172540ff6b8b 126 BIT_DEPTH_8, // 1 sets fast read mode, hence the inversion
ashleymills 12:172540ff6b8b 127 BIT_DEPTH_UNKNOWN
ashleymills 10:ca9ba7ad4e94 128 };
ashleymills 11:dfd1e0afcb7b 129
ashleymills 11:dfd1e0afcb7b 130 enum DataRateHz {
ashleymills 11:dfd1e0afcb7b 131 RATE_800=0x00,
ashleymills 11:dfd1e0afcb7b 132 RATE_400,
ashleymills 11:dfd1e0afcb7b 133 RATE_200,
ashleymills 11:dfd1e0afcb7b 134 RATE_100,
ashleymills 11:dfd1e0afcb7b 135 RATE_50,
ashleymills 11:dfd1e0afcb7b 136 RATE_12_5,
ashleymills 11:dfd1e0afcb7b 137 RATE_6_25,
ashleymills 11:dfd1e0afcb7b 138 RATE_1_563,
ashleymills 11:dfd1e0afcb7b 139 RATE_UNKNOWN
ashleymills 11:dfd1e0afcb7b 140 };
ashleymills 11:dfd1e0afcb7b 141
nherriot 0:bcf2aa85d7f9 142
ashleymills 15:7620a11149b8 143 /**
ashleymills 15:7620a11149b8 144 * Create an accelerometer object connected to the specified I2C pins.
nherriot 0:bcf2aa85d7f9 145 *
nherriot 0:bcf2aa85d7f9 146 * @param sda I2C data port
ashleymills 15:7620a11149b8 147 * @param scl I2C clock port
ashleymills 15:7620a11149b8 148 * @param frequency
nherriot 0:bcf2aa85d7f9 149 *
nherriot 0:bcf2aa85d7f9 150 */
ashleymills 10:ca9ba7ad4e94 151 MMA8452(PinName sda, PinName scl, int frequency);
nherriot 0:bcf2aa85d7f9 152
ashleymills 15:7620a11149b8 153 /// Destructor
ashleymills 10:ca9ba7ad4e94 154 ~MMA8452();
nherriot 3:ffb0b1650ca2 155
ashleymills 15:7620a11149b8 156 /**
ashleymills 15:7620a11149b8 157 * Puts the MMA8452 in active mode.
ashleymills 15:7620a11149b8 158 * @return 0 on success, 1 on failure.
ashleymills 15:7620a11149b8 159 */
nherriot 0:bcf2aa85d7f9 160 int activate();
nherriot 3:ffb0b1650ca2 161
ashleymills 15:7620a11149b8 162 /**
ashleymills 15:7620a11149b8 163 * Puts the MMA8452 in standby.
ashleymills 15:7620a11149b8 164 * @return 0 on success, 1 on failure.
ashleymills 15:7620a11149b8 165 */
ashleymills 15:7620a11149b8 166 int standby();
nherriot 0:bcf2aa85d7f9 167
nherriot 0:bcf2aa85d7f9 168 /** Initialization of device MMA8452 (required)
nherriot 0:bcf2aa85d7f9 169 */
nherriot 0:bcf2aa85d7f9 170 void init();
nherriot 0:bcf2aa85d7f9 171
ashleymills 15:7620a11149b8 172 /**
ashleymills 15:7620a11149b8 173 * Read the device ID from the accelerometer (should be 0x2a)
nherriot 1:ef026bf28798 174 *
ashleymills 15:7620a11149b8 175 * @param pointer to store the ID
ashleymills 15:7620a11149b8 176 * @return 0 on success, 1 on failure.
nherriot 1:ef026bf28798 177 */
ashleymills 11:dfd1e0afcb7b 178 int getDeviceID(char* dst);
nherriot 0:bcf2aa85d7f9 179
ashleymills 12:172540ff6b8b 180 int getStatus(char* dst);
nherriot 1:ef026bf28798 181
ashleymills 12:172540ff6b8b 182 /**
ashleymills 12:172540ff6b8b 183 * Read the x,y, and z registers of the MMA8452.
nherriot 1:ef026bf28798 184 *
ashleymills 12:172540ff6b8b 185 * @param dst The destination buffer. Note that this needs to be 3 bytes for
ashleymills 12:172540ff6b8b 186 * BIT_DEPTH_8 and 6 bytes for BIT_DEPTH_12. It is upto the caller to ensure this.
ashleymills 12:172540ff6b8b 187 * @return 0 for success, and 1 for failure
nherriot 1:ef026bf28798 188 */
ashleymills 15:7620a11149b8 189 int readXYZRaw(char *dst);
ashleymills 15:7620a11149b8 190
ashleymills 15:7620a11149b8 191 /**
ashleymills 15:7620a11149b8 192 * Read the x,y, and z counts of the MMA7452.
ashleymills 15:7620a11149b8 193 */
ashleymills 13:4bd8b4cd479d 194 int readXYZCounts(int *x, int *y, int *z);
ashleymills 13:4bd8b4cd479d 195 int readXYZGravity(double *x, double *y, double *z);
ashleymills 12:172540ff6b8b 196
ashleymills 13:4bd8b4cd479d 197 int isXReady();
ashleymills 13:4bd8b4cd479d 198 int isYReady();
ashleymills 13:4bd8b4cd479d 199 int isZReady();
ashleymills 12:172540ff6b8b 200 int isXYZReady();
nherriot 0:bcf2aa85d7f9 201
ashleymills 15:7620a11149b8 202 /**
ashleymills 15:7620a11149b8 203 * Read from specified MMA8452 register.
ashleymills 12:172540ff6b8b 204 *
ashleymills 12:172540ff6b8b 205 * @param addr The internal registeraddress of the MMA8452
ashleymills 12:172540ff6b8b 206 * @return The value of the register
ashleymills 12:172540ff6b8b 207 */
ashleymills 11:dfd1e0afcb7b 208 int readRegister(char addr, char *dst);
ashleymills 11:dfd1e0afcb7b 209
ashleymills 11:dfd1e0afcb7b 210 int readRegister(char addr, char *dst, int nbytes);
nherriot 0:bcf2aa85d7f9 211
ashleymills 12:172540ff6b8b 212 /**
ashleymills 12:172540ff6b8b 213 * Write to the specified MMA8452 register.
nherriot 0:bcf2aa85d7f9 214 *
ashleymills 12:172540ff6b8b 215 * @param addr The internal register address
ashleymills 12:172540ff6b8b 216 * @param data Data to write
nherriot 0:bcf2aa85d7f9 217 */
ashleymills 11:dfd1e0afcb7b 218 int writeRegister(char addr, char data);
ashleymills 12:172540ff6b8b 219
ashleymills 12:172540ff6b8b 220 /**
ashleymills 12:172540ff6b8b 221 * Write a data buffer to the specified MMA8452 register.
ashleymills 12:172540ff6b8b 222 *
ashleymills 12:172540ff6b8b 223 * @param addr The internal register address
ashleymills 12:172540ff6b8b 224 * @param data Data buffer to write
ashleymills 12:172540ff6b8b 225 * @param nbytes The length of the data buffer to write
ashleymills 12:172540ff6b8b 226 */
ashleymills 11:dfd1e0afcb7b 227 int writeRegister(char addr, char *data, int nbytes);
ashleymills 11:dfd1e0afcb7b 228
ashleymills 11:dfd1e0afcb7b 229 int logicalANDRegister(char addr, char mask);
ashleymills 11:dfd1e0afcb7b 230 int logicalORRegister(char addr, char mask);
ashleymills 11:dfd1e0afcb7b 231 int logicalXORRegister(char addr, char mask);
nherriot 0:bcf2aa85d7f9 232
ashleymills 11:dfd1e0afcb7b 233 int setDynamicRange(DynamicRange range, int toggleActivation=1);
ashleymills 11:dfd1e0afcb7b 234 int setBitDepth(BitDepth depth, int toggleActivation=1);
ashleymills 11:dfd1e0afcb7b 235 int setDataRate(DataRateHz dataRate, int toggleActivation=1);
ashleymills 15:7620a11149b8 236
ashleymills 11:dfd1e0afcb7b 237 DynamicRange getDynamicRange();
ashleymills 11:dfd1e0afcb7b 238 DataRateHz getDataRate();
ashleymills 12:172540ff6b8b 239 BitDepth getBitDepth();
ashleymills 11:dfd1e0afcb7b 240
ashleymills 11:dfd1e0afcb7b 241 void debugRegister(char reg);
nherriot 0:bcf2aa85d7f9 242
nherriot 0:bcf2aa85d7f9 243 private:
ashleymills 10:ca9ba7ad4e94 244 int readRaw(char src, char *dst, int len);
ashleymills 11:dfd1e0afcb7b 245 int maskAndApplyRegister(char reg, char mask, char value, int toggleActivation);
ashleymills 13:4bd8b4cd479d 246
ashleymills 13:4bd8b4cd479d 247 int twelveBitToSigned(char *buf);
ashleymills 13:4bd8b4cd479d 248 int eightBitToSigned(char *buf);
ashleymills 13:4bd8b4cd479d 249 double convertCountToGravity(int count, int countsPerG);
ashleymills 16:d6dde2318edc 250 char getMaskedRegister(int reg, char mask);
ashleymills 8:89272163f395 251
ashleymills 11:dfd1e0afcb7b 252 I2C _i2c;
ashleymills 11:dfd1e0afcb7b 253 int _frequency;
ashleymills 6:f6bde04bf8be 254 int _readAddress;
ashleymills 6:f6bde04bf8be 255 int _writeAddress;
ashleymills 12:172540ff6b8b 256
ashleymills 12:172540ff6b8b 257 BitDepth _bitDepth;
ashleymills 13:4bd8b4cd479d 258 DynamicRange _dynamicRange;
nherriot 0:bcf2aa85d7f9 259
ashleymills 15:7620a11149b8 260 };