diff --git a/src/shared/sensors/LIS3DSH-ettore/LIS3DSH.cpp b/src/shared/sensors/LIS3DSH-ettore/LIS3DSH.cpp index a0b041da8584d798353303e7413382d1f3e9b457..c7ed2fede74e18a3783b7e1609ef4b545b429bc3 100644 --- a/src/shared/sensors/LIS3DSH-ettore/LIS3DSH.cpp +++ b/src/shared/sensors/LIS3DSH-ettore/LIS3DSH.cpp @@ -1,5 +1,6 @@ #include "LIS3DSH.h" -namespace Boardcore { +namespace Boardcore +{ LIS3DSHettore::LIS3DSHettore(uint8_t odr, uint8_t bdu, uint8_t fullScale) : odr(odr), bdu(bdu), fullScale(fullScale) @@ -8,7 +9,8 @@ LIS3DSHettore::LIS3DSHettore(uint8_t odr, uint8_t bdu, uint8_t fullScale) bool LIS3DSHettore::checkWhoAmI() { - uint8_t who_am_i = spi_driver.read(WHO_AM_I_REG); // <-- we need to go deeper + uint8_t who_am_i = + spi_driver.read(WHO_AM_I_REG); // <-- we need to go deeper if (who_am_i == WHO_AM_I_VALUE) { return true; @@ -18,10 +20,10 @@ bool LIS3DSHettore::checkWhoAmI() bool LIS3DSHettore::init() { - spi_driver.config(); + spi_driver.config(); printf("LIS3DSH: init \n"); printf("Sensitive: %f\n", sensitivity); - if (!checkWhoAmI()) // wrong who_am_i value + if (!checkWhoAmI()) // wrong who_am_i value { printf("LIS3DSH: wrong who_am_i value \n"); return false; @@ -30,170 +32,165 @@ bool LIS3DSHettore::init() uint8_t ctrl_reg4_value = (odr << 4) | (bdu << 3) | (7 << 0); spi_driver.write(CTRL_REG4, ctrl_reg4_value); - // set the full scale in CTRL_REG5 - uint8_t ctrl_reg5_value = (fullScale << 3); - spi_driver.write(CTRL_REG5, ctrl_reg5_value); + // set the full scale + setFullScale(fullScale); - sensitivity = 0.06; - return true; // correctly initialized } void LIS3DSHettore::setFullScale(uint8_t fullScale) { - //LIS3DSH - //CTRL_REG5 = 0x24 - //set full scale + // LIS3DSH + // CTRL_REG5 = 0x24 + // set full scale uint8_t ctrlReg5Value = (fullScale << 3); spi_driver.write(CTRL_REG5, ctrlReg5Value); switch (fullScale) { - case FULL_SCALE_2G: - sensitivity = sensitivityValues[0]; - break; - case FULL_SCALE_4G: - sensitivity = sensitivityValues[1]; - break; - case FULL_SCALE_6G: - sensitivity = sensitivityValues[2]; - break; - case FULL_SCALE_8G: - sensitivity = sensitivityValues[3]; - break; - case FULL_SCALE_16G: - sensitivity = sensitivityValues[4]; - break; - default: - break; + case FULL_SCALE_2G: + sensitivity = sensitivityValues[0]; + break; + case FULL_SCALE_4G: + sensitivity = sensitivityValues[1]; + break; + case FULL_SCALE_6G: + sensitivity = sensitivityValues[2]; + break; + case FULL_SCALE_8G: + sensitivity = sensitivityValues[3]; + break; + case FULL_SCALE_16G: + sensitivity = sensitivityValues[4]; + break; + default: + break; } printf("LIS3DSH: set full scale \n"); printf("Sensitive: %f\n", sensitivity); } -int8_t LIS3DSHettore::getTemperature() +LIS3DSHData LIS3DSHettore::sampleImpl() { + + AccelerometerData accelData = readAccelData(); + TemperatureData tempData = readTemperature(); + return LIS3DSHData(accelData, tempData); +} + +TemperatureData LIS3DSHettore::readTemperature() +{ + // the temperature is given as a 8-bits integer (in 2-complement) - // 1 LSB/deg - 8-bit resolution - // also, reading zero means 25 °C, so add the temperature reference - return spi_driver.read(OUT_T) + TEMPERATURE_REF; + int8_t t = spi_driver.read(OUT_T); + + return TemperatureData{ + TimestampTimer::getTimestamp(), + (float)t + + TEMPERATURE_REF}; // add the 'zero' of the temperature sensor } bool LIS3DSHettore::selfTest() { - //LIS3DSH - //CTRL_REG5 = 0x24 - //set data rate to 50 Hz - const int samples = 10; - uint8_t ctrlReg4Value = (OutputDataRate::ODR_100_HZ << 4) | - (BlockDataUpdate::UPDATE_AFTER_READ_MODE << 3) | - (7 << 0); - float X_ST[samples] = {0}; - float Y_ST[samples] = {0}; - float Z_ST[samples] = {0}; - float X_NO_ST[samples] = {0}; - float Y_NO_ST[samples] = {0}; - float Z_NO_ST[samples] = {0}; - float AVG_ST[3] = {0}; // one element per axis - float AVG_NO_ST[3] = {0}; // one element per axis + // LIS3DSH + // CTRL_REG5 = 0x24 + // set data rate to 50 Hz + const int samples = 10; + uint8_t ctrlReg4Value = (OutputDataRate::ODR_100_HZ << 4) | + (BlockDataUpdate::UPDATE_AFTER_READ_MODE << 3) | + (7 << 0); + float xST[samples] = {0}; + float yST[samples] = {0}; + float zST[samples] = {0}; + float xNoST[samples] = {0}; + float yNoST[samples] = {0}; + float zNoST[samples] = {0}; + float avgST[3] = {0}; // one element per axis + float avgNoST[3] = {0}; // one element per axis spi_driver.write(CTRL_REG4, ctrlReg4Value); - uint8_t ctrlReg5Value = (FullScale::FULL_SCALE_2G << 3) ; + uint8_t ctrlReg5Value = (FullScale::FULL_SCALE_2G << 3); spi_driver.write(CTRL_REG5, ctrlReg5Value); - for (uint8_t i = 0; i < samples; i++) { - //read using function - float x = getAccX(); - float y = getAccY(); - float z = getAccZ(); - //store the samples - X_ST[i] = x; - Y_ST[i] = y; - Z_ST[i] = z; - //wait 10 ms + for (uint8_t i = 0; i < samples; i++) + { + // read using function + AccelerometerData accelData = readAccelData(); + // store the samples + xST[i] = accelData.accelerationX; + yST[i] = accelData.accelerationY; + zST[i] = accelData.accelerationZ; + // wait 10 ms miosix::Thread::sleep(10); } - //reset the registers + // reset the registers ctrlReg5Value = (fullScale << 3); spi_driver.write(CTRL_REG5, ctrlReg5Value); - for (uint8_t i = 0; i < samples; i++) { - //read using function - float x = getAccX(); - float y = getAccY(); - float z = getAccZ(); - //store the samples - X_NO_ST[i] = x; - Y_NO_ST[i] = y; - Z_NO_ST[i] = z; - //wait 10 ms + for (uint8_t i = 0; i < samples; i++) + { + // read using function + AccelerometerData accelData = readAccelData(); + // store the samples + xNoST[i] = accelData.accelerationX; + yNoST[i] = accelData.accelerationY; + zNoST[i] = accelData.accelerationZ; + // wait 10 ms miosix::Thread::sleep(10); } - //calculate the average - for (uint8_t i = 0; i < samples; i++) { - AVG_ST[0] += X_ST[i]; - AVG_ST[1] += Y_ST[i]; - AVG_ST[2] += Z_ST[i]; - AVG_NO_ST[0] += X_NO_ST[i]; - AVG_NO_ST[1] += Y_NO_ST[i]; - AVG_NO_ST[2] += Z_NO_ST[i]; + // calculate the average + for (uint8_t i = 0; i < samples; i++) + { + avgST[0] += xST[i]; + avgST[1] += yST[i]; + avgST[2] += zST[i]; + avgNoST[0] += xNoST[i]; + avgNoST[1] += yNoST[i]; + avgNoST[2] += zNoST[i]; } - for (uint8_t i = 0; i < 3; i++) { - AVG_ST[i] /= samples; - AVG_NO_ST[i] /= samples; + for (uint8_t i = 0; i < 3; i++) + { + avgST[i] /= samples; + avgNoST[i] /= samples; } - //calculate delta + // calculate delta float delta[3] = {0}; - for (uint8_t i = 0; i < 3; i++) { - delta[i] = fabs(AVG_NO_ST[i] - AVG_ST[i]); + for (uint8_t i = 0; i < 3; i++) + { + delta[i] = fabs(avgNoST[i] - avgST[i]); printf("delta[%d] = %f\n", i, delta[i]); } - if ((delta[0] > - SELF_TEST_DIFF_X_Y + SELF_TEST_DIFF_X_Y * SELF_TEST_TOLERANCE) || - (delta[1] > - SELF_TEST_DIFF_X_Y + SELF_TEST_DIFF_X_Y * SELF_TEST_TOLERANCE) || - (delta[2] > - SELF_TEST_DIFF_Z + SELF_TEST_DIFF_Z * SELF_TEST_TOLERANCE)) - { - printf("LIS3DSH: self test failed\n"); - return false; - } + if ((delta[0] > + SELF_TEST_DIFF_X_Y + SELF_TEST_DIFF_X_Y * SELF_TEST_TOLERANCE) || + (delta[1] > + SELF_TEST_DIFF_X_Y + SELF_TEST_DIFF_X_Y * SELF_TEST_TOLERANCE) || + (delta[2] > SELF_TEST_DIFF_Z + SELF_TEST_DIFF_Z * SELF_TEST_TOLERANCE)) + { + printf("LIS3DSH: self test failed\n"); + return false; + } return true; } -uint64_t LIS3DSHettore::getAccelerationTimestamp() -{ - return TimestampTimer::getTimestamp(); -} - int16_t combine(uint8_t msb, uint8_t lsb) { return (msb << 8) | lsb; } - -float LIS3DSHettore::getAccX() +// readacceldata eredita da LIS3DSHEttore +AccelerometerData LIS3DSHettore::readAccelData() { - //LIS3DSH - //OUT_X_L = 0x28 - //OUT_X_H = 0x29 + AccelerometerData accelData; + accelData.accelerationTimestamp = TimestampTimer::getTimestamp(); + int8_t accelL = spi_driver.read(OUT_X_L); int8_t accelH = spi_driver.read(OUT_X_H); - return static_cast<float>(combine(accelH, accelL)) * sensitivity; -} + accelData.accelerationX = + static_cast<float>(combine(accelH, accelL)) * sensitivity; -float LIS3DSHettore::getAccY() -{ - //LIS3DSH - //OUT_Y_L = 0x2A - //OUT_Y_H = 0x2B - int8_t accelL = spi_driver.read(OUT_Y_L); - int8_t accelH = spi_driver.read(OUT_Y_H); - return static_cast<float>(combine(accelH, accelL)) * sensitivity; -} + accelL = spi_driver.read(OUT_Y_L); + accelH = spi_driver.read(OUT_Y_H); + accelData.accelerationY = + static_cast<float>(combine(accelH, accelL)) * sensitivity; -float LIS3DSHettore::getAccZ() -{ - //LIS3DSH - //OUT_Z_L = 0x2C - //OUT_Z_H = 0x2D - int8_t accelL = spi_driver.read(OUT_Z_L); - int8_t accelH = spi_driver.read(OUT_Z_H); - return static_cast<float>(combine(accelH, accelL)) * sensitivity; -} + accelL = spi_driver.read(OUT_Z_L); + accelH = spi_driver.read(OUT_Z_H); + accelData.accelerationZ = + static_cast<float>(combine(accelH, accelL)) * sensitivity; + return accelData; } - +} // namespace Boardcore diff --git a/src/shared/sensors/LIS3DSH-ettore/LIS3DSH.h b/src/shared/sensors/LIS3DSH-ettore/LIS3DSH.h index 8d890b313e48a769c75944f8054a9b24cb6873d9..789e6ccae627a4d68d8ce425c45d7dd2fc2a9d10 100644 --- a/src/shared/sensors/LIS3DSH-ettore/LIS3DSH.h +++ b/src/shared/sensors/LIS3DSH-ettore/LIS3DSH.h @@ -1,43 +1,85 @@ - +/* Copyright (c) 2023 Skyward Experimental Rocketry + * Author: Ettore Luigi Pane + * + * 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. + */ #pragma once -#include "drivers/ettore/SPIDriver.h" #include <drivers/timer/TimestampTimer.h> #include <math.h> +#include <sensors/Sensor.h> + +#include "LIS3DSHData.h" +#include "drivers/ettore/SPIDriver.h" using namespace miosix; namespace Boardcore { -class LIS3DSHettore +class LIS3DSHettore : public Sensor<LIS3DSHData> { public: - LIS3DSHettore(uint8_t odr, uint8_t bdu, - uint8_t fullScale = FullScale::FULL_SCALE_2G); - + /** + * @brief Constructor. + * + * @param odr data rate output (default is 100Hz). + * @param bdu BlockDataUpdate, defines the data reading mode. + * Default value is to update after data + * has been read (BDU=1). + * @param fullScale full scale range (from +/-2g up to +/-16g). + * Default value is +/-2g. + */ + LIS3DSHettore(uint8_t odr, uint8_t bdu, + uint8_t fullScale = FullScale::FULL_SCALE_2G); + + /** + * @brief Initialize the sensor. + * + * @return true if the sensor is correctly initialized, false otherwise. + */ bool init(); + /** + * @brief Checks onboard who_am_i register. + * + * @return true if the who_am_i value is correct, false otherwise. + */ bool checkWhoAmI(); - int8_t getTemperature(); - + /** + * @brief Set the full scale range. + * + * @param fullScale full scale range (from +/-2g up to +/-16g). + */ void setFullScale(uint8_t fullScale); - uint64_t getAccelerationTimestamp(); - - float getAccX(); - float getAccY(); - float getAccZ(); - - - - + /** + * @brief Do a full self test of the sensor. + * + * @return true if the self test is passed, false otherwise. + */ bool selfTest(); - enum OutputDataRate : uint8_t + enum OutputDataRate : uint8_t { ODR_POWER_DOWN = 0, // default value ODR_3_125_HZ = 1, @@ -54,24 +96,25 @@ public: enum BlockDataUpdate : uint8_t { CONTINUOUS_UPDATE_MODE = 0, - UPDATE_AFTER_READ_MODE = 1 // values updated only when MSB and LSB are read + UPDATE_AFTER_READ_MODE = + 1 // values updated only when MSB and LSB are read }; enum Registers : uint8_t { - WHO_AM_I_REG = 0x0F, + WHO_AM_I_REG = 0x0F, CTRL_REG4 = 0x20, // control register to set ODR and BDU CTRL_REG5 = 0x24, // control register to set self-test - OUT_T = 0x0C, // temperature output register - OUT_X_L = 0x28, - OUT_X_H = 0x29, - OUT_Y_L = 0x2A, - OUT_Y_H = 0x2B, - OUT_Z_L = 0x2C, - OUT_Z_H = 0x2D, + OUT_T = 0x0C, // temperature output register + OUT_X_L = 0x28, + OUT_X_H = 0x29, + OUT_Y_L = 0x2A, + OUT_Y_H = 0x2B, + OUT_Z_L = 0x2C, + OUT_Z_H = 0x2D, }; - enum FullScale + enum FullScale { FULL_SCALE_2G = 0, // 000, +/- 2g FULL_SCALE_4G = 1, // 001, +/- 4g @@ -80,30 +123,53 @@ public: FULL_SCALE_16G = 4, // 100 +/- 16g }; - - - + /** + * @brief Sensitivity of the sensor. + */ + float sensitivity = 0.06; private: - + /** + * @brief SPI driver. + */ SpiDriver spi_driver; + /** + * @brief Output data rate. + */ uint8_t odr; + /** + * @brief Block data update. + */ uint8_t bdu; + /** + * @brief Full scale range. + */ uint8_t fullScale; // full scale value, default +/- 2g + /** + * @brief Sensitivity values for each full scale range. + */ const float sensitivityValues[5] = {0.06, 0.12, 0.18, 0.24, 0.73}; - float sensitivity = 0.06; + /** + * @brief Read the accelerometer data. + * + * @return AccelerometerData struct. + */ + LIS3DSHData sampleImpl(); - const uint8_t WHO_AM_I_VALUE = 63; + AccelerometerData readAccelData(); + TemperatureData readTemperature(); + + const uint8_t WHO_AM_I_VALUE = 63; const uint8_t TEMPERATURE_REF = 25; }; } // namespace Boardcore - const float SELF_TEST_DIFF_X_Y = 140.0f; // 140 mg - const float SELF_TEST_DIFF_Z = 590.0f; // 590 mg - const float SELF_TEST_TOLERANCE = 0.3f; +const float SELF_TEST_DIFF_X_Y = 140.0f; // 140 mg +const float SELF_TEST_DIFF_Z = 590.0f; // 590 mg +const float SELF_TEST_TOLERANCE = 0.3f; enum OutputDataRate : uint8_t { @@ -124,4 +190,3 @@ enum BlockDataUpdate : uint8_t CONTINUOUS_UPDATE_MODE = 0, UPDATE_AFTER_READ_MODE = 1 // values updated only when MSB and LSB are read }; - diff --git a/src/shared/sensors/LIS3DSH-ettore/LIS3DSHData.h b/src/shared/sensors/LIS3DSH-ettore/LIS3DSHData.h new file mode 100644 index 0000000000000000000000000000000000000000..828f4ae0dc704e8dcd03fe7d5a219ccacf35a523 --- /dev/null +++ b/src/shared/sensors/LIS3DSH-ettore/LIS3DSHData.h @@ -0,0 +1,44 @@ +/* Copyright (c) 2023 Skyward Experimental Rocketry + * Author: Ettore Luigi Pane + * + * 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. + */ +#pragma once + +#include <sensors/SensorData.h> + +namespace Boardcore +{ +struct LIS3DSHData : public AccelerometerData, public TemperatureData +{ + /* + @brief Default constructor for LIS3DSHData (including timestamp) + */ + LIS3DSHData() : AccelerometerData{0, 0.0, 0.0, 0.0}, TemperatureData{0, 0.0} + { + } + + LIS3DSHData(AccelerometerData acc, TemperatureData temp) + : AccelerometerData{acc.accelerationTimestamp, acc.accelerationX, + acc.accelerationY, acc.accelerationZ}, + TemperatureData{temp.temperatureTimestamp, temp.temperature} + { + } +}; +} // namespace Boardcore \ No newline at end of file diff --git a/src/tests/sensors/test-ettore.cpp b/src/tests/sensors/test-ettore.cpp index a33eb5c56267e84e6b828561b824e0260f4d1145..80fe5b8e7f2023116733986a58f8318ed4d230be 100644 --- a/src/tests/sensors/test-ettore.cpp +++ b/src/tests/sensors/test-ettore.cpp @@ -1,5 +1,27 @@ +/* Copyright (c) 2023 Skyward Experimental Rocketry + * Author: Ettore Luigi Pane + * + * 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 <miosix.h> #include <utils/Debug.h> + #include "sensors/LIS3DSH-ettore/LIS3DSH.h" using namespace miosix; @@ -8,17 +30,18 @@ using namespace Boardcore; int main() { LIS3DSHettore driver(LIS3DSHettore::OutputDataRate::ODR_100_HZ, - LIS3DSHettore::BlockDataUpdate::CONTINUOUS_UPDATE_MODE, - LIS3DSHettore::FullScale::FULL_SCALE_2G); + LIS3DSHettore::BlockDataUpdate::CONTINUOUS_UPDATE_MODE, + LIS3DSHettore::FullScale::FULL_SCALE_2G); + LIS3DSHData data; - - printf("Ciao\n"); if (driver.init()) { if (driver.selfTest()) { printf("Self test passed\n"); - } else { + } + else + { while (true) { TRACE("Self test failed\n"); @@ -27,24 +50,27 @@ int main() } driver.setFullScale(LIS3DSHettore::FullScale::FULL_SCALE_4G); - + while (true) { - TRACE("Temp : %d °C \n", driver.getTemperature()); - TRACE("Timestamp : %llu \n", driver.getAccelerationTimestamp()); - float accX = driver.getAccX(); - float accY = driver.getAccY(); - float accZ = driver.getAccZ(); - TRACE("AccX RAW : %f\n", accX ); + driver.sample(); + data = driver.getLastSample(); + + TRACE("Temp : %d °C \n", data.temperature); + TRACE("Timestamp : %llu \n", data.accelerationTimestamp); + float accX = data.accelerationX; + float accY = data.accelerationY; + float accZ = data.accelerationZ; + TRACE("AccX RAW : %f\n", accX); TRACE("AccY RAW: %f\n", accY); TRACE("AccZ RAW: %f\n", accZ); - - Thread::sleep(200); } - } else { - while (true) + } + else + { + while (true) { TRACE("error \n"); printf("Ciao\n");