380 lines
12 KiB
C++
380 lines
12 KiB
C++
/**************************************************************************/
|
|
/*!
|
|
@file Adafruit_MSA301.cpp
|
|
@author Limor Fried (Adafruit Industries)
|
|
@license BSD (see license.txt)
|
|
|
|
This is a library for the Adafruit MSA301 Accel breakout board
|
|
----> https://www.adafruit.com
|
|
|
|
Adafruit invests time and resources providing this open source code,
|
|
please support Adafruit and open-source hardware by purchasing
|
|
products from Adafruit!
|
|
|
|
*/
|
|
/**************************************************************************/
|
|
|
|
#if ARDUINO >= 100
|
|
#include "Arduino.h"
|
|
#else
|
|
#include "WProgram.h"
|
|
#endif
|
|
|
|
#include <Wire.h>
|
|
#include <Adafruit_MSA301.h>
|
|
|
|
|
|
/**************************************************************************/
|
|
/*!
|
|
@brief Instantiates a new MSA301 class
|
|
*/
|
|
/**************************************************************************/
|
|
Adafruit_MSA301::Adafruit_MSA301() {}
|
|
|
|
|
|
/*!
|
|
* @brief Sets up the hardware and initializes I2C
|
|
* @param i2c_address
|
|
* The I2C address to be used.
|
|
* @param wire
|
|
* The Wire object to be used for I2C connections.
|
|
* @return True if initialization was successful, otherwise false.
|
|
*/
|
|
bool Adafruit_MSA301::begin(uint8_t i2c_address, TwoWire *wire) {
|
|
i2c_dev = new Adafruit_I2CDevice(i2c_address, wire);
|
|
|
|
if (!i2c_dev->begin()) {
|
|
Serial.println("Failed to init i2c address");
|
|
return false;
|
|
}
|
|
|
|
// Check connection
|
|
Adafruit_BusIO_Register chip_id =
|
|
Adafruit_BusIO_Register(i2c_dev, MSA301_REG_PARTID, 1);
|
|
|
|
|
|
// make sure we're talking to the right chip
|
|
if (chip_id.read() != 0x13) {
|
|
// No MSA301 detected ... return false
|
|
return false;
|
|
}
|
|
|
|
// enable all axes
|
|
enableAxes(true, true, true);
|
|
// normal mode
|
|
setPowerMode(MSA301_NORMALMODE);
|
|
// 500Hz rate
|
|
setDataRate(MSA301_DATARATE_500_HZ);
|
|
// 250Hz bw
|
|
setBandwidth(MSA301_BANDWIDTH_250_HZ);
|
|
setRange(MSA301_RANGE_4_G);
|
|
setResolution(MSA301_RESOLUTION_14);
|
|
|
|
/*
|
|
// DRDY on INT1
|
|
writeRegister8(MSA301_REG_CTRL3, 0x10);
|
|
|
|
// Turn on orientation config
|
|
//writeRegister8(MSA301_REG_PL_CFG, 0x40);
|
|
|
|
*/
|
|
/*
|
|
for (uint8_t i=0; i<0x30; i++) {
|
|
Serial.print("$");
|
|
Serial.print(i, HEX); Serial.print(" = 0x");
|
|
Serial.println(readRegister8(i), HEX);
|
|
}
|
|
*/
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
|
|
/**************************************************************************/
|
|
/*!
|
|
@brief Sets the data rate for the MSA301 (controls power consumption)
|
|
*/
|
|
/**************************************************************************/
|
|
void Adafruit_MSA301::setDataRate(msa301_dataRate_t dataRate)
|
|
{
|
|
Adafruit_BusIO_Register ODR =
|
|
Adafruit_BusIO_Register(i2c_dev, MSA301_REG_ODR, 1);
|
|
Adafruit_BusIO_RegisterBits dataratebits = Adafruit_BusIO_RegisterBits(&ODR, 4, 0);
|
|
dataratebits.write((uint8_t)dataRate);
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/*!
|
|
@brief Sets the data rate for the MSA301 (controls power consumption)
|
|
*/
|
|
/**************************************************************************/
|
|
msa301_dataRate_t Adafruit_MSA301::getDataRate(void)
|
|
{
|
|
Adafruit_BusIO_Register ODR =
|
|
Adafruit_BusIO_Register(i2c_dev, MSA301_REG_ODR, 1);
|
|
Adafruit_BusIO_RegisterBits dataratebits = Adafruit_BusIO_RegisterBits(&ODR, 4, 0);
|
|
return (msa301_dataRate_t)dataratebits.read();
|
|
}
|
|
|
|
void Adafruit_MSA301::enableAxes(bool enableX, bool enableY, bool enableZ) {
|
|
Adafruit_BusIO_Register ODR =
|
|
Adafruit_BusIO_Register(i2c_dev, MSA301_REG_ODR, 1);
|
|
|
|
Adafruit_BusIO_RegisterBits x = Adafruit_BusIO_RegisterBits(&ODR, 1, 7);
|
|
Adafruit_BusIO_RegisterBits y = Adafruit_BusIO_RegisterBits(&ODR, 1, 6);
|
|
Adafruit_BusIO_RegisterBits z = Adafruit_BusIO_RegisterBits(&ODR, 1, 5);
|
|
x.write(!enableX); // these are *disable* bits, yeah...
|
|
y.write(!enableY);
|
|
z.write(!enableZ);
|
|
}
|
|
|
|
void Adafruit_MSA301::setPowerMode(msa301_powermode_t mode)
|
|
{
|
|
Adafruit_BusIO_Register PowerMode =
|
|
Adafruit_BusIO_Register(i2c_dev, MSA301_REG_POWERMODE, 1);
|
|
Adafruit_BusIO_RegisterBits powermodebits = Adafruit_BusIO_RegisterBits(&PowerMode, 2, 6);
|
|
powermodebits.write((uint8_t)mode);
|
|
}
|
|
|
|
|
|
msa301_powermode_t Adafruit_MSA301::getPowerMode(void)
|
|
{
|
|
Adafruit_BusIO_Register PowerMode =
|
|
Adafruit_BusIO_Register(i2c_dev, MSA301_REG_POWERMODE, 1);
|
|
Adafruit_BusIO_RegisterBits powermodebits = Adafruit_BusIO_RegisterBits(&PowerMode, 2, 6);
|
|
return (msa301_powermode_t)powermodebits.read();
|
|
}
|
|
|
|
|
|
void Adafruit_MSA301::setBandwidth(msa301_bandwidth_t bandwidth)
|
|
{
|
|
Adafruit_BusIO_Register PowerMode =
|
|
Adafruit_BusIO_Register(i2c_dev, MSA301_REG_POWERMODE, 1);
|
|
Adafruit_BusIO_RegisterBits bandwidthbits = Adafruit_BusIO_RegisterBits(&PowerMode, 4, 1);
|
|
bandwidthbits.write((uint8_t)bandwidth);
|
|
}
|
|
|
|
|
|
msa301_bandwidth_t Adafruit_MSA301::getBandwidth(void)
|
|
{
|
|
Adafruit_BusIO_Register PowerMode =
|
|
Adafruit_BusIO_Register(i2c_dev, MSA301_REG_POWERMODE, 1);
|
|
Adafruit_BusIO_RegisterBits bandwidthbits = Adafruit_BusIO_RegisterBits(&PowerMode, 4, 1);
|
|
return (msa301_bandwidth_t)bandwidthbits.read();
|
|
}
|
|
|
|
|
|
|
|
/**************************************************************************/
|
|
/*!
|
|
@brief Sets the g range for the accelerometer
|
|
*/
|
|
/**************************************************************************/
|
|
void Adafruit_MSA301::setRange(msa301_range_t range)
|
|
{
|
|
Adafruit_BusIO_Register ResRange =
|
|
Adafruit_BusIO_Register(i2c_dev, MSA301_REG_RESRANGE, 1);
|
|
Adafruit_BusIO_RegisterBits rangebits = Adafruit_BusIO_RegisterBits(&ResRange, 2, 0);
|
|
rangebits.write((uint8_t)range);
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/*!
|
|
@brief Gets the g range for the accelerometer
|
|
*/
|
|
/**************************************************************************/
|
|
msa301_range_t Adafruit_MSA301::getRange(void)
|
|
{
|
|
Adafruit_BusIO_Register ResRange =
|
|
Adafruit_BusIO_Register(i2c_dev, MSA301_REG_RESRANGE, 1);
|
|
Adafruit_BusIO_RegisterBits rangebits = Adafruit_BusIO_RegisterBits(&ResRange, 2, 0);
|
|
return (msa301_range_t)rangebits.read();
|
|
}
|
|
|
|
|
|
/**************************************************************************/
|
|
/*!
|
|
@brief
|
|
*/
|
|
/**************************************************************************/
|
|
void Adafruit_MSA301::setResolution(msa301_resolution_t resolution)
|
|
{
|
|
Adafruit_BusIO_Register ResRange =
|
|
Adafruit_BusIO_Register(i2c_dev, MSA301_REG_RESRANGE, 1);
|
|
Adafruit_BusIO_RegisterBits resbits = Adafruit_BusIO_RegisterBits(&ResRange, 2, 2);
|
|
resbits.write((uint8_t)resolution);
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/*!
|
|
@brief
|
|
*/
|
|
/**************************************************************************/
|
|
msa301_resolution_t Adafruit_MSA301::getResolution(void)
|
|
{
|
|
Adafruit_BusIO_Register ResRange =
|
|
Adafruit_BusIO_Register(i2c_dev, MSA301_REG_RESRANGE, 1);
|
|
Adafruit_BusIO_RegisterBits resbits = Adafruit_BusIO_RegisterBits(&ResRange, 2, 2);
|
|
return (msa301_resolution_t)resbits.read();
|
|
}
|
|
|
|
|
|
|
|
void Adafruit_MSA301::read(void) {
|
|
uint8_t buffer[6];
|
|
|
|
Adafruit_BusIO_Register XYZDataReg =
|
|
Adafruit_BusIO_Register(i2c_dev, MSA301_REG_OUT_X_L, 6);
|
|
XYZDataReg.read(buffer, 6);
|
|
x = buffer[0]; x |= buffer[1] << 8;
|
|
y = buffer[2]; y |= buffer[3] << 8;
|
|
z = buffer[4]; z |= buffer[5] << 8;
|
|
|
|
// 14 bits of data in 16 bit range
|
|
x >>= 2;
|
|
y >>= 2;
|
|
z >>= 2;
|
|
|
|
msa301_range_t range = getRange();
|
|
float scale = 1;
|
|
if (range == MSA301_RANGE_16_G) scale = 512;
|
|
if (range == MSA301_RANGE_8_G) scale = 1024;
|
|
if (range == MSA301_RANGE_4_G) scale = 2048;
|
|
if (range == MSA301_RANGE_2_G) scale = 4096;
|
|
|
|
x_g = (float)x / scale;
|
|
y_g = (float)y / scale;
|
|
z_g = (float)z / scale;
|
|
}
|
|
|
|
|
|
/**************************************************************************/
|
|
/*!
|
|
@brief Set INT to output for single or double click
|
|
*/
|
|
/**************************************************************************/
|
|
|
|
void Adafruit_MSA301::setClick(bool tap_quiet, bool tap_shock, msa301_tapduration_t tapduration, uint8_t tapthresh) {
|
|
Adafruit_BusIO_Register TapDur =
|
|
Adafruit_BusIO_Register(i2c_dev, MSA301_REG_TAPDUR, 1);
|
|
Adafruit_BusIO_RegisterBits quietbit = Adafruit_BusIO_RegisterBits(&TapDur, 1, 7);
|
|
quietbit.write(tap_quiet);
|
|
Adafruit_BusIO_RegisterBits shockbit = Adafruit_BusIO_RegisterBits(&TapDur, 1, 6);
|
|
shockbit.write(tap_shock);
|
|
Adafruit_BusIO_RegisterBits durationbits = Adafruit_BusIO_RegisterBits(&TapDur, 3, 0);
|
|
durationbits.write(tapduration);
|
|
|
|
Adafruit_BusIO_Register TapTh =
|
|
Adafruit_BusIO_Register(i2c_dev, MSA301_REG_TAPTH, 1);
|
|
Adafruit_BusIO_RegisterBits threshbits = Adafruit_BusIO_RegisterBits(&TapTh, 5, 0);
|
|
threshbits.write(tapthresh);
|
|
}
|
|
|
|
|
|
|
|
uint8_t Adafruit_MSA301::getClick(void) {
|
|
Adafruit_BusIO_Register ClickStatus =
|
|
Adafruit_BusIO_Register(i2c_dev, MSA301_REG_CLICKSTATUS, 1);
|
|
|
|
return ClickStatus.read();
|
|
}
|
|
|
|
void Adafruit_MSA301::enableInterrupts(bool singletap, bool doubletap,
|
|
bool activeX, bool activeY, bool activeZ,
|
|
bool newData, bool freefall, bool orient) {
|
|
Adafruit_BusIO_Register IntSet0 =
|
|
Adafruit_BusIO_Register(i2c_dev, MSA301_REG_INTSET0, 1);
|
|
Adafruit_BusIO_Register IntSet1 =
|
|
Adafruit_BusIO_Register(i2c_dev, MSA301_REG_INTSET1, 1);
|
|
uint8_t irqs = 0;
|
|
irqs |= orient << 6;
|
|
irqs |= singletap << 5;
|
|
irqs |= doubletap << 4;
|
|
irqs |= activeX << 0;
|
|
irqs |= activeY << 1;
|
|
irqs |= activeZ << 2;
|
|
IntSet0.write(irqs);
|
|
irqs = 0;
|
|
irqs |= newData << 4;
|
|
irqs |= freefall << 3;
|
|
IntSet1.write(irqs);
|
|
}
|
|
|
|
void Adafruit_MSA301::mapInterruptPin(bool singletap, bool doubletap, bool activity,
|
|
bool newData, bool freefall, bool orient) {
|
|
Adafruit_BusIO_Register IntMap0 =
|
|
Adafruit_BusIO_Register(i2c_dev, MSA301_REG_INTMAP0, 1);
|
|
Adafruit_BusIO_Register IntMap1 =
|
|
Adafruit_BusIO_Register(i2c_dev, MSA301_REG_INTMAP1, 1);
|
|
uint8_t irqs = 0;
|
|
irqs |= orient << 6;
|
|
irqs |= singletap << 5;
|
|
irqs |= doubletap << 4;
|
|
irqs |= activity << 2;
|
|
irqs |= freefall << 0;
|
|
IntMap0.write(irqs);
|
|
irqs = newData << 0;
|
|
IntMap1.write(irqs);
|
|
}
|
|
|
|
uint8_t Adafruit_MSA301::getMotionInterruptStatus(void) {
|
|
Adafruit_BusIO_Register IntStatus =
|
|
Adafruit_BusIO_Register(i2c_dev, MSA301_REG_MOTIONINT, 1);
|
|
|
|
return IntStatus.read();
|
|
}
|
|
|
|
uint8_t Adafruit_MSA301::getDataInterruptStatus(void) {
|
|
Adafruit_BusIO_Register IntStatus =
|
|
Adafruit_BusIO_Register(i2c_dev, MSA301_REG_DATAINT, 1);
|
|
|
|
return IntStatus.read();
|
|
}
|
|
|
|
|
|
/**************************************************************************/
|
|
/*!
|
|
@brief Gets the most recent sensor event
|
|
*/
|
|
/**************************************************************************/
|
|
bool Adafruit_MSA301::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();
|
|
|
|
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_MSA301::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, "MSA301", 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;
|
|
}
|
|
|