diff --git a/boards/common/msb-430/Makefile b/boards/common/msb-430/Makefile
index baa55d873151f46154b83eaf906cf985093e8d3b..4695a0f76122f2071ad699558c56d5db8c4cc60a 100644
--- a/boards/common/msb-430/Makefile
+++ b/boards/common/msb-430/Makefile
@@ -1,5 +1,3 @@
 MODULE = boards_common_msb-430
 
-DIRS = drivers
-
 include $(RIOTBASE)/Makefile.base
diff --git a/boards/common/msb-430/Makefile.include b/boards/common/msb-430/Makefile.include
index 3125ba07156dde89ca3ac1024abab859dc231b86..5c054c4c66a56b51993fd9b50f34c582d588156a 100644
--- a/boards/common/msb-430/Makefile.include
+++ b/boards/common/msb-430/Makefile.include
@@ -25,6 +25,3 @@ export DEBUGGER_FLAGS = --tui --ex="target remote localhost:2000" --ex "monitor
 
 # export common msb-430 includes
 export INCLUDES += -I$(RIOTBOARD)/common/msb-430/include
-export INCLUDES += -I$(RIOTBOARD)/common/msb-430/drivers/include
-
-USEMODULE += boards_common_msb-430-drivers
diff --git a/boards/common/msb-430/drivers/Makefile b/boards/common/msb-430/drivers/Makefile
deleted file mode 100644
index ed11f0ae340a4b762ad012b7380fdc0f9e5aaecf..0000000000000000000000000000000000000000
--- a/boards/common/msb-430/drivers/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-MODULE = boards_common_msb-430-drivers
-
-include $(RIOTBOARD)/$(BOARD)/Makefile.include
-
-include $(RIOTBASE)/Makefile.base
diff --git a/boards/common/msb-430/drivers/include/sht1x-board.h b/boards/common/msb-430/drivers/include/sht1x-board.h
deleted file mode 100644
index 873504d47c92fa511c7eb611de1f8a4b0800941d..0000000000000000000000000000000000000000
--- a/boards/common/msb-430/drivers/include/sht1x-board.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2013, Freie Universitaet Berlin (FUB). All rights reserved.
- *
- * This file is subject to the terms and conditions of the GNU Lesser
- * General Public License v2.1. See the file LICENSE in the top level
- * directory for more details.
- */
-
-#ifndef SHT1X_BOARD_H
-#define SHT1X_BOARD_H
-
-/**
- * @ingroup     boards_common_msb-430
- * @{
- */
-
-/**
- * @file
- * @brief       SHT11 Device Driver Configuration For MSB-430 Platform
- *
- * @author      Freie Universität Berlin, Computer Systems & Telematics, RIOT
- *
- */
-#include <msp430x16x.h>
-#include "bitarithm.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* SCK  = P3B5
- * DATA = P3B4
- */
-
-#define SHT1X_SCK_LOW   P3OUT &= ~(BIT5);     /**< serial clock line low */
-#define SHT1X_SCK_HIGH  P3OUT |= BIT5;      /**< serial clock line high */
-#define SHT1X_DATA      (P3IN & BIT5)      /**< read serial I/O */
-#define SHT1X_DATA_LOW  P3OUT &= ~(BIT5);   /**< serial I/O line low */
-#define SHT1X_DATA_HIGH P3OUT |= BIT5;      /**< serial I/O line high */
-#define SHT1X_DATA_IN   P3DIR &= ~(BIT5);      /**< serial I/O as input */
-#define SHT1X_DATA_OUT  P3DIR |= BIT5;      /**< serial I/O as output */
-#define SHT1X_INIT      P3DIR |= BIT5;      /* FIO1DIR |= BIT25; PINSEL3 &= ~(BIT14|BIT15 | BIT16|BIT17); */
-
-#ifdef __cplusplus
-}
-#endif
-
-/** @} */
-#endif /* SHT1X_BOARD_H */
diff --git a/boards/common/msba2/Makefile b/boards/common/msba2/Makefile
index a8c0997289fe79230595a9ce38d8fe672455deb8..ccf58a08443576884bb286094d185f5f49707ff5 100644
--- a/boards/common/msba2/Makefile
+++ b/boards/common/msba2/Makefile
@@ -1,5 +1,3 @@
 MODULE = boards_common_msba2
 
-DIRS = drivers
-
 include $(RIOTBASE)/Makefile.base
diff --git a/boards/common/msba2/Makefile.include b/boards/common/msba2/Makefile.include
index 5ba3b3d01cf3a541777712afb7d7229d2298ef75..00260c06232bfe698b32669e1ecf753e1c35a622 100644
--- a/boards/common/msba2/Makefile.include
+++ b/boards/common/msba2/Makefile.include
@@ -27,8 +27,5 @@ endif
 export FFLAGS = $(PORT) $(HEXFILE)
 
 INCLUDES += -I$(RIOTBOARD)/common/msba2/include
-INCLUDES += -I$(RIOTBOARD)/common/msba2/drivers/include
 
 export UNDEF += $(BINDIR)/cpu/startup.o
-
-USEMODULE += boards_common_msba2-drivers
diff --git a/boards/common/msba2/drivers/Makefile b/boards/common/msba2/drivers/Makefile
deleted file mode 100644
index 26dd1f4f5da09469500439c62212c5d5f9aa905b..0000000000000000000000000000000000000000
--- a/boards/common/msba2/drivers/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-MODULE = boards_common_msba2-drivers
-
-include $(RIOTBASE)/Makefile.base
diff --git a/boards/common/msba2/drivers/include/sht1x-board.h b/boards/common/msba2/drivers/include/sht1x-board.h
deleted file mode 100644
index a70589b9ab7c2e80caf32a48de00315e30c9cdeb..0000000000000000000000000000000000000000
--- a/boards/common/msba2/drivers/include/sht1x-board.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright 2009, Freie Universitaet Berlin (FUB). All rights reserved.
- *
- * This file is subject to the terms and conditions of the GNU Lesser
- * General Public License v2.1. See the file LICENSE in the top level
- * directory for more details.
- */
-
-#ifndef SHT1X_BOARD_H
-#define SHT1X_BOARD_H
-
-/**
- * @ingroup     boards_common_msba2
- * @{
- */
-
-/**
- * @file
- * @brief       LPC2387 SHT11 Device Driver
- *
- * @author      Freie Universität Berlin, Computer Systems & Telematics, FeuerWhere project
- * @version     $Revision$
- *
- * @note        $Id$
- */
-
-#include "cpu.h"
-#include "board.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*  serial clock line low */
-#define SHT1X_SCK_LOW   FIO1CLR = BIT25;
-/*  serial clock line high */
-#define SHT1X_SCK_HIGH  FIO1SET = BIT25;
-/*  read serial I/O */
-#define SHT1X_DATA      ((FIO1PIN & BIT26) != 0)
-/*  serial I/O line low */
-#define SHT1X_DATA_LOW  (FIO1CLR = BIT26);
-/*  serial I/O line high */
-#define SHT1X_DATA_HIGH (FIO1SET = BIT26);
-/*  serial I/O as input */
-#define SHT1X_DATA_IN   (FIO1DIR &= ~BIT26)
-/*  serial I/O as output */
-#define SHT1X_DATA_OUT  (FIO1DIR |= BIT26)
-
-#define SHT1X_INIT      FIO1DIR |= BIT25; PINSEL3 &= ~(BIT14|BIT15 | BIT16|BIT17);
-
-#ifdef __cplusplus
-}
-#endif
-
-/** @} */
-#endif /* SHT1X_BOARD_H */
diff --git a/boards/msb-430/Makefile.dep b/boards/msb-430/Makefile.dep
new file mode 100644
index 0000000000000000000000000000000000000000..f5124575543f30d05365553fb31a71cf64b4ab33
--- /dev/null
+++ b/boards/msb-430/Makefile.dep
@@ -0,0 +1,3 @@
+ifneq (,$(filter saul_default,$(USEMODULE)))
+  USEMODULE += sht11
+endif
diff --git a/boards/msb-430/include/board.h b/boards/msb-430/include/board.h
index a053c327f338d41cdb072833b4845f9a31e44820..7baa71f1aa0a16d481f5c8df2cc139a2c1a06732 100644
--- a/boards/msb-430/include/board.h
+++ b/boards/msb-430/include/board.h
@@ -59,6 +59,14 @@ extern "C" {
 #define MSP430_HAS_EXTERNAL_CRYSTAL 0
 /** @} */
 
+/**
+ * @name   Configure on-board SHT11 device
+ * @{
+ */
+#define SHT1X_PARAM_CLK             (GPIO_PIN(3, 5))
+#define SHT1X_PARAM_DATA            (GPIO_PIN(3, 4))
+/** @} */
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/boards/msb-430h/Makefile.dep b/boards/msb-430h/Makefile.dep
new file mode 100644
index 0000000000000000000000000000000000000000..f5124575543f30d05365553fb31a71cf64b4ab33
--- /dev/null
+++ b/boards/msb-430h/Makefile.dep
@@ -0,0 +1,3 @@
+ifneq (,$(filter saul_default,$(USEMODULE)))
+  USEMODULE += sht11
+endif
diff --git a/boards/msb-430h/include/board.h b/boards/msb-430h/include/board.h
index 8fc284faa1f3e9e1463c13ccc82d6f55edd99058..ae744f1b5f0432a32c9a636daea553f06a5ba5d3 100644
--- a/boards/msb-430h/include/board.h
+++ b/boards/msb-430h/include/board.h
@@ -47,6 +47,14 @@ extern "C" {
 #define MSP430_HAS_EXTERNAL_CRYSTAL 1
 /** @} */
 
+/**
+ * @name   Configure on-board SHT11 device
+ * @{
+ */
+#define SHT1X_PARAM_CLK             (GPIO_PIN(3, 5))
+#define SHT1X_PARAM_DATA            (GPIO_PIN(3, 4))
+/** @} */
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/boards/msba2/Makefile.dep b/boards/msba2/Makefile.dep
index e5d94f2d25850c062976f10d5a38ff3fca618243..d7230f86c2db4c22efab874deb9b8f70a1c0c7f2 100644
--- a/boards/msba2/Makefile.dep
+++ b/boards/msba2/Makefile.dep
@@ -3,3 +3,7 @@ include $(RIOTBOARD)/common/msba2/Makefile.dep
 ifneq (,$(filter netdev_default gnrc_netdev_default,$(USEMODULE)))
   USEMODULE += cc110x
 endif
+
+ifneq (,$(filter saul_default,$(USEMODULE)))
+  USEMODULE += sht11
+endif
diff --git a/drivers/Makefile.dep b/drivers/Makefile.dep
index 4a95122c303a9035400815ed9c3eb62feb76981b..75e0bdb4d4fd4fc4076b4f3cd00cd577759ec578 100644
--- a/drivers/Makefile.dep
+++ b/drivers/Makefile.dep
@@ -304,6 +304,7 @@ endif
 
 ifneq (,$(filter sht1%,$(USEMODULE)))
   USEMODULE += sht1x
+  FEATURES_REQUIRED += periph_gpio
   USEMODULE += xtimer
 endif
 
diff --git a/drivers/Makefile.include b/drivers/Makefile.include
index 8c7a1c44826fa5fa58ee8c033687976a779dcd45..3832016dd3104ff888186d2d841d36be70f4a92c 100644
--- a/drivers/Makefile.include
+++ b/drivers/Makefile.include
@@ -50,6 +50,10 @@ ifneq (,$(filter dht,$(USEMODULE)))
   USEMODULE_INCLUDES += $(RIOTBASE)/drivers/dht/include
 endif
 
+ifneq (,$(filter sht1x,$(USEMODULE)))
+  USEMODULE_INCLUDES += $(RIOTBASE)/drivers/sht1x/include
+endif
+
 ifneq (,$(filter ds1307,$(USEMODULE)))
   USEMODULE_INCLUDES += $(RIOTBASE)/drivers/ds1307/include
 endif
diff --git a/drivers/include/sht1x.h b/drivers/include/sht1x.h
index 447aa74a1f48b67610b2d94bf3683bf028d974ec..b8c7bd87197323e29e0f5728f1d48490e744e6e2 100644
--- a/drivers/include/sht1x.h
+++ b/drivers/include/sht1x.h
@@ -1,5 +1,6 @@
 /*
- * Copyright 2009, Freie Universitaet Berlin (FUB). All rights reserved.
+ * Copyright 2009 Freie Universitaet Berlin (FUB)
+ *           2018 Otto-von-Guericke-Universität Magdeburg
  *
  * This file is subject to the terms and conditions of the GNU Lesser
  * General Public License v2.1. See the file LICENSE in the top level
@@ -16,90 +17,168 @@
  * @file
  * @brief       SHT10/SHT11/SHT15 Device Driver
  *
- * @author      Freie Universität Berlin, Computer Systems & Telematics
+ * @author      Marian Buschsieweke <marian.buschsieweke@ovgu.de>
  */
 
 #ifndef SHT1X_H
 #define SHT1X_H
 
 #include <stdint.h>
+#include <periph/gpio.h>
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-#define SHT1X_NO_ACK        (0)     /**< don't ack read in `read_byte` */
-#define SHT1X_ACK           (1)     /**< do acknowledge read in `read_byte` */
-/* adr command  r/w */
-#define SHT1X_STATUS_REG_W  (0x06)  /**< will write to status register */
-#define SHT1X_STATUS_REG_R  (0x07)  /**< will read from status register */
-#define SHT1X_MEASURE_TEMP  (0x03)  /**< tell sensor to measure temperature */
-#define SHT1X_MEASURE_HUMI  (0x05)  /**< tell sensor to measure humidity */
-#define SHT1X_RESET         (0x1E)  /**< reset the sensor */
+/**
+ * @brief Possible configuration (=status byte) values of the SHT10/11/15
+ *
+ * These values can be or'ed together to get the configuration.
+ */
+typedef enum {
+    /** Use 8/12 bit resolution instead of 12/14 bit for temp/hum */
+    SHT1X_CONF_LOW_RESOLUTION   = 0x01,
+    /** Don't upload calibration data to register to safe 10 millisec */
+    SHT1X_CONF_SKIP_CALIBRATION = 0x02,
+    /** Waste 8mA at 5V to increase the sensor temperature up to 10°C */
+    SHT1X_CONF_ENABLE_HEATER    = 0x04,
+    /** Skip the CRC check (and reading the CRC byte) to safe time */
+    SHT1X_CONF_SKIP_CRC         = 0x08,
+} sht1x_conf_t;
 
-/** time to wait after toggling the data line */
-#define SHT1X_DATA_WAIT     (1)
-/** time to wait after toggling the clock line */
-#define SHT1X_CLK_WAIT      (1)
+/**
+ * @brief Possible values for Vdd (measured temperature depends on it)
+ */
+typedef enum {
+    SHT1X_VDD_5_0V = 0,
+    SHT1X_VDD_4_0V = 1,
+    SHT1X_VDD_3_5V = 2,
+    SHT1X_VDD_3_0V = 3,
+    SHT1X_VDD_2_5V = 4,
+} sht1x_vdd_t;
 
-/** set measurement timeout to 1 second */
-#define SHT1X_MEASURE_TIMEOUT   (1000)
+/**
+ * @brief SHT10/11/15 temperature humidity sensor
+ */
+typedef struct {
+    gpio_t  clk;      /**< GPIO connected to the clock pin of the SHT1X */
+    gpio_t  data;     /**< GPIO connected to the data pin of the SHT1X */
+    int16_t temp_off; /**< Offset to add to the measured temperature */
+    int16_t hum_off;  /**< Offset to add to the measured humidity */
+    uint8_t conf;     /**< Status byte (containing configuration) of the SHT1X */
+    uint8_t vdd;      /**< Supply voltage of the SHT1X (as sht1x_vdd_t) */
+} sht1x_dev_t;
 
 /**
- * @brief   sht11 measureable data
+ * @brief Parameters required to set up the SHT10/11/15 device driver
  */
 typedef struct {
-    float   temperature;    /**< temperature value */
-    float   relhum;         /**< linear relative humidity */
-    float   relhum_temp;    /**< temperature compensated relative humidity */
-} sht1x_val_t;
+    gpio_t      clk;  /**< GPIO connected to the clock pin of the SHT1X */
+    gpio_t      data; /**< GPIO connected to the data pin of the SHT1X */
+    sht1x_vdd_t vdd;  /**< The supply voltage of the SHT1X */
+} sht1x_params_t;
 
 /**
- * @brief   SHT11 modes that can be measured
+ * @brief             Initialize the SHT10/11/15 sensor
+ *
+ * @param  dev        SHT1X sensor to initialize
+ * @param  params     Information on how the SHT1X is connected to the board
+ *
+ * @retval  0         Success
+ * @retval -EIO       IO failure (`gpio_init()` failed)
+ * @retval -EPROTO    Sensor did not acknowledge reset command
  */
-typedef enum {
-    TEMPERATURE = 1,
-    HUMIDITY = 2
-} sht1x_mode_t;
+int sht1x_init(sht1x_dev_t *dev, const sht1x_params_t *params);
 
 /**
- * @brief   Initialize SHT11 ports
+ * @brief             Calculate the temperature from the raw input
+ * @note              This internal function is exposed for unit tests
+ *
+ * @param dev         Device from which the raw value was received
+ * @param raw         The raw (unprocessed) temperature value
+ *
+ * @return            The correct temperature in E-02 °C
+ * @retval INT16_MIN  Passed `NULL` for parameter `dev` or `dev->vdd`
+ */
+int16_t sht1x_temperature(const sht1x_dev_t *dev, uint16_t raw);
+
+/**
+ * @brief             Calculate the relative humidity from the raw input
+ * @note              This internal function is exposed for unit tests
+ *
+ * @param dev         Device from which the raw value was received
+ * @param raw         The raw (unprocessed) temperature value
+ * @param temp        The temperature at which the humidity was measure in
+ *                    E-02 °C
+ *
+ * @return            The correct temperature in E-02 %
+ * @retval -1         Passed `NULL` for parameter `dev`
  */
-void sht1x_init(void);
+int16_t sht1x_humidity(const sht1x_dev_t *dev, uint16_t raw, int16_t temp);
 
 /**
- * @brief   Read sensor
+ * @brief             Read the current temperature
+ *
+ * @param dev         SHT1X sensor to read
+ * @param temp        Store the measured temperature in E-02 °C here
+ * @param hum         Store the measured relative humidity in E-02 % here
+ *
+ * @retval  0         Success
+ * @retval -EIO       IO failure (`gpio_init()` failed)
+ * @retval -EBADMSG   CRC-8 checksum didn't match (--> Retry)
+ * @retval -EINVAL    Passed `NULL` for dev or for both `temp` and `hum`
+ * @retval -EBADMSG   CRC checksum didn't match
+ * @retval -ECANCELED Measurement timed out
+ * @retval -EPROTO    Sensor did not acknowledge command
  *
- * @param value The struct to be filled with measured values
- * @param mode  Specifies type of data to be read
+ * For either `temp` or `hum` `NULL` can be passed, if only one value is of
+ * interest. Passing `NULL` for `hum` speeds up the communication, but
+ * passing `NULL` for `temp` does not. The temperature value is required to
+ * calculate the relative humidity from the raw input. So the temperature is
+ * measured in any case, it is just not returned if `temp` is `NULL`.
+ */
+int sht1x_read(const sht1x_dev_t *dev, int16_t *temp, int16_t *hum);
+
+/**
+ * @brief             Apply the given configuration (= status byte) to
  *
- * @return  1 on success, 0 otherwise
+ * @param dev         SHT1X device to configure
+ * @param conf        Configuration to apply
  *
- * Example:
- * \code sht1x_val sht11;
- * sht1x_read_sensor(&sht11, HUMIDITY|TEMPERATURE);
- * printf("%-6.2f °C %5.2f %% %5.2f %%\n", sht11.temperature, sht11.relhum, sht11.relhum_temp); \endcode
+ * @retval  0         Configuration applied
+ * @retval -EINVAL    Called with `dev == NULL`
+ * @retval -EIO       I/O error (`gpio_init()` failed)
+ * @retval -EPROTO    Sensor did not acknowledge command
+ * @retval -ECANCELED Sensor did not apply configuration
+ * @retval -EBADMSG   CRC checksum error while verifying uploaded configuration
  */
-uint8_t sht1x_read_sensor(sht1x_val_t *value, sht1x_mode_t mode);
+int sht1x_configure(sht1x_dev_t *dev, sht1x_conf_t conf);
 
 /**
- * @brief   Write status register
+ * @brief             Read the status byte of an SHT1X sensor
  *
- * @param   p_value The value to write
+ * @param dev         SHT1X device to receive the status from
+ * @param status      Store the received status byte here
  *
- * @return  1 on success, 0 otherwise
+ * @retval  0         Configuration applied
+ * @retval -EINVAL    Called with `dev == NULL`
+ * @retval -EIO       I/O error (`gpio_init()` failed)
+ * @retval -EPROTO    Sensor did not acknowledge command
+ * @retval -EBADMSG   CRC checksum didn't match
  */
-uint8_t sht1x_write_status(uint8_t *p_value);
+int sht1x_read_status(sht1x_dev_t *dev, uint8_t *status);
 
 /**
- * @brief   Read status register with checksum
+ * @brief             Reset the sensor's configuration to default values
  *
- * @param   p_value The read value
- * @param   p_checksum The received checksum
+ * @param dev         SHT1X device to reset
  *
- * return   1 on success, 0 otherwise
+ * @retval  0         Reset successful
+ * @retval -EINVAL    Called with `dev == NULL`
+ * @retval -EIO       I/O error (`gpio_init()` failed)
+ * @retval -EPROTO    Sensor did not acknowledge reset command
  */
-uint8_t sht1x_read_status(uint8_t *p_value, uint8_t *p_checksum);
+int sht1x_reset(sht1x_dev_t *dev);
 
 #ifdef __cplusplus
 }
diff --git a/drivers/sht1x/include/sht1x_defines.h b/drivers/sht1x/include/sht1x_defines.h
new file mode 100644
index 0000000000000000000000000000000000000000..0327387ab08d78cedf0c80f87eb46ea52b5c8514
--- /dev/null
+++ b/drivers/sht1x/include/sht1x_defines.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2009 Freie Universitaet Berlin (FUB)
+ *           2018 Otto-von-Guericke-Universität Magdeburg
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser
+ * General Public License v2.1. See the file LICENSE in the top level
+ * directory for more details.
+ */
+
+/**
+ * @ingroup     drivers_sht1x
+ * @{
+ *
+ * @file
+ * @brief       Internal defines required by the SHT10/SHT11/SHT15 driver
+ *
+ * @author      Marian Buschsieweke <marian.buschsieweke@ovgu.de>
+ */
+
+#ifndef SHT1X_DEFINES_H
+#define SHT1X_DEFINES_H
+
+#include <stdint.h>
+#include <periph/gpio.h>
+#include <mutex.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @name Possible values to pass as `ack` parameter to `write_byte`
+ * @see write_byte
+ * @{
+ */
+#define SHT1X_NO_ACK           (1)      /**< don't ack read in `read_byte` */
+#define SHT1X_ACK              (0)      /**< do acknowledge read in `read_byte` */
+/** @} */
+
+/**
+ * @name Commands that can be sent to the SHT1X driver
+ * @{
+ */
+#define SHT1X_STATUS_REG_W     (0x06)   /**< will write to status register */
+#define SHT1X_STATUS_REG_R     (0x07)   /**< will read from status register */
+#define SHT1X_MEASURE_TEMP     (0x03)   /**< tell sensor to measure temperature */
+#define SHT1X_MEASURE_HUM      (0x05)   /**< tell sensor to measure humidity */
+#define SHT1X_RESET            (0x1E)   /**< reset the sensor */
+/** @} */
+
+/**
+ * @name Timing parameters for the SHT10/SHT1X/SHT15
+ * @{
+ */
+#define SHT1X_HALF_CLOCK        (1)     /**< Half clock length in µsec */
+#define SHT1X_MEASURE_TIMEOUT   (1000)  /**< Timeout for the SHT1x to complete
+                                             the measurement (in millisec) */
+#define SHT1X_RESET_WAIT        (11000) /**< Wait 11ms after soft reset */
+/** @} */
+
+#define SHT1X_CONF_MASK         (0x07)  /**< Bitmask to get writable bits of the
+                                             status byte */
+#define SHT1X_SAUL_RETRIES      (3)     /**< How often reading the sensor should
+                                             be retried in case of communication
+                                             failures */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SHT1X_DEFINES_H */
+/** @} */
diff --git a/drivers/sht1x/include/sht1x_params.h b/drivers/sht1x/include/sht1x_params.h
new file mode 100644
index 0000000000000000000000000000000000000000..f7cd54f8a71f989753957d51e5b625001d0f8436
--- /dev/null
+++ b/drivers/sht1x/include/sht1x_params.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2018 Otto-von-Guericke-Universität Magdeburg
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser
+ * General Public License v2.1. See the file LICENSE in the top level
+ * directory for more details.
+ */
+
+/**
+ * @ingroup     drivers_sht1x
+ *
+ * @{
+ * @file
+ * @brief       Default configuration for SHT10/SHT11/SHT15 devices
+ *
+ * @author      Marian Buschsieweke <marian.buschsieweke@ovgu.de>
+ */
+
+#ifndef SHT1X_PARAMS_H
+#define SHT1X_PARAMS_H
+
+#include "board.h"
+#include "sht1x.h"
+#include "saul_reg.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @name    Set default configuration parameters for the SHT1X devices
+ * @{
+ */
+#ifndef SHT1X_PARAM_CLK
+#define SHT1X_PARAM_CLK               (GPIO_PIN(1, 25))
+#endif
+#ifndef SHT1X_PARAM_DATA
+#define SHT1X_PARAM_DATA              (GPIO_PIN(1, 26))
+#endif
+#ifndef SHT1X_PARAM_VDD
+#define SHT1X_PARAM_VDD               (SHT1X_VDD_3_5V)
+#endif
+#ifndef SHT1X_PARAMS
+#define SHT1X_PARAMS                  { .clk = SHT1X_PARAM_CLK,  \
+                                        .data = SHT1X_PARAM_DATA, \
+                                        .vdd = SHT1X_PARAM_VDD }
+#endif
+/**@}*/
+
+/**
+ * @brief   Configure SHT1X devices
+ */
+static const sht1x_params_t sht1x_params[] =
+{
+    SHT1X_PARAMS
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SHT1X_PARAMS_H */
+/** @} */
diff --git a/drivers/sht1x/sht1x.c b/drivers/sht1x/sht1x.c
index c48d03a177e6c832c1832a0ef5162a1398b2b6f2..f2a55cc0139e168001c18a47e374fca56ad69558 100644
--- a/drivers/sht1x/sht1x.c
+++ b/drivers/sht1x/sht1x.c
@@ -1,5 +1,6 @@
 /*
- * Copyright 2009, Freie Universitaet Berlin (FUB). All rights reserved.
+ * Copyright 2009 Freie Universitaet Berlin (FUB)
+ *           2018 Otto-von-Guericke-Universität Magdeburg
  *
  * This file is subject to the terms and conditions of the GNU Lesser
  * General Public License v2.1. See the file LICENSE in the top level
@@ -8,343 +9,686 @@
 
 /**
  * @ingroup     drivers_sht1x
- * @brief       Driver for the Sensirion SHT11 humidity and temperature sensor
+ * @brief       Driver for the Sensirion SHT10/SHT11/SHT15 humidity and
+ *              temperature sensor
  * @{
  *
  * @file
- * @brief       SHT11 Device Driver
+ * @brief       SHT10/SHT11/SHT15 Device Driver
+ * @author      Marian Buschsieweke <marian.buschsieweke@ovgu.de>
  *
- * @version     $Revision: 2396 $
- *
- * @note        $Id: sht1x.c 2396 2010-07-06 15:12:35Z ziegert $
  * @}
  */
-
-#include <stdio.h>
+#include <errno.h>
 #include <stdint.h>
 
 #include "xtimer.h"
-#include "mutex.h"
 #include "sht1x.h"
-#include "sht1x-board.h"
+#include "sht1x_defines.h"
 #include "bitarithm.h"
 
-float sht1x_temperature_offset;
+#define ENABLE_DEBUG (0)
+#include "debug.h"
 
 /**
- * @brief   Perform measurement
+ * @brief             Perform measurement
  *
- * @param   p_value Measured value (14 or 12 bit -> 2 bytes)
- * @param   p_checksum Checksum of measurement
- * @param   mode The requestested measurement mode: temperature or humidity
+ * @param dev         SHT1X device to use
+ * @param value       Measured value
+ * @param mode        The requested measurement mode: temperature or humidity
  *
- * @return  1 on success, 0 otherwise
+ * @retval  0         Success
+ * @retval -EIO       I/O failure (`gpio_init()` failed)
+ * @retval -EBADMSG   CRC-8 checksum didn't match
+ * @retval -EPROTO    SHT1x did not acknowledge command
+ * @retval -ECANCELED Measurement timed out
  */
-static uint8_t measure(uint8_t *p_value, uint8_t *p_checksum, uint8_t mode);
+static int measure(const sht1x_dev_t *dev, uint16_t *value, uint8_t mode);
 
 /**
- * @brief   Write one byte
+ * @brief             Write one byte
  *
- * @param   value The value to write
+ * @param  dev        SHT1X device to send the byte to
+ * @param  value      The value to write
  *
- * @return  1 for acknowledged write, 0 otherwise
+ * @retval  1         Write was acknowledged
+ * @retval  0         Write was *NOT* acknowledged (communication failure)
+ * @retval -EIO       I/O failure (`gpio_init()` failed)
  */
-static uint8_t write_byte(uint8_t value);
+static int write_byte(const sht1x_dev_t *dev, uint8_t value);
 
 /**
- * @brief   Read ony byte
+ * @brief             Read one byte
  *
- * @param   ack Set if the data read should be acknowledged
+ * @param  dev        SHT1X device to receive the byte from
+ * @param  dest       Store the received byte here
+ * @param  ack        `SHT1X_ACK` to acknowledge byte, `SHT1X_NO_ACK` otherwise
  *
- * @return  The read byte
+ * @retval  0         Success
+ * @retval -EIO       I/O failure (`gpio_init()` failed)
  */
-static uint8_t read_byte(uint8_t ack);
+static int read_byte(const sht1x_dev_t *dev, uint8_t *dest, int ack);
 
 /**
- * @brief   Communication reset
+ * @brief             Communication reset
+ *
+ * @param  dev        SHT1X device to reset the connection to
+ *
+ * @retval  0         Success
+ * @retval -EIO       I/O failure (`gpio_init()` failed)
  */
-static void connection_reset(void);
+static int connection_reset(const sht1x_dev_t *dev);
 
 /**
- * @brief   Send start of transmision sequence
+ * @brief             Send start of transmission sequence
+ *
+ * @param  dev        SHT1X device to send the transmission start sequence to
+ *
+ * @retval  0         Success
+ * @retval -EIO       I/O failure (`gpio_init()` failed)
  */
-static void transmission_start(void);
+static int transmission_start(const sht1x_dev_t *dev);
 
 /**
- * @brief   Toggle the clock line
+ * @brief             Toggle the clock line
+ *
+ * @param  dev        SHT1X device to send one clock signal to
  */
-static inline void clk_signal(void);
+static inline void clk_signal(const sht1x_dev_t *dev);
 
-/* mutex for exclusive measurement operation */
-mutex_t sht1x_mutex = MUTEX_INIT;
+/**
+ * @brief             Calculate the initial value of the CRC-8 checksum
+ *
+ * @param status      The current sensor status
+ *
+ * @return            The initial value of the CRC-8 checksum
+ */
+static inline uint8_t crc_initial_value(uint8_t status);
+
+/**
+ * @brief             Reverse the order of bits in a byte (needed for CRC)
+ *
+ * @param value       The byte to reverse the bits of
+ *
+ * @return            The reversed input
+ */
+static inline uint8_t reverse_byte(uint8_t value);
+
+/**
+ * @brief             Look up table required for CRC-8 calculation
+ *
+ * Values taken from the Application Note PDF of Sensirion (December 2011)
+ */
+static const uint8_t crc_lookup_table[] = {
+    0x00, 0x31, 0x62, 0x53,  0xc4, 0xf5, 0xa6, 0x97,
+    0xb9, 0x88, 0xdb, 0xea,  0x7d, 0x4c, 0x1f, 0x2e,
+    0x43, 0x72, 0x21, 0x10,  0x87, 0xb6, 0xe5, 0xd4,
+    0xfa, 0xcb, 0x98, 0xa9,  0x3e, 0x0f, 0x5c, 0x6d,
+    0x86, 0xb7, 0xe4, 0xd5,  0x42, 0x73, 0x20, 0x11,
+    0x3f, 0x0e, 0x5d, 0x6c,  0xfb, 0xca, 0x99, 0xa8,
+    0xc5, 0xf4, 0xa7, 0x96,  0x01, 0x30, 0x63, 0x52,
+    0x7c, 0x4d, 0x1e, 0x2f,  0xb8, 0x89, 0xda, 0xeb,
+    0x3d, 0x0c, 0x5f, 0x6e,  0xf9, 0xc8, 0x9b, 0xaa,
+    0x84, 0xb5, 0xe6, 0xd7,  0x40, 0x71, 0x22, 0x13,
+    0x7e, 0x4f, 0x1c, 0x2d,  0xba, 0x8b, 0xd8, 0xe9,
+    0xc7, 0xf6, 0xa5, 0x94,  0x03, 0x32, 0x61, 0x50,
+    0xbb, 0x8a, 0xd9, 0xe8,  0x7f, 0x4e, 0x1d, 0x2c,
+    0x02, 0x33, 0x60, 0x51,  0xc6, 0xf7, 0xa4, 0x95,
+    0xf8, 0xc9, 0x9a, 0xab,  0x3c, 0x0d, 0x5e, 0x6f,
+    0x41, 0x70, 0x23, 0x12,  0x85, 0xb4, 0xe7, 0xd6,
+    0x7a, 0x4b, 0x18, 0x29,  0xbe, 0x8f, 0xdc, 0xed,
+    0xc3, 0xf2, 0xa1, 0x90,  0x07, 0x36, 0x65, 0x54,
+    0x39, 0x08, 0x5b, 0x6a,  0xfd, 0xcc, 0x9f, 0xae,
+    0x80, 0xb1, 0xe2, 0xd3,  0x44, 0x75, 0x26, 0x17,
+    0xfc, 0xcd, 0x9e, 0xaf,  0x38, 0x09, 0x5a, 0x6b,
+    0x45, 0x74, 0x27, 0x16,  0x81, 0xb0, 0xe3, 0xd2,
+    0xbf, 0x8e, 0xdd, 0xec,  0x7b, 0x4a, 0x19, 0x28,
+    0x06, 0x37, 0x64, 0x55,  0xc2, 0xf3, 0xa0, 0x91,
+    0x47, 0x76, 0x25, 0x14,  0x83, 0xb2, 0xe1, 0xd0,
+    0xfe, 0xcf, 0x9c, 0xad,  0x3a, 0x0b, 0x58, 0x69,
+    0x04, 0x35, 0x66, 0x57,  0xc0, 0xf1, 0xa2, 0x93,
+    0xbd, 0x8c, 0xdf, 0xee,  0x79, 0x48, 0x1b, 0x2a,
+    0xc1, 0xf0, 0xa3, 0x92,  0x05, 0x34, 0x67, 0x56,
+    0x78, 0x49, 0x1a, 0x2b,  0xbc, 0x8d, 0xde, 0xef,
+    0x82, 0xb3, 0xe0, 0xd1,  0x46, 0x77, 0x24, 0x15,
+    0x3b, 0x0a, 0x59, 0x68,  0xff, 0xce, 0x9d, 0xac,
+};
+
+/** @brief Lookuptable for d1 parameter depending on supply voltage */
+static const int16_t sht1x_d1[] = { -4010, -3980, -3970, -3960, -3940 };
 
 /*---------------------------------------------------------------------------*/
-static inline void clk_signal(void)
+static inline void clk_signal(const sht1x_dev_t *dev)
 {
-    SHT1X_SCK_HIGH;
-    xtimer_usleep(SHT1X_CLK_WAIT);
-    SHT1X_SCK_LOW;
-    xtimer_usleep(SHT1X_CLK_WAIT);
+    gpio_set(dev->clk);
+    xtimer_usleep(SHT1X_HALF_CLOCK);
+    gpio_clear(dev->clk);
+    xtimer_usleep(SHT1X_HALF_CLOCK);
 }
 
 /*---------------------------------------------------------------------------*/
-static uint8_t write_byte(uint8_t value)
+static int write_byte(const sht1x_dev_t *dev, uint8_t value)
 {
-    uint8_t i;
-    uint8_t ack;
+    int ack;
 
-    SHT1X_DATA_OUT;
+    if (gpio_init(dev->data, GPIO_OUT) == -1) {
+        return -EIO;
+    }
 
-    /* send value bit by bit to sht11 */
-    for (i = 0; i < 8; i++) {
+    /* send value bit by bit to sht1x */
+    for (int i = 0; i < 8; i++) {
         if (value & BIT7) {
-            SHT1X_DATA_HIGH;
-            xtimer_usleep(SHT1X_DATA_WAIT);
+            gpio_set(dev->data);
         }
         else {
-            SHT1X_DATA_LOW;
-            xtimer_usleep(SHT1X_DATA_WAIT);
+            gpio_clear(dev->data);
         }
+        xtimer_usleep(SHT1X_HALF_CLOCK);
 
         /* trigger clock signal */
-        clk_signal();
+        clk_signal(dev);
 
         /* shift value to write next bit */
-        value = value << 1;
+        value <<= 1;
     }
 
     /* wait for ack */
-    SHT1X_DATA_IN;
-    xtimer_usleep(SHT1X_CLK_WAIT);
-    ack = SHT1X_DATA;
+    if (gpio_init(dev->data, GPIO_IN) == -1) {
+        return -EIO;
+    }
+    xtimer_usleep(SHT1X_HALF_CLOCK);
+    ack = gpio_read(dev->data);
 
-    clk_signal();
+    clk_signal(dev);
 
     return ack;
 }
+
 /*---------------------------------------------------------------------------*/
-static uint8_t read_byte(uint8_t ack)
+static int read_byte(const sht1x_dev_t *dev, uint8_t *dest, int ack)
 {
-    uint8_t i;
     uint8_t value = 0;
 
-    SHT1X_DATA_IN;
-    xtimer_usleep(SHT1X_DATA_WAIT);
+    xtimer_usleep(SHT1X_HALF_CLOCK);
 
     /* read value bit by bit */
-    for (i = 0; i < 8; i++) {
-        value = value << 1;
-        SHT1X_SCK_HIGH;
-        xtimer_usleep(SHT1X_CLK_WAIT);
-
-        if (SHT1X_DATA) {
-            /* increase data by one when DATA is high */
-            value++;
+    for (int i = 0; i < 8; i++) {
+        value <<= 1;
+        gpio_set(dev->clk);
+        xtimer_usleep(SHT1X_HALF_CLOCK);
+
+        if (gpio_read(dev->data)) {
+            /* set bit when DATA is high */
+            value |= 0x01;
         }
 
-        SHT1X_SCK_LOW;
-        xtimer_usleep(SHT1X_CLK_WAIT);
+        gpio_clear(dev->clk);
+        xtimer_usleep(SHT1X_HALF_CLOCK);
     }
 
     /* send ack if necessary */
-    SHT1X_DATA_OUT;
-
-    if (ack) {
-        SHT1X_DATA_LOW;
-        xtimer_usleep(SHT1X_DATA_WAIT);
-    }
-    else {
-        SHT1X_DATA_HIGH;
-        xtimer_usleep(SHT1X_DATA_WAIT);
+    if (gpio_init(dev->data, GPIO_OUT) == -1) {
+        return -EIO;
     }
 
-    clk_signal();
+    gpio_write(dev->data, ack);
+    xtimer_usleep(SHT1X_HALF_CLOCK);
+
+    clk_signal(dev);
 
     /* release data line */
-    SHT1X_DATA_IN;
+    if (gpio_init(dev->data, GPIO_IN) == -1) {
+        return -EIO;
+    }
+
+    *dest = value;
 
-    return value;
+    return 0;
 }
+
 /*---------------------------------------------------------------------------*/
-static void transmission_start(void)
+static int transmission_start(const sht1x_dev_t *dev)
 {
     /*       _____         ________
        DATA:      |_______|
                  ___     ___
        SCK : ___|   |___|   |______
-    */
-    SHT1X_DATA_OUT;
+     */
+    if (gpio_init(dev->data, GPIO_OUT) == -1) {
+        return -EIO;
+    }
 
     /* set initial state */
-    SHT1X_DATA_HIGH;
-    xtimer_usleep(SHT1X_DATA_WAIT);
-    SHT1X_SCK_LOW;
-    xtimer_usleep(SHT1X_CLK_WAIT);
+    gpio_set(dev->data);
+    xtimer_usleep(SHT1X_HALF_CLOCK);
+    gpio_clear(dev->clk);
+    xtimer_usleep(SHT1X_HALF_CLOCK);
+
+    gpio_set(dev->clk);
+    xtimer_usleep(SHT1X_HALF_CLOCK);
+
+    gpio_clear(dev->data);
+    xtimer_usleep(SHT1X_HALF_CLOCK);
 
-    SHT1X_SCK_HIGH;
-    xtimer_usleep(SHT1X_CLK_WAIT);
+    gpio_clear(dev->clk);
+    xtimer_usleep(SHT1X_HALF_CLOCK);
 
-    SHT1X_DATA_LOW;
-    xtimer_usleep(SHT1X_DATA_WAIT);
+    gpio_set(dev->clk);
+    xtimer_usleep(SHT1X_HALF_CLOCK);
 
-    SHT1X_SCK_LOW;
-    xtimer_usleep(SHT1X_CLK_WAIT);
+    gpio_set(dev->data);
+    xtimer_usleep(SHT1X_HALF_CLOCK);
 
-    SHT1X_SCK_HIGH;
-    xtimer_usleep(SHT1X_CLK_WAIT);
+    gpio_clear(dev->clk);
+    xtimer_usleep(SHT1X_HALF_CLOCK);
 
-    SHT1X_DATA_HIGH;
-    xtimer_usleep(SHT1X_DATA_WAIT);
+    if (gpio_init(dev->data, GPIO_IN) == -1) {
+        return -EIO;
+    }
 
-    SHT1X_SCK_LOW;
-    xtimer_usleep(SHT1X_CLK_WAIT);
+    return 0;
 }
+
 /*---------------------------------------------------------------------------*/
-static void connection_reset(void)
+static int connection_reset(const sht1x_dev_t *dev)
 {
     /*       _____________________________________________________         ____
        DATA:                                                      |_______|
                 _    _    _    _    _    _    _    _    _        ___     ___
        SCK : __| |__| |__| |__| |__| |__| |__| |__| |__| |______|   |___|   |__
-    */
-    uint8_t i;
-    SHT1X_DATA_HIGH;
-    xtimer_usleep(SHT1X_DATA_WAIT);
-    SHT1X_SCK_LOW;
-    xtimer_usleep(SHT1X_CLK_WAIT);
+     */
+    if (gpio_init(dev->data, GPIO_OUT) == -1) {
+        return -EIO;
+    }
+
+    gpio_set(dev->data);
+    xtimer_usleep(SHT1X_HALF_CLOCK);
+    gpio_clear(dev->clk);
+    xtimer_usleep(SHT1X_HALF_CLOCK);
 
-    for (i = 0; i < 9; i++) {
-        clk_signal();
+    for (int i = 0; i < 9; i++) {
+        clk_signal(dev);
     }
 
-    transmission_start();
+    return transmission_start(dev);
 }
+
 /*---------------------------------------------------------------------------*/
-static uint8_t measure(uint8_t *p_value, uint8_t *p_checksum, uint8_t mode)
+static inline uint8_t crc_initial_value(uint8_t status)
 {
-    uint8_t error = 0;
-    uint8_t ack = 1;
-    uint16_t i;
+    status &= 0x07;
 
-    transmission_start();
-    error = write_byte(mode);
+    return (
+        ((0x01 & status) << 7) |
+        ((0x02 & status) << 5) |
+        ((0x04 & status) << 3)
+        );
+}
 
-    xtimer_usleep(1000);
+/*---------------------------------------------------------------------------*/
+static inline uint8_t reverse_byte(uint8_t value)
+{
+    uint8_t result = (value & 0x01) << 7;
 
-    /* wait untile sensor has finished measurement or timeout */
-    for (i = 0; (i < SHT1X_MEASURE_TIMEOUT) && (!error); i++) {
-        ack = SHT1X_DATA;
+    result |= (value & 0x02) << 5;
+    result |= (value & 0x04) << 3;
+    result |= (value & 0x08) << 1;
+    result |= (value & 0x10) >> 1;
+    result |= (value & 0x20) >> 3;
+    result |= (value & 0x40) >> 5;
+    result |= (value & 0x80) >> 7;
 
-        if (!ack) {
+    return result;
+}
+
+/*---------------------------------------------------------------------------*/
+static int measure(const sht1x_dev_t *dev, uint16_t *value, uint8_t mode)
+{
+    uint8_t data[2] = { 0, 0 };
+    int retval;
+
+    retval = transmission_start(dev);
+    if (retval != 0) {
+        return retval;
+    }
+
+    switch (write_byte(dev, mode)) {
+        case -EIO:
+            return -EIO;
+        case 0:
             break;
+        default:
+        case 1:
+            return -EPROTO;
+    }
+
+    /* wait until sensor has finished measurement or timeout */
+    {
+        int ack = 1;
+        for (int i = 0; ack != 0; i++) {
+            if (i > SHT1X_MEASURE_TIMEOUT) {
+                return -ECANCELED;
+            }
+
+            xtimer_usleep(1000);
+            ack = gpio_read(dev->data);
         }
+    }
 
-        xtimer_usleep(1000);
+    /* read MSB */
+    retval = read_byte(dev, &data[0], SHT1X_ACK);
+    if (retval != 0) {
+        return retval;
     }
 
-    error += ack;
+    /* read LSB, send ACK only if CRC checking is enabled */
+    retval = (dev->conf & SHT1X_CONF_SKIP_CRC) ? SHT1X_NO_ACK : SHT1X_ACK;
+    retval = read_byte(dev, &data[1], retval);
+    if (retval != 0) {
+        return retval;
+    }
 
-    /* read MSB */
-    *(p_value + 1) = read_byte(SHT1X_ACK);
-    /* read LSB */
-    *(p_value) = read_byte(SHT1X_ACK);
-    /* read checksum */
-    *p_checksum = read_byte(SHT1X_NO_ACK);
+    if (!(dev->conf & SHT1X_CONF_SKIP_CRC)) {
+        uint8_t crc;
+        uint8_t expected;
+
+        retval = read_byte(dev, &crc, SHT1X_NO_ACK);
+        if (retval != 0) {
+            return retval;
+        }
+
+        expected = crc_initial_value(dev->conf);
+        expected = crc_lookup_table[expected ^ mode];
+        expected = crc_lookup_table[expected ^ data[0]];
+        expected = crc_lookup_table[expected ^ data[1]];
+        expected = reverse_byte(expected);
+        if (expected != crc) {
+            DEBUG("[sht1x] CRC expected: 0x%02x, got: 0x%02x\n"
+                  "        CRC0: 0x%02x, CMD: 0x%02x, data: {0x%02x, 0x%02x}\n",
+                  (int)expected, (int)crc,
+                  (int)crc_initial_value(dev->conf), mode,
+                  (int)data[0], (int)data[1]);
+            return -EBADMSG;
+        }
+    }
 
-    return (!error);
+    *value = (((uint16_t)data[0]) << 8) | (uint16_t)data[1];
+    return 0;
 }
+
 /*---------------------------------------------------------------------------*/
-void sht1x_init(void)
+int sht1x_init(sht1x_dev_t *dev, const sht1x_params_t *params)
 {
-    sht1x_temperature_offset = 0;
-    SHT1X_INIT;
-    xtimer_usleep(11 * 1000);
+    if (
+        !dev ||
+        !params ||
+        (((uint8_t)params->vdd) >= sizeof(sht1x_d1) / sizeof(sht1x_d1[0]))
+        ) {
+        return -EINVAL;
+    }
+
+    dev->clk = params->clk;
+    dev->data = params->data;
+    if (gpio_init(dev->clk, GPIO_OUT) || gpio_init(dev->data, GPIO_IN)) {
+        return -EIO;
+    }
+
+    dev->temp_off = 0;
+    dev->hum_off = 0;
+    dev->conf = 0;
+    dev->vdd = (uint8_t)params->vdd;
+    return sht1x_reset(dev);
 }
+
 /*---------------------------------------------------------------------------*/
-uint8_t sht1x_read_status(uint8_t *p_value, uint8_t *p_checksum)
+int16_t sht1x_temperature(const sht1x_dev_t *dev, uint16_t raw)
 {
-    uint8_t error = 0;
+    if (!dev || (dev->vdd >= sizeof(sht1x_d1) / sizeof(sht1x_d1[0]))) {
+        return INT16_MIN;
+    }
 
-    transmission_start();
-    error |= write_byte(SHT1X_STATUS_REG_R);
-    *p_value = read_byte(SHT1X_ACK);
-    *p_checksum = read_byte(SHT1X_NO_ACK);
-    return (!error);
+    int16_t d1 = sht1x_d1[dev->vdd];
+    int16_t d2 = (dev->conf & SHT1X_CONF_LOW_RESOLUTION) ? 4 : 1;
+    return d1 + d2 * ((int16_t)raw);
 }
+
 /*---------------------------------------------------------------------------*/
-uint8_t sht1x_write_status(uint8_t *p_value)
+int16_t sht1x_humidity(const sht1x_dev_t *dev, uint16_t raw, int16_t temp)
 {
-    uint8_t error = 0;
+    if (!dev) {
+        return -1;
+    }
+
+    static const int32_t c1 = -20468;
+    static const int32_t t1 = 1;
+    int32_t c2, c3, c4, t2;
+    if (dev->conf & SHT1X_CONF_LOW_RESOLUTION) {
+        c2 = 5872;
+        c3 = 494801;
+        c4 = 1000000;
+        t2 = 781;
+    }
+    else {
+        c2 = 367;
+        c3 = 791684;
+        c4 = 100000;
+        t2 = 12500;
+    }
+
+    /*
+     * Calculate linear humidity, but slightly different. Original formula:
+     *
+     * hum_lin = c1 + c2 * raw + c3 * (raw * raw)
+     *
+     * But we use:
+     *
+     * hum_lin = c1 + c2 * raw - (c4 * raw / c3') * (c4 * raw / c3')
+     *
+     * where: c3' = 1 / (sqrt(-c3) / c4)
+     *
+     * (This better fits for integer calculation)
+     */
+
+    int32_t res = ((int32_t)raw * c4) / c3;
+    res = c1 + c2 * (int32_t)raw - (res * res);
+
+    /*
+     * Perform temperature compensation, again slightly different.
+     * Original formula:
+     *
+     * hum_true = (temp - 25) * (t1 + t2 * raw) + hum_lin
+     *
+     * But we use:
+     *
+     * hum_true = (temp - 25) * t1 + (temp - 25) * raw / t2') + hum_lin
+     *
+     * where t2' = 1/t2
+     */
+    int32_t temp_diff = temp - 2500;
+    res = temp_diff * t1 + (temp_diff * (int32_t)raw * 100) / t2 + res;
+    return (int16_t)(res / 100);
+}
+
+
+/*---------------------------------------------------------------------------*/
+int sht1x_read(const sht1x_dev_t *dev, int16_t *temp, int16_t *rel_hum)
+{
+    uint16_t temp_raw;
+    int16_t t;
+    uint16_t hum_raw;
+    int retval;
+
+    if (
+        !dev ||
+        (dev->vdd >= sizeof(sht1x_d1) / sizeof(sht1x_d1[0])) ||
+        (!temp && !rel_hum)
+        ) {
+        return -EINVAL;
+    }
+
+    retval = measure(dev, &temp_raw, SHT1X_MEASURE_TEMP);
+    if (retval != 0) {
+        connection_reset(dev);
+        return retval;
+    }
+
+    t = sht1x_temperature(dev, temp_raw) + dev->temp_off;
+
+    if (temp != NULL) {
+        *temp = t;
+    }
+
+    if (rel_hum != NULL) {
+        retval = measure(dev, &hum_raw, SHT1X_MEASURE_HUM);
+        if (retval != 0) {
+            connection_reset(dev);
+            return retval;
+        }
 
-    transmission_start();
-    error += write_byte(SHT1X_STATUS_REG_W);
-    error += write_byte(*p_value);
-    return (!error);
+        *rel_hum = sht1x_humidity(dev, hum_raw, t) + dev->hum_off;
+    }
+
+    return 0;
 }
+
 /*---------------------------------------------------------------------------*/
-uint8_t sht1x_read_sensor(sht1x_val_t *value, sht1x_mode_t mode)
+int sht1x_configure(sht1x_dev_t *dev, sht1x_conf_t conf)
 {
-    uint8_t error = 0;
-    uint8_t checksum;
-    uint16_t humi_int, temp_int;
+    if (!dev) {
+        return -EINVAL;
+    }
 
-    /* Temperature arithmetic where S0(T) is read value
-     * T = D1 + D2 * S0(T) */
-    const float D1 = -39.6;
-    const float D2 = 0.01;
+    /* Apply config that is not stored on the sensor */
+    dev->conf &= SHT1X_CONF_MASK;
+    dev->conf |= conf & (~(SHT1X_CONF_MASK));
 
-    /* Arithmetic for linear humdity where S0(RH) is read value
-     * HL = C1 + C2 * S0(RH) + C3 * SO(RH)^2 */
-    const float C1 = -4.0;
-    const float C2 = +0.0405;
-    const float C3 = -0.0000028;
+    /* Send new status byte to sensor, if on-device config was changed */
+    if ((conf & SHT1X_CONF_MASK) != (dev->conf & SHT1X_CONF_MASK)) {
+        int retval = transmission_start(dev);
+        if (retval != 0) {
+            return retval;
+        }
+
+        switch (write_byte(dev, SHT1X_STATUS_REG_W)) {
+            case -EIO:
+                return -EIO;
+            case 0:
+                break;
+            default:
+            case 1:
+                return -EPROTO;
+        }
 
-    /* Arithmetic for temperature compesated relative humdity
-     * HT = (T-25) * ( T1 + T2 * SO(RH) ) + HL */
-    const float T1 = +0.01;
-    const float T2 = +0.00008;
+        switch (write_byte(dev, conf & SHT1X_CONF_MASK)) {
+            case -EIO:
+                return -EIO;
+            case 0:
+                break;
+            default:
+            case 1:
+                return -EPROTO;
+        }
 
-    /* check for valid buffer */
-    if (value == NULL) {
-        return 0;
+        /* Read back uploaded configuration to verify that sensor applied it */
+        uint8_t status;
+        retval = sht1x_read_status(dev, &status);
+        if (retval != 0) {
+            return retval;
+        }
+        if (dev->conf != conf) {
+            /* Configuration was not applied by sensor */
+            return -ECANCELED;
+        }
     }
 
-    value->temperature = 0;
-    value->relhum = 0;
-    value->relhum_temp = 0;
+    return 0;
+}
 
-    mutex_lock(&sht1x_mutex);
-    connection_reset();
+/*---------------------------------------------------------------------------*/
+int sht1x_read_status(sht1x_dev_t *dev, uint8_t *status)
+{
+    int retval;
 
-    /* measure humidity */
-    if (mode & HUMIDITY) {
-        error += (!measure((uint8_t *) &humi_int, &checksum, SHT1X_MEASURE_HUMI));
+    if (!dev || !status) {
+        return -EINVAL;
     }
 
-    /* measure temperature */
-    if (mode & TEMPERATURE) {
-        error += (!measure((uint8_t *) &temp_int, &checksum, SHT1X_MEASURE_TEMP));
+    retval = transmission_start(dev);
+    if (retval != 0) {
+        return retval;
     }
 
-    /* break on error */
-    if (error != 0) {
-        connection_reset();
-        mutex_unlock(&sht1x_mutex);
-        return 0;
+    switch (write_byte(dev, SHT1X_STATUS_REG_R)) {
+        case -EIO:
+            return -EIO;
+        case 0:
+            break;
+        default:
+        case 1:
+            return -EPROTO;
     }
 
-    if (mode & TEMPERATURE) {
-        value->temperature = D1 + (D2 * ((float) temp_int)) + sht1x_temperature_offset;
+    retval = read_byte(dev, status, SHT1X_ACK);
+    if (retval != 0) {
+        return retval;
     }
 
-    if (mode & HUMIDITY) {
-        value->relhum = C1 + (C2 * ((float) humi_int)) + (C3 * ((float) humi_int) * ((float) humi_int));
+    {
+        uint8_t crc;
+        uint8_t expected;
+        /* read checksum */
+        retval = read_byte(dev, &crc, SHT1X_NO_ACK);
+        if (retval != 0) {
+            return retval;
+        }
 
-        if (mode & TEMPERATURE) {
-            value->relhum_temp = (value->temperature - 25) * (T1 + (T2 * (float) humi_int)) + value->relhum;
+        expected = crc_initial_value(*status);
+        expected = crc_lookup_table[expected ^ SHT1X_STATUS_REG_R];
+        expected = crc_lookup_table[expected ^ *status];
+        expected = reverse_byte(expected);
+        if (expected != crc) {
+            DEBUG("[sht1x] CRC expected: 0x%02x, got: 0x%02x\n"
+                  "        CRC0: 0x%02x, CMD: 0x%02x, data: {0x%02x}\n",
+                  (int)expected, (int)crc,
+                  (int)crc_initial_value(*status), SHT1X_STATUS_REG_R,
+                  (int)*status);
+            return -EBADMSG;
         }
     }
 
-    mutex_unlock(&sht1x_mutex);
-    return 1;
+    /* Extract config from status and store it after CRC check passed */
+    dev->conf &= ~(SHT1X_CONF_MASK);
+    dev->conf |= *status & SHT1X_CONF_MASK;
+
+    return 0;
+}
+
+/*---------------------------------------------------------------------------*/
+int sht1x_reset(sht1x_dev_t *dev)
+{
+    int retval;
+
+    if (!dev) {
+        return -EINVAL;
+    }
+
+    retval = transmission_start(dev);
+    if (retval != 0) {
+        return retval;
+    }
+
+    switch (write_byte(dev, SHT1X_RESET)) {
+        case -EIO:
+            return -EIO;
+        case 0:
+            break;
+        default:
+        case 1:
+            return -EPROTO;
+    }
+
+    dev->conf = 0;
+    xtimer_usleep(SHT1X_RESET_WAIT);
+
+    return 0;
 }
diff --git a/sys/auto_init/auto_init.c b/sys/auto_init/auto_init.c
index 617a0735235962e8a7fb5a165ff40cc3dbbcfb35..bdfda5229b5e2bb849cf60231556600b83f51d96 100644
--- a/sys/auto_init/auto_init.c
+++ b/sys/auto_init/auto_init.c
@@ -20,10 +20,6 @@
 
 #include "auto_init.h"
 
-#ifdef MODULE_SHT1X
-#include "sht1x.h"
-#endif
-
 #ifdef MODULE_MCI
 #include "diskio.h"
 #endif
@@ -101,10 +97,6 @@ void auto_init(void)
     DEBUG("Auto init xtimer module.\n");
     xtimer_init();
 #endif
-#ifdef MODULE_SHT1X
-    DEBUG("Auto init SHT1X module.\n");
-    sht1x_init();
-#endif
 #ifdef MODULE_MCI
     DEBUG("Auto init mci module.\n");
     mci_initialize();
@@ -275,6 +267,12 @@ void auto_init(void)
 #endif
 
 /* initialize sensors and actuators */
+#ifdef MODULE_SHT1X
+    DEBUG("Auto init SHT1X module (SHT10/SHT11/SHT15 sensor driver).\n");
+    extern void auto_init_sht1x(void);
+    auto_init_sht1x();
+#endif
+
 #ifdef MODULE_AUTO_INIT_SAUL
     DEBUG("auto_init SAUL\n");
 
diff --git a/sys/auto_init/auto_init_sht1x.c b/sys/auto_init/auto_init_sht1x.c
new file mode 100644
index 0000000000000000000000000000000000000000..49d9e6f5c9c0d1341e138d1aaf576039d3806fd7
--- /dev/null
+++ b/sys/auto_init/auto_init_sht1x.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2018 Otto-von-Guericke-Universität Magdeburg
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser
+ * General Public License v2.1. See the file LICENSE in the top level
+ * directory for more details.
+ *
+ */
+
+/*
+ * @ingroup sys_auto_init
+ * @{
+ *
+ * @file
+ * @brief       Auto initialization for SHT1X temperature/humidity sensors
+ *
+ * @author      Marian Buschsieweke <marian.buschsieweke@ovgu.de>
+ *
+ * @}
+ */
+
+#ifdef MODULE_SHT1X
+
+#include "log.h"
+#include "sht1x_params.h"
+#include "sht1x.h"
+
+#define ENABLE_DEBUG (0)
+#include "debug.h"
+
+/**
+ * @brief   Define the number of configured sensors
+ */
+#define SHT1X_NUM     (sizeof(sht1x_params) / sizeof(sht1x_params[0]))
+
+/**
+ * @brief   Allocate memory for the device descriptors
+ */
+sht1x_dev_t sht1x_devs[SHT1X_NUM];
+
+static void sht1x_error(unsigned int num, const char *reason)
+{
+    LOG_ERROR("[auto_init] error initializing SHT10/SHT11/SHT15 sensor "
+              "#%u: %s\n", num, reason);
+}
+
+void auto_init_sht1x(void)
+{
+    for (unsigned int i = 0; i < SHT1X_NUM; i++) {
+        DEBUG("[auto_init_sht1x] Initializing SHT1X sensor #%u\n", i);
+
+        switch (sht1x_init(&sht1x_devs[i], &sht1x_params[i])) {
+            case 0:
+                break;
+            case -EIO:
+                sht1x_error(i, "Failed to initialize GPIOs");
+                continue;
+            case -EINVAL:
+                sht1x_error(i, "Invalid configuration for VDD");
+                continue;
+            case -EPROTO:
+                sht1x_error(i, "Reset command not acknowledged");
+                continue;
+            default:
+                /* Should not happen, but better safe than sorry */
+                sht1x_error(i, "?");
+                continue;
+        }
+    }
+}
+
+#else
+typedef int dont_be_pedantic;
+#endif /* MODULE_SHT1X */
diff --git a/sys/shell/commands/sc_sht1x.c b/sys/shell/commands/sc_sht1x.c
index 2a379def5cce0afc2addf3ac1c2fbdd40fe4a10e..c814ccff484d7afb4a89ece2bfaa535377657b53 100644
--- a/sys/shell/commands/sc_sht1x.c
+++ b/sys/shell/commands/sc_sht1x.c
@@ -1,5 +1,6 @@
 /*
- * Copyright (C) 2013  INRIA.
+ * Copyright (C) 2013 INRIA
+ *               2018 Otto-von-Guericke-Universität Magdeburg
  *
  * This file is subject to the terms and conditions of the GNU Lesser
  * General Public License v2.1. See the file LICENSE in the top level
@@ -11,102 +12,367 @@
  * @{
  *
  * @file
- * @brief       Provides shell commands to poll sht11 sensor
+ * @brief       Provides shell commands to access SHT10/SHT11/SHT15 sensors
  *
  * @author      Oliver Hahm <oliver.hahm@inria.fr>
+ * @author      Marian Buschsieweke <marian.buschsieweke@ovgu.de>
  *
  * @}
  */
 
+#ifdef MODULE_SHT1X
+
 #include <stdio.h>
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
 #include "sht1x.h"
+#include "sht1x_params.h"
 
-#ifdef MODULE_SHT1X
+#define SHT1X_NUM     (sizeof(sht1x_params) / sizeof(sht1x_params[0]))
 
-extern float sht1x_temperature_offset;
+extern sht1x_dev_t sht1x_devs[SHT1X_NUM];
 
-int _get_humidity_handler(int argc, char **argv)
+static sht1x_dev_t *get_dev(int argc, char **argv)
 {
-    (void) argc;
-    (void) argv;
+    switch (argc) {
+        case 1:
+            return &sht1x_devs[0];
+        case 2:
+        {
+            int pos = atoi(argv[1]);
+            if ((pos < 0) || (pos >= (int)SHT1X_NUM)) {
+                printf("No SHT10/SHT11/SHT15 device with number %i\n", pos);
+                return NULL;
+            }
+            return &sht1x_devs[pos];
+        }
+        default:
+            break;
+    }
+
+    printf("Usage: %s [DEVICE_NUMBER]\n", argv[0]);
+    return NULL;
+}
 
-    uint8_t success;
-    sht1x_val_t sht1x_val;
-    success = sht1x_read_sensor(&sht1x_val, HUMIDITY | TEMPERATURE);
+static void error_msg(const char *msg)
+{
+    printf("[sht1x] Operation failed: %s\n", msg);
+}
 
-    if (!success) {
-        printf("Error reading SHT11\n");
+static int read_sensor(int16_t *temp, int16_t *hum, int argc, char **argv)
+{
+    const sht1x_dev_t *dev = get_dev(argc, argv);
 
-        return 1;
+    if (!dev) {
+        return -1;
     }
-    else {
-        printf("Relative humidity: %5.2f%% / Temperature compensated humidity; %5.2f%%\n",
-               (double) sht1x_val.relhum, (double) sht1x_val.relhum_temp);
 
-        return 0;
+    switch (sht1x_read(dev, temp, hum)) {
+        case 0:
+            break;
+        case -EIO:
+            error_msg("gpio_init() failed");
+            return -1;
+        case -EBADMSG:
+            error_msg("CRC checksum error");
+            return -1;
+        case -ECANCELED:
+            error_msg("Measurement timed out");
+            return -1;
+        case -EPROTO:
+            error_msg("Sensor did not acknowledge command");
+            return -1;
+        default:
+            /* Should never happen, but better safe the sorry */
+            error_msg("Unknown error");
+            return -1;
     }
+
+    return 0;
 }
 
-int _get_temperature_handler(int argc, char **argv)
+int _get_humidity_handler(int argc, char **argv)
 {
-    (void) argc;
-    (void) argv;
+    int16_t hum;
 
-    uint8_t success;
-    sht1x_val_t sht1x_val;
-    success = sht1x_read_sensor(&sht1x_val, TEMPERATURE);
+    if (read_sensor(NULL, &hum, argc, argv)) {
+        return -1;
+    }
 
-    if (!success) {
-        printf("Error reading SHT11\n");
+    printf("Relative humidity: %i.%02i%%\n", (int)hum / 100, (int)hum % 100);
+    return 0;
+}
 
-        return 1;
-    }
-    else {
-        printf("Temperature: %-6.2f°C\n", (double) sht1x_val.temperature);
+int _get_temperature_handler(int argc, char **argv)
+{
+    int16_t temp;
 
-        return 0;
+    if (read_sensor(&temp, NULL, argc, argv)) {
+        return -1;
     }
+
+    printf("Temperature: %i.%02i°C\n", (int)temp / 100, (int)temp % 100);
+    return 0;
 }
 
 int _get_weather_handler(int argc, char **argv)
 {
-    (void) argc;
-    (void) argv;
+    int16_t hum;
+    int16_t temp;
+
+    if (read_sensor(&temp, &hum, argc, argv)) {
+        return -1;
+    }
+
+    printf("Relative humidity: %i.%02i%%\n", (int)hum / 100, (int)hum % 100);
+    printf("Temperature: %i.%02i°C\n", (int)temp / 100, (int)temp % 100);
+    return 0;
+}
+
+static void print_config(const sht1x_dev_t *dev)
+{
+    const char *vdds[] = { "5.0", "4.0", "3.5", "3.0", "2.5" };
 
-    uint8_t success;
-    sht1x_val_t sht1x_val;
-    success = sht1x_read_sensor(&sht1x_val, HUMIDITY | TEMPERATURE);
+    printf("Sensor VDD = %s\n", vdds[dev->vdd]);
+    printf("Temperature offset [-t]: %i\n", (int)dev->temp_off);
+    printf("Humidity offset [-h]: %i\n", (int)dev->hum_off);
+    printf("Resolution [-r]: %s\n",
+           (dev->conf & SHT1X_CONF_LOW_RESOLUTION) ? "low" : "high");
+    printf("Skip calibration (faster reading) [-c]: %s\n",
+           (dev->conf & SHT1X_CONF_SKIP_CALIBRATION) ? "yes" : "no");
+    printf("Heater [-H]: %s\n",
+           (dev->conf & SHT1X_CONF_ENABLE_HEATER) ? "on" : "off");
+    printf("CRC checking [-C]: %s\n",
+           (dev->conf & SHT1X_CONF_SKIP_CRC) ? "off" : "on");
+}
 
-    if (!success) {
-        printf("Error reading SHT11\n");
+static void unknown_parameter(int index, char **argv)
+{
+    printf("Unknown parameter \"%s\"\n"
+           "Usage: \"%s [PARAMS]\", run \"%s --help\" for help\n",
+           argv[index], argv[0], argv[0]);
+}
 
-        return 1;
-    }
-    else {
-        printf("Relative humidity: %5.2f%% / Temperature compensated humidity; %5.2f%% ",
-               (double) sht1x_val.relhum, (double) sht1x_val.relhum_temp);
-        printf("Temperature: %-6.2f°C\n", (double) sht1x_val.temperature);
+static void missing_argument(int index, char **argv)
+{
+    printf("Missing argument for parameter \"%s\"\n"
+           "Usage: \"%s [%s <ARG>][PARAMS]\", run \"%s --help\" for help\n",
+           argv[index], argv[0], argv[index], argv[0]);
+}
 
-        return 0;
-    }
+static void invalid_argument(int index, char **argv, const char *valid)
+{
+    printf("Invalid argument \"%s\" for parameter \"%s\"\n"
+           "Valid arguments are: \"%s\", run \"%s --help\" for help\n",
+           argv[index + 1], argv[index], valid, argv[0]);
 }
 
-int _set_offset_handler(int argc, char **argv)
+int _sht_config_handler(int argc, char **argv)
 {
-    if (argc != 2) {
-        printf("Usage: %s <OFFSET>\n", argv[0]);
+    uint8_t set_conf = 0;
+    uint8_t unset_conf = 0;
+    int16_t temp_off = INT16_MAX;
+    int16_t hum_off = INT16_MAX;
+    int dev_num = 0;
 
-        return 1;
+    if ((argc == 2) && (strcmp("--help", argv[1]) == 0)) {
+        printf("Usage: \"%s [PARMS]\n"
+               "\n"
+               "Supported parameters:\n"
+               "  -d <NUM>\n"
+               "    Use SHT10/11/15 sensor number <NUM>. Default: 0\n"
+               "\n"
+               "  -t <OFFSET>\n"
+               "    Add <OFFSET> (in e-2°C) to all temperature measurements\n"
+               "\n"
+               "  -h <OFFSET>\n"
+               "    Add <OFFSET> (in e-2%%) to all humidity measurements\n"
+               "\n"
+               "  -r l/h\n"
+               "    Set resolution to low/high. Low resolution trades "
+               "presicion for speed\n"
+               "\n"
+               "  -H y/n\n"
+               "    Turns heater on/off. Can increase temperature by up to "
+               "10°C\n"
+               "\n"
+               "  -C y/n\n"
+               "    Turns on/off CRC checking. No checking trades robustness "
+               "for speed\n",
+               argv[0]);
+        return 0;
     }
-    else {
-        sht1x_temperature_offset = atoi(argv[1]);
-        printf("Temperature offset set to %f\n", (double) sht1x_temperature_offset);
 
-        return 0;
+    for (int i = 1; i < argc; i++) {
+        if ((argv[i][0] != '-') || (!argv[i][1]) || (argv[i][2])) {
+            unknown_parameter(i, argv);
+            return -1;
+        }
+
+        switch (argv[i][1]) {
+            case 'd':
+                if (++i >= argc) {
+                    missing_argument(i - 1, argv);
+                    return -1;
+                }
+                dev_num = atoi(argv[i]);
+                if ((dev_num < 0) || (dev_num >= (int)SHT1X_NUM)) {
+                    printf("No SHT10/11/15 sensor with number %i\n", dev_num);
+                    return -1;
+                }
+                break;
+            case 't':
+                if (++i >= argc) {
+                    missing_argument(i - 1, argv);
+                    return -1;
+                }
+                temp_off = (int16_t)atoi(argv[i]);
+                break;
+            case 'h':
+                if (++i >= argc) {
+                    missing_argument(i - 1, argv);
+                    return -1;
+                }
+                hum_off = (int16_t)atoi(argv[i]);
+                break;
+            case 'r':
+                if (++i >= argc) {
+                    missing_argument(i - 1, argv);
+                    return -1;
+                }
+                if ((!argv[i][0]) || (argv[i][1])) {
+                    invalid_argument(i - 1, argv, "l, h");
+                    return -1;
+                }
+                switch (argv[i][0]) {
+                    case 'l':
+                        set_conf |= SHT1X_CONF_LOW_RESOLUTION;
+                        break;
+                    case 'h':
+                        unset_conf |= SHT1X_CONF_LOW_RESOLUTION;
+                        break;
+                    default:
+                        invalid_argument(i - 1, argv, "l, h");
+                        return -1;
+                }
+                break;
+            case 'c':
+                if (++i >= argc) {
+                    missing_argument(i - 1, argv);
+                    return -1;
+                }
+                if ((!argv[i][0]) || (argv[i][1])) {
+                    invalid_argument(i - 1, argv, "y, n");
+                    return -1;
+                }
+                switch (argv[i][0]) {
+                    case 'y':
+                        set_conf |= SHT1X_CONF_SKIP_CALIBRATION;
+                        break;
+                    case 'n':
+                        unset_conf |= SHT1X_CONF_SKIP_CALIBRATION;
+                        break;
+                    default:
+                        invalid_argument(i - 1, argv, "y, n");
+                        return -1;
+                }
+                break;
+            case 'H':
+                if (++i >= argc) {
+                    missing_argument(i - 1, argv);
+                    return -1;
+                }
+                if ((!argv[i][0]) || (argv[i][1])) {
+                    invalid_argument(i - 1, argv, "y, n");
+                    return -1;
+                }
+                switch (argv[i][0]) {
+                    case 'y':
+                        set_conf |= SHT1X_CONF_ENABLE_HEATER;
+                        break;
+                    case 'n':
+                        unset_conf |= SHT1X_CONF_ENABLE_HEATER;
+                        break;
+                    default:
+                        invalid_argument(i - 1, argv, "y, n");
+                        return -1;
+                }
+                break;
+            case 'C':
+                if (++i >= argc) {
+                    missing_argument(i - 1, argv);
+                    return -1;
+                }
+                if ((!argv[i][0]) || (argv[i][1])) {
+                    invalid_argument(i - 1, argv, "y, n");
+                    return -1;
+                }
+                switch (argv[i][0]) {
+                    case 'y':
+                        unset_conf |= SHT1X_CONF_SKIP_CRC;
+                        break;
+                    case 'n':
+                        set_conf |= SHT1X_CONF_SKIP_CRC;
+                        break;
+                    default:
+                        invalid_argument(i - 1, argv, "y, n");
+                        return -1;
+                }
+                break;
+            default:
+                unknown_parameter(i, argv);
+                return -1;
+        }
+    }
+
+    if ((set_conf) || (unset_conf)) {
+        /* Apply new configuration */
+        uint8_t new_conf = sht1x_devs[dev_num].conf;
+        new_conf &= ~(unset_conf);
+        new_conf |= set_conf;
+        switch (sht1x_configure(&sht1x_devs[dev_num], new_conf)) {
+            case 0:
+                break;
+            case -EIO:
+                error_msg("gpio_init() failed");
+                return -1;
+            case -EBADMSG:
+                error_msg("CRC checksum error");
+                return -1;
+            case -ECANCELED:
+                error_msg("Sensor did not apply configuration");
+                return -1;
+            case -EPROTO:
+                error_msg("Sensor did not acknowledge command");
+                return -1;
+            default:
+                /* Should never happen, but better safe the sorry */
+                error_msg("Unknown error");
+                return -1;
+        }
     }
+
+    if (temp_off != INT16_MAX) {
+        if ((temp_off > 2000) || (temp_off < -2000)) {
+            printf("A temperature offset of %i.%02i°C is unreasonable\n",
+                   (int)temp_off / 100, (int)temp_off % 100);
+            return -1;
+        }
+        sht1x_devs[dev_num].temp_off = temp_off;
+    }
+
+    if (hum_off != INT16_MAX) {
+        if ((hum_off > 1000) || (hum_off < -1000)) {
+            printf("A humidity offset of %i.%02i%% is unreasonable\n",
+                   (int)hum_off / 100, (int)hum_off % 100);
+            return -1;
+        }
+        sht1x_devs[dev_num].hum_off = hum_off;
+    }
+
+    print_config(&sht1x_devs[dev_num]);
+    return 0;
 }
 
 #endif
diff --git a/sys/shell/commands/shell_commands.c b/sys/shell/commands/shell_commands.c
index ce73861323c392790bcfdc716cac1a4010ec570a..a9871517d3e64da7b5cdbd5642db37827d1f3e27 100644
--- a/sys/shell/commands/shell_commands.c
+++ b/sys/shell/commands/shell_commands.c
@@ -41,7 +41,7 @@ extern int _ps_handler(int argc, char **argv);
 extern int _get_temperature_handler(int argc, char **argv);
 extern int _get_humidity_handler(int argc, char **argv);
 extern int _get_weather_handler(int argc, char **argv);
-extern int _set_offset_handler(int argc, char **argv);
+extern int _sht_config_handler(int argc, char **argv);
 #endif
 
 #ifdef MODULE_LTC4150
@@ -157,7 +157,7 @@ const shell_command_t _shell_command_list[] = {
     {"temp", "Prints measured temperature.", _get_temperature_handler},
     {"hum", "Prints measured humidity.", _get_humidity_handler},
     {"weather", "Prints measured humidity and temperature.", _get_weather_handler},
-    {"offset", "Set temperature offset.", _set_offset_handler},
+    {"sht-config", "Get/set SHT10/11/15 sensor configuration.", _sht_config_handler},
 #endif
 #ifdef MODULE_LTC4150
     {"cur", "Prints current and average power consumption.", _get_current_handler},