Library for Freescale MMA8452 Accelerometer
Dependents: acce_ChenZhengyang mbed_ProjectC_Accelerometer AccelerometerProject mbed_Accelerometer ... more
MMA8452.cpp@0:df3b9e41edf3, 2015-03-08 (annotated)
- Committer:
- eencae
- Date:
- Sun Mar 08 15:31:02 2015 +0000
- Revision:
- 0:df3b9e41edf3
Library for Freescale MMA8452 accelerometer.
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 | |
eencae | 0:df3b9e41edf3 | 39 | //// Can also change default 2g range to 4g or 8g (p22 datasheet) |
eencae | 0:df3b9e41edf3 | 40 | data = readByteFromRegister(XYZ_DATA_CFG); |
eencae | 0:df3b9e41edf3 | 41 | data |= (1<<0); // set bit 0 - 4g range |
eencae | 0:df3b9e41edf3 | 42 | sendByteToRegister(data,XYZ_DATA_CFG); |
eencae | 0:df3b9e41edf3 | 43 | |
eencae | 0:df3b9e41edf3 | 44 | // set ACTIVE |
eencae | 0:df3b9e41edf3 | 45 | data = readByteFromRegister(CTRL_REG1); |
eencae | 0:df3b9e41edf3 | 46 | data |= (1<<0); // set bit 0 in CTRL_REG1 |
eencae | 0:df3b9e41edf3 | 47 | sendByteToRegister(data,CTRL_REG1); |
eencae | 0:df3b9e41edf3 | 48 | |
eencae | 0:df3b9e41edf3 | 49 | } |
eencae | 0:df3b9e41edf3 | 50 | |
eencae | 0:df3b9e41edf3 | 51 | // read acceleration data from device |
eencae | 0:df3b9e41edf3 | 52 | Acceleration MMA8452::readValues() |
eencae | 0:df3b9e41edf3 | 53 | { |
eencae | 0:df3b9e41edf3 | 54 | // acceleration data stored in 6 registers (0x01 to 0x06) |
eencae | 0:df3b9e41edf3 | 55 | // device automatically increments register, so can read 6 bytes starting from OUT_X_MSB |
eencae | 0:df3b9e41edf3 | 56 | char data[6]; |
eencae | 0:df3b9e41edf3 | 57 | readBytesFromRegister(OUT_X_MSB,6,data); |
eencae | 0:df3b9e41edf3 | 58 | |
eencae | 0:df3b9e41edf3 | 59 | char x_MSB = data[0]; // extract MSB and LSBs for x,y,z values |
eencae | 0:df3b9e41edf3 | 60 | char x_LSB = data[1]; |
eencae | 0:df3b9e41edf3 | 61 | char y_MSB = data[2]; |
eencae | 0:df3b9e41edf3 | 62 | char y_LSB = data[3]; |
eencae | 0:df3b9e41edf3 | 63 | char z_MSB = data[4]; |
eencae | 0:df3b9e41edf3 | 64 | char z_LSB = data[5]; |
eencae | 0:df3b9e41edf3 | 65 | |
eencae | 0:df3b9e41edf3 | 66 | // [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 | 67 | // need to type-cast as numbers are in signed (2's complement) form (p20 datasheet) |
eencae | 0:df3b9e41edf3 | 68 | int x = (int16_t) (x_MSB << 8) | x_LSB; // combine bytes |
eencae | 0:df3b9e41edf3 | 69 | x >>= 4; // are left-aligned, so shift 4 places right to right-align |
eencae | 0:df3b9e41edf3 | 70 | int y = (int16_t) (y_MSB << 8) | y_LSB; |
eencae | 0:df3b9e41edf3 | 71 | y >>= 4; |
eencae | 0:df3b9e41edf3 | 72 | int z = (int16_t) (z_MSB << 8) | z_LSB; |
eencae | 0:df3b9e41edf3 | 73 | z >>= 4; |
eencae | 0:df3b9e41edf3 | 74 | |
eencae | 0:df3b9e41edf3 | 75 | // sensitivity is 1024 counts/g in 2g mode (pg 9 datasheet) |
eencae | 0:df3b9e41edf3 | 76 | // " " 512 " 4g " |
eencae | 0:df3b9e41edf3 | 77 | // " " 256 " 8g " |
eencae | 0:df3b9e41edf3 | 78 | Acceleration acc; |
eencae | 0:df3b9e41edf3 | 79 | |
eencae | 0:df3b9e41edf3 | 80 | acc.x = x/512.0; |
eencae | 0:df3b9e41edf3 | 81 | acc.y = y/512.0; |
eencae | 0:df3b9e41edf3 | 82 | acc.z = z/512.0; |
eencae | 0:df3b9e41edf3 | 83 | |
eencae | 0:df3b9e41edf3 | 84 | return acc; |
eencae | 0:df3b9e41edf3 | 85 | } |
eencae | 0:df3b9e41edf3 | 86 | |
eencae | 0:df3b9e41edf3 | 87 | // reads a byte from a specific register |
eencae | 0:df3b9e41edf3 | 88 | char MMA8452::readByteFromRegister(char reg) |
eencae | 0:df3b9e41edf3 | 89 | { |
eencae | 0:df3b9e41edf3 | 90 | int nack = i2c->write(MMA8452_W_ADDRESS,®,1,true); // send the register address to the slave |
eencae | 0:df3b9e41edf3 | 91 | // true as need to send repeated start condition (5.10.1 datasheet) |
eencae | 0:df3b9e41edf3 | 92 | // http://www.i2c-bus.org/repeated-start-condition/ |
eencae | 0:df3b9e41edf3 | 93 | if (nack) |
eencae | 0:df3b9e41edf3 | 94 | error(); // if we don't receive acknowledgement, flash error message |
eencae | 0:df3b9e41edf3 | 95 | |
eencae | 0:df3b9e41edf3 | 96 | char rx; |
eencae | 0:df3b9e41edf3 | 97 | nack = i2c->read(MMA8452_R_ADDRESS,&rx,1); // read a byte from the register and store in buffer |
eencae | 0:df3b9e41edf3 | 98 | if (nack) |
eencae | 0:df3b9e41edf3 | 99 | error(); // if we don't receive acknowledgement, flash error message |
eencae | 0:df3b9e41edf3 | 100 | |
eencae | 0:df3b9e41edf3 | 101 | return rx; |
eencae | 0:df3b9e41edf3 | 102 | } |
eencae | 0:df3b9e41edf3 | 103 | |
eencae | 0:df3b9e41edf3 | 104 | // reads a series of bytes, starting from a specific register |
eencae | 0:df3b9e41edf3 | 105 | void MMA8452::readBytesFromRegister(char reg,int numberOfBytes,char bytes[]) |
eencae | 0:df3b9e41edf3 | 106 | { |
eencae | 0:df3b9e41edf3 | 107 | |
eencae | 0:df3b9e41edf3 | 108 | int nack = i2c->write(MMA8452_W_ADDRESS,®,1,true); // send the slave write address and the configuration register address |
eencae | 0:df3b9e41edf3 | 109 | // true as need to send repeated start condition (5.10.1 datasheet) |
eencae | 0:df3b9e41edf3 | 110 | // http://www.i2c-bus.org/repeated-start-condition/ |
eencae | 0:df3b9e41edf3 | 111 | |
eencae | 0:df3b9e41edf3 | 112 | if (nack) |
eencae | 0:df3b9e41edf3 | 113 | error(); // if we don't receive acknowledgement, flash error message |
eencae | 0:df3b9e41edf3 | 114 | |
eencae | 0:df3b9e41edf3 | 115 | nack = i2c->read(MMA8452_R_ADDRESS,bytes,numberOfBytes); // read bytes |
eencae | 0:df3b9e41edf3 | 116 | if (nack) |
eencae | 0:df3b9e41edf3 | 117 | error(); // if we don't receive acknowledgement, flash error message |
eencae | 0:df3b9e41edf3 | 118 | |
eencae | 0:df3b9e41edf3 | 119 | } |
eencae | 0:df3b9e41edf3 | 120 | |
eencae | 0:df3b9e41edf3 | 121 | // sends a byte to a specific register |
eencae | 0:df3b9e41edf3 | 122 | void MMA8452::sendByteToRegister(char byte,char reg) |
eencae | 0:df3b9e41edf3 | 123 | { |
eencae | 0:df3b9e41edf3 | 124 | char data[2]; |
eencae | 0:df3b9e41edf3 | 125 | data[0] = reg; |
eencae | 0:df3b9e41edf3 | 126 | data[1] = byte; |
eencae | 0:df3b9e41edf3 | 127 | // send the register address, followed by the data |
eencae | 0:df3b9e41edf3 | 128 | int nack = i2c->write(MMA8452_W_ADDRESS,data,2); |
eencae | 0:df3b9e41edf3 | 129 | if (nack) |
eencae | 0:df3b9e41edf3 | 130 | error(); // if we don't receive acknowledgement, flash error message |
eencae | 0:df3b9e41edf3 | 131 | |
eencae | 0:df3b9e41edf3 | 132 | } |
eencae | 0:df3b9e41edf3 | 133 | |
eencae | 0:df3b9e41edf3 | 134 | void MMA8452::error() |
eencae | 0:df3b9e41edf3 | 135 | { |
eencae | 0:df3b9e41edf3 | 136 | while(1) { |
eencae | 0:df3b9e41edf3 | 137 | leds->write(15); |
eencae | 0:df3b9e41edf3 | 138 | wait(0.1); |
eencae | 0:df3b9e41edf3 | 139 | leds->write(0); |
eencae | 0:df3b9e41edf3 | 140 | wait(0.1); |
eencae | 0:df3b9e41edf3 | 141 | } |
eencae | 0:df3b9e41edf3 | 142 | } |