diff --git a/CMakeLists.txt b/CMakeLists.txt
index 56309e4d6f92f5c10bb689b5cb7f14354b3d54e3..5352d725ddc0f3e19aa9932c03a262cc4933a085 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -327,7 +327,7 @@ add_executable(test-ads1118 src/tests/sensors/test-ads1118.cpp)
 sbs_target(test-ads1118 stm32f407vg_stm32f4discovery)
 
 add_executable(test-ads131m04 src/tests/sensors/test-ads131m04.cpp)
-sbs_target(test-ads131m04 stm32f429zi_stm32f4discovery)
+sbs_target(test-ads131m04 stm32f429zi_skyward_death_stack_v3)
 
 add_executable(test-ads131m08 src/tests/sensors/test-ads131m08.cpp)
 sbs_target(test-ads131m08 stm32f767zi_compute_unit)
diff --git a/src/shared/sensors/ADS131M04/ADS131M04.cpp b/src/shared/sensors/ADS131M04/ADS131M04.cpp
index 727ed16a8371926cc7f6d2d3816a46f743acd72c..2f5f7dfda2095b4aff8ffbefd32c37215e6fcd31 100644
--- a/src/shared/sensors/ADS131M04/ADS131M04.cpp
+++ b/src/shared/sensors/ADS131M04/ADS131M04.cpp
@@ -33,37 +33,26 @@ namespace Boardcore
 {
 
 ADS131M04::ADS131M04(SPIBusInterface &bus, miosix::GpioPin cs,
-                     SPIBusConfig config)
-    : ADS131M04(SPISlave(bus, cs, config))
+                     SPIBusConfig spiConfig, const Config &config)
+    : spiSlave(bus, cs, spiConfig), config(config)
 {
+    // Impose the correct spi mode
+    spiSlave.config.mode = SPI::Mode::MODE_1;
 }
 
-ADS131M04::ADS131M04(SPISlave spiSlave) : spiSlave(spiSlave)
+bool ADS131M04::init()
 {
-    // Initialize the channel configurations to the default values
-    for (int i = 0; i < CHANNELS_NUM; i++)
-    {
-        channelsPGAGain[i] = PGA::PGA_1;
-        channelsOffset[i]  = 0;
-        channelsGain[i]    = 1.0;
-    }
-}
+    reset();
+    applyConfig(config);
 
-SPIBusConfig ADS131M04::getDefaultSPIConfig()
-{
-    SPIBusConfig spiConfig{};
-    spiConfig.clockDivider = SPI::ClockDivider::DIV_64;
-    spiConfig.mode         = SPI::Mode::MODE_1;
-    return spiConfig;
+    return true;
 }
 
-bool ADS131M04::init() { return true; }
-
 bool ADS131M04::reset()
 {
     SPITransaction transaction(spiSlave);
 
-    uint8_t data[ADS131M04Defs::FULL_FRAME_SIZE] = {0};
+    uint8_t data[FULL_FRAME_SIZE] = {0};
     sendCommand(transaction, Command::RESET, data);
 
     // The reset command takes typically 5us to reload the register contents.
@@ -85,21 +74,44 @@ bool ADS131M04::reset()
     return true;
 }
 
-void ADS131M04::calibrateOffset()
+void ADS131M04::applyConfig(Config config)
 {
-    // The device internal data chain firsts subtracts the offset and then
-    // multiplies for the gain. To calibrate the offset we first reset it, then
-    // take some samples and apply the average as the new offset.
-    // So we need to reset the offset and gain
     for (int i = 0; i < CHANNELS_NUM; i++)
     {
-        setChannelOffsetImpl(static_cast<Channel>(i), 0);
-        setChannelGainCalibrationImpl(static_cast<Channel>(i), 1.0);
+        applyChannelConfig(static_cast<Channel>(i), config.channelsConfig[i]);
     }
 
-    // Sample the channels and average the samples
-    int32_t averageValues[CHANNELS_NUM] = {0};
-    int realSampleCount                 = 0;
+    setOversamplingRatio(config.oversamplingRatio);
+    if (config.globalChopModeEnabled)
+    {
+        enableGlobalChopMode();
+    }
+    else
+    {
+        disableGlobalChopMode();
+    }
+
+    // Save the newly applied configuration
+    this->config = config;
+}
+
+void ADS131M04::calibrateOffset(Channel channel)
+{
+    // The device internal data chain firsts subtracts the offset and then
+    // multiplies for the gain. To calibrate the offset we first reset it, then
+    // take some samples and apply the average as the new offset.
+    // So we need to reset the offset and gain
+    Config::ChannelConfig calibrationConfig{
+        .enabled = true,
+        .pga     = PGA::PGA_1,
+        .offset  = 0,
+        .gain    = 1.0,
+    };
+    applyChannelConfig(channel, calibrationConfig);
+
+    // Sample the channel and average the samples
+    int32_t averageValue = 0;
+    int realSampleCount  = 0;
     for (int i = 0; i < CALIBRATION_SAMPLES; i++)
     {
         // Wait for a sample to be ready
@@ -113,10 +125,7 @@ void ADS131M04::calibrateOffset()
             continue;
         }
 
-        for (int j = 0; j < CHANNELS_NUM; j++)
-        {
-            averageValues[j] += rawValues[j];
-        }
+        averageValue += rawValues[static_cast<int>(channel)];
 
         realSampleCount++;
     }
@@ -127,88 +136,43 @@ void ADS131M04::calibrateOffset()
     }
     else
     {
-        for (int i = 0; i < CHANNELS_NUM; i++)
+        // Compute the average
+        averageValue /= realSampleCount;
+        LOG_INFO(logger, "Channel {} average offset: {}",
+                 static_cast<int>(channel),
+                 averageValue * getLSBSizeFromGain(calibrationConfig.pga));
+
+        // Set the new offset only if valid, otherwise keep the old one
+        if (averageValue != 0)
         {
-            // Compute the average
-            averageValues[i] /= realSampleCount;
-            LOG_INFO(logger, "Channel {} average offset: {}", i,
-                     averageValues[i] * getLSBSizeFromGain(channelsPGAGain[i]));
-
-            // Set the new offset only if valid, otherwise keep the old one
-            if (averageValues[i] != 0)
-            {
-                channelsOffset[i] = averageValues[i];
-            }
+            config.channelsConfig[static_cast<int>(channel)].offset =
+                averageValue;
         }
     }
 
-    // Update the offset values and reset the gain as it was before
-    for (int i = 0; i < CHANNELS_NUM; i++)
-    {
-        setChannelOffset(static_cast<Channel>(i), channelsOffset[i]);
-        setChannelGainCalibrationImpl(static_cast<Channel>(i), channelsGain[i]);
-    }
-}
-
-void ADS131M04::setOversamplingRatio(OversamplingRatio ratio)
-{
-    changeRegister(Register::REG_CLOCK, static_cast<uint16_t>(ratio),
-                   RegClockMasks::OSR);
-}
-
-void ADS131M04::setChannelPGA(Channel channel, PGA gain)
-{
-    setChannelPGAImpl(channel, gain);
-    channelsPGAGain[static_cast<int>(channel)] = gain;
-}
-
-void ADS131M04::setChannelOffset(Channel channel, uint32_t offset)
-{
-    setChannelOffsetImpl(channel, offset);
-    channelsOffset[static_cast<int>(channel)] = offset;
-}
-
-void ADS131M04::setChannelGainCalibration(Channel channel, double gain)
-{
-    setChannelGainCalibrationImpl(channel, gain);
-    channelsGain[static_cast<int>(channel)] = gain;
-}
-
-void ADS131M04::enableChannel(Channel channel)
-{
-    changeRegister(Register::REG_CLOCK, 1 << (static_cast<int>(channel) + 8),
-                   1 << (static_cast<int>(channel) + 8));
-}
-
-void ADS131M04::disableChannel(Channel channel)
-{
-    changeRegister(Register::REG_CLOCK, 0,
-                   1 << (static_cast<int>(channel) + 8));
-}
-
-void ADS131M04::enableGlobalChopMode()
-{
-    changeRegister(Register::REG_CFG, RegConfigurationMasks::GC_EN,
-                   RegConfigurationMasks::GC_EN);
-}
-
-void ADS131M04::disableGlobalChopMode()
-{
-    changeRegister(Register::REG_CFG, 0, RegConfigurationMasks::GC_EN);
+    // Reset the original configuration with the new offset value
+    applyChannelConfig(channel,
+                       config.channelsConfig[static_cast<int>(channel)]);
 }
 
 bool ADS131M04::selfTest()
 {
     bool success = true;
 
-    // Reset PGA, offsets and gains and connect the positive test signal
+    // Reset configuration and connect the positive test signal
+    Config::ChannelConfig selfTestConfig{
+        .enabled = true,
+        .pga     = PGA::PGA_1,
+        .offset  = 0,
+        .gain    = 1.0,
+    };
     for (int i = 0; i < CHANNELS_NUM; i++)
     {
-        setChannelPGAImpl(static_cast<Channel>(i), PGA::PGA_1);
-        setChannelOffsetImpl(static_cast<Channel>(i), 0);
-        setChannelGainCalibrationImpl(static_cast<Channel>(i), 1.0);
+        applyChannelConfig(static_cast<Channel>(i), selfTestConfig);
         setChannelInput(static_cast<Channel>(i), Input::POSITIVE_DC_TEST);
     }
+    setOversamplingRatio(OversamplingRatio::OSR_16256);
+    disableGlobalChopMode();
 
     // Take some samples
     int32_t averageValues[CHANNELS_NUM] = {0};
@@ -249,7 +213,8 @@ bool ADS131M04::selfTest()
             averageValues[i] /= realSampleCount;
 
             // Convert the value to Volts
-            float volts = averageValues[i] * getLSBSizeFromGain(PGA::PGA_1);
+            float volts =
+                averageValues[i] * getLSBSizeFromGain(selfTestConfig.pga);
 
             // Check if the value is in the acceptable range
             if (volts < V_REF * TEST_SIGNAL_FACTOR - TEST_SIGNAL_SLACK)
@@ -311,7 +276,8 @@ bool ADS131M04::selfTest()
             averageValues[i] /= realSampleCount;
 
             // Convert the value to Volts
-            float volts = averageValues[i] * getLSBSizeFromGain(PGA::PGA_1);
+            float volts =
+                averageValues[i] * getLSBSizeFromGain(selfTestConfig.pga);
 
             // Check if the value is in the acceptable range
             if (volts > -V_REF * TEST_SIGNAL_FACTOR + TEST_SIGNAL_SLACK)
@@ -326,15 +292,15 @@ bool ADS131M04::selfTest()
         }
     }
 
-    // Reset channels previous configuration
+    // Reset channels input to default
     for (int i = 0; i < CHANNELS_NUM; i++)
     {
-        setChannelPGAImpl(static_cast<Channel>(i), channelsPGAGain[i]);
-        setChannelOffsetImpl(static_cast<Channel>(i), channelsOffset[i]);
-        setChannelGainCalibrationImpl(static_cast<Channel>(i), channelsGain[i]);
         setChannelInput(static_cast<Channel>(i), Input::DEFAULT);
     }
 
+    // Reset to previous configuration
+    applyConfig(config);
+
     // We fail even if one channel didn't pass the test
     return success;
 }
@@ -355,26 +321,42 @@ ADS131M04Data ADS131M04::sampleImpl()
     for (int i = 0; i < CHANNELS_NUM; i++)
     {
         adcData.voltage[i] =
-            rawValues[i] * getLSBSizeFromGain(channelsPGAGain[i]);
+            rawValues[i] * getLSBSizeFromGain(config.channelsConfig[i].pga);
     }
 
     return adcData;
 }
 
-void ADS131M04::setChannelInput(Channel channel, Input input)
+void ADS131M04::applyChannelConfig(Channel channel,
+                                   Config::ChannelConfig config)
 {
-    Register reg = getChannelConfigRegister(channel);
-    changeRegister(reg, static_cast<uint16_t>(input), RegChannelMasks::CFG_MUX);
+    if (config.enabled)
+    {
+        setChannelPGA(channel, config.pga);
+        setChannelOffset(channel, config.offset);
+        setChannelGain(channel, config.gain);
+        enableChannel(channel);
+    }
+    else
+    {
+        disableChannel(channel);
+    }
 }
 
-void ADS131M04::setChannelPGAImpl(Channel channel, PGA gain)
+void ADS131M04::setOversamplingRatio(OversamplingRatio ratio)
+{
+    changeRegister(Register::REG_CLOCK, static_cast<uint16_t>(ratio),
+                   RegClockMasks::OSR);
+}
+
+void ADS131M04::setChannelPGA(Channel channel, PGA gain)
 {
     int shift = static_cast<int>(channel) * 4;
     changeRegister(Register::REG_GAIN, static_cast<uint16_t>(gain) << shift,
                    RegGainMasks::PGA_GAIN_0 << shift);
 }
 
-void ADS131M04::setChannelOffsetImpl(Channel channel, uint32_t offset)
+void ADS131M04::setChannelOffset(Channel channel, uint32_t offset)
 {
     // The offset is a 24 bit value. Its two most significant bytes are stored
     // in the MSB register, and the least significant in the LSB register, like
@@ -392,7 +374,7 @@ void ADS131M04::setChannelOffsetImpl(Channel channel, uint32_t offset)
     writeRegister(getChannelOffsetRegisterLSB(channel), offset << 8);
 }
 
-void ADS131M04::setChannelGainCalibrationImpl(Channel channel, double gain)
+void ADS131M04::setChannelGain(Channel channel, double gain)
 {
     // If the user passes a value outside the range [0, 2] we cap it.
     if (gain < 0)
@@ -404,7 +386,7 @@ void ADS131M04::setChannelGainCalibrationImpl(Channel channel, double gain)
         gain = 2;
     }
 
-    // The ADS131M08 corrects for gain errors by multiplying the ADC conversion
+    // The ADS131M04 corrects for gain errors by multiplying the ADC conversion
     // result using the gain calibration registers.
     // The contents of the gain calibration registers are interpreted by the
     // dives as 24-bit unsigned values corresponding to linear steps from 0 to
@@ -430,6 +412,35 @@ void ADS131M04::setChannelGainCalibrationImpl(Channel channel, double gain)
     writeRegister(getChannelGainRegisterLSB(channel), rawGain << 8);
 }
 
+void ADS131M04::enableChannel(Channel channel)
+{
+    changeRegister(Register::REG_CLOCK, 1 << (static_cast<int>(channel) + 8),
+                   1 << (static_cast<int>(channel) + 8));
+}
+
+void ADS131M04::disableChannel(Channel channel)
+{
+    changeRegister(Register::REG_CLOCK, 0,
+                   1 << (static_cast<int>(channel) + 8));
+}
+
+void ADS131M04::enableGlobalChopMode()
+{
+    changeRegister(Register::REG_CFG, RegConfigurationMasks::GC_EN,
+                   RegConfigurationMasks::GC_EN);
+}
+
+void ADS131M04::disableGlobalChopMode()
+{
+    changeRegister(Register::REG_CFG, 0, RegConfigurationMasks::GC_EN);
+}
+
+void ADS131M04::setChannelInput(Channel channel, Input input)
+{
+    Register reg = getChannelConfigRegister(channel);
+    changeRegister(reg, static_cast<uint16_t>(input), RegChannelMasks::CFG_MUX);
+}
+
 Register ADS131M04::getChannelConfigRegister(Channel channel)
 {
     switch (static_cast<int>(channel))
diff --git a/src/shared/sensors/ADS131M04/ADS131M04.h b/src/shared/sensors/ADS131M04/ADS131M04.h
index c5ac7068f0699efc9bde3edcd39ff392bad77699..d8142f18c33e9e28e3321f82f4158fcf02985bc4 100644
--- a/src/shared/sensors/ADS131M04/ADS131M04.h
+++ b/src/shared/sensors/ADS131M04/ADS131M04.h
@@ -75,27 +75,69 @@ namespace Boardcore
 class ADS131M04 : public Sensor<ADS131M04Data>
 {
 public:
-    ADS131M04(SPIBusInterface& bus, miosix::GpioPin cs,
-              SPIBusConfig config = getDefaultSPIConfig());
+    struct Config
+    {
+        struct ChannelConfig
+        {
+            bool enabled           = true;
+            ADS131M04Defs::PGA pga = ADS131M04Defs::PGA::PGA_1;
+            int32_t offset         = 0;
+            double gain            = 1.0;
+        };
+
+        ChannelConfig channelsConfig[ADS131M04Defs::CHANNELS_NUM];
+
+        ADS131M04Defs::OversamplingRatio oversamplingRatio =
+            ADS131M04Defs::OversamplingRatio::OSR_16256;
+        bool globalChopModeEnabled = false;
+    };
+
+    ADS131M04(SPIBusInterface& bus, miosix::GpioPin cs, SPIBusConfig spiConfig,
+              const Config& config);
 
-    explicit ADS131M04(SPISlave spiSlave);
+    bool init() override;
+
+    bool reset();
 
     /**
-     * Constructs the default config for SPI Bus.
+     * @brief Overwrites the sensor settings.
      *
-     * @returns The default SPIBusConfig.
+     * Writes a certain config to the sensor registers. This method is
+     * automatically called in ADS131M04::init() using as parameter the
+     * configuration given in the constructor.
+     *
+     * @param config The configuration to be applied.
      */
-    static SPIBusConfig getDefaultSPIConfig();
-
-    bool init() override;
-
-    bool reset();
+    void applyConfig(Config config);
 
     /**
      * @brief Samples each channel, averages the samples and applies offset
      * compensation in the device.
      */
-    void calibrateOffset();
+    void calibrateOffset(ADS131M04Defs::Channel channel);
+
+    /**
+     * @brief The self test samples internally connects each channel to known
+     * test signals and verifies if the sampled values are in an expected range.
+     *
+     * @returns True if the self test is successful, false otherwise.
+     */
+    bool selfTest() override;
+
+private:
+    ADS131M04Data sampleImpl() override;
+
+    /**
+     * @brief Overwrites the channel settings.
+     *
+     * Writes a certain configuration to the sensor registers. This method is
+     * automatically called in ADS131M04::applyConfig and in other routines.
+     *
+     * @param channel Specific channel where the configuration will be applied.
+     * @param config The configuration to be applied.
+     */
+    void applyChannelConfig(ADS131M04Defs::Channel channel,
+                            Config::ChannelConfig config);
 
     /**
      * @brief changes the oversampling ratio.
@@ -130,7 +172,7 @@ public:
      * @param gain Gain value between 0 and 2. Values outside this range will be
      * capped.
      */
-    void setChannelGainCalibration(ADS131M04Defs::Channel channel, double gain);
+    void setChannelGain(ADS131M04Defs::Channel channel, double gain);
 
     void enableChannel(ADS131M04Defs::Channel channel);
 
@@ -159,40 +201,9 @@ public:
      */
     void disableGlobalChopMode();
 
-    /**
-     * @brief The self test samples internally connects each channel to known
-     * test signals and verifies if the sampled values are in an expected range.
-     *
-     * @returns True if the self test is successful, false otherwise.
-     */
-    bool selfTest() override;
-
-private:
-    ADS131M04Data sampleImpl() override;
-
     void setChannelInput(ADS131M04Defs::Channel channel,
                          ADS131M04Defs::Input input);
 
-    /**
-     * setChannelPGS() implementation without saving the gain value in
-     * the local variable.
-     */
-    void setChannelPGAImpl(ADS131M04Defs::Channel channel,
-                           ADS131M04Defs::PGA gain);
-
-    /**
-     * setChannelOffset() implementation without saving the offset value in
-     * the local variable.
-     */
-    void setChannelOffsetImpl(ADS131M04Defs::Channel channel, uint32_t offset);
-
-    /**
-     * setChannelGainCalibration() implementation without saving the gain value
-     * in the local variable.
-     */
-    void setChannelGainCalibrationImpl(ADS131M04Defs::Channel channel,
-                                       double gain);
-
     ADS131M04Defs::Register getChannelConfigRegister(
         ADS131M04Defs::Channel channel);
 
@@ -234,12 +245,8 @@ private:
 
     SPISlave spiSlave;
 
-    // Saving the current configuration of the device
-    // This is necessary because the selfTest and calibrateOffset functions
-    // temporarily resets the channels configuration
-    ADS131M04Defs::PGA channelsPGAGain[ADS131M04Defs::CHANNELS_NUM];
-    uint32_t channelsOffset[ADS131M04Defs::CHANNELS_NUM];
-    double channelsGain[ADS131M04Defs::CHANNELS_NUM];
+    // Current device configuration
+    Config config;
 
     PrintLogger logger = Logging::getLogger("ads131m04");
 };
diff --git a/src/shared/sensors/ADS131M04/ADS131M04Data.h b/src/shared/sensors/ADS131M04/ADS131M04Data.h
index d04b55a3d560f4c26b307e42af91525ef40cab5d..57057fde47c8402c5c2b2c1a99ba74323730149f 100644
--- a/src/shared/sensors/ADS131M04/ADS131M04Data.h
+++ b/src/shared/sensors/ADS131M04/ADS131M04Data.h
@@ -22,10 +22,13 @@
 
 #pragma once
 
+#include <sensors/SensorData.h>
 #include <stdint.h>
 
 #include <ostream>
 
+#include "ADS131M04Defs.h"
+
 namespace Boardcore
 {
 
@@ -57,6 +60,12 @@ struct ADS131M04Data
         os << timestamp << "," << voltage[0] << "," << voltage[1] << ","
            << voltage[2] << "," << voltage[3] << "\n";
     }
+
+    const ADCData getVoltage(ADS131M04Defs::Channel channel)
+    {
+        return {timestamp, static_cast<uint8_t>(channel),
+                voltage[static_cast<uint8_t>(channel)]};
+    }
 };
 
 }  // namespace Boardcore
diff --git a/src/shared/sensors/ADS131M08/ADS131M08.cpp b/src/shared/sensors/ADS131M08/ADS131M08.cpp
index 4dbff38b1a83d647e844b082c98cbf80630b719b..a1e10248313ac0d7b2c309b175a870a550231b93 100644
--- a/src/shared/sensors/ADS131M08/ADS131M08.cpp
+++ b/src/shared/sensors/ADS131M08/ADS131M08.cpp
@@ -33,37 +33,26 @@ namespace Boardcore
 {
 
 ADS131M08::ADS131M08(SPIBusInterface &bus, miosix::GpioPin cs,
-                     SPIBusConfig config)
-    : ADS131M08(SPISlave(bus, cs, config))
+                     SPIBusConfig spiConfig, const Config &config)
+    : spiSlave(bus, cs, spiConfig), config(config)
 {
+    // Impose the correct spi mode
+    spiSlave.config.mode = SPI::Mode::MODE_1;
 }
 
-ADS131M08::ADS131M08(SPISlave spiSlave) : spiSlave(spiSlave)
+bool ADS131M08::init()
 {
-    // Initialize the channel configurations to the default values
-    for (int i = 0; i < CHANNELS_NUM; i++)
-    {
-        channelsPGAGain[i] = PGA::PGA_1;
-        channelsOffset[i]  = 0;
-        channelsGain[i]    = 1.0;
-    }
-}
+    reset();
+    applyConfig(config);
 
-SPIBusConfig ADS131M08::getDefaultSPIConfig()
-{
-    SPIBusConfig spiConfig{};
-    spiConfig.clockDivider = SPI::ClockDivider::DIV_64;
-    spiConfig.mode         = SPI::Mode::MODE_1;
-    return spiConfig;
+    return true;
 }
 
-bool ADS131M08::init() { return true; }
-
 bool ADS131M08::reset()
 {
     SPITransaction transaction(spiSlave);
 
-    uint8_t data[ADS131M08Defs::FULL_FRAME_SIZE] = {0};
+    uint8_t data[FULL_FRAME_SIZE] = {0};
     sendCommand(transaction, Command::RESET, data);
 
     // The reset command takes typically 5us to reload the register contents.
@@ -85,21 +74,44 @@ bool ADS131M08::reset()
     return true;
 }
 
-void ADS131M08::calibrateOffset()
+void ADS131M08::applyConfig(Config config)
 {
-    // The device internal data chain firsts subtracts the offset and then
-    // multiplies for the gain. To calibrate the offset we first reset it, then
-    // take some samples and apply the average as the new offset.
-    // So we need to reset the offset and gain
     for (int i = 0; i < CHANNELS_NUM; i++)
     {
-        setChannelOffsetImpl(static_cast<Channel>(i), 0);
-        setChannelGainCalibrationImpl(static_cast<Channel>(i), 1.0);
+        applyChannelConfig(static_cast<Channel>(i), config.channelsConfig[i]);
     }
 
-    // Sample the channels and average the samples
-    int32_t averageValues[CHANNELS_NUM] = {0};
-    int realSampleCount                 = 0;
+    setOversamplingRatio(config.oversamplingRatio);
+    if (config.globalChopModeEnabled)
+    {
+        enableGlobalChopMode();
+    }
+    else
+    {
+        disableGlobalChopMode();
+    }
+
+    // Save the newly applied configuration
+    this->config = config;
+}
+
+void ADS131M08::calibrateOffset(Channel channel)
+{
+    // The device internal data chain firsts subtracts the offset and then
+    // multiplies for the gain. To calibrate the offset we first reset it, then
+    // take some samples and apply the average as the new offset.
+    // So we need to reset the offset and gain
+    Config::ChannelConfig calibrationConfig{
+        .enabled = true,
+        .pga     = PGA::PGA_1,
+        .offset  = 0,
+        .gain    = 1.0,
+    };
+    applyChannelConfig(channel, calibrationConfig);
+
+    // Sample the channel and average the samples
+    int32_t averageValue = 0;
+    int realSampleCount  = 0;
     for (int i = 0; i < CALIBRATION_SAMPLES; i++)
     {
         // Wait for a sample to be ready
@@ -113,10 +125,7 @@ void ADS131M08::calibrateOffset()
             continue;
         }
 
-        for (int j = 0; j < CHANNELS_NUM; j++)
-        {
-            averageValues[j] += rawValues[j];
-        }
+        averageValue += rawValues[static_cast<int>(channel)];
 
         realSampleCount++;
     }
@@ -127,88 +136,43 @@ void ADS131M08::calibrateOffset()
     }
     else
     {
-        for (int i = 0; i < CHANNELS_NUM; i++)
+        // Compute the average
+        averageValue /= realSampleCount;
+        LOG_INFO(logger, "Channel {} average offset: {}",
+                 static_cast<int>(channel),
+                 averageValue * getLSBSizeFromGain(calibrationConfig.pga));
+
+        // Set the new offset only if valid, otherwise keep the old one
+        if (averageValue != 0)
         {
-            // Compute the average
-            averageValues[i] /= realSampleCount;
-            LOG_INFO(logger, "Channel {} average offset: {}", i,
-                     averageValues[i] * getLSBSizeFromGain(channelsPGAGain[i]));
-
-            // Set the new offset only if valid, otherwise keep the old one
-            if (averageValues[i] != 0)
-            {
-                channelsOffset[i] = averageValues[i];
-            }
+            config.channelsConfig[static_cast<int>(channel)].offset =
+                averageValue;
         }
     }
 
-    // Update the offset values and reset the gain as it was before
-    for (int i = 0; i < CHANNELS_NUM; i++)
-    {
-        setChannelOffset(static_cast<Channel>(i), channelsOffset[i]);
-        setChannelGainCalibrationImpl(static_cast<Channel>(i), channelsGain[i]);
-    }
-}
-
-void ADS131M08::setOversamplingRatio(OversamplingRatio ratio)
-{
-    changeRegister(Register::REG_CLOCK, static_cast<uint16_t>(ratio),
-                   RegClockMasks::OSR);
-}
-
-void ADS131M08::setChannelPGA(Channel channel, PGA gain)
-{
-    setChannelPGAImpl(channel, gain);
-    channelsPGAGain[static_cast<int>(channel)] = gain;
-}
-
-void ADS131M08::setChannelOffset(Channel channel, uint32_t offset)
-{
-    setChannelOffsetImpl(channel, offset);
-    channelsOffset[static_cast<int>(channel)] = offset;
-}
-
-void ADS131M08::setChannelGainCalibration(Channel channel, double gain)
-{
-    setChannelGainCalibrationImpl(channel, gain);
-    channelsGain[static_cast<int>(channel)] = gain;
-}
-
-void ADS131M08::enableChannel(Channel channel)
-{
-    changeRegister(Register::REG_CLOCK, 1 << (static_cast<int>(channel) + 8),
-                   1 << (static_cast<int>(channel) + 8));
-}
-
-void ADS131M08::disableChannel(Channel channel)
-{
-    changeRegister(Register::REG_CLOCK, 0,
-                   1 << (static_cast<int>(channel) + 8));
-}
-
-void ADS131M08::enableGlobalChopMode()
-{
-    changeRegister(Register::REG_CFG, RegConfigurationMasks::GC_EN,
-                   RegConfigurationMasks::GC_EN);
-}
-
-void ADS131M08::disableGlobalChopMode()
-{
-    changeRegister(Register::REG_CFG, 0, RegConfigurationMasks::GC_EN);
+    // Reset the original configuration with the new offset value
+    applyChannelConfig(channel,
+                       config.channelsConfig[static_cast<int>(channel)]);
 }
 
 bool ADS131M08::selfTest()
 {
     bool success = true;
 
-    // Reset PGA, offsets and gains and connect the positive test signal
+    // Reset configuration and connect the positive test signal
+    Config::ChannelConfig selfTestConfig{
+        .enabled = true,
+        .pga     = PGA::PGA_1,
+        .offset  = 0,
+        .gain    = 1.0,
+    };
     for (int i = 0; i < CHANNELS_NUM; i++)
     {
-        setChannelPGAImpl(static_cast<Channel>(i), PGA::PGA_1);
-        setChannelOffsetImpl(static_cast<Channel>(i), 0);
-        setChannelGainCalibrationImpl(static_cast<Channel>(i), 1.0);
+        applyChannelConfig(static_cast<Channel>(i), selfTestConfig);
         setChannelInput(static_cast<Channel>(i), Input::POSITIVE_DC_TEST);
     }
+    setOversamplingRatio(OversamplingRatio::OSR_16256);
+    disableGlobalChopMode();
 
     // Take some samples
     int32_t averageValues[CHANNELS_NUM] = {0};
@@ -249,7 +213,8 @@ bool ADS131M08::selfTest()
             averageValues[i] /= realSampleCount;
 
             // Convert the value to Volts
-            float volts = averageValues[i] * getLSBSizeFromGain(PGA::PGA_1);
+            float volts =
+                averageValues[i] * getLSBSizeFromGain(selfTestConfig.pga);
 
             // Check if the value is in the acceptable range
             if (volts < V_REF * TEST_SIGNAL_FACTOR - TEST_SIGNAL_SLACK)
@@ -311,7 +276,8 @@ bool ADS131M08::selfTest()
             averageValues[i] /= realSampleCount;
 
             // Convert the value to Volts
-            float volts = averageValues[i] * getLSBSizeFromGain(PGA::PGA_1);
+            float volts =
+                averageValues[i] * getLSBSizeFromGain(selfTestConfig.pga);
 
             // Check if the value is in the acceptable range
             if (volts > -V_REF * TEST_SIGNAL_FACTOR + TEST_SIGNAL_SLACK)
@@ -326,15 +292,15 @@ bool ADS131M08::selfTest()
         }
     }
 
-    // Reset channels previous configuration
+    // Reset channels input to default
     for (int i = 0; i < CHANNELS_NUM; i++)
     {
-        setChannelPGAImpl(static_cast<Channel>(i), channelsPGAGain[i]);
-        setChannelOffsetImpl(static_cast<Channel>(i), channelsOffset[i]);
-        setChannelGainCalibrationImpl(static_cast<Channel>(i), channelsGain[i]);
         setChannelInput(static_cast<Channel>(i), Input::DEFAULT);
     }
 
+    // Reset to previous configuration
+    applyConfig(config);
+
     // We fail even if one channel didn't pass the test
     return success;
 }
@@ -355,19 +321,35 @@ ADS131M08Data ADS131M08::sampleImpl()
     for (int i = 0; i < CHANNELS_NUM; i++)
     {
         adcData.voltage[i] =
-            rawValues[i] * getLSBSizeFromGain(channelsPGAGain[i]);
+            rawValues[i] * getLSBSizeFromGain(config.channelsConfig[i].pga);
     }
 
     return adcData;
 }
 
-void ADS131M08::setChannelInput(Channel channel, Input input)
+void ADS131M08::applyChannelConfig(Channel channel,
+                                   Config::ChannelConfig config)
 {
-    Register reg = getChannelConfigRegister(channel);
-    changeRegister(reg, static_cast<uint16_t>(input), RegChannelMasks::CFG_MUX);
+    if (config.enabled)
+    {
+        setChannelPGA(channel, config.pga);
+        setChannelOffset(channel, config.offset);
+        setChannelGain(channel, config.gain);
+        enableChannel(channel);
+    }
+    else
+    {
+        disableChannel(channel);
+    }
+}
+
+void ADS131M08::setOversamplingRatio(OversamplingRatio ratio)
+{
+    changeRegister(Register::REG_CLOCK, static_cast<uint16_t>(ratio),
+                   RegClockMasks::OSR);
 }
 
-void ADS131M08::setChannelPGAImpl(Channel channel, PGA gain)
+void ADS131M08::setChannelPGA(Channel channel, PGA gain)
 {
     if (channel <= Channel::CHANNEL_3)
     {
@@ -385,7 +367,7 @@ void ADS131M08::setChannelPGAImpl(Channel channel, PGA gain)
     }
 }
 
-void ADS131M08::setChannelOffsetImpl(Channel channel, uint32_t offset)
+void ADS131M08::setChannelOffset(Channel channel, int32_t offset)
 {
     // The offset is a 24 bit value. Its two most significant bytes are stored
     // in the MSB register, and the least significant in the LSB register, like
@@ -403,7 +385,7 @@ void ADS131M08::setChannelOffsetImpl(Channel channel, uint32_t offset)
     writeRegister(getChannelOffsetRegisterLSB(channel), offset << 8);
 }
 
-void ADS131M08::setChannelGainCalibrationImpl(Channel channel, double gain)
+void ADS131M08::setChannelGain(Channel channel, double gain)
 {
     // If the user passes a value outside the range [0, 2] we cap it.
     if (gain < 0)
@@ -441,6 +423,35 @@ void ADS131M08::setChannelGainCalibrationImpl(Channel channel, double gain)
     writeRegister(getChannelGainRegisterLSB(channel), rawGain << 8);
 }
 
+void ADS131M08::enableChannel(Channel channel)
+{
+    changeRegister(Register::REG_CLOCK, 1 << (static_cast<int>(channel) + 8),
+                   1 << (static_cast<int>(channel) + 8));
+}
+
+void ADS131M08::disableChannel(Channel channel)
+{
+    changeRegister(Register::REG_CLOCK, 0,
+                   1 << (static_cast<int>(channel) + 8));
+}
+
+void ADS131M08::enableGlobalChopMode()
+{
+    changeRegister(Register::REG_CFG, RegConfigurationMasks::GC_EN,
+                   RegConfigurationMasks::GC_EN);
+}
+
+void ADS131M08::disableGlobalChopMode()
+{
+    changeRegister(Register::REG_CFG, 0, RegConfigurationMasks::GC_EN);
+}
+
+void ADS131M08::setChannelInput(Channel channel, Input input)
+{
+    Register reg = getChannelConfigRegister(channel);
+    changeRegister(reg, static_cast<uint16_t>(input), RegChannelMasks::CFG_MUX);
+}
+
 Register ADS131M08::getChannelConfigRegister(Channel channel)
 {
     switch (static_cast<int>(channel))
diff --git a/src/shared/sensors/ADS131M08/ADS131M08.h b/src/shared/sensors/ADS131M08/ADS131M08.h
index 01ad2c733f0883054976fa1e03209ce33415ef7a..a83fdaf0978013227e8990c83a7540ce7268cf9d 100644
--- a/src/shared/sensors/ADS131M08/ADS131M08.h
+++ b/src/shared/sensors/ADS131M08/ADS131M08.h
@@ -75,27 +75,69 @@ namespace Boardcore
 class ADS131M08 : public Sensor<ADS131M08Data>
 {
 public:
-    ADS131M08(SPIBusInterface& bus, miosix::GpioPin cs,
-              SPIBusConfig config = getDefaultSPIConfig());
+    struct Config
+    {
+        struct ChannelConfig
+        {
+            bool enabled           = true;
+            ADS131M08Defs::PGA pga = ADS131M08Defs::PGA::PGA_1;
+            int32_t offset         = 0;
+            double gain            = 1.0;
+        };
+
+        ChannelConfig channelsConfig[ADS131M08Defs::CHANNELS_NUM];
+
+        ADS131M08Defs::OversamplingRatio oversamplingRatio =
+            ADS131M08Defs::OversamplingRatio::OSR_16256;
+        bool globalChopModeEnabled = false;
+    };
+
+    ADS131M08(SPIBusInterface& bus, miosix::GpioPin cs, SPIBusConfig spiConfig,
+              const Config& config);
 
-    explicit ADS131M08(SPISlave spiSlave);
+    bool init() override;
+
+    bool reset();
 
     /**
-     * Constructs the default config for SPI Bus.
+     * @brief Overwrites the sensor settings.
      *
-     * @returns The default SPIBusConfig.
+     * Writes a certain config to the sensor registers. This method is
+     * automatically called in ADS131M08::init() using as parameter the
+     * configuration given in the constructor.
+     *
+     * @param config The configuration to be applied.
      */
-    static SPIBusConfig getDefaultSPIConfig();
-
-    bool init() override;
-
-    bool reset();
+    void applyConfig(Config config);
 
     /**
      * @brief Samples each channel, averages the samples and applies offset
      * compensation in the device.
      */
-    void calibrateOffset();
+    void calibrateOffset(ADS131M08Defs::Channel channel);
+
+    /**
+     * @brief The self test samples internally connects each channel to known
+     * test signals and verifies if the sampled values are in an expected range.
+     *
+     * @returns True if the self test is successful, false otherwise.
+     */
+    bool selfTest() override;
+
+private:
+    ADS131M08Data sampleImpl() override;
+
+    /**
+     * @brief Overwrites the channel settings.
+     *
+     * Writes a certain configuration to the sensor registers. This method is
+     * automatically called in ADS131M08::applyConfig and in other routines.
+     *
+     * @param channel Specific channel where the configuration will be applied.
+     * @param config The configuration to be applied.
+     */
+    void applyChannelConfig(ADS131M08Defs::Channel channel,
+                            Config::ChannelConfig config);
 
     /**
      * @brief changes the oversampling ratio.
@@ -122,7 +164,7 @@ public:
      *
      * Note that the device offset is a 24bit two complement.
      */
-    void setChannelOffset(ADS131M08Defs::Channel channel, uint32_t offset);
+    void setChannelOffset(ADS131M08Defs::Channel channel, int32_t offset);
 
     /**
      * @brief Sets the channel gain calibration.
@@ -130,7 +172,7 @@ public:
      * @param gain Gain value between 0 and 2. Values outside this range will be
      * capped.
      */
-    void setChannelGainCalibration(ADS131M08Defs::Channel channel, double gain);
+    void setChannelGain(ADS131M08Defs::Channel channel, double gain);
 
     void enableChannel(ADS131M08Defs::Channel channel);
 
@@ -159,40 +201,9 @@ public:
      */
     void disableGlobalChopMode();
 
-    /**
-     * @brief The self test samples internally connects each channel to known
-     * test signals and verifies if the sampled values are in an expected range.
-     *
-     * @returns True if the self test is successful, false otherwise.
-     */
-    bool selfTest() override;
-
-private:
-    ADS131M08Data sampleImpl() override;
-
     void setChannelInput(ADS131M08Defs::Channel channel,
                          ADS131M08Defs::Input input);
 
-    /**
-     * setChannelPGS() implementation without saving the gain value in
-     * the local variable.
-     */
-    void setChannelPGAImpl(ADS131M08Defs::Channel channel,
-                           ADS131M08Defs::PGA gain);
-
-    /**
-     * setChannelOffset() implementation without saving the offset value in
-     * the local variable.
-     */
-    void setChannelOffsetImpl(ADS131M08Defs::Channel channel, uint32_t offset);
-
-    /**
-     * setChannelGainCalibration() implementation without saving the gain value
-     * in the local variable.
-     */
-    void setChannelGainCalibrationImpl(ADS131M08Defs::Channel channel,
-                                       double gain);
-
     ADS131M08Defs::Register getChannelConfigRegister(
         ADS131M08Defs::Channel channel);
 
@@ -234,12 +245,8 @@ private:
 
     SPISlave spiSlave;
 
-    // Saving the current configuration of the device
-    // This is necessary because the selfTest and calibrateOffset functions
-    // temporarily resets the channels configuration
-    ADS131M08Defs::PGA channelsPGAGain[ADS131M08Defs::CHANNELS_NUM];
-    uint32_t channelsOffset[ADS131M08Defs::CHANNELS_NUM];
-    double channelsGain[ADS131M08Defs::CHANNELS_NUM];
+    // Current device configuration
+    Config config;
 
     PrintLogger logger = Logging::getLogger("ads131m08");
 };
diff --git a/src/shared/sensors/ADS131M08/ADS131M08Data.h b/src/shared/sensors/ADS131M08/ADS131M08Data.h
index ac28f168b6dc248e23f5e5ebfa566ced2353c17a..35ab9fe02e543594c2ecaca4ae384a7a85dc78ec 100644
--- a/src/shared/sensors/ADS131M08/ADS131M08Data.h
+++ b/src/shared/sensors/ADS131M08/ADS131M08Data.h
@@ -22,6 +22,7 @@
 
 #pragma once
 
+#include <sensors/SensorData.h>
 #include <stdint.h>
 
 #include <ostream>
@@ -67,7 +68,7 @@ struct ADS131M08Data
            << voltage[5] << "," << voltage[6] << "," << voltage[7] << "\n";
     }
 
-    ADCData getVoltage(ADS131M08Defs::Channel channel)
+    const ADCData getVoltage(ADS131M08Defs::Channel channel)
     {
         return {timestamp, static_cast<uint8_t>(channel),
                 voltage[static_cast<uint8_t>(channel)]};
diff --git a/src/tests/sensors/test-ads131m04.cpp b/src/tests/sensors/test-ads131m04.cpp
index cda44e9bc792c530de52472beecf5f095163a90b..1e073ee6ecd1ade54b7697fb307433c22a9d9519 100644
--- a/src/tests/sensors/test-ads131m04.cpp
+++ b/src/tests/sensors/test-ads131m04.cpp
@@ -28,10 +28,10 @@
 using namespace miosix;
 using namespace Boardcore;
 
-GpioPin sckPin  = GpioPin(GPIOE_BASE, 2);
-GpioPin misoPin = GpioPin(GPIOE_BASE, 5);
-GpioPin mosiPin = GpioPin(GPIOE_BASE, 6);
-GpioPin csPin   = GpioPin(GPIOE_BASE, 4);
+GpioPin sckPin  = GpioPin(GPIOA_BASE, 5);
+GpioPin misoPin = GpioPin(GPIOA_BASE, 6);
+GpioPin mosiPin = GpioPin(GPIOA_BASE, 7);
+GpioPin csPin   = GpioPin(GPIOA_BASE, 4);
 
 void initBoard()
 {
@@ -51,21 +51,17 @@ int main()
     // Enable SPI clock and set gpios
     initBoard();
 
-    // SPI configuration setup
-    SPIBus spiBus(SPI4);
-    SPISlave spiSlave(spiBus, csPin, ADS131M04::getDefaultSPIConfig());
+    // ADC configuration
+    ADS131M04::Config config{
+        .oversamplingRatio     = ADS131M04Defs::OversamplingRatio::OSR_8192,
+        .globalChopModeEnabled = true,
+    };
 
     // Device initialization
-    ADS131M04 ads131(spiSlave);
+    SPIBus spiBus(SPI1);
+    ADS131M04 ads131(spiBus, csPin, {}, config);
 
-    ads131.reset();
-
-    ads131.enableGlobalChopMode();
-    ads131.setOversamplingRatio(ADS131M04Defs::OversamplingRatio::OSR_16256);
-
-    // WARNING: After changing the OSR the device needs some time to settle
-    delayMs(20);
-    ads131.calibrateOffset();
+    ads131.init();
 
     printf("Now performing self test...\n");
     if (ads131.selfTest())
@@ -77,13 +73,18 @@ int main()
         printf("Self test failed!\n");
     }
 
+    // ads131.calibrateOffset(ADS131M04Defs::Channel::CHANNEL_0);
+    // ads131.calibrateOffset(ADS131M04Defs::Channel::CHANNEL_1);
+    // ads131.calibrateOffset(ADS131M04Defs::Channel::CHANNEL_2);
+    // ads131.calibrateOffset(ADS131M04Defs::Channel::CHANNEL_3);
+
     while (true)
     {
         ads131.sample();
 
         ADS131M04Data data = ads131.getLastSample();
 
-        printf("% 2.5f\t% 2.5f\t% 2.5f\t% 2.5f\n", data.voltage[0],
+        printf("% 2.8f\t% 2.8f\t% 2.8f\t% 2.8f\n", data.voltage[0],
                data.voltage[1], data.voltage[2], data.voltage[3]);
 
         delayMs(50);
diff --git a/src/tests/sensors/test-ads131m08.cpp b/src/tests/sensors/test-ads131m08.cpp
index ee199d39c61f76a303429d0b08f83c93ae261c70..ea36065dc7d26525788b7ad0fddfda30f779a43f 100644
--- a/src/tests/sensors/test-ads131m08.cpp
+++ b/src/tests/sensors/test-ads131m08.cpp
@@ -51,21 +51,17 @@ int main()
     // Enable SPI clock and set gpios
     initBoard();
 
-    // SPI configuration setup
-    SPIBus spiBus(SPI4);
-    SPISlave spiSlave(spiBus, csPin, ADS131M08::getDefaultSPIConfig());
+    // ADC configuration
+    ADS131M08::Config config{
+        .oversamplingRatio     = ADS131M08Defs::OversamplingRatio::OSR_8192,
+        .globalChopModeEnabled = true,
+    };
 
     // Device initialization
-    ADS131M08 ads131(spiSlave);
-
-    ads131.reset();
-
-    ads131.enableGlobalChopMode();
-    ads131.setOversamplingRatio(ADS131M08Defs::OversamplingRatio::OSR_16256);
+    SPIBus spiBus(SPI4);
+    ADS131M08 ads131(spiBus, csPin, {}, config);
 
-    // WARNING: After changing the OSR the device needs some time to settle
-    delayMs(20);
-    ads131.calibrateOffset();
+    ads131.init();
 
     printf("Now performing self test...\n");
     if (ads131.selfTest())
@@ -77,6 +73,15 @@ int main()
         printf("Self test failed!\n");
     }
 
+    ads131.calibrateOffset(ADS131M08Defs::Channel::CHANNEL_0);
+    ads131.calibrateOffset(ADS131M08Defs::Channel::CHANNEL_1);
+    ads131.calibrateOffset(ADS131M08Defs::Channel::CHANNEL_2);
+    ads131.calibrateOffset(ADS131M08Defs::Channel::CHANNEL_3);
+    ads131.calibrateOffset(ADS131M08Defs::Channel::CHANNEL_4);
+    ads131.calibrateOffset(ADS131M08Defs::Channel::CHANNEL_5);
+    ads131.calibrateOffset(ADS131M08Defs::Channel::CHANNEL_6);
+    ads131.calibrateOffset(ADS131M08Defs::Channel::CHANNEL_7);
+
     while (true)
     {
         ads131.sample();
@@ -84,10 +89,10 @@ int main()
         ADS131M08Data data = ads131.getLastSample();
 
         printf(
-            "% 2.5f\t% 2.5f\t% 2.5f\t% 2.5f\t% 2.5f\t% 2.5f\t% 2.5f\t% 2.5f\n",
+            "% 2.8f\t% 2.8f\t% 2.8f\t% 2.8f\t% 2.8f\t% 2.8f\t% 2.8f\t% 2.8f\n",
             data.voltage[0], data.voltage[1], data.voltage[2], data.voltage[3],
             data.voltage[4], data.voltage[5], data.voltage[6], data.voltage[7]);
 
-        delayMs(50);
+        delayMs(100);
     }
 }