-
Notifications
You must be signed in to change notification settings - Fork 36
/
Copy pathAdafruit_MMA8451.cpp
244 lines (214 loc) · 7.28 KB
/
Adafruit_MMA8451.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
/*!
* @file Adafruit_MMA8451.h
*
* @mainpage Adafruit MMA8451 Accelerometer Library
*
* @section intro_sec Introduction
*
* This is a library for the Adafruit MMA8451 Accel breakout board
* ----> https://www.adafruit.com/products/2019
*
* Adafruit invests time and resources providing this open source code,
* please support Adafruit and open-source hardware by purchasing
* products from Adafruit!
*
* @author K. Townsend (Adafruit Industries)
*
* @section HISTORY
*
* v1.0 - First release
*
* @ section license License
*
* BSD (see license.txt)
*/
#if ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#include <Adafruit_MMA8451.h>
/**************************************************************************/
/*!
@brief Writes 8-bits to the specified destination register
*/
/**************************************************************************/
void Adafruit_MMA8451::writeRegister8(uint8_t reg, uint8_t value) {
uint8_t buffer[2] = {reg, value};
i2c_dev->write(buffer, 2);
}
/**************************************************************************/
/*!
@brief Reads 8-bits from the specified register
*/
/**************************************************************************/
uint8_t Adafruit_MMA8451::readRegister8(uint8_t reg) {
uint8_t buffer[1] = {reg};
i2c_dev->write_then_read(buffer, 1, buffer, 1);
return buffer[0];
}
/**************************************************************************/
/*!
@brief Instantiates a new MMA8451 class in I2C mode
*/
/**************************************************************************/
Adafruit_MMA8451::Adafruit_MMA8451(int32_t sensorID) { _sensorID = sensorID; }
/**************************************************************************/
/*!
@brief Setups the HW (reads coefficients values, etc.)
*/
/**************************************************************************/
bool Adafruit_MMA8451::begin(uint8_t i2caddr, TwoWire *theWire) {
if (i2c_dev)
delete i2c_dev;
i2c_dev = new Adafruit_I2CDevice(i2caddr, theWire);
if (!i2c_dev->begin())
return false;
/* Check connection */
uint8_t deviceid = readRegister8(MMA8451_REG_WHOAMI);
if (deviceid != 0x1A) {
/* No MMA8451 detected ... return false */
// Serial.println(deviceid, HEX);
return false;
}
writeRegister8(MMA8451_REG_CTRL_REG2, 0x40); // reset
while (readRegister8(MMA8451_REG_CTRL_REG2) & 0x40)
;
// enable 4G range
writeRegister8(MMA8451_REG_XYZ_DATA_CFG, MMA8451_RANGE_4_G);
// High res
writeRegister8(MMA8451_REG_CTRL_REG2, 0x02);
// DRDY on INT1
writeRegister8(MMA8451_REG_CTRL_REG4, 0x01);
writeRegister8(MMA8451_REG_CTRL_REG5, 0x01);
// Turn on orientation config
writeRegister8(MMA8451_REG_PL_CFG, 0x40);
// Activate at max rate, low noise mode
writeRegister8(MMA8451_REG_CTRL_REG1, 0x01 | 0x04);
/*
for (uint8_t i=0; i<0x30; i++) {
Serial.print("$");
Serial.print(i, HEX); Serial.print(" = 0x");
Serial.println(readRegister8(i), HEX);
}
*/
return true;
}
void Adafruit_MMA8451::read(void) {
// read x y z at once
uint8_t buffer[6] = {MMA8451_REG_OUT_X_MSB, 0, 0, 0, 0, 0};
i2c_dev->write_then_read(buffer, 1, buffer, 6);
x = buffer[0];
x <<= 8;
x |= buffer[1];
x >>= 2;
y = buffer[2];
y <<= 8;
y |= buffer[3];
y >>= 2;
z = buffer[4];
z <<= 8;
z |= buffer[5];
z >>= 2;
uint8_t range = getRange();
uint16_t divider = 1;
if (range == MMA8451_RANGE_8_G)
divider = 1024;
if (range == MMA8451_RANGE_4_G)
divider = 2048;
if (range == MMA8451_RANGE_2_G)
divider = 4096;
x_g = (float)x / divider;
y_g = (float)y / divider;
z_g = (float)z / divider;
}
/**************************************************************************/
/*!
@brief Read the orientation:
Portrait/Landscape + Up/Down/Left/Right + Front/Back
*/
/**************************************************************************/
uint8_t Adafruit_MMA8451::getOrientation(void) {
return readRegister8(MMA8451_REG_PL_STATUS) & 0x07;
}
/**************************************************************************/
/*!
@brief Sets the g range for the accelerometer
*/
/**************************************************************************/
void Adafruit_MMA8451::setRange(mma8451_range_t range) {
uint8_t reg1 = readRegister8(MMA8451_REG_CTRL_REG1);
writeRegister8(MMA8451_REG_CTRL_REG1, 0x00); // deactivate
writeRegister8(MMA8451_REG_XYZ_DATA_CFG, range & 0x3);
writeRegister8(MMA8451_REG_CTRL_REG1, reg1 | 0x01); // activate
}
/**************************************************************************/
/*!
@brief Gets the g range for the accelerometer
*/
/**************************************************************************/
mma8451_range_t Adafruit_MMA8451::getRange(void) {
/* Read the data format register to preserve bits */
return (mma8451_range_t)(readRegister8(MMA8451_REG_XYZ_DATA_CFG) & 0x03);
}
/**************************************************************************/
/*!
@brief Sets the data rate for the MMA8451 (controls power consumption)
*/
/**************************************************************************/
void Adafruit_MMA8451::setDataRate(mma8451_dataRate_t dataRate) {
uint8_t ctl1 = readRegister8(MMA8451_REG_CTRL_REG1);
writeRegister8(MMA8451_REG_CTRL_REG1, 0x00); // deactivate
ctl1 &= ~(MMA8451_DATARATE_MASK << 3); // mask off bits
ctl1 |= (dataRate << 3);
writeRegister8(MMA8451_REG_CTRL_REG1, ctl1 | 0x01); // activate
}
/**************************************************************************/
/*!
@brief Gets the data rate for the MMA8451 (controls power consumption)
*/
/**************************************************************************/
mma8451_dataRate_t Adafruit_MMA8451::getDataRate(void) {
return (mma8451_dataRate_t)((readRegister8(MMA8451_REG_CTRL_REG1) >> 3) &
MMA8451_DATARATE_MASK);
}
#ifdef USE_SENSOR
/**************************************************************************/
/*!
@brief Gets the most recent sensor event
*/
/**************************************************************************/
bool Adafruit_MMA8451::getEvent(sensors_event_t *event) {
/* Clear the event */
memset(event, 0, sizeof(sensors_event_t));
event->version = sizeof(sensors_event_t);
event->sensor_id = _sensorID;
event->type = SENSOR_TYPE_ACCELEROMETER;
event->timestamp = 0;
read();
// Convert Acceleration Data to m/s^2
event->acceleration.x = x_g * SENSORS_GRAVITY_STANDARD;
event->acceleration.y = y_g * SENSORS_GRAVITY_STANDARD;
event->acceleration.z = z_g * SENSORS_GRAVITY_STANDARD;
return true;
}
/**************************************************************************/
/*!
@brief Gets the sensor_t data
*/
/**************************************************************************/
void Adafruit_MMA8451::getSensor(sensor_t *sensor) {
/* Clear the sensor_t object */
memset(sensor, 0, sizeof(sensor_t));
/* Insert the sensor name in the fixed length char array */
strncpy(sensor->name, "MMA8451", sizeof(sensor->name) - 1);
sensor->name[sizeof(sensor->name) - 1] = 0;
sensor->version = 1;
sensor->sensor_id = _sensorID;
sensor->type = SENSOR_TYPE_ACCELEROMETER;
sensor->min_delay = 0;
sensor->max_value = 0;
sensor->min_value = 0;
sensor->resolution = 0;
}
#endif