diff --git a/.vscode/settings.json b/.vscode/settings.json index 1641f81b44c6020c1fa98d5444302f7a55bc6e5c..072d70fa988631832257ac7032e75f479dc907ec 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -150,6 +150,7 @@ "cwise", "cyaw", "DATABUS", + "datasheet", "deleteme", "DMEIE", "Doxyfile", diff --git a/src/shared/sensors/LIS2MDL/LIS2MDL.cpp b/src/shared/sensors/LIS2MDL/LIS2MDL.cpp index 9d8ab34794b58844f20bc56470b017d1b7ec98ef..9017aaa365ce084fa2e52e955cab6a972234fc37 100644 --- a/src/shared/sensors/LIS2MDL/LIS2MDL.cpp +++ b/src/shared/sensors/LIS2MDL/LIS2MDL.cpp @@ -24,8 +24,13 @@ #include <drivers/timer/TimestampTimer.h> #include <miosix.h> +#include <sensors/calibration/SensorDataExtra/SensorDataExtra.h> #include <utils/Debug.h> +#include <iostream> + +using namespace Eigen; + namespace Boardcore { @@ -86,20 +91,18 @@ bool LIS2MDL::selfTest() return false; } - constexpr int NUM_SAMPLES = 5; - 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 ST_min = 0.015; - constexpr float ST_max = 0.500; + /** + * The device has to be kept still while the self-test is ongoing. + * See AN5069 for further details on the self-test procedure. + */ - float avgX = 0.f, avgY = 0.f, avgZ = 0.f; + static constexpr int NUM_SAMPLES = 50; // 50 samples suggested by AN5069 + static constexpr int SLEEP_TIME = 10; // 100Hz -> 10ms between samples + Vector3f avgPreTest = Vector3f::Zero(); + Vector3f avgPostTest = Vector3f::Zero(); + Vector3f tmp; - // Set configuration for selfTest procedure. selfTest still not enabled + // 1. Set configuration for selfTest procedure. selfTest still not enabled { SPITransaction spi(slave); spi.writeRegister(CFG_REG_A, @@ -108,60 +111,80 @@ bool LIS2MDL::selfTest() spi.readRegister(CFG_REG_B) | OFFSET_CANCELLATION); spi.writeRegister(CFG_REG_C, spi.readRegister(CFG_REG_C) | ENABLE_BDU); } + + // Wait for power up, ~20ms for a stable output miosix::Thread::sleep(20); - for (int i = 0; i < NUM_SAMPLES; ++i) + // 2. Averaging fifty samples before enabling the self-test { - miosix::Thread::sleep(SLEEP_TIME); + for (int i = 0; i < NUM_SAMPLES - 1; i++) + { + tmp << static_cast<MagnetometerData>(sampleImpl()); + avgPreTest += tmp; - LIS2MDLData lastData = sampleImpl(); - avgX += lastData.magneticFieldX; - avgY += lastData.magneticFieldY; - avgZ += lastData.magneticFieldZ; - } + miosix::Thread::sleep(SLEEP_TIME); + } + tmp << static_cast<MagnetometerData>(sampleImpl()); + avgPreTest += tmp; - avgX /= NUM_SAMPLES; - avgY /= NUM_SAMPLES; - avgZ /= NUM_SAMPLES; + // Compute average + avgPreTest /= NUM_SAMPLES; + } + // 3. Enable self-test { - // selfTest is enabled SPITransaction spi(slave); spi.writeRegister(CFG_REG_C, spi.readRegister(CFG_REG_C) | ENABLE_SELF_TEST); } - miosix::Thread::sleep(60); - // Deltas: absolute difference between the values measured before and after - float deltas[3]; - - LIS2MDLData lastData = sampleImpl(); - deltas[0] = std::abs(lastData.magneticFieldX - avgX); - deltas[1] = std::abs(lastData.magneticFieldY - avgY); - deltas[2] = std::abs(lastData.magneticFieldZ - avgZ); + // Wait 60ms (suggested in AN) + miosix::Thread::sleep(60); - bool passed = true; - for (int j = 0; j < 3; ++j) - if (deltas[j] < (ST_max - t) && deltas[j] > (ST_min + t)) - passed = false; + // 4. Averaging fifty samples after enabling the self-test + { + for (int i = 0; i < NUM_SAMPLES - 1; i++) + { + tmp << static_cast<MagnetometerData>(sampleImpl()); + avgPostTest += tmp; - // Reset configuration, then return - applyConfig(configuration); + miosix::Thread::sleep(SLEEP_TIME); + } + tmp << static_cast<MagnetometerData>(sampleImpl()); + avgPostTest += tmp; - if (!passed) - { - lastError = SELF_TEST_FAIL; - return false; + // Compute average + avgPostTest /= NUM_SAMPLES; } + // 5. Computing the difference in the module for each axis and verifying + // that is falls in the given range: the min and max value are provided + // in the datasheet. { - // Disable selfTest - SPITransaction spi(slave); - spi.writeRegister(CFG_REG_C, - spi.readRegister(CFG_REG_C) & ~ENABLE_SELF_TEST); - } + Vector3f deltas = (avgPostTest - avgPreTest).cwiseAbs(); - return true; + // Range which delta must be between, one for axis and expressed as + // {min, max}. The unit is gauss. + static constexpr float ST_MIN = 0.015; // [Gauss] + static constexpr float ST_MAX = 0.500; // [Gauss] + + bool passed = + (ST_MIN < deltas.array()).all() && (deltas.array() < ST_MAX).all(); + + // Reset configuration, then return + applyConfig(configuration); + + if (!passed) + { + LOG_ERR(logger, "selfTest() failed"); + lastError = SELF_TEST_FAIL; + return false; + } + else + { + return true; + } + } } bool LIS2MDL::applyConfig(Config config) @@ -170,7 +193,7 @@ bool LIS2MDL::applyConfig(Config config) uint8_t reg = 0; // CFG_REG_A: configuration register - reg |= config.odr << 2; + reg |= config.odr; reg |= config.deviceMode; reg |= (1 << 7); reg |= (spi.readRegister(CFG_REG_A) & 0b01110000); diff --git a/src/shared/sensors/LIS2MDL/LIS2MDL.h b/src/shared/sensors/LIS2MDL/LIS2MDL.h index 3fdaf088700edde9513c1da38354c8a42cf0f4a1..77227a9f22638a84799210af4973be53eb543be9 100644 --- a/src/shared/sensors/LIS2MDL/LIS2MDL.h +++ b/src/shared/sensors/LIS2MDL/LIS2MDL.h @@ -40,9 +40,9 @@ public: enum ODR : uint8_t { ODR_10_HZ = 0x00, ///< 10 Hz - ODR_20_HZ = 0x01, ///< 20 Hz - ODR_50_HZ = 0x02, ///< 50 Hz - ODR_100_HZ = 0x03, ///< 100 Hz + ODR_20_HZ = 0x04, ///< 20 Hz + ODR_50_HZ = 0x08, ///< 50 Hz + ODR_100_HZ = 0x18, ///< 100 Hz }; enum OperativeMode : uint8_t