Aleksandr Koptevtsov
/
adxl345
ADXL345 test on L476
Diff: adxl345.cpp
- Revision:
- 0:a0f7c6807a3a
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/adxl345.cpp Thu Nov 30 20:01:44 2017 +0000 @@ -0,0 +1,692 @@ +#include "adxl345.h" + +I2C i2c(PB_9, PB_8); + +#define ADXL345_DEVICE (0xA6) // Device Address for ADXL345 +#define ADXL345_TO_READ (6) // Number of chars Read - Two chars Per Axis + +ADXL345::ADXL345() { + status = ADXL345_OK; + error_code = ADXL345_NO_ERROR; + + gains[0] = 0.00376390; // Original gain 0.00376390 + gains[1] = 0.00376009; // Original gain 0.00376009 + gains[2] = 0.00349265; // Original gain 0.00349265 +} + + +void ADXL345::powerOn() { + + //ADXL345 TURN ON + writeToI2C(ADXL345_POWER_CTL, 0); // Wakeup + writeToI2C(ADXL345_POWER_CTL, 16); // Auto_Sleep + writeToI2C(ADXL345_POWER_CTL, 8); // Measure + +} + + +/*********************** READING ACCELERATION ***********************/ +/* Reads Acceleration into Three Variables: x, y and z */ + +void ADXL345::readAccel(int *xyz){ + readAccel(xyz, xyz + 1, xyz + 2); +} + +void ADXL345::readAccel(int *x, int *y, int *z) { + readFromI2C(ADXL345_DATAX0, ADXL345_TO_READ, _buff); // Read Accel Data from ADXL345 + + // Each Axis @ All g Ranges: 10 Bit Resolution (2 chars) + + *x = (int16_t)((((int)_buff[1]) << 8) | _buff[0]); + *y = (int16_t)((((int)_buff[3]) << 8) | _buff[2]); + *z = (int16_t)((((int)_buff[5]) << 8) | _buff[4]); + +} + +void ADXL345::get_Gxyz(double *xyz){ + int i; + int xyz_int[3]; + readAccel(xyz_int); + for(i=0; i<3; i++){ + xyz[i] = xyz_int[i] * gains[i]; + } +} + + +/*************************** WRITE TO I2C ***************************/ +/* Start; Send Register Address; Send Value To Write; End */ +void ADXL345::writeToI2C(char _address, char _val) { + + char data_write[2]; + data_write[0] = _address; + data_write[1] = _val; + + i2c.write(ADXL345_DEVICE, data_write, 2, 0); +} + +/*************************** READ FROM I2C **************************/ +/* Start; Send Address To Read; End */ +void ADXL345::readFromI2C(char address, int num, char _buff[]) { + + char data_write[1]; + data_write[0] = address; + i2c.write(ADXL345_DEVICE, data_write, 1, 1); + i2c.read(ADXL345_DEVICE, _buff, num, 0); +} + +void ADXL345::setRangeSetting(int val) { + char _s; + char _b; + + switch (val) { + case 2: + _s = 00000000; + break; + case 4: + _s = 00000001; + break; + case 8: + _s = 00000010; + break; + case 16: + _s = 00000011; + break; + default: + _s = 00000000; + } + readFromI2C(ADXL345_DATA_FORMAT, 1, &_b); + _s |= (_b & 11101100); + writeToI2C(ADXL345_DATA_FORMAT, _s); +} + +/*************************** SELF_TEST BIT **************************/ +/* ~ GET & SET */ +bool ADXL345::getSelfTestBit() { + return getRegisterBit(ADXL345_DATA_FORMAT, 7); +} + +// If Set (1) Self-Test Applied. Electrostatic Force exerted on the sensor +// causing a shift in the output data. +// If Set (0) Self-Test Disabled. +void ADXL345::setSelfTestBit(bool selfTestBit) { + setRegisterBit(ADXL345_DATA_FORMAT, 7, selfTestBit); +} + + +/*********************** INT_INVERT BIT STATE ***********************/ +/* ~ GET & SET */ +bool ADXL345::getInterruptLevelBit() { + return getRegisterBit(ADXL345_DATA_FORMAT, 5); +} + +// If Set (0) Sets the Interrupts to Active HIGH +// If Set (1) Sets the Interrupts to Active LOW +void ADXL345::setInterruptLevelBit(bool interruptLevelBit) { + setRegisterBit(ADXL345_DATA_FORMAT, 5, interruptLevelBit); +} + +/************************* FULL_RES BIT STATE ***********************/ +/* ~ GET & SET */ +bool ADXL345::getFullResBit() { + return getRegisterBit(ADXL345_DATA_FORMAT, 3); +} + +// If Set (1) Device is in Full Resolution Mode: Output Resolution Increase with G Range +// Set by the Range Bits to Maintain a 4mg/LSB Scale Factor +// If Set (0) Device is in 10-bit Mode: Range Bits Determine Maximum G Range +// And Scale Factor +void ADXL345::setFullResBit(bool fullResBit) { + setRegisterBit(ADXL345_DATA_FORMAT, 3, fullResBit); +} + +/*************************** JUSTIFY BIT STATE **************************/ +/* ~ GET & SET */ +bool ADXL345::getJustifyBit() { + return getRegisterBit(ADXL345_DATA_FORMAT, 2); +} + +// If Set (1) Selects the Left Justified Mode +// If Set (0) Selects Right Justified Mode with Sign Extension +void ADXL345::setJustifyBit(bool justifyBit) { + setRegisterBit(ADXL345_DATA_FORMAT, 2, justifyBit); +} + +/*********************** THRESH_TAP char VALUE **********************/ +/* ~ SET & GET */ +// Should Set Between 0 and 255 +// Scale Factor is 62.5 mg/LSB +// A Value of 0 May Result in Undesirable Behavior +void ADXL345::setTapThreshold(int tapThreshold) { + if(tapThreshold < 0) + { + tapThreshold = 0; + } + if(tapThreshold > 255) + { + tapThreshold = 255; + } + + char _b = char (tapThreshold); + writeToI2C(ADXL345_THRESH_TAP, _b); +} + +// Return Value Between 0 and 255 +// Scale Factor is 62.5 mg/LSB +int ADXL345::getTapThreshold() { + char _b; + readFromI2C(ADXL345_THRESH_TAP, 1, &_b); + return int (_b); +} + +/****************** GAIN FOR EACH AXIS IN Gs / COUNT *****************/ +/* ~ SET & GET */ +void ADXL345::setAxisGains(double *_gains){ + int i; + for(i = 0; i < 3; i++){ + gains[i] = _gains[i]; + } +} +void ADXL345::getAxisGains(double *_gains){ + int i; + for(i = 0; i < 3; i++){ + _gains[i] = gains[i]; + } +} + +/********************* OFSX, OFSY and OFSZ charS ********************/ +/* ~ SET & GET */ +// OFSX, OFSY and OFSZ: User Offset Adjustments in Twos Complement Format +// Scale Factor of 15.6mg/LSB +void ADXL345::setAxisOffset(int x, int y, int z) { + writeToI2C(ADXL345_OFSX, char (x)); + writeToI2C(ADXL345_OFSY, char (y)); + writeToI2C(ADXL345_OFSZ, char (z)); +} + +void ADXL345::getAxisOffset(int* x, int* y, int*z) { + char _b; + readFromI2C(ADXL345_OFSX, 1, &_b); + *x = int (_b); + readFromI2C(ADXL345_OFSY, 1, &_b); + *y = int (_b); + readFromI2C(ADXL345_OFSZ, 1, &_b); + *z = int (_b); +} + +/****************************** DUR char ****************************/ +/* ~ SET & GET */ +// DUR char: Contains an Unsigned Time Value Representing the Max Time +// that an Event must be Above the THRESH_TAP Threshold to qualify +// as a Tap Event +// The scale factor is 625µs/LSB +// Value of 0 Disables the Tap/Double Tap Funcitons. Max value is 255. +void ADXL345::setTapDuration(int tapDuration) { + if(tapDuration < 0) + { + tapDuration = 0; + } + if(tapDuration > 255) + { + tapDuration = 255; + } + char _b = char (tapDuration); + writeToI2C(ADXL345_DUR, _b); +} + +int ADXL345::getTapDuration() { + char _b; + readFromI2C(ADXL345_DUR, 1, &_b); + return int (_b); +} + +/************************** LATENT REGISTER *************************/ +/* ~ SET & GET */ +// Contains Unsigned Time Value Representing the Wait Time from the Detection +// of a Tap Event to the Start of the Time Window (defined by the Window +// Register) during which a possible Second Tap Even can be Detected. +// Scale Factor is 1.25ms/LSB. +// A Value of 0 Disables the Double Tap Function. +// It Accepts a Maximum Value of 255. +void ADXL345::setDoubleTapLatency(int doubleTapLatency) { + char _b = char (doubleTapLatency); + writeToI2C(ADXL345_LATENT, _b); +} + +int ADXL345::getDoubleTapLatency() { + char _b; + readFromI2C(ADXL345_LATENT, 1, &_b); + return int (_b); +} + +/************************** WINDOW REGISTER *************************/ +/* ~ SET & GET */ +// Contains an Unsigned Time Value Representing the Amount of Time +// After the Expiration of the Latency Time (determined by Latent register) +// During which a Second Valid Tape can Begin. +// Scale Factor is 1.25ms/LSB. +// Value of 0 Disables the Double Tap Function. +// It Accepts a Maximum Value of 255. +void ADXL345::setDoubleTapWindow(int doubleTapWindow) { + if(doubleTapWindow < 0) + { + doubleTapWindow = 0; + } + if(doubleTapWindow > 255) + { + doubleTapWindow = 255; + } + char _b = char (doubleTapWindow); + writeToI2C(ADXL345_WINDOW, _b); +} + +int ADXL345::getDoubleTapWindow() { + char _b; + readFromI2C(ADXL345_WINDOW, 1, &_b); + return int (_b); +} + +/*********************** THRESH_ACT REGISTER ************************/ +/* ~ SET & GET */ +// Holds the Threshold Value for Detecting Activity. +// Data Format is Unsigned, so the Magnitude of the Activity Event is Compared +// with the Value is Compared with the Value in the THRESH_ACT Register. +// The Scale Factor is 62.5mg/LSB. +// Value of 0 may Result in Undesirable Behavior if the Activity Interrupt Enabled. +// It Accepts a Maximum Value of 255. +void ADXL345::setActivityThreshold(int activityThreshold) { + if(activityThreshold < 0) + { + activityThreshold = 0; + } + if(activityThreshold > 255) + { + activityThreshold = 255; + } + char _b = char (activityThreshold); + writeToI2C(ADXL345_THRESH_ACT, _b); +} + +// Gets the THRESH_ACT char +int ADXL345::getActivityThreshold() { + char _b; + readFromI2C(ADXL345_THRESH_ACT, 1, &_b); + return int (_b); +} + +/********************** THRESH_INACT REGISTER ***********************/ +/* ~ SET & GET */ +// Holds the Threshold Value for Detecting Inactivity. +// The Data Format is Unsigned, so the Magnitude of the INactivity Event is +// Compared with the value in the THRESH_INACT Register. +// Scale Factor is 62.5mg/LSB. +// Value of 0 May Result in Undesirable Behavior if the Inactivity Interrupt Enabled. +// It Accepts a Maximum Value of 255. +void ADXL345::setInactivityThreshold(int inactivityThreshold) { + if(inactivityThreshold < 0) + { + inactivityThreshold = 0; + } + if(inactivityThreshold > 255) + { + inactivityThreshold = 255; + } + char _b = char (inactivityThreshold); + writeToI2C(ADXL345_THRESH_INACT, _b); +} + +int ADXL345::getInactivityThreshold() { + char _b; + readFromI2C(ADXL345_THRESH_INACT, 1, &_b); + return int (_b); +} + +/*********************** TIME_INACT RESIGER *************************/ +/* ~ SET & GET */ +// Contains an Unsigned Time Value Representing the Amount of Time that +// Acceleration must be Less Than the Value in the THRESH_INACT Register +// for Inactivity to be Declared. +// Uses Filtered Output Data* unlike other Interrupt Functions +// Scale Factor is 1sec/LSB. +// Value Must Be Between 0 and 255. +void ADXL345::setTimeInactivity(int timeInactivity) { + if(timeInactivity < 0) + { + timeInactivity = 0; + } + if(timeInactivity > 255) + { + timeInactivity = 255; + } + char _b = char (timeInactivity); + writeToI2C(ADXL345_TIME_INACT, _b); +} + +int ADXL345::getTimeInactivity() { + char _b; + readFromI2C(ADXL345_TIME_INACT, 1, &_b); + return int (_b); +} + +/*********************** THRESH_FF Register *************************/ +/* ~ SET & GET */ +// Holds the Threshold Value, in Unsigned Format, for Free-Fall Detection +// The Acceleration on all Axes is Compared with the Value in THRES_FF to +// Determine if a Free-Fall Event Occurred. +// Scale Factor is 62.5mg/LSB. +// Value of 0 May Result in Undesirable Behavior if the Free-Fall interrupt Enabled. +// Accepts a Maximum Value of 255. +void ADXL345::setFreeFallThreshold(int freeFallThreshold) { + if(freeFallThreshold < 0) + { + freeFallThreshold = 0; + } + if(freeFallThreshold > 255) + { + freeFallThreshold = 255; + } + char _b = char (freeFallThreshold); + writeToI2C(ADXL345_THRESH_FF, _b); +} + +int ADXL345::getFreeFallThreshold() { + char _b; + readFromI2C(ADXL345_THRESH_FF, 1, &_b); + return int (_b); +} + +/************************ TIME_FF Register **************************/ +/* ~ SET & GET */ +// Stores an Unsigned Time Value Representing the Minimum Time that the Value +// of all Axes must be Less Than THRES_FF to Generate a Free-Fall Interrupt. +// Scale Factor is 5ms/LSB. +// Value of 0 May Result in Undesirable Behavior if the Free-Fall Interrupt Enabled. +// Accepts a Maximum Value of 255. +void ADXL345::setFreeFallDuration(int freeFallDuration) { + if(freeFallDuration < 0) + { + freeFallDuration = 0; + } + if(freeFallDuration > 255) + { + freeFallDuration = 255; + } + char _b = char (freeFallDuration); + writeToI2C(ADXL345_TIME_FF, _b); +} + +int ADXL345::getFreeFallDuration() { + char _b; + readFromI2C(ADXL345_TIME_FF, 1, &_b); + return int (_b); +} + +/************************** ACTIVITY BITS ***************************/ +/* */ +bool ADXL345::isActivityXEnabled() { + return getRegisterBit(ADXL345_ACT_INACT_CTL, 6); +} +bool ADXL345::isActivityYEnabled() { + return getRegisterBit(ADXL345_ACT_INACT_CTL, 5); +} +bool ADXL345::isActivityZEnabled() { + return getRegisterBit(ADXL345_ACT_INACT_CTL, 4); +} +bool ADXL345::isInactivityXEnabled() { + return getRegisterBit(ADXL345_ACT_INACT_CTL, 2); +} +bool ADXL345::isInactivityYEnabled() { + return getRegisterBit(ADXL345_ACT_INACT_CTL, 1); +} +bool ADXL345::isInactivityZEnabled() { + return getRegisterBit(ADXL345_ACT_INACT_CTL, 0); +} + +void ADXL345::setActivityX(bool state) { + setRegisterBit(ADXL345_ACT_INACT_CTL, 6, state); +} +void ADXL345::setActivityY(bool state) { + setRegisterBit(ADXL345_ACT_INACT_CTL, 5, state); +} +void ADXL345::setActivityZ(bool state) { + setRegisterBit(ADXL345_ACT_INACT_CTL, 4, state); +} +void ADXL345::setActivityXYZ(bool stateX, bool stateY, bool stateZ) { + setActivityX(stateX); + setActivityY(stateY); + setActivityZ(stateZ); +} +void ADXL345::setInactivityX(bool state) { + setRegisterBit(ADXL345_ACT_INACT_CTL, 2, state); +} +void ADXL345::setInactivityY(bool state) { + setRegisterBit(ADXL345_ACT_INACT_CTL, 1, state); +} +void ADXL345::setInactivityZ(bool state) { + setRegisterBit(ADXL345_ACT_INACT_CTL, 0, state); +} +void ADXL345::setInactivityXYZ(bool stateX, bool stateY, bool stateZ) { + setInactivityX(stateX); + setInactivityY(stateY); + setInactivityZ(stateZ); +} + +bool ADXL345::isActivityAc() { + return getRegisterBit(ADXL345_ACT_INACT_CTL, 7); +} +bool ADXL345::isInactivityAc(){ + return getRegisterBit(ADXL345_ACT_INACT_CTL, 3); +} + +void ADXL345::setActivityAc(bool state) { + setRegisterBit(ADXL345_ACT_INACT_CTL, 7, state); +} +void ADXL345::setInactivityAc(bool state) { + setRegisterBit(ADXL345_ACT_INACT_CTL, 3, state); +} + +/************************* SUPPRESS BITS ****************************/ +/* */ +bool ADXL345::getSuppressBit(){ + return getRegisterBit(ADXL345_TAP_AXES, 3); +} +void ADXL345::setSuppressBit(bool state) { + setRegisterBit(ADXL345_TAP_AXES, 3, state); +} + +/**************************** TAP BITS ******************************/ +/* */ +bool ADXL345::isTapDetectionOnX(){ + return getRegisterBit(ADXL345_TAP_AXES, 2); +} +void ADXL345::setTapDetectionOnX(bool state) { + setRegisterBit(ADXL345_TAP_AXES, 2, state); +} +bool ADXL345::isTapDetectionOnY(){ + return getRegisterBit(ADXL345_TAP_AXES, 1); +} +void ADXL345::setTapDetectionOnY(bool state) { + setRegisterBit(ADXL345_TAP_AXES, 1, state); +} +bool ADXL345::isTapDetectionOnZ(){ + return getRegisterBit(ADXL345_TAP_AXES, 0); +} +void ADXL345::setTapDetectionOnZ(bool state) { + setRegisterBit(ADXL345_TAP_AXES, 0, state); +} + +void ADXL345::setTapDetectionOnXYZ(bool stateX, bool stateY, bool stateZ) { + setTapDetectionOnX(stateX); + setTapDetectionOnY(stateY); + setTapDetectionOnZ(stateZ); +} + +bool ADXL345::isActivitySourceOnX(){ + return getRegisterBit(ADXL345_ACT_TAP_STATUS, 6); +} +bool ADXL345::isActivitySourceOnY(){ + return getRegisterBit(ADXL345_ACT_TAP_STATUS, 5); +} +bool ADXL345::isActivitySourceOnZ(){ + return getRegisterBit(ADXL345_ACT_TAP_STATUS, 4); +} + +bool ADXL345::isTapSourceOnX(){ + return getRegisterBit(ADXL345_ACT_TAP_STATUS, 2); +} +bool ADXL345::isTapSourceOnY(){ + return getRegisterBit(ADXL345_ACT_TAP_STATUS, 1); +} +bool ADXL345::isTapSourceOnZ(){ + return getRegisterBit(ADXL345_ACT_TAP_STATUS, 0); +} + +/*************************** ASLEEP BIT *****************************/ +/* */ +bool ADXL345::isAsleep(){ + return getRegisterBit(ADXL345_ACT_TAP_STATUS, 3); +} + +/************************** LOW POWER BIT ***************************/ +/* */ +bool ADXL345::isLowPower(){ + return getRegisterBit(ADXL345_BW_RATE, 4); +} +void ADXL345::setLowPower(bool state) { + setRegisterBit(ADXL345_BW_RATE, 4, state); +} + + +/************************* TRIGGER CHECK ***************************/ +/* */ +// Check if Action was Triggered in Interrupts +// Example triggered(interrupts, ADXL345_SINGLE_TAP); +bool ADXL345::triggered(char interrupts, int mask){ + return ((interrupts >> mask) & 1); +} + +/* + ADXL345_DATA_READY + ADXL345_SINGLE_TAP + ADXL345_DOUBLE_TAP + ADXL345_ACTIVITY + ADXL345_INACTIVITY + ADXL345_FREE_FALL + ADXL345_WATERMARK + ADXL345_OVERRUNY + */ + + +char ADXL345::getInterruptSource() { + char _b; + readFromI2C(ADXL345_INT_SOURCE, 1, &_b); + return _b; +} + +bool ADXL345::getInterruptSource(char interruptBit) { + return getRegisterBit(ADXL345_INT_SOURCE,interruptBit); +} + +bool ADXL345::getInterruptMapping(char interruptBit) { + return getRegisterBit(ADXL345_INT_MAP,interruptBit); +} + +/*********************** INTERRUPT MAPPING **************************/ +/* Set the Mapping of an Interrupt to pin1 or pin2 */ +// eg: setInterruptMapping(ADXL345_INT_DOUBLE_TAP_BIT,ADXL345_INT2_PIN); +void ADXL345::setInterruptMapping(char interruptBit, bool interruptPin) { + setRegisterBit(ADXL345_INT_MAP, interruptBit, interruptPin); +} + +void ADXL345::setImportantInterruptMapping(int single_tap, int double_tap, int free_fall, int activity, int inactivity) { + if(single_tap == 1) { + setInterruptMapping( ADXL345_INT_SINGLE_TAP_BIT, ADXL345_INT1_PIN );} + else if(single_tap == 2) { + setInterruptMapping( ADXL345_INT_SINGLE_TAP_BIT, ADXL345_INT2_PIN );} + + if(double_tap == 1) { + setInterruptMapping( ADXL345_INT_DOUBLE_TAP_BIT, ADXL345_INT1_PIN );} + else if(double_tap == 2) { + setInterruptMapping( ADXL345_INT_DOUBLE_TAP_BIT, ADXL345_INT2_PIN );} + + if(free_fall == 1) { + setInterruptMapping( ADXL345_INT_FREE_FALL_BIT, ADXL345_INT1_PIN );} + else if(free_fall == 2) { + setInterruptMapping( ADXL345_INT_FREE_FALL_BIT, ADXL345_INT2_PIN );} + + if(activity == 1) { + setInterruptMapping( ADXL345_INT_ACTIVITY_BIT, ADXL345_INT1_PIN );} + else if(activity == 2) { + setInterruptMapping( ADXL345_INT_ACTIVITY_BIT, ADXL345_INT2_PIN );} + + if(inactivity == 1) { + setInterruptMapping( ADXL345_INT_INACTIVITY_BIT, ADXL345_INT1_PIN );} + else if(inactivity == 2) { + setInterruptMapping( ADXL345_INT_INACTIVITY_BIT, ADXL345_INT2_PIN );} +} + +bool ADXL345::isInterruptEnabled(char interruptBit) { + return getRegisterBit(ADXL345_INT_ENABLE,interruptBit); +} + +void ADXL345::setInterrupt(char interruptBit, bool state) { + setRegisterBit(ADXL345_INT_ENABLE, interruptBit, state); +} + +void ADXL345::singleTapINT(bool status) { + if(status) { + setInterrupt( ADXL345_INT_SINGLE_TAP_BIT, 1); + } + else { + setInterrupt( ADXL345_INT_SINGLE_TAP_BIT, 0); + } +} +void ADXL345::doubleTapINT(bool status) { + if(status) { + setInterrupt( ADXL345_INT_DOUBLE_TAP_BIT, 1); + } + else { + setInterrupt( ADXL345_INT_DOUBLE_TAP_BIT, 0); + } +} +void ADXL345::FreeFallINT(bool status) { + if(status) { + setInterrupt( ADXL345_INT_FREE_FALL_BIT, 1); + } + else { + setInterrupt( ADXL345_INT_FREE_FALL_BIT, 0); + } +} +void ADXL345::ActivityINT(bool status) { + if(status) { + setInterrupt( ADXL345_INT_ACTIVITY_BIT, 1); + } + else { + setInterrupt( ADXL345_INT_ACTIVITY_BIT, 0); + } +} +void ADXL345::InactivityINT(bool status) { + if(status) { + setInterrupt( ADXL345_INT_INACTIVITY_BIT, 1); + } + else { + setInterrupt( ADXL345_INT_INACTIVITY_BIT, 0); + } +} + +void ADXL345::setRegisterBit(char regAdress, int bitPos, bool state) { + char _b; + readFromI2C(regAdress, 1, &_b); + if (state) { + _b |= (1 << bitPos); // Forces nth Bit of _b to 1. Other Bits Unchanged. + } + else { + _b &= ~(1 << bitPos); // Forces nth Bit of _b to 0. Other Bits Unchanged. + } + writeToI2C(regAdress, _b); +} + +bool ADXL345::getRegisterBit(char regAdress, int bitPos) { + char _b; + readFromI2C(regAdress, 1, &_b); + return ((_b >> bitPos) & 1); +}