/* A library for Grove - 3-Axis Digital Accelerometer ±2g to 16g Ultra-low Power(BMA400) Copyright (c) 2018 seeed technology co., ltd. Author : Wayen Weng Create Time : June 2018 Change Log : The MIT License (MIT) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "BMA400.h" BMA400::BMA400(void) { devAddr = BMA400_ADDRESS; } void BMA400::initialize(power_type_t power, scale_type_t range, odr_type_t odr) { setPoweMode(power); setFullScaleRange(range); setOutputDataRate(odr); } void BMA400::gen1Setup(int enable, data_auto_low_type_t low_power_trigger, data_src_type_t filt, gen1_act_refu_type_t refu, gen1_act_hyst_type_t hyst, gen1_comb_sel_type_t comb, gen1_criterion_sel_type_t crit, uint8_t thresh, uint8_t intduration, latched_interrupt_type_t latch, uint8_t active_state) { if(enable == 1) { gen1map(); XYZcontrol(); activeState(active_state); gen1DataSource(filt); gen1RefUpdate(refu); gen1hysteresis(hyst); gen1combsel(comb); latchedInterrupt(latch); gen1criterionsel(crit); gen1interruptThreshold(thresh); gen1interruptDuration(intduration); gen1interruptDuration2(intduration); delay(100); autolowpower(low_power_trigger); gen1Enable(); } } void BMA400::wakeupInterrupt(int enable, data_auto_low_type_t low_power_trigger, wkup_enable_type_t enableXYZ,wakeup_interrupt_type_t wkup_refu, uint8_t samples, uint8_t threshold_wakeup, uint8_t wkup_x,uint8_t wkup_y, uint8_t wkup_z) { if(enable == 1) { wakeupmap(); XYZwakeup(enableXYZ); wakeupRefUpdate(wkup_refu); wakeupSamples(samples); wakeupThreshold(threshold_wakeup); wakeupX(wkup_x); wakeupY(wkup_y); wakeupZ(wkup_z); delay(100); autowakeup(low_power_trigger); } } void BMA400::activeState(uint8_t state) { uint8_t data = 0; data = read8(BMA400_INT_1_2_CTRL); data = (data & 0xef) | (state << 1); write8(BMA400_INT_1_2_CTRL, data); } void BMA400::wakeupSamples(uint8_t samples) { uint8_t data = 0; data = read8(BMA400_WAKE_UP_INT_CONFIG_0); data = (data & 0xf3) | (samples << 2); write8(BMA400_WAKE_UP_INT_CONFIG_0, data); } void BMA400::XYZcontrol(void) { uint8_t data = 0; data = read8(BMA400_GEN_1_INT_CONFIG_0); data = (data & 0x1f); write8(BMA400_ACC_CONFIG_0, data); } void BMA400::gen1interruptThreshold(uint8_t gen1thresh) { uint8_t data = 0; data = read8(BMA400_GEN_1_INT_CONFIG_2); data = (data & 0x00) | gen1thresh; write8(BMA400_GEN_1_INT_CONFIG_2, data); } void BMA400::gen1map(void) { uint8_t data = 0; data = read8(BMA400_INT_2_MAP); data = (data & 0x04); write8(BMA400_INT_2_MAP, data); } void BMA400::wakeupmap(void) { uint8_t data = 0; data = read8(BMA400_INT_1_MAP); data = (data & 0x01); write8(BMA400_INT_1_MAP, data); } void BMA400::latchedInterrupt(latched_interrupt_type_t latch) { uint8_t data = 0; data = read8(BMA400_INT_CONFIG_1); data = (data & 0x80) | (latch << 4); write8(BMA400_INT_CONFIG_1, data); } void BMA400::gen1interruptDuration2(uint8_t intduration) { uint8_t data = 0; data = read8(BMA400_GEN_1_INT_CONFIG_3_1); data = (data & 0x00) | intduration; write8(BMA400_GEN_1_INT_CONFIG_3_1, data); } void BMA400::gen1RefUpdate(gen1_act_refu_type_t refu) { uint8_t data = 0; data = read8(BMA400_GEN_1_INT_CONFIG_0); data = (data & 0xf3) | (refu << 2); write8(BMA400_GEN_1_INT_CONFIG_0, data); } void BMA400::wakeupX(uint8_t wkup_x) { uint8_t data = 0; data = read8(BMA400_WAKE_UP_INT_CONFIG_2); data = (data & 0x00) | wkup_x; write8(BMA400_WAKE_UP_INT_CONFIG_2, data); } void BMA400::wakeupY(uint8_t wkup_y) { uint8_t data = 0; data = read8(BMA400_WAKE_UP_INT_CONFIG_3); data = (data & 0x00) | wkup_y; write8(BMA400_WAKE_UP_INT_CONFIG_3, data); } void BMA400::wakeupZ(uint8_t wkup_z) { uint8_t data = 0; data = read8(BMA400_WAKE_UP_INT_CONFIG_4); data = (data & 0x00) | wkup_z; write8(BMA400_WAKE_UP_INT_CONFIG_4, data); } void BMA400::gen1combsel(gen1_comb_sel_type_t comb) { uint8_t data = 0; data = read8(BMA400_GEN_1_INT_CONFIG_1); data = (data & 0xfe) | comb; write8(BMA400_GEN_1_INT_CONFIG_1, data); } void BMA400::gen1hysteresis(gen1_act_hyst_type_t hyst) { uint8_t data = 0; data = read8(BMA400_GEN_1_INT_CONFIG_0); data = (data & 0xc0) | hyst; write8(BMA400_GEN_1_INT_CONFIG_0, data); } void BMA400::wakeupRefUpdate(wakeup_interrupt_type_t wkup_refu) { uint8_t data = 0; data = read8(BMA400_WAKE_UP_INT_CONFIG_0); data = (data & 0x0c) | wkup_refu; write8(BMA400_WAKE_UP_INT_CONFIG_0, data); } void BMA400::sampleNumber(uint8_t samples) { uint8_t data = 0; data = read8(BMA400_WAKE_UP_INT_CONFIG_0); data = (data & 0xe3) | (samples << 2); write8(BMA400_WAKE_UP_INT_CONFIG_0, data); } void BMA400::gen1DataSource(data_src_type_t filt) { uint8_t data = 0; data = read8(BMA400_GEN_1_INT_CONFIG_0); data = (data & 0xef) | (filt << 4); write8(BMA400_GEN_1_INT_CONFIG_0, data); } void BMA400::autolowpower(data_auto_low_type_t low_power_trigger) { uint8_t data = 0; data = read8(BMA400_AUTO_LOW_POW_1); data = (data &0xfe) | (low_power_trigger << 1); write8(BMA400_AUTO_LOW_POW_1, data); } void BMA400::autowakeup(data_auto_low_type_t low_power_trigger) { uint8_t data = 0; data = read8(BMA400_AUTO_WAKE_UP_1); data = (data &0xfe) | (low_power_trigger << 1); write8(BMA400_AUTO_WAKE_UP_1, data); } void BMA400::XYZwakeup(wkup_enable_type_t enableXYZWakeup) { uint8_t data1 = 0, data2 = 0, data3 = 0; data1 = read8(BMA400_WAKE_UP_INT_CONFIG_0); data1 = (data1 & 0xd0) | (enableXYZWakeup << 5); write8(BMA400_WAKE_UP_INT_CONFIG_0, data1); data2 = read8(BMA400_WAKE_UP_INT_CONFIG_0); data2 = (data2 & 0xb0) | (enableXYZWakeup << 6); write8(BMA400_WAKE_UP_INT_CONFIG_0, data2); data3 = read8(BMA400_WAKE_UP_INT_CONFIG_0); data3 = (data3 & 0x70) | (enableXYZWakeup << 7); write8(BMA400_WAKE_UP_INT_CONFIG_0, data3); } void BMA400::wakeupThreshold(uint8_t threshold_wakeup) { uint8_t data = 0; data = read8(BMA400_WAKE_UP_INT_CONFIG_1); data = (data & 0x00) | threshold_wakeup; write8(BMA400_WAKE_UP_INT_CONFIG_1, data); } void BMA400::gen1criterionsel(gen1_criterion_sel_type_t crit) { uint8_t data = 0; data = read8(BMA400_GEN_1_INT_CONFIG_1); data = (data & 0xfd) | crit; write8(BMA400_GEN_1_INT_CONFIG_1, data); } void BMA400::gen1Enable(void) { uint8_t data = 0; data = read8(BMA400_INT_CONFIG_0); data = (data & 0x04); write8(BMA400_INT_CONFIG_0, data); } void BMA400::gen1interruptDuration(uint8_t intduration) { uint8_t data = 0; data = read8(BMA400_GEN_1_INT_CONFIG_3); data = (data & 0x00) | intduration; write8(BMA400_GEN_1_INT_CONFIG_3, data); } bool BMA400::isConnection(void) { return (getDeviceID() == 0x90); } uint8_t BMA400::getDeviceID(void) { return read8(BMA400_CHIPID); } void BMA400::reset(void) { write8(BMA400_CMD, 0xb6); } void BMA400::setPoweMode(power_type_t mode) { uint8_t data = 0; data = read8(BMA400_ACC_CONFIG_0); data = (data & 0xfc) | mode; write8(BMA400_ACC_CONFIG_0, data); } void BMA400::setFullScaleRange(scale_type_t range) { uint8_t data = 0; if (range == RANGE_2G) { accRange = 2000; } else if (range == RANGE_4G) { accRange = 4000; } else if (range == RANGE_8G) { accRange = 8000; } else if (range == RANGE_16G) { accRange = 16000; } data = read8(BMA400_ACC_CONFIG_1); data = (data & 0x3f) | (range << 6); write8(BMA400_ACC_CONFIG_1, data); } void BMA400::setOutputDataRate(odr_type_t odr) { uint8_t data = 0; data = read8(BMA400_ACC_CONFIG_1); data = (data & 0xf0) | odr; write8(BMA400_ACC_CONFIG_1, data); } void BMA400::getAcceleration(float* x, float* y, float* z) { uint8_t buf[6] = {0}; uint16_t ax = 0, ay = 0, az = 0; float value = 0; read(BMA400_ACC_X_LSB, buf, 6); ax = buf[0] | (buf[1] << 8); ay = buf[2] | (buf[3] << 8); az = buf[4] | (buf[5] << 8); if (ax > 2047) { ax = ax - 4096; } if (ay > 2047) { ay = ay - 4096; } if (az > 2047) { az = az - 4096; } value = (int16_t)ax; *x = accRange * value / 2048; value = (int16_t)ay; *y = accRange * value / 2048; value = (int16_t)az; *z = accRange * value / 2048; } float BMA400::getAccelerationX(void) { uint16_t ax = 0; float value = 0; ax = read16(BMA400_ACC_X_LSB); if (ax > 2047) { ax = ax - 4096; } value = (int16_t)ax; value = accRange * value / 2048; return value; } float BMA400::getAccelerationY(void) { uint16_t ay = 0; float value = 0; ay = read16(BMA400_ACC_Y_LSB); if (ay > 2047) { ay = ay - 4096; } value = (int16_t)ay; value = accRange * value / 2048; return value; } float BMA400::getAccelerationZ(void) { uint16_t az = 0; float value = 0; az = read16(BMA400_ACC_Z_LSB); if (az > 2047) { az = az - 4096; } value = (int16_t)az; value = accRange * value / 2048; return value; } int16_t BMA400::getTemperature(void) { int8_t data = 0; int16_t temp = 0; data = (int8_t)read8(BMA400_TEMP_DATA); temp = data / 2 + 23; return temp; } void BMA400::write8(uint8_t reg, uint8_t val) { Wire.beginTransmission(devAddr); Wire.write(reg); Wire.write(val); Wire.endTransmission(); } uint8_t BMA400::read8(uint8_t reg) { uint8_t data = 0; Wire.beginTransmission(devAddr); Wire.write(reg); Wire.endTransmission(); Wire.requestFrom((int16_t)devAddr, 1); while (Wire.available()) { data = Wire.read(); } return data; } uint16_t BMA400::read16(uint8_t reg) { uint16_t msb = 0, lsb = 0; Wire.beginTransmission(devAddr); Wire.write(reg); Wire.endTransmission(); Wire.requestFrom((int16_t)devAddr, 2); while (Wire.available()) { lsb = Wire.read(); msb = Wire.read(); } return (lsb | (msb << 8)); } uint32_t BMA400::read24(uint8_t reg) { uint32_t hsb = 0, msb = 0, lsb = 0; Wire.beginTransmission(devAddr); Wire.write(reg); Wire.endTransmission(); Wire.requestFrom((int16_t)devAddr, 3); while (Wire.available()) { lsb = Wire.read(); msb = Wire.read(); hsb = Wire.read(); } return (lsb | (msb << 8) | (hsb << 16)); } void BMA400::read(uint8_t reg, uint8_t* buf, uint16_t len) { Wire.beginTransmission(devAddr); Wire.write(reg); Wire.endTransmission(); Wire.requestFrom((int16_t)devAddr, len); while (Wire.available()) { for (uint16_t i = 0; i < len; i ++) { buf[i] = Wire.read(); } } } BMA400 bma400;