diff --git a/cmake/boardcore.cmake b/cmake/boardcore.cmake index a38c686066fed81df16df3fd247bf487af8f56e9..c8a098bfa534801c17a0535e20143685b34fbdda 100644 --- a/cmake/boardcore.cmake +++ b/cmake/boardcore.cmake @@ -75,6 +75,7 @@ foreach(OPT_BOARD ${BOARDS}) ${SBS_BASE}/src/shared/sensors/BMX160/BMX160.cpp ${SBS_BASE}/src/shared/sensors/BMX160/BMX160WithCorrection.cpp ${SBS_BASE}/src/shared/sensors/HX711/HX711.cpp + ${SBS_BASE}/src/shared/sensors/LIS3MDL/LIS3MDL.cpp ${SBS_BASE}/src/shared/sensors/calibration/SensorDataExtra.cpp ${SBS_BASE}/src/shared/sensors/MAX6675/MAX6675.cpp ${SBS_BASE}/src/shared/sensors/MAX31855/MAX31855.cpp diff --git a/src/shared/sensors/BMP280/BMP280.h b/src/shared/sensors/BMP280/BMP280.h index 8b3263dfaa376c6108bec7bf03ef154bace53423..5786a0c4854d033077e8f91249c6fec5b740e0d0 100644 --- a/src/shared/sensors/BMP280/BMP280.h +++ b/src/shared/sensors/BMP280/BMP280.h @@ -242,7 +242,7 @@ private: */ bool checkWhoAmI(); - enum BMP280Registers : uint8_t + enum Registers : uint8_t { REG_CALIB_0 = 0x88, // Calibration register 1-25 diff --git a/src/shared/sensors/LIS3MDL/LIS3MDL.cpp b/src/shared/sensors/LIS3MDL/LIS3MDL.cpp new file mode 100644 index 0000000000000000000000000000000000000000..10e257b61c226c10acbf6d51cb85b1d79825970a --- /dev/null +++ b/src/shared/sensors/LIS3MDL/LIS3MDL.cpp @@ -0,0 +1,325 @@ +/* Copyright (c) 2020 Skyward Experimental Rocketry + * Author: Riccardo Musso + * + * 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 "LIS3MDL.h" + +#include <drivers/timer/TimestampTimer.h> + +namespace Boardcore +{ + +LIS3MDL::LIS3MDL(SPIBusInterface& bus, miosix::GpioPin pin, + SPIBusConfig spiConfig, Config config) + : mSlave(bus, pin, spiConfig), mConfig(config), currDiv(0), + isInitialized(false) +{ +} + +bool LIS3MDL::init() +{ + if (isInitialized) + { + LOG_ERR(logger, "Attempted to initialized sensor twice but failed"); + lastError = ALREADY_INIT; + return false; + } + + { + SPITransaction spi(mSlave); + uint8_t res = spi.readRegister(WHO_AM_I); + + if (res != WHO_AM_I_VALUE) + { + LOG_ERR(logger, + "WHO_AM_I value differs from expectation: read 0x{02x} " + "but expected 0x{02x}", + res, WHO_AM_I_VALUE); + lastError = INVALID_WHOAMI; + return false; + } + } + + isInitialized = true; + return applyConfig(mConfig); +} + +bool LIS3MDL::selfTest() +{ + if (!isInitialized) + { + LOG_ERR(logger, "Invoked selfTest() but sensor was uninitialized"); + lastError = NOT_INIT; + return false; + } + + // NUM_SAMPLES: # of samples used to take the average value before tests + constexpr int NUM_SAMPLES = 5; + + // NUM_TESTS: # of actual tests + constexpr int NUM_TESTS = 5; + + // SLEEP_TIME: milliseconds between samples/tests + constexpr int SLEEP_TIME = 50; + + // Absolute value of extra tolerance + constexpr float t = 0.1f; + + // Range which delta must be between, one for axis and expressed as {min, + // max}. The unit is gauss. + constexpr float r[3][2] = {{1.f, 3.f}, {1.f, 3.f}, {0.1f, 1.f}}; + + float avgX = 0.f, avgY = 0.f, avgZ = 0.f; + + { + SPITransaction spi(mSlave); + spi.writeRegister(CTRL_REG2, FS_12_GAUSS); + } + updateUnit(FS_12_GAUSS); + + for (int i = 0; i < NUM_SAMPLES; ++i) + { + miosix::Thread::sleep(SLEEP_TIME); + + LIS3MDLData lastData = sampleImpl(); + avgX += lastData.magneticFieldX; + avgY += lastData.magneticFieldY; + avgZ += lastData.magneticFieldZ; + } + + avgX /= NUM_SAMPLES; + avgY /= NUM_SAMPLES; + avgZ /= NUM_SAMPLES; + + // Setting up the sensor settings for proper usage of the self test mode. + { + SPITransaction spi(mSlave); + + spi.writeRegister(CTRL_REG1, ODR_20_HZ | ENABLE_SELF_TEST | + (OM_ULTRA_HIGH_POWER << 4)); + spi.writeRegister(CTRL_REG2, FS_12_GAUSS); + spi.writeRegister(CTRL_REG4, OM_ULTRA_HIGH_POWER << 2); + } + + // Deltas: absolute difference between the values measured before and after + float d[3]; + + for (int i = 0; i < NUM_TESTS; ++i) + { + miosix::Thread::sleep(SLEEP_TIME); + + LIS3MDLData lastData = sampleImpl(); + d[0] = std::abs(lastData.magneticFieldX - avgX); + d[1] = std::abs(lastData.magneticFieldY - avgY); + d[2] = std::abs(lastData.magneticFieldZ - avgZ); + + bool passed = true; + for (int j = 0; j < 3; ++j) + if (d[j] < (r[j][0] - t) || d[j] > (r[j][1] + t)) + passed = false; + + if (!passed) + { + // reset configuration, then return + applyConfig(mConfig); + + lastError = SELF_TEST_FAIL; + return false; + } + } + + return applyConfig(mConfig); +} + +bool LIS3MDL::applyConfig(Config config) +{ + + SPITransaction spi(mSlave); + uint8_t reg = 0, err = 0; + + mConfig = config; + currDiv = 0; + + // CTRL_REG1 + if (config.enableTemperature) + { + reg = ENABLE_TEMPERATURE; + } + reg |= config.odr; + + // odr <= 80Hz + if (!(config.odr & FAST_ODR_BIT)) + reg |= config.xyMode << 4; + spi.writeRegister(CTRL_REG1, reg); + err |= spi.readRegister(CTRL_REG1) != reg; + + // CTRL_REG2 + reg = config.scale; + spi.writeRegister(CTRL_REG2, reg); + err |= spi.readRegister(CTRL_REG2) != reg; + + // CTRL_REG3 + reg = CONTINUOS_CONVERSION; + spi.writeRegister(CTRL_REG3, reg); + err |= spi.readRegister(CTRL_REG3) != reg; + + // CTRL_REG4 + reg = config.zMode << 2; + spi.writeRegister(CTRL_REG4, reg); + err |= spi.readRegister(CTRL_REG4) != reg; + + // CTRL_REG5 + if (config.doBlockDataUpdate) + reg = ENABLE_BDU; + else + reg = 0; + + spi.writeRegister(CTRL_REG5, reg); + err |= spi.readRegister(CTRL_REG5) != reg; + + // INT_CFG + if (config.enableInterrupt[0]) + reg = ENABLE_INT_X; + else + reg = 0; + + if (config.enableInterrupt[1]) + reg |= ENABLE_INT_Y; + if (config.enableInterrupt[2]) + reg |= ENABLE_INT_Z; + + // The interrupt of at least one axis is enabled + if (reg) + reg |= ENABLE_INT_PIN; + + reg |= 0x08; + spi.writeRegister(INT_CFG, reg); + err |= spi.readRegister(INT_CFG) != reg; + + // INT_THS + uint16_t val = static_cast<uint16_t>(std::abs(config.threshold / mUnit)); + reg = static_cast<uint8_t>(0xff & val); + spi.writeRegister(INT_THS_L, reg); + err |= spi.readRegister(INT_THS_L) != reg; + + reg = static_cast<uint8_t>(val >> 8); + reg &= 0x7f; // Remove MSB (according to the datasheet, it must be zero) + spi.writeRegister(INT_THS_H, reg); + err |= spi.readRegister(INT_THS_H) != reg; + + // Set mUnit according to scale + updateUnit(config.scale); + + if (err) + { + LOG_ERR(logger, "Spi error"); + lastError = BUS_FAULT; + return false; + } + + return true; +} + +LIS3MDLData LIS3MDL::sampleImpl() +{ + if (!isInitialized) + { + LOG_ERR(logger, "Invoked sampleImpl() but sensor was uninitialized"); + lastError = NOT_INIT; + return lastSample; + } + + SPITransaction spi(mSlave); + + if (!spi.readRegister(STATUS_REG)) + { + lastError = NO_NEW_DATA; + return lastSample; + } + + // Reset any error + lastError = SensorErrors::NO_ERRORS; + + int16_t val; + LIS3MDLData newData{}; + + if (mConfig.enableTemperature) + { + if (currDiv == 0) + { + val = spi.readRegister(TEMP_OUT_L); + val |= spi.readRegister(TEMP_OUT_H) << 8; + + newData.temperatureTimestamp = + TimestampTimer::getInstance().getTimestamp(); + newData.temperature = static_cast<float>(val) / LSB_PER_CELSIUS + + REFERENCE_TEMPERATURE; + } + else + { + // Keep old value + newData.temperature = lastSample.temperature; + } + + currDiv = (currDiv + 1) % mConfig.temperatureDivider; + } + + newData.magneticFieldTimestamp = + TimestampTimer::getInstance().getTimestamp(); + + val = spi.readRegister(OUT_X_L); + val |= spi.readRegister(OUT_X_H) << 8; + newData.magneticFieldX = mUnit * val; + + val = spi.readRegister(OUT_Y_L); + val |= spi.readRegister(OUT_Y_H) << 8; + newData.magneticFieldY = mUnit * val; + + val = spi.readRegister(OUT_Z_L); + val |= spi.readRegister(OUT_Z_H) << 8; + newData.magneticFieldZ = mUnit * val; + + return newData; +} + +void LIS3MDL::updateUnit(FullScale fs) +{ + switch (fs) + { + case FS_4_GAUSS: + mUnit = 1.f / LSB_PER_GAUSS_FS_4; + break; + + case FS_8_GAUSS: + mUnit = 1.f / LSB_PER_GAUSS_FS_8; + break; + + case FS_12_GAUSS: + mUnit = 1.f / LSB_PER_GAUSS_FS_12; + break; + + case FS_16_GAUSS: + mUnit = 1.f / LSB_PER_GAUSS_FS_16; + break; + } +}; + +} // namespace Boardcore diff --git a/src/shared/sensors/LIS3MDL/LIS3MDL.h b/src/shared/sensors/LIS3MDL/LIS3MDL.h index 5038c79167cf32e0a4c3f3cf60b1a2182acb6f9f..698432e934826d9c7358fa81adbbcd2b151dbd22 100644 --- a/src/shared/sensors/LIS3MDL/LIS3MDL.h +++ b/src/shared/sensors/LIS3MDL/LIS3MDL.h @@ -24,11 +24,9 @@ #include <diagnostic/PrintLogger.h> #include <drivers/spi/SPIDriver.h> -#include <drivers/timer/TimestampTimer.h> #include <sensors/Sensor.h> #include "LIS3MDLData.h" -#include "miosix.h" namespace Boardcore { @@ -40,12 +38,11 @@ class LIS3MDL : public Sensor<LIS3MDLData> { public: /** - * Constants for Output Data Rate configuration. + * @brief Constants for Output Data Rate configuration. * - * Note: constants values already include - * axis operative mode selection and FAST_ODR - * options, so they are ready to be put inside - * CTRL_REG1 along with TEMP_EN and ST + * Note: constants values already include axis operative mode selection and + * FAST_ODR options, so they are ready to be put inside CTRL_REG1 along with + * TEMP_EN and ST. */ enum ODR : uint8_t { @@ -72,17 +69,17 @@ public: enum FullScale : uint8_t { - FS_4_GAUSS = 0x00, //!< +/- 4 gauss - FS_8_GAUSS = 0x20, //!< +/- 8 gauss - FS_12_GAUSS = 0x40, //!< +/- 12 gauss - FS_16_GAUSS = 0x60, //!< +/- 16 gauss + FS_4_GAUSS = 0x00, ///< +/- 4 gauss + FS_8_GAUSS = 0x20, ///< +/- 8 gauss + FS_12_GAUSS = 0x40, ///< +/- 12 gauss + FS_16_GAUSS = 0x60, ///< +/- 16 gauss }; /** - * @brief Operative mode constants + * @brief Operative mode constants. * - * Operative mode (that is power consumpion) options. - * Higher power implies better performance. + * Operative mode (that is power consumption) options. Higher power implies + * better performance. */ enum OperativeMode : uint8_t { @@ -102,14 +99,11 @@ public: */ struct Config { - /** - * @brief Constructor - * Creates an instance with the default settings. - */ Config() {} /** - * Full scale setting + * @brief Full scale setting. + * * @see LIS3MDL::FullScale */ FullScale scale = FS_8_GAUSS; @@ -119,21 +113,18 @@ public: * * Default: 40 Hz * - * Important: if ODR is set more than 80 Hz, - * operative mode of x and y axis will be set - * accordingly. + * Important: if ODR is set more than 80 Hz, operative mode of x and y + * axis will be set accordingly. * * @see LIS3MDL::ODR */ ODR odr = ODR_40_HZ; /** - * Operative mode for x and y axis. - * Note: if ODR is greater than 80 Hz, - * this setting will be ignored and actual - * operative mode will be set depending of - * the chosen frequency. - * Default: ultra high performance + * @brief Operative mode for x and y axis. + * + * Note: if ODR is greater than 80 Hz, this setting will be ignored and + * actual operative mode will be set depending of the chosen frequency. * * @see LIS3MDL::OperativeMode */ @@ -141,7 +132,6 @@ public: /** * Operative mode for z axis. - * Default: ultra high performance * * @see LIS3MDL::OM */ @@ -162,404 +152,60 @@ public: * to sampleImpl(), so for example: * 2 -> updated half the times, * 1 -> updated every time. - * By default the divider is set to 1 - * */ unsigned temperatureDivider = 1; /** * @brief Enables interrupts * - * Whether are interrupts enabled respectively - * on the x, y and z axis. If it is set to true - * on at least one axis, the interrupts will be - * generated otherwise, they will be completely - * disabled by the driver. - * - * Default: disabled on all axis. + * Whether are interrupts enabled respectively on the x, y and z axis. + * If it is set to true on at least one axis, the interrupts will be + * generated otherwise, they will be completely disabled by the driver. */ bool enableInterrupt[3] = {false, false, false}; /** * Absolute value of the threshold that triggers the interrupt - * (expressed in gauss). Default: 0 + * (expressed in gauss). */ float threshold = 0; /** * @brief BDU setting * - * If set to true, the sensor won't update the data - * until it is read, if false the sensor data will be - * continously updated. Default: false + * If set to true, the sensor won't update the data until it is read, if + * false the sensor data will be continuously updated. */ bool doBlockDataUpdate = false; }; - /** - * Constructs the default config for SPI Bus. - * - * @returns the default SPIBusConfig - */ - static SPIBusConfig getDefaultSPIConfig() - { - SPIBusConfig config{}; - config.clockDivider = SPI::ClockDivider::DIV_32; - return config; - } - - /** - * @brief The constructor. - * - * Takes all relevant SPI info and the settings - * for the sensor. If no SPIBusConfig is given, it will - * be used the default configuration. - * - * @param bus The SPI interface - * @param pin The CS pin - * @param spiConfig SPI configuration, optional - * @param config Driver configuration, optional - * - * @see LIS3MDL::Config - */ LIS3MDL(SPIBusInterface& bus, miosix::GpioPin pin, - SPIBusConfig spiConfig = getDefaultSPIConfig(), Config config = {}) - : mSlave{bus, pin, spiConfig}, mConfig(config), currDiv(0), - isInitialized(false) - { - } - - bool init() override - { - if (isInitialized) - { - LOG_ERR(logger, "Attempted to initialized sensor twice but failed"); - lastError = ALREADY_INIT; - return false; - } - - { - SPITransaction spi(mSlave); - uint8_t res = spi.readRegister(WHO_AM_I); - - if (res != WHO_AM_I_VALUE) - { - LOG_ERR(logger, - "WHO_AM_I value differs from expectation: read 0x{02x} " - "but expected 0x{02x}", - res, WHO_AM_I_VALUE); - lastError = INVALID_WHOAMI; - return false; - } - } - - isInitialized = true; - return applyConfig(mConfig); - } - - /** - * @brief Executes self test - * - * The init() method must have been called before. - * - * @returns false if the sensor failed the self test, true otherwise. - */ - bool selfTest() override - { - if (!isInitialized) - { - LOG_ERR(logger, "Invoked selfTest() but sensor was unitialized"); - lastError = NOT_INIT; - return false; - } - - /* - * NUM_SAMPLES: number of samples used - * to take the average value before tests. - * NUM_TESTS: number of actual tests. - * SLEEP_TIME: millis between samples/tests - */ - constexpr int NUM_SAMPLES = 5, NUM_TESTS = 5, SLEEP_TIME = 50; + SPIBusConfig spiConfig = {}, Config config = {}); - /* - * Absolute value of extra tolerance - */ - constexpr float t = 0.1f; - - /* - * Range which delta must be between, one for - * axis and expressed as {min, max}. The unit is gauss - */ - constexpr float r[3][2] = {{1.f, 3.f}, {1.f, 3.f}, {0.1f, 1.f}}; + bool init() override; - float avgX = 0.f, avgY = 0.f, avgZ = 0.f; - - { - SPITransaction spi(mSlave); - spi.writeRegister(CTRL_REG2, FS_12_GAUSS); - } - updateUnit(FS_12_GAUSS); - - for (int i = 0; i < NUM_SAMPLES; ++i) - { - miosix::Thread::sleep(SLEEP_TIME); - - LIS3MDLData lastData = sampleImpl(); - avgX += lastData.magneticFieldX; - avgY += lastData.magneticFieldY; - avgZ += lastData.magneticFieldZ; - } - - avgX /= NUM_SAMPLES; - avgY /= NUM_SAMPLES; - avgZ /= NUM_SAMPLES; - - /* - * Setting up the sensor settings for - * proper usage of the self test mode. - */ - { - SPITransaction spi(mSlave); - - spi.writeRegister(CTRL_REG1, ODR_20_HZ | ENABLE_SELF_TEST | - (OM_ULTRA_HIGH_POWER << 4)); - spi.writeRegister(CTRL_REG2, FS_12_GAUSS); - spi.writeRegister(CTRL_REG4, OM_ULTRA_HIGH_POWER << 2); - } - - /* - * Deltas: absolute difference between - * the values measured before and during - * selftest - */ - float d[3]; - - for (int i = 0; i < NUM_TESTS; ++i) - { - miosix::Thread::sleep(SLEEP_TIME); - - LIS3MDLData lastData = sampleImpl(); - d[0] = std::abs(lastData.magneticFieldX - avgX); - d[1] = std::abs(lastData.magneticFieldY - avgY); - d[2] = std::abs(lastData.magneticFieldZ - avgZ); - - bool passed = true; - for (int j = 0; j < 3; ++j) - { - if (d[j] < (r[j][0] - t) || d[j] > (r[j][1] + t)) - passed = false; - } - - if (!passed) - { - // reset configuration, then return - applyConfig(mConfig); - - lastError = SELF_TEST_FAIL; - return false; - } - } - - return applyConfig(mConfig); - } + bool selfTest() override; /** * @brief Overwrites the sensor settings. * - * Writes a certain config to the sensor - * registers. This method is automatically - * called in LIS3MDL::init() using as parameter - * the configuration given in the constructor. + * Writes a certain config to the sensor registers. This method is + * automatically called in LIS3MDL::init() using as parameter the + * configuration given in the constructor. * - * This method checks if the values were actually - * written in the sensor's registers and returns false - * if at least one of them was not as expected. + * This method checks if the values were actually written in the sensor's + * registers and returns false if at least one of them was not as expected. * - * @param config The configuration to be applied - * @returns true if the configuration was applied successfully, + * @param config The configuration to be applied. + * @returns True if the configuration was applied successfully, * false otherwise. */ - bool applyConfig(Config config) - { - - SPITransaction spi(mSlave); - uint8_t reg = 0, err = 0; - - mConfig = config; - currDiv = 0; - - /* -- CTRL_REG1 -- */ - if (config.enableTemperature) - { - reg = ENABLE_TEMPERATURE; - } - reg |= config.odr; - - // odr <= 80Hz - if (!(config.odr & FAST_ODR_BIT)) - reg |= config.xyMode << 4; - spi.writeRegister(CTRL_REG1, reg); - err |= spi.readRegister(CTRL_REG1) != reg; - - /* -- CTRL_REG2 -- */ - reg = config.scale; - spi.writeRegister(CTRL_REG2, reg); - err |= spi.readRegister(CTRL_REG2) != reg; - - /* -- CTRL_REG3 -- */ - reg = CONTINOUS_CONVERSION; - spi.writeRegister(CTRL_REG3, reg); - err |= spi.readRegister(CTRL_REG3) != reg; - - /* -- CTRL_REG4 -- */ - reg = config.zMode << 2; - spi.writeRegister(CTRL_REG4, reg); - err |= spi.readRegister(CTRL_REG4) != reg; - - /* -- CTRL_REG5 -- */ - if (config.doBlockDataUpdate) - { - reg = ENABLE_BDU; - } - else - { - reg = 0; - } - - spi.writeRegister(CTRL_REG5, reg); - err |= spi.readRegister(CTRL_REG5) != reg; - - /* -- INT_CFG -- */ - if (config.enableInterrupt[0]) - { - reg = ENABLE_INT_X; - } - else - { - reg = 0; - } - if (config.enableInterrupt[1]) - { - reg |= ENABLE_INT_Y; - } - if (config.enableInterrupt[2]) - { - reg |= ENABLE_INT_Z; - } - - // the interrupt of at least one axis is enabled - if (reg) - { - reg |= ENABLE_INT_PIN; - } - - reg |= 0x08; - spi.writeRegister(INT_CFG, reg); - err |= spi.readRegister(INT_CFG) != reg; - - /** INT_THS */ - uint16_t val = - static_cast<uint16_t>(std::abs(config.threshold / mUnit)); - reg = static_cast<uint8_t>(0xff & val); - spi.writeRegister(INT_THS_L, reg); - err |= spi.readRegister(INT_THS_L) != reg; - - reg = static_cast<uint8_t>(val >> 8); - reg &= - 0x7f; // remove MSB (according to the datasheet, it must be zero) - spi.writeRegister(INT_THS_H, reg); - err |= spi.readRegister(INT_THS_H) != reg; - - /* Set mUnit according to scale */ - updateUnit(config.scale); - - if (err) - { - LOG_ERR(logger, "Spi error"); - lastError = BUS_FAULT; - return false; - } - - return true; - } + bool applyConfig(Config config); private: - /** - * @brief Reads data from the sensor - * - * The init method must have been called before. - * Output data can be fetched with the methods - * compassDataPtr() and tempDataPtr inherited respectevely - * from CompassSensor and TemperatureSensor classes. - * Important: the temperature will be taken only once in a while - * according to the value of `temperatureDivider` - * - * @returns false if the sensor was unitialized, true otherwise. - */ - LIS3MDLData sampleImpl() override - { - if (!isInitialized) - { - LOG_ERR(logger, - "Invoked sampleImpl() but sensor was " - "unitialized"); - lastError = NOT_INIT; - return lastSample; - } - - SPITransaction spi(mSlave); - - if (!spi.readRegister(STATUS_REG)) - { - lastError = NO_NEW_DATA; - return lastSample; - } - - // Reset any error - lastError = SensorErrors::NO_ERRORS; - - int16_t val; - LIS3MDLData newData{}; - - if (mConfig.enableTemperature) - { - if (currDiv == 0) - { - val = spi.readRegister(TEMP_OUT_L); - val |= spi.readRegister(TEMP_OUT_H) << 8; - - newData.temperatureTimestamp = - TimestampTimer::getInstance().getTimestamp(); - newData.temperature = - static_cast<float>(val) / LSB_PER_CELSIUS + - REFERENCE_TEMPERATURE; - } - else - { - // Keep old value - newData.temperature = lastSample.temperature; - } - - currDiv = (currDiv + 1) % mConfig.temperatureDivider; - } - - newData.magneticFieldTimestamp = - TimestampTimer::getInstance().getTimestamp(); - - val = spi.readRegister(OUT_X_L); - val |= spi.readRegister(OUT_X_H) << 8; - newData.magneticFieldX = mUnit * val; - - val = spi.readRegister(OUT_Y_L); - val |= spi.readRegister(OUT_Y_H) << 8; - newData.magneticFieldY = mUnit * val; - - val = spi.readRegister(OUT_Z_L); - val |= spi.readRegister(OUT_Z_H) << 8; - newData.magneticFieldZ = mUnit * val; - - return newData; - } + LIS3MDLData sampleImpl() override; + + void updateUnit(FullScale fs); SPISlave mSlave; Config mConfig; @@ -568,32 +214,7 @@ private: bool isInitialized; float mUnit = 0; - void updateUnit(FullScale fs) - { - switch (fs) - { - case FS_4_GAUSS: - mUnit = 1.f / LSB_PER_GAUSS_FS_4; - break; - - case FS_8_GAUSS: - mUnit = 1.f / LSB_PER_GAUSS_FS_8; - break; - - case FS_12_GAUSS: - mUnit = 1.f / LSB_PER_GAUSS_FS_12; - break; - - case FS_16_GAUSS: - mUnit = 1.f / LSB_PER_GAUSS_FS_16; - break; - } - }; - - /** - * List of addresses of sensor registers - */ - enum Reg : uint8_t + enum Registers : uint8_t { WHO_AM_I = 0x0f, @@ -619,15 +240,11 @@ private: INT_THS_H = 0x33, }; - /** - * Misc. constants used by the driver. They are not - * particularly useful to the user. - */ enum Constants : unsigned { WHO_AM_I_VALUE = 0x3d, - CONTINOUS_CONVERSION = 0x0, + CONTINUOS_CONVERSION = 0x0, REFERENCE_TEMPERATURE = 25, LSB_PER_CELSIUS = 8, diff --git a/src/shared/sensors/MS5803/MS5803.h b/src/shared/sensors/MS5803/MS5803.h index 6065ebcbab862231cf4fcd37e12d857cb4119198..48c7af2c1ca147e62995b2067a21af8c970c8935 100644 --- a/src/shared/sensors/MS5803/MS5803.h +++ b/src/shared/sensors/MS5803/MS5803.h @@ -24,9 +24,9 @@ #include <diagnostic/PrintLogger.h> #include <drivers/spi/SPIDriver.h> -#include <sensors/MS5803/MS5803Data.h> #include <sensors/Sensor.h> -#include <utils/Debug.h> + +#include "MS5803Data.h" namespace Boardcore {