Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of MMA8452 by
MMA8452.cpp@1:6aa59bbc3e38, 2015-05-11 (annotated)
- Committer:
- arthuryuan
- Date:
- Mon May 11 03:00:46 2015 +0000
- Revision:
- 1:6aa59bbc3e38
- Parent:
- 0:df3b9e41edf3
landscape/portrait startup
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
eencae | 0:df3b9e41edf3 | 1 | /** |
eencae | 0:df3b9e41edf3 | 2 | @file MMA8452.cpp |
eencae | 0:df3b9e41edf3 | 3 | |
eencae | 0:df3b9e41edf3 | 4 | @brief Member functions implementations |
eencae | 0:df3b9e41edf3 | 5 | |
eencae | 0:df3b9e41edf3 | 6 | */ |
eencae | 0:df3b9e41edf3 | 7 | #include "mbed.h" |
eencae | 0:df3b9e41edf3 | 8 | #include "MMA8452.h" |
eencae | 0:df3b9e41edf3 | 9 | |
eencae | 0:df3b9e41edf3 | 10 | MMA8452:: MMA8452(PinName sdaPin, PinName sclPin) |
eencae | 0:df3b9e41edf3 | 11 | { |
eencae | 0:df3b9e41edf3 | 12 | i2c = new I2C(sdaPin,sclPin); // create new I2C instance and initialise |
eencae | 0:df3b9e41edf3 | 13 | i2c->frequency(400000); // I2C Fast Mode - 400kHz |
eencae | 0:df3b9e41edf3 | 14 | leds = new BusOut(LED4,LED3,LED2,LED1); // for debug |
eencae | 0:df3b9e41edf3 | 15 | } |
eencae | 0:df3b9e41edf3 | 16 | |
eencae | 0:df3b9e41edf3 | 17 | void MMA8452::init() |
eencae | 0:df3b9e41edf3 | 18 | { |
eencae | 0:df3b9e41edf3 | 19 | |
eencae | 0:df3b9e41edf3 | 20 | i2c->frequency(400000); // set Fast Mode I2C frequency (5.10 datasheet) |
eencae | 0:df3b9e41edf3 | 21 | |
eencae | 0:df3b9e41edf3 | 22 | char data = readByteFromRegister(WHO_AM_I); // p18 datasheet |
eencae | 0:df3b9e41edf3 | 23 | if (data != 0x2A) { // if correct ID not found, hand and flash error message |
eencae | 0:df3b9e41edf3 | 24 | error(); |
eencae | 0:df3b9e41edf3 | 25 | } |
eencae | 0:df3b9e41edf3 | 26 | |
eencae | 0:df3b9e41edf3 | 27 | // put into STANDBY while configuring |
eencae | 0:df3b9e41edf3 | 28 | data = readByteFromRegister(CTRL_REG1); // get current value of register |
eencae | 0:df3b9e41edf3 | 29 | data &= ~(1<<0); // clear bit 0 (p37 datasheet) |
eencae | 0:df3b9e41edf3 | 30 | sendByteToRegister(data,CTRL_REG1); |
eencae | 0:df3b9e41edf3 | 31 | |
eencae | 0:df3b9e41edf3 | 32 | // Set output data rate, default is 800 Hz, will set to 100 Hz (clear b5, set b4/b3 - p37 datasheet) |
eencae | 0:df3b9e41edf3 | 33 | data = readByteFromRegister(CTRL_REG1); |
eencae | 0:df3b9e41edf3 | 34 | data &= ~(1<<5); |
eencae | 0:df3b9e41edf3 | 35 | data |= (1<<4); |
eencae | 0:df3b9e41edf3 | 36 | data |= (1<<3); |
eencae | 0:df3b9e41edf3 | 37 | sendByteToRegister(data,CTRL_REG1); |
eencae | 0:df3b9e41edf3 | 38 | |
arthuryuan | 1:6aa59bbc3e38 | 39 | //Interrupt Control Register (Set b1 - Interrupt polarity ACTIVE high - p39 Datasheet) |
arthuryuan | 1:6aa59bbc3e38 | 40 | data = readByteFromRegister(CTRL_REG3); |
arthuryuan | 1:6aa59bbc3e38 | 41 | data |= (1<<1); //IPOL bit selects the polarity of the interrupt signal. |
arthuryuan | 1:6aa59bbc3e38 | 42 | //When IPOL is ‘0’ (default value) any interrupt event will signaled with a logical 0. |
arthuryuan | 1:6aa59bbc3e38 | 43 | sendByteToRegister(data,CTRL_REG3); |
arthuryuan | 1:6aa59bbc3e38 | 44 | |
eencae | 0:df3b9e41edf3 | 45 | //// Can also change default 2g range to 4g or 8g (p22 datasheet) |
eencae | 0:df3b9e41edf3 | 46 | data = readByteFromRegister(XYZ_DATA_CFG); |
eencae | 0:df3b9e41edf3 | 47 | data |= (1<<0); // set bit 0 - 4g range |
eencae | 0:df3b9e41edf3 | 48 | sendByteToRegister(data,XYZ_DATA_CFG); |
eencae | 0:df3b9e41edf3 | 49 | |
eencae | 0:df3b9e41edf3 | 50 | // set ACTIVE |
eencae | 0:df3b9e41edf3 | 51 | data = readByteFromRegister(CTRL_REG1); |
eencae | 0:df3b9e41edf3 | 52 | data |= (1<<0); // set bit 0 in CTRL_REG1 |
eencae | 0:df3b9e41edf3 | 53 | sendByteToRegister(data,CTRL_REG1); |
eencae | 0:df3b9e41edf3 | 54 | |
arthuryuan | 1:6aa59bbc3e38 | 55 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
arthuryuan | 1:6aa59bbc3e38 | 56 | // only apply for landscape/portrait orientation |
arthuryuan | 1:6aa59bbc3e38 | 57 | /* |
arthuryuan | 1:6aa59bbc3e38 | 58 | //Set the PL_EN bit in Register.This will enable the orientation detection. |
arthuryuan | 1:6aa59bbc3e38 | 59 | data = readByteFromRegister (0x11); |
arthuryuan | 1:6aa59bbc3e38 | 60 | data |= 0x40; |
arthuryuan | 1:6aa59bbc3e38 | 61 | sendByteToRegister(0x11, PL_CFG); |
arthuryuan | 1:6aa59bbc3e38 | 62 | |
arthuryuan | 1:6aa59bbc3e38 | 63 | |
arthuryuan | 1:6aa59bbc3e38 | 64 | //Set the Back/Front Angle trip points |
arthuryuan | 1:6aa59bbc3e38 | 65 | data = readByteFromRegister(0x13); |
arthuryuan | 1:6aa59bbc3e38 | 66 | data &= 0x3F; //Clear bit 7 and 6 |
arthuryuan | 1:6aa59bbc3e38 | 67 | data |= 0x00; |
arthuryuan | 1:6aa59bbc3e38 | 68 | sendByteToRegister(0x13,PL_BF_ZCOMP); |
arthuryuan | 1:6aa59bbc3e38 | 69 | |
arthuryuan | 1:6aa59bbc3e38 | 70 | //Set the Z-Lockout angle trip point |
arthuryuan | 1:6aa59bbc3e38 | 71 | data = readByteFromRegister(0x1C); //Read out contents of the register |
arthuryuan | 1:6aa59bbc3e38 | 72 | |
arthuryuan | 1:6aa59bbc3e38 | 73 | |
arthuryuan | 1:6aa59bbc3e38 | 74 | //Set the Trip Threshold Angle |
arthuryuan | 1:6aa59bbc3e38 | 75 | data = readByteFromRegister(0x14); |
arthuryuan | 1:6aa59bbc3e38 | 76 | //P_L_THS_Data& = 0x07; |
arthuryuan | 1:6aa59bbc3e38 | 77 | //P_L_THS_Data | = (0x07)<<3; //Set Threshold to 15° |
arthuryuan | 1:6aa59bbc3e38 | 78 | //sendByteToRegister(0x14, P_L_THS); |
arthuryuan | 1:6aa59bbc3e38 | 79 | |
arthuryuan | 1:6aa59bbc3e38 | 80 | //Set the Hysteresis Angle |
arthuryuan | 1:6aa59bbc3e38 | 81 | data = readByteFromRegister(0x14); |
arthuryuan | 1:6aa59bbc3e38 | 82 | //P_L_THS_Data | = 0x01; //Set Hysteresis to ±4° |
arthuryuan | 1:6aa59bbc3e38 | 83 | //sendByteToRegister(0x14, P_L_THS); |
arthuryuan | 1:6aa59bbc3e38 | 84 | |
arthuryuan | 1:6aa59bbc3e38 | 85 | //Register 0x2D, Control Register 4 configures all embedded features for interrupt detection. |
arthuryuan | 1:6aa59bbc3e38 | 86 | data = readByteFromRegister(0x2D); //Read out the contents of the register |
arthuryuan | 1:6aa59bbc3e38 | 87 | data |= 0x10; //Set bit 4 |
arthuryuan | 1:6aa59bbc3e38 | 88 | sendByteToRegister(0x2D, CTRL_REG4); //Set the bit and write into CTRL_REG4 |
arthuryuan | 1:6aa59bbc3e38 | 89 | |
arthuryuan | 1:6aa59bbc3e38 | 90 | //Register 0x2E is Control Register 5 which gives the option of routing the interrupt |
arthuryuan | 1:6aa59bbc3e38 | 91 | data = readByteFromRegister(0x2E); |
arthuryuan | 1:6aa59bbc3e38 | 92 | data |= 0x10; //Set bit 4 to choose the interrupt to route to INT1 |
arthuryuan | 1:6aa59bbc3e38 | 93 | sendByteToRegister(0x2E, CTRL_REG5); //Write in the interrupt routing selection |
arthuryuan | 1:6aa59bbc3e38 | 94 | |
arthuryuan | 1:6aa59bbc3e38 | 95 | // Set the debounce counter in register |
arthuryuan | 1:6aa59bbc3e38 | 96 | sendByteToRegister(0x12, 0x05); //This sets the debounce counter to 100 ms at 50 Hz */ |
arthuryuan | 1:6aa59bbc3e38 | 97 | |
arthuryuan | 1:6aa59bbc3e38 | 98 | /////////////////////////////////////////////////////////////////////////////////////////////////////// |
eencae | 0:df3b9e41edf3 | 99 | } |
eencae | 0:df3b9e41edf3 | 100 | |
arthuryuan | 1:6aa59bbc3e38 | 101 | |
eencae | 0:df3b9e41edf3 | 102 | // read acceleration data from device |
eencae | 0:df3b9e41edf3 | 103 | Acceleration MMA8452::readValues() |
eencae | 0:df3b9e41edf3 | 104 | { |
eencae | 0:df3b9e41edf3 | 105 | // acceleration data stored in 6 registers (0x01 to 0x06) |
eencae | 0:df3b9e41edf3 | 106 | // device automatically increments register, so can read 6 bytes starting from OUT_X_MSB |
eencae | 0:df3b9e41edf3 | 107 | char data[6]; |
eencae | 0:df3b9e41edf3 | 108 | readBytesFromRegister(OUT_X_MSB,6,data); |
eencae | 0:df3b9e41edf3 | 109 | |
eencae | 0:df3b9e41edf3 | 110 | char x_MSB = data[0]; // extract MSB and LSBs for x,y,z values |
eencae | 0:df3b9e41edf3 | 111 | char x_LSB = data[1]; |
eencae | 0:df3b9e41edf3 | 112 | char y_MSB = data[2]; |
eencae | 0:df3b9e41edf3 | 113 | char y_LSB = data[3]; |
eencae | 0:df3b9e41edf3 | 114 | char z_MSB = data[4]; |
eencae | 0:df3b9e41edf3 | 115 | char z_LSB = data[5]; |
eencae | 0:df3b9e41edf3 | 116 | |
eencae | 0:df3b9e41edf3 | 117 | // [0:7] of MSB are 8 MSB of 12-bit value , [7:4] of LSB are 4 LSB's of 12-bit value |
eencae | 0:df3b9e41edf3 | 118 | // need to type-cast as numbers are in signed (2's complement) form (p20 datasheet) |
eencae | 0:df3b9e41edf3 | 119 | int x = (int16_t) (x_MSB << 8) | x_LSB; // combine bytes |
eencae | 0:df3b9e41edf3 | 120 | x >>= 4; // are left-aligned, so shift 4 places right to right-align |
eencae | 0:df3b9e41edf3 | 121 | int y = (int16_t) (y_MSB << 8) | y_LSB; |
eencae | 0:df3b9e41edf3 | 122 | y >>= 4; |
eencae | 0:df3b9e41edf3 | 123 | int z = (int16_t) (z_MSB << 8) | z_LSB; |
eencae | 0:df3b9e41edf3 | 124 | z >>= 4; |
eencae | 0:df3b9e41edf3 | 125 | |
eencae | 0:df3b9e41edf3 | 126 | // sensitivity is 1024 counts/g in 2g mode (pg 9 datasheet) |
eencae | 0:df3b9e41edf3 | 127 | // " " 512 " 4g " |
eencae | 0:df3b9e41edf3 | 128 | // " " 256 " 8g " |
eencae | 0:df3b9e41edf3 | 129 | Acceleration acc; |
arthuryuan | 1:6aa59bbc3e38 | 130 | |
eencae | 0:df3b9e41edf3 | 131 | acc.x = x/512.0; |
eencae | 0:df3b9e41edf3 | 132 | acc.y = y/512.0; |
eencae | 0:df3b9e41edf3 | 133 | acc.z = z/512.0; |
arthuryuan | 1:6aa59bbc3e38 | 134 | |
eencae | 0:df3b9e41edf3 | 135 | return acc; |
eencae | 0:df3b9e41edf3 | 136 | } |
eencae | 0:df3b9e41edf3 | 137 | |
eencae | 0:df3b9e41edf3 | 138 | // reads a byte from a specific register |
eencae | 0:df3b9e41edf3 | 139 | char MMA8452::readByteFromRegister(char reg) |
eencae | 0:df3b9e41edf3 | 140 | { |
eencae | 0:df3b9e41edf3 | 141 | int nack = i2c->write(MMA8452_W_ADDRESS,®,1,true); // send the register address to the slave |
eencae | 0:df3b9e41edf3 | 142 | // true as need to send repeated start condition (5.10.1 datasheet) |
eencae | 0:df3b9e41edf3 | 143 | // http://www.i2c-bus.org/repeated-start-condition/ |
eencae | 0:df3b9e41edf3 | 144 | if (nack) |
eencae | 0:df3b9e41edf3 | 145 | error(); // if we don't receive acknowledgement, flash error message |
eencae | 0:df3b9e41edf3 | 146 | |
eencae | 0:df3b9e41edf3 | 147 | char rx; |
eencae | 0:df3b9e41edf3 | 148 | nack = i2c->read(MMA8452_R_ADDRESS,&rx,1); // read a byte from the register and store in buffer |
eencae | 0:df3b9e41edf3 | 149 | if (nack) |
eencae | 0:df3b9e41edf3 | 150 | error(); // if we don't receive acknowledgement, flash error message |
eencae | 0:df3b9e41edf3 | 151 | |
eencae | 0:df3b9e41edf3 | 152 | return rx; |
eencae | 0:df3b9e41edf3 | 153 | } |
eencae | 0:df3b9e41edf3 | 154 | |
eencae | 0:df3b9e41edf3 | 155 | // reads a series of bytes, starting from a specific register |
eencae | 0:df3b9e41edf3 | 156 | void MMA8452::readBytesFromRegister(char reg,int numberOfBytes,char bytes[]) |
eencae | 0:df3b9e41edf3 | 157 | { |
eencae | 0:df3b9e41edf3 | 158 | |
eencae | 0:df3b9e41edf3 | 159 | int nack = i2c->write(MMA8452_W_ADDRESS,®,1,true); // send the slave write address and the configuration register address |
eencae | 0:df3b9e41edf3 | 160 | // true as need to send repeated start condition (5.10.1 datasheet) |
eencae | 0:df3b9e41edf3 | 161 | // http://www.i2c-bus.org/repeated-start-condition/ |
eencae | 0:df3b9e41edf3 | 162 | |
eencae | 0:df3b9e41edf3 | 163 | if (nack) |
eencae | 0:df3b9e41edf3 | 164 | error(); // if we don't receive acknowledgement, flash error message |
eencae | 0:df3b9e41edf3 | 165 | |
eencae | 0:df3b9e41edf3 | 166 | nack = i2c->read(MMA8452_R_ADDRESS,bytes,numberOfBytes); // read bytes |
eencae | 0:df3b9e41edf3 | 167 | if (nack) |
eencae | 0:df3b9e41edf3 | 168 | error(); // if we don't receive acknowledgement, flash error message |
eencae | 0:df3b9e41edf3 | 169 | |
eencae | 0:df3b9e41edf3 | 170 | } |
eencae | 0:df3b9e41edf3 | 171 | |
eencae | 0:df3b9e41edf3 | 172 | // sends a byte to a specific register |
eencae | 0:df3b9e41edf3 | 173 | void MMA8452::sendByteToRegister(char byte,char reg) |
eencae | 0:df3b9e41edf3 | 174 | { |
eencae | 0:df3b9e41edf3 | 175 | char data[2]; |
eencae | 0:df3b9e41edf3 | 176 | data[0] = reg; |
eencae | 0:df3b9e41edf3 | 177 | data[1] = byte; |
eencae | 0:df3b9e41edf3 | 178 | // send the register address, followed by the data |
eencae | 0:df3b9e41edf3 | 179 | int nack = i2c->write(MMA8452_W_ADDRESS,data,2); |
eencae | 0:df3b9e41edf3 | 180 | if (nack) |
eencae | 0:df3b9e41edf3 | 181 | error(); // if we don't receive acknowledgement, flash error message |
eencae | 0:df3b9e41edf3 | 182 | |
eencae | 0:df3b9e41edf3 | 183 | } |
eencae | 0:df3b9e41edf3 | 184 | |
eencae | 0:df3b9e41edf3 | 185 | void MMA8452::error() |
eencae | 0:df3b9e41edf3 | 186 | { |
eencae | 0:df3b9e41edf3 | 187 | while(1) { |
eencae | 0:df3b9e41edf3 | 188 | leds->write(15); |
eencae | 0:df3b9e41edf3 | 189 | wait(0.1); |
eencae | 0:df3b9e41edf3 | 190 | leds->write(0); |
eencae | 0:df3b9e41edf3 | 191 | wait(0.1); |
eencae | 0:df3b9e41edf3 | 192 | } |
eencae | 0:df3b9e41edf3 | 193 | } |