arthur yuan / MMA8452

Fork of MMA8452 by Craig Evans

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?

UserRevisionLine numberNew 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,&reg,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,&reg,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 }