diff --git a/sbs.conf b/sbs.conf
index e1c6bca46034ca431f7c12905a67e777d29fa2c0..09a02da7f16e580d7722d5a0e10eca62a060baee 100644
--- a/sbs.conf
+++ b/sbs.conf
@@ -490,3 +490,11 @@ BinName:    test-rls
 Include:    %shared
 Defines:
 Main:       test-rls
+
+[test-lis3dsh]
+Type:       test
+BoardId:    stm32f407vg_skyward_tortellino
+BinName:    test-lis3dsh
+Include:    %shared %spi
+Defines:
+Main:       drivers/test-lis3dsh
\ No newline at end of file
diff --git a/src/shared/sensors/LIS3DSH/LIS3DSH.h b/src/shared/sensors/LIS3DSH/LIS3DSH.h
new file mode 100644
index 0000000000000000000000000000000000000000..78d5094e8c6a89de8023e165675dff96114227e1
--- /dev/null
+++ b/src/shared/sensors/LIS3DSH/LIS3DSH.h
@@ -0,0 +1,458 @@
+/* Copyright (c) 2020 Skyward Experimental Rocketry
+ * Authors: Luca Conterio
+ *
+ * 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/Sensor.h"
+#include "drivers/spi/SPIDriver.h"
+
+/**
+ * Driver for stm32f407vg discovery on-board 3-axis 
+ * accelerometer + temperature sensor.
+ *
+ * The sensor is connected to SPI1 using the 
+ * following GPIOs: PA5 : clock
+ *                  PA6 : miso
+ *                  PA7 : mosi 
+ *                  PE3 : chip select
+*/
+class LIS3DSH: public AccelSensor, public TemperatureSensor
+{ 
+    public:
+
+        /**
+         *  @brief Constructor.
+         * 
+         *  @param bus          the spi bus.
+         *  @param chip_select  the chip_select for the sensor.
+         *  @param _odr         output data rate for the accelerometer. 
+         *                      Default value is 100 Hz.
+         *  @param _bdu         BDU value, continuous or non-continuous update mode. 
+         *                      Default value is to update after data has been read (BDU=1).
+         *  @param _full_scale  full scale range (from +/-2g up to +/-16g). 
+         *                      Default value is +/-2g.
+         */
+        LIS3DSH(SPIBusInterface& bus,
+                    GpioPin chip_select,
+                    uint8_t _odr=ODR_100_HZ,
+                    uint8_t _bdu=UPDATE_AFTER_READ_MODE, 
+                    uint8_t _full_scale=FULL_SCALE_2G): 
+                spi_slave(bus, chip_select, {}), odr(_odr), bdu(_bdu), full_scale(_full_scale) 
+        {
+            spi_slave.config.clock_div = SPIClockDivider::DIV64;  // used to set the spi baud rate (maximum is 10 Mhz)
+        }
+        
+        /**
+         *  @brief Constructor.
+         * 
+         *  @param bus          the spi bus.
+         *  @param chip_select  the chip_select for the sensor.
+         *  @param config       the spi bus configurations.
+         *  @param _odr         output data rate for the accelerometer. 
+         *                      Default value is 100 Hz.
+         *  @param _bdu         BDU value, continuous or non-continuous update mode. 
+         *                      Default value is to update after data has been read (BDU=1).
+         *  @param _full_scale  full scale range (from +/-2g up to +/-16g). 
+         *                      Default value is +/-2g.
+         */
+        LIS3DSH(SPIBusInterface& bus,
+                    GpioPin chip_select,
+                    SPIBusConfig config,
+                    uint8_t _odr=ODR_100_HZ,
+                    uint8_t _bdu=UPDATE_AFTER_READ_MODE, 
+                    uint8_t _full_scale=FULL_SCALE_2G): 
+                spi_slave(bus, chip_select, config), odr(_odr), bdu(_bdu), full_scale(_full_scale) {}
+
+        /**
+         * @brief Initialize the sensor.
+         * 
+         * @return boolean value indicating whether the operation succeded or not
+         */
+        bool init() override {
+            // check if the sensor is already initialized
+            if (initialized) {
+                TRACE("[LIS3DSH] init() : already initialized \n");
+                return false;
+            }
+
+            // check if the sensor is working properly
+            if (!checkWhoAmI()) { // whoami default value
+                return false; // sensor correctly initialized
+            }
+
+            SPITransaction spi(spi_slave);
+
+            // set the full scale value in CTRL_REG5
+            uint8_t ctrl_reg5_value = (full_scale << 3);
+            spi.write(CTRL_REG5, ctrl_reg5_value);
+
+            // select the correct sensitivity
+            // for the specified full scale range
+            sensitivity = select_sensitivity();
+
+            // set the output data rate and the BDU in CTRL_REG4
+            // the three least significant bits are enable bits for X, Y and Z axis
+            uint8_t ctrl_reg4_value = (odr << 4) | (bdu << 3) | (7 << 0);  // 7 = 111 -> enable the 3 axis
+            spi.write(CTRL_REG4, ctrl_reg4_value);
+            
+            TRACE("[LIS3DSH] init() : ok \n");
+
+            initialized = true;
+
+            return true;
+        }
+
+        /**
+         * @brief Read new data from the accelerometer.
+         *        Acceleretions are returned in mg.
+         * 
+         * @return boolean value indicating whether the operation succeded or not
+         */
+        bool onSimpleUpdate() override {
+            // check if the sensor is initialized
+            if (!initialized) {
+                TRACE("[LIS3DSH] onSimpleUpdate() : not initialized, unable to sample data \n");
+                return false;
+            }
+            return readAccelData();
+        }
+
+        /**
+         * @brief Read temperature data.
+         *        The temperature returned by the sensor is an 8-bits integer.
+         * 
+         * @return boolean value indicating whether the operation succeded or not
+         */
+        bool updateTemperature() {
+            // check if the sensor is initialized
+            if (!initialized) {
+                TRACE("[LIS3DSH] updateTemperature() : not initialized, unable to sample data \n");
+                return false;
+            }
+
+            SPITransaction spi(spi_slave);
+
+            // NOTE: the temperature is given as a 8-bits integer (in 2-complement)
+            //       while the TemperatureSensor interface returns a float value  
+            //       through the method tempDataPtr()
+            mLastTemp = spi.read(OUT_T) + TEMPERATURE_REF; // add the 'zero' of the temperature sensor
+
+            return true;
+        }
+
+         /**
+         * @brief Check if the sensor is working.
+         * 
+         * @return boolean indicating whether the sensor is correctly working or not
+         */
+        bool selfTest() override {
+            // check if the sensor is initialized
+            if (!initialized) {
+                TRACE("[LIS3DSH] selfTest() : not initialized, unable to self-test \n");
+                return false;
+            }
+
+            SPITransaction spi(spi_slave);
+            
+            const uint8_t num_samples = 5; // number of samples to be used
+            // vectors for storing samples, both
+            // in self-test and no-self-test modes
+            float X_ST[] = {0, 0, 0, 0, 0};
+            float Y_ST[] = {0, 0, 0, 0, 0};
+            float Z_ST[] = {0, 0, 0, 0, 0};
+            float X_NO_ST[] = {0, 0, 0, 0, 0};
+            float Y_NO_ST[] = {0, 0, 0, 0, 0};
+            float Z_NO_ST[] = {0, 0, 0, 0, 0};
+            // vectors containing avg values for each axis
+            float AVG_ST[] = {0, 0, 0}; // one element per axis
+            float AVG_NO_ST[] = {0, 0, 0}; // one element per axis
+
+            // set full scale to default value +/-2g
+            // enable the self-test mode with positive sign
+            uint8_t ctrl_reg5_value = (FULL_SCALE_2G << 3) | (1 << 1);
+            spi.write(CTRL_REG5, ctrl_reg5_value);
+            // read samples in self-test positive sign mode
+            for (int i = 0; i < num_samples; i++) {
+                readAccelData();
+                X_ST[i] = mLastAccel.getX();
+                Y_ST[i] = mLastAccel.getY();
+                Z_ST[i] = mLastAccel.getZ();
+                miosix::Thread::sleep(10);
+            }
+            // reset the self-test bits
+            ctrl_reg5_value &= ~(3 << 1);
+            // normal mode with full scale range +/-2g
+            ctrl_reg5_value |= (FULL_SCALE_2G << 3);
+            spi.write(CTRL_REG5, ctrl_reg5_value);
+            // read samples in normal mode
+            for (int i = 0; i < num_samples; i++) {
+                readAccelData();
+                X_NO_ST[i] = mLastAccel.getX();
+                Y_NO_ST[i] = mLastAccel.getY();
+                Z_NO_ST[i] = mLastAccel.getZ();
+                miosix::Thread::sleep(10);
+            }
+            // compute averages vectors:
+            // they contain one element for each axis 
+            // (position 0 for x, 1 for y and 2 for z)
+            // AVG_ST    : for self-test samples
+            // AVG_NO_ST : for normal mode samples
+            for (int i = 0; i < num_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];
+            }
+            for (int i = 0; i < 3; i++) {
+                AVG_ST[i] /= num_samples;
+                AVG_NO_ST[i] /= num_samples;
+            }
+
+            // Reset registers values with the ones
+            // specified in the constructor:
+            // set the full scale value in CTRL_REG5
+            ctrl_reg5_value = (full_scale << 3); // normal mode
+            spi.write(CTRL_REG5, ctrl_reg5_value);
+
+            // check that the averages differences
+            // do not exceed maximum tolerance
+            if ((AVG_NO_ST[0] - AVG_ST[0] > SELF_TEST_TOLERANCE_X_Y) ||
+                    (AVG_NO_ST[1] - AVG_ST[1] > SELF_TEST_TOLERANCE_X_Y) ||
+                    (AVG_NO_ST[2] - AVG_ST[2] > SELF_TEST_TOLERANCE_Z)) {
+                TRACE("[LIS3DSH] selfTest() : failed \n");
+                return false;
+            }
+            TRACE("[LIS3DSH] selfTest() : ok \n");
+            return true;
+        }
+
+        /**
+         * @brief Output data rate allowed values (4 bits).
+         */
+        enum ODR {
+            ODR_POWER_DOWN = 0, // 0000
+            ODR_3_125_HZ   = 1, // 0001, 3.125 Hz
+            ODR_6_25_HZ    = 2, // 0010, 6.25  Hz
+            ODR_12_5_HZ    = 3, // 0011, 12.5  Hz
+            ODR_25_HZ      = 4, // 0100
+            ODR_50_HZ      = 5, // 0101
+            ODR_100_HZ     = 6, // 0110, default value
+            ODR_400_HZ     = 7, // 0111
+            ODR_800_HZ     = 8, // 1000
+            ODR_1600_HZ    = 9  // 1001
+        };
+
+        /** 
+         * @brief Full scale range allowed values (3 bits).
+         */
+        enum FULL_SCALE {
+            FULL_SCALE_2G  = 0, // 000, +/- 2g
+            FULL_SCALE_4G  = 1, // 001, +/- 4g
+            FULL_SCALE_6G  = 2, // 010, +/- 6g
+            FULL_SCALE_8G  = 3, // 011, +/- 8g
+            FULL_SCALE_16G = 4, // 100  +/- 16g
+        };
+
+        /** 
+         * @brief Block data update allowed modes (1 bit).
+         */
+        enum BDU {
+            CONTINUOUS_UPDATE_MODE = 0,      // continuous update of accelerometer data
+            UPDATE_AFTER_READ_MODE = 1   // values updated only when MSB and LSB are read (recommended)
+        };
+
+    private:
+
+        /**
+         * @brief Read data from the accelerometer.
+         * 
+         * @return whether the operation succeded or not
+         */
+        bool readAccelData() {
+            SPITransaction spi(spi_slave);
+
+            // read the sensor's status register
+            uint8_t status = spi.read(STATUS);
+
+            if (status & 0x08) {  // bit 3 of status set to 1 (new data available)
+                if (status & 0x80) {  // bit 7 of status set to 1 (some data overwritten)
+
+                    // read acceleration on X
+                    int8_t acc_L = spi.read(OUT_X_L);
+                    int8_t acc_H = spi.read(OUT_X_H);
+                    int16_t acceleration = combine(acc_H, acc_L) * sensitivity;
+                    mLastAccel.setX(acceleration);
+                    
+                    // read acceleration on Y
+                    acc_L = spi.read(OUT_Y_L);
+                    acc_H = spi.read(OUT_Y_H);
+                    acceleration = combine(acc_H, acc_L) * sensitivity;
+                    mLastAccel.setY(acceleration);
+                    
+                    // read acceleration on Z
+                    acc_L = spi.read(OUT_Z_L);
+                    acc_H = spi.read(OUT_Z_H);
+                    acceleration = combine(acc_H, acc_L) * sensitivity;
+                    mLastAccel.setZ(acceleration);
+
+                    return true;
+                }
+            }
+
+            return false;
+        }
+
+        /**
+         * @brief Check that the WHO_AM_I register 
+         *        contains the correct value.
+         * 
+         * @return boolean value indicating whether the value read
+         *          from the WHO_AM_I register is correct or not
+         */
+        bool checkWhoAmI() {
+            SPITransaction spi(spi_slave);
+
+            // check the WHO_AM_I_REG register
+            uint8_t who_am_i_value = spi.read(WHO_AM_I_REG);
+            if (who_am_i_value == WHO_AM_I_DEFAULT_VALUE) { // whoami default value
+                TRACE("[LIS3DSH] WHO_AM_I : ok \n");
+                return true;
+            }
+            else {
+                TRACE("[LIS3DSH] WHO_AM_I : wrong value, %d instead of %d \n", 
+                                            who_am_i_value, WHO_AM_I_DEFAULT_VALUE);
+                last_error = ERR_NOT_ME;
+            }
+            
+            return false;
+        }
+
+        /** 
+         * @brief Combine low and high bits in a single number.
+         * 
+         * @param msb   the most significatn bits
+         * @param lsb   the least significant bits
+         * @return MSB and LSB combined in one value
+         */
+        int16_t combine(uint8_t msb, uint8_t lsb) {
+            return (msb << 8) | lsb;
+        }
+
+        /**
+         * @brief Given the requested full scale range, select the correct sensitivity value.
+         * 
+         * @return the sensitivity value corresponding to the requested full scale range
+         */ 
+        float select_sensitivity() {
+            float s;
+            switch (full_scale) {
+                case FULL_SCALE_2G:
+                    s = sensitivity_values._2G;
+                    break;
+                case FULL_SCALE_4G:
+                    s =  sensitivity_values._4G;
+                    break;
+                case FULL_SCALE_6G:
+                    s = sensitivity_values._6G;
+                    break;
+                case FULL_SCALE_8G:
+                    s = sensitivity_values._8G;
+                    break;
+                case FULL_SCALE_16G:
+                    s = sensitivity_values._16G;
+                    break;
+                default:
+                    TRACE("[LIS3DSH] Invalid full scale range given, using +/-2g \n");
+                    this->full_scale = FULL_SCALE_2G;
+                    s = sensitivity_values._2G;
+                    break;
+            }
+            return s;
+        }
+
+        /**
+         * @brief Registers' addresses definition.
+         */
+        enum REG {
+
+            // whoami register
+            WHO_AM_I_REG = 0x0F,  
+
+            // control registers for the accelerometer
+            CTRL_REG4 = 0x20, // control register to set accelerometer's ODR and BDU
+            CTRL_REG1 = 0x21, // state Machine 1 interrupt configuration register
+            CTRL_REG2 = 0x22, // state Machine 2 interrupt configuration register
+            CTRL_REG3 = 0x23,
+            CTRL_REG5 = 0x24, // control register to set the accelerometer full scale range, 
+                              // anti-aliansing filter and self-test enable
+            CTRL_REG6 = 0x25,
+
+            // status register
+            STATUS  = 0x27,
+
+            // accelerometer output registers 
+            // for x, y and z axis 
+            // (low and high bits in separate registers)
+            OUT_X_L = 0x28,
+            OUT_X_H = 0x29,
+            OUT_Y_L = 0x2A,
+            OUT_Y_H = 0x2B,
+            OUT_Z_L = 0x2C,
+            OUT_Z_H = 0x2D,
+
+            // temperature output register
+            OUT_T   = 0x0C,
+        };
+
+        /**
+         * @brief Definition of each sensitivity value,
+         *        corresponding to full scale range allowed values.
+         */
+        struct SENSITIVITY {
+            const float _2G  = 0.06; // +/- 2g
+            const float _4G  = 0.12; // +/- 4g
+            const float _6G  = 0.18; // +/- 6g
+            const float _8G  = 0.24; // +/- 8g
+            const float _16G = 0.73; // +/- 16g
+        };
+        SENSITIVITY sensitivity_values;
+
+        SPISlave spi_slave;
+
+        bool initialized = false;   // whether the sensor has been initialized or not
+
+        uint8_t odr;                // output data rate, default 100 Hz
+        uint8_t bdu;                // continuous mode or not, default is 0 (continuous update)
+        uint8_t full_scale;         // full scale range value (default +/-2g)
+
+        float sensitivity = sensitivity_values._2G;   // default sensitivity value
+
+        uint8_t WHO_AM_I_DEFAULT_VALUE = 63;   // 00111111
+
+        uint8_t TEMPERATURE_REF = 25; // temperature sensor 'zero'/reference value
+                                      // (value 0x00 from the sensor corresponds to 25 degrees celsius)
+
+        uint16_t SELF_TEST_TOLERANCE_X_Y = 140; // 140 mg
+        uint16_t SELF_TEST_TOLERANCE_Z   = 590; // 590 mg
+};
diff --git a/src/shared/sensors/LIS3DSH/LIS3DSHData.h b/src/shared/sensors/LIS3DSH/LIS3DSHData.h
new file mode 100644
index 0000000000000000000000000000000000000000..b9d834d5ea7a8ddb8fe45ad5ff4d313022060901
--- /dev/null
+++ b/src/shared/sensors/LIS3DSH/LIS3DSHData.h
@@ -0,0 +1,44 @@
+/* Copyright (c) 2020 Skyward Experimental Rocketry
+ * Authors: Luca Conterio
+ *
+ * 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 <ostream>
+#include "math/Vec3.h"
+
+struct LIS3DSHData
+{
+    long long timestamp;
+    Vec3 accel;
+    int8_t temperature;
+
+    static std::string header()
+    {
+        return "timestamp,acc_x,acc_y,acc_z,temperature\n";
+    }
+
+    void print(std::ostream& os) const
+    {
+        os << timestamp << "," << accel.getX() << "," << accel.getY() << ","
+           << accel.getZ() << temperature << "\n";
+    }
+};
diff --git a/src/tests/drivers/test-lis3dsh.cpp b/src/tests/drivers/test-lis3dsh.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..79fc511fa17bd7a64f22be5a9b48def0fce47180
--- /dev/null
+++ b/src/tests/drivers/test-lis3dsh.cpp
@@ -0,0 +1,111 @@
+/* Copyright (c) 2020 Skyward Experimental Rocketry
+ * Authors: Luca Conterio
+ *
+ * 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 <drivers/spi/SPIDriver.h>
+#include "sensors/LIS3DSH/LIS3DSH.h"
+#include "sensors/LIS3DSH/LIS3DSHData.h"
+
+using namespace std;
+using namespace miosix;
+
+SPIBus bus(SPI1);
+GpioPin cs(GPIOE_BASE, 3);
+
+int main() {
+
+    {
+        FastInterruptDisableLock dLock;
+
+        RCC->APB2ENR |= RCC_APB2ENR_SPI1EN; // SPI1 ENABLE
+
+        cs.mode(Mode::OUTPUT);
+    }
+    cs.high();
+    
+    LIS3DSH sensor(
+            bus,
+            cs,
+            sensor.ODR_100_HZ, 
+            sensor.UPDATE_AFTER_READ_MODE, 
+            sensor.FULL_SCALE_4G
+    );
+
+    Vec3 acc;
+    int8_t temp;
+
+    // sensor not initialized, should return false
+    if (sensor.onSimpleUpdate() || sensor.updateTemperature()) {
+        printf("\nTest failed: sensor not initialized \n");
+        return -1;
+    }
+
+    bool initialized = false;
+    // initialize imu
+    if (!sensor.init()) {
+        if (sensor.getLastError() == sensor.ERR_NOT_ME) {
+            printf("Test failed: invalid WHO_AM_I value, init failed \n");
+        }
+        else {
+            printf("Test failed: init failed \n");
+        }
+        return -1;
+    }
+    initialized = true;
+
+    // check if the sensor is properly working
+    if (!sensor.selfTest()) {
+        printf("\nTest failed: self-test failed \n");
+        return -1;
+    }
+
+    // if sensor already inizialized, init() should return false
+    if (initialized) {
+        if (sensor.init()) {
+            printf("\nTest failed: sensor is already initialized \n");
+            return -1;
+        }
+    }
+
+    Thread::sleep(500);
+    
+    // sample some data from the sensor
+    for(int i = 0; i < 5; i++) {
+        sensor.updateTemperature();
+        // sensor intitialized, should return true (false if no new data exist)
+        if (!sensor.onSimpleUpdate()) {
+            printf("\nWarning: no new data to be read \n");
+        }
+
+        acc = *(sensor.accelDataPtr());
+        temp = (int8_t) *(sensor.tempDataPtr());
+
+        printf("\nAccel: x: %.2f | y: %.2f | z: %.2f \n", acc.getX(), acc.getY(), acc.getZ());
+        printf("Temp: %d C \n", temp);
+        
+        Thread::sleep(200);
+    }
+
+    printf("\nTest ok \n");
+
+    return 0;
+}
\ No newline at end of file