mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-01-17 04:52:59 +01:00
drivers/sht1x: Major refactoring
- Use RIOT's GPIO interface to access the sensor to increase portability - Changed API to allow more than one sensor per board - Added `sht1x_params.h` that specifies how the sensors is connected - each board can overwrite default settings by #defining SHT1X_PARAM_CLK and SHT1X_PARAM_DATA - Changed arithmetic to use integer calculations only instead of floating point arithmetic - Added support for checking the CRC sum - Allow optional skipping of the CRC check to speed up measuring - Added support for advanced features like reducing the resolution and skipping calibration to speed up measuring - Allow specifying the supply voltage of sensor which heavily influences the temperature result (and use that information to calculate the correct temperature) - Reset sensor on initialization to bring it in a well known state - Support for the obscure heater feature. (Can be useful to check the temperature sensor?) - Updated old SHT11 shell commands to the new driver interface, thus allowing more than one SHT10/11/15 sensor to be used - Added new shell command to allow full configuration of all attached SHT1x sensors - Removed old command for setting the SHT11 temperature offset, as this feature is implemented in the new configuration command
This commit is contained in:
parent
d208c224b0
commit
de9b67bdc2
@ -1,5 +1,3 @@
|
||||
MODULE = boards_common_msb-430
|
||||
|
||||
DIRS = drivers
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
||||
|
@ -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
|
||||
|
@ -1,5 +0,0 @@
|
||||
MODULE = boards_common_msb-430-drivers
|
||||
|
||||
include $(RIOTBOARD)/$(BOARD)/Makefile.include
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
@ -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 */
|
@ -1,5 +1,3 @@
|
||||
MODULE = boards_common_msba2
|
||||
|
||||
DIRS = drivers
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
||||
|
@ -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
|
||||
|
@ -1,3 +0,0 @@
|
||||
MODULE = boards_common_msba2-drivers
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
@ -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 */
|
3
boards/msb-430/Makefile.dep
Normal file
3
boards/msb-430/Makefile.dep
Normal file
@ -0,0 +1,3 @@
|
||||
ifneq (,$(filter saul_default,$(USEMODULE)))
|
||||
USEMODULE += sht11
|
||||
endif
|
@ -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
|
||||
|
3
boards/msb-430h/Makefile.dep
Normal file
3
boards/msb-430h/Makefile.dep
Normal file
@ -0,0 +1,3 @@
|
||||
ifneq (,$(filter saul_default,$(USEMODULE)))
|
||||
USEMODULE += sht11
|
||||
endif
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -304,6 +304,7 @@ endif
|
||||
|
||||
ifneq (,$(filter sht1%,$(USEMODULE)))
|
||||
USEMODULE += sht1x
|
||||
FEATURES_REQUIRED += periph_gpio
|
||||
USEMODULE += xtimer
|
||||
endif
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
||||
/** 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)
|
||||
|
||||
/** set measurement timeout to 1 second */
|
||||
#define SHT1X_MEASURE_TIMEOUT (1000)
|
||||
|
||||
/**
|
||||
* @brief sht11 measureable data
|
||||
*/
|
||||
typedef struct {
|
||||
float temperature; /**< temperature value */
|
||||
float relhum; /**< linear relative humidity */
|
||||
float relhum_temp; /**< temperature compensated relative humidity */
|
||||
} sht1x_val_t;
|
||||
|
||||
/**
|
||||
* @brief SHT11 modes that can be measured
|
||||
* @brief Possible configuration (=status byte) values of the SHT10/11/15
|
||||
*
|
||||
* These values can be or'ed together to get the configuration.
|
||||
*/
|
||||
typedef enum {
|
||||
TEMPERATURE = 1,
|
||||
HUMIDITY = 2
|
||||
} sht1x_mode_t;
|
||||
/** 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;
|
||||
|
||||
/**
|
||||
* @brief Initialize SHT11 ports
|
||||
* @brief Possible values for Vdd (measured temperature depends on it)
|
||||
*/
|
||||
void sht1x_init(void);
|
||||
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;
|
||||
|
||||
/**
|
||||
* @brief Read sensor
|
||||
*
|
||||
* @param value The struct to be filled with measured values
|
||||
* @param mode Specifies type of data to be read
|
||||
*
|
||||
* @return 1 on success, 0 otherwise
|
||||
*
|
||||
* 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
|
||||
* @brief SHT10/11/15 temperature humidity sensor
|
||||
*/
|
||||
uint8_t sht1x_read_sensor(sht1x_val_t *value, sht1x_mode_t mode);
|
||||
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 Write status register
|
||||
*
|
||||
* @param p_value The value to write
|
||||
*
|
||||
* @return 1 on success, 0 otherwise
|
||||
* @brief Parameters required to set up the SHT10/11/15 device driver
|
||||
*/
|
||||
uint8_t sht1x_write_status(uint8_t *p_value);
|
||||
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 */
|
||||
sht1x_vdd_t vdd; /**< The supply voltage of the SHT1X */
|
||||
} sht1x_params_t;
|
||||
|
||||
/**
|
||||
* @brief Read status register with checksum
|
||||
* @brief Initialize the SHT10/11/15 sensor
|
||||
*
|
||||
* @param p_value The read value
|
||||
* @param p_checksum The received checksum
|
||||
* @param dev SHT1X sensor to initialize
|
||||
* @param params Information on how the SHT1X is connected to the board
|
||||
*
|
||||
* return 1 on success, 0 otherwise
|
||||
* @retval 0 Success
|
||||
* @retval -EIO IO failure (`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_init(sht1x_dev_t *dev, const sht1x_params_t *params);
|
||||
|
||||
/**
|
||||
* @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`
|
||||
*/
|
||||
int16_t sht1x_humidity(const sht1x_dev_t *dev, uint16_t raw, int16_t temp);
|
||||
|
||||
/**
|
||||
* @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
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* @param dev SHT1X device to configure
|
||||
* @param conf Configuration to apply
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
int sht1x_configure(sht1x_dev_t *dev, sht1x_conf_t conf);
|
||||
|
||||
/**
|
||||
* @brief Read the status byte of an SHT1X sensor
|
||||
*
|
||||
* @param dev SHT1X device to receive the status from
|
||||
* @param status Store the received status byte here
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
int sht1x_read_status(sht1x_dev_t *dev, uint8_t *status);
|
||||
|
||||
/**
|
||||
* @brief Reset the sensor's configuration to default values
|
||||
*
|
||||
* @param dev SHT1X device to reset
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
int sht1x_reset(sht1x_dev_t *dev);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
72
drivers/sht1x/include/sht1x_defines.h
Normal file
72
drivers/sht1x/include/sht1x_defines.h
Normal file
@ -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 */
|
||||
/** @} */
|
63
drivers/sht1x/include/sht1x_params.h
Normal file
63
drivers/sht1x/include/sht1x_params.h
Normal file
@ -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 */
|
||||
/** @} */
|
@ -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);
|
||||
for (int i = 0; i < 8; i++) {
|
||||
value <<= 1;
|
||||
gpio_set(dev->clk);
|
||||
xtimer_usleep(SHT1X_HALF_CLOCK);
|
||||
|
||||
if (SHT1X_DATA) {
|
||||
/* increase data by one when DATA is high */
|
||||
value++;
|
||||
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;
|
||||
}
|
||||
|
||||
return value;
|
||||
*dest = 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);
|
||||
|
||||
SHT1X_SCK_HIGH;
|
||||
xtimer_usleep(SHT1X_CLK_WAIT);
|
||||
gpio_set(dev->clk);
|
||||
xtimer_usleep(SHT1X_HALF_CLOCK);
|
||||
|
||||
SHT1X_DATA_LOW;
|
||||
xtimer_usleep(SHT1X_DATA_WAIT);
|
||||
gpio_clear(dev->data);
|
||||
xtimer_usleep(SHT1X_HALF_CLOCK);
|
||||
|
||||
SHT1X_SCK_LOW;
|
||||
xtimer_usleep(SHT1X_CLK_WAIT);
|
||||
gpio_clear(dev->clk);
|
||||
xtimer_usleep(SHT1X_HALF_CLOCK);
|
||||
|
||||
SHT1X_SCK_HIGH;
|
||||
xtimer_usleep(SHT1X_CLK_WAIT);
|
||||
gpio_set(dev->clk);
|
||||
xtimer_usleep(SHT1X_HALF_CLOCK);
|
||||
|
||||
SHT1X_DATA_HIGH;
|
||||
xtimer_usleep(SHT1X_DATA_WAIT);
|
||||
gpio_set(dev->data);
|
||||
xtimer_usleep(SHT1X_HALF_CLOCK);
|
||||
|
||||
SHT1X_SCK_LOW;
|
||||
xtimer_usleep(SHT1X_CLK_WAIT);
|
||||
gpio_clear(dev->clk);
|
||||
xtimer_usleep(SHT1X_HALF_CLOCK);
|
||||
|
||||
if (gpio_init(dev->data, GPIO_IN) == -1) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
for (i = 0; i < 9; i++) {
|
||||
clk_signal();
|
||||
*/
|
||||
if (gpio_init(dev->data, GPIO_OUT) == -1) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
transmission_start();
|
||||
gpio_set(dev->data);
|
||||
xtimer_usleep(SHT1X_HALF_CLOCK);
|
||||
gpio_clear(dev->clk);
|
||||
xtimer_usleep(SHT1X_HALF_CLOCK);
|
||||
|
||||
for (int i = 0; i < 9; i++) {
|
||||
clk_signal(dev);
|
||||
}
|
||||
|
||||
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) {
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
xtimer_usleep(1000);
|
||||
/*---------------------------------------------------------------------------*/
|
||||
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;
|
||||
}
|
||||
|
||||
error += ack;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/* 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);
|
||||
|
||||
return (!error);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void sht1x_init(void)
|
||||
{
|
||||
sht1x_temperature_offset = 0;
|
||||
SHT1X_INIT;
|
||||
xtimer_usleep(11 * 1000);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
uint8_t sht1x_read_status(uint8_t *p_value, uint8_t *p_checksum)
|
||||
{
|
||||
uint8_t error = 0;
|
||||
|
||||
transmission_start();
|
||||
error |= write_byte(SHT1X_STATUS_REG_R);
|
||||
*p_value = read_byte(SHT1X_ACK);
|
||||
*p_checksum = read_byte(SHT1X_NO_ACK);
|
||||
return (!error);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
uint8_t sht1x_write_status(uint8_t *p_value)
|
||||
{
|
||||
uint8_t error = 0;
|
||||
|
||||
transmission_start();
|
||||
error += write_byte(SHT1X_STATUS_REG_W);
|
||||
error += write_byte(*p_value);
|
||||
return (!error);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
uint8_t sht1x_read_sensor(sht1x_val_t *value, sht1x_mode_t mode)
|
||||
{
|
||||
uint8_t error = 0;
|
||||
uint8_t checksum;
|
||||
uint16_t humi_int, temp_int;
|
||||
|
||||
/* Temperature arithmetic where S0(T) is read value
|
||||
* T = D1 + D2 * S0(T) */
|
||||
const float D1 = -39.6;
|
||||
const float D2 = 0.01;
|
||||
|
||||
/* 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;
|
||||
|
||||
/* Arithmetic for temperature compesated relative humdity
|
||||
* HT = (T-25) * ( T1 + T2 * SO(RH) ) + HL */
|
||||
const float T1 = +0.01;
|
||||
const float T2 = +0.00008;
|
||||
|
||||
/* check for valid buffer */
|
||||
if (value == NULL) {
|
||||
return 0;
|
||||
retval = read_byte(dev, &data[0], SHT1X_ACK);
|
||||
if (retval != 0) {
|
||||
return retval;
|
||||
}
|
||||
|
||||
value->temperature = 0;
|
||||
value->relhum = 0;
|
||||
value->relhum_temp = 0;
|
||||
|
||||
mutex_lock(&sht1x_mutex);
|
||||
connection_reset();
|
||||
|
||||
/* measure humidity */
|
||||
if (mode & HUMIDITY) {
|
||||
error += (!measure((uint8_t *) &humi_int, &checksum, SHT1X_MEASURE_HUMI));
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* measure temperature */
|
||||
if (mode & TEMPERATURE) {
|
||||
error += (!measure((uint8_t *) &temp_int, &checksum, SHT1X_MEASURE_TEMP));
|
||||
}
|
||||
if (!(dev->conf & SHT1X_CONF_SKIP_CRC)) {
|
||||
uint8_t crc;
|
||||
uint8_t expected;
|
||||
|
||||
/* break on error */
|
||||
if (error != 0) {
|
||||
connection_reset();
|
||||
mutex_unlock(&sht1x_mutex);
|
||||
return 0;
|
||||
}
|
||||
retval = read_byte(dev, &crc, SHT1X_NO_ACK);
|
||||
if (retval != 0) {
|
||||
return retval;
|
||||
}
|
||||
|
||||
if (mode & TEMPERATURE) {
|
||||
value->temperature = D1 + (D2 * ((float) temp_int)) + sht1x_temperature_offset;
|
||||
}
|
||||
|
||||
if (mode & HUMIDITY) {
|
||||
value->relhum = C1 + (C2 * ((float) humi_int)) + (C3 * ((float) humi_int) * ((float) humi_int));
|
||||
|
||||
if (mode & TEMPERATURE) {
|
||||
value->relhum_temp = (value->temperature - 25) * (T1 + (T2 * (float) humi_int)) + value->relhum;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&sht1x_mutex);
|
||||
return 1;
|
||||
*value = (((uint16_t)data[0]) << 8) | (uint16_t)data[1];
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int sht1x_init(sht1x_dev_t *dev, const sht1x_params_t *params)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int16_t sht1x_temperature(const sht1x_dev_t *dev, uint16_t raw)
|
||||
{
|
||||
if (!dev || (dev->vdd >= sizeof(sht1x_d1) / sizeof(sht1x_d1[0]))) {
|
||||
return INT16_MIN;
|
||||
}
|
||||
|
||||
int16_t d1 = sht1x_d1[dev->vdd];
|
||||
int16_t d2 = (dev->conf & SHT1X_CONF_LOW_RESOLUTION) ? 4 : 1;
|
||||
return d1 + d2 * ((int16_t)raw);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int16_t sht1x_humidity(const sht1x_dev_t *dev, uint16_t raw, int16_t temp)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
*rel_hum = sht1x_humidity(dev, hum_raw, t) + dev->hum_off;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int sht1x_configure(sht1x_dev_t *dev, sht1x_conf_t conf)
|
||||
{
|
||||
if (!dev) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Apply config that is not stored on the sensor */
|
||||
dev->conf &= SHT1X_CONF_MASK;
|
||||
dev->conf |= conf & (~(SHT1X_CONF_MASK));
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
switch (write_byte(dev, conf & SHT1X_CONF_MASK)) {
|
||||
case -EIO:
|
||||
return -EIO;
|
||||
case 0:
|
||||
break;
|
||||
default:
|
||||
case 1:
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int sht1x_read_status(sht1x_dev_t *dev, uint8_t *status)
|
||||
{
|
||||
int retval;
|
||||
|
||||
if (!dev || !status) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
retval = transmission_start(dev);
|
||||
if (retval != 0) {
|
||||
return retval;
|
||||
}
|
||||
|
||||
switch (write_byte(dev, SHT1X_STATUS_REG_R)) {
|
||||
case -EIO:
|
||||
return -EIO;
|
||||
case 0:
|
||||
break;
|
||||
default:
|
||||
case 1:
|
||||
return -EPROTO;
|
||||
}
|
||||
|
||||
retval = read_byte(dev, status, SHT1X_ACK);
|
||||
if (retval != 0) {
|
||||
return retval;
|
||||
}
|
||||
|
||||
{
|
||||
uint8_t crc;
|
||||
uint8_t expected;
|
||||
/* read checksum */
|
||||
retval = read_byte(dev, &crc, SHT1X_NO_ACK);
|
||||
if (retval != 0) {
|
||||
return retval;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
@ -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");
|
||||
|
||||
|
74
sys/auto_init/auto_init_sht1x.c
Normal file
74
sys/auto_init/auto_init_sht1x.c
Normal file
@ -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 */
|
@ -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];
|
||||
|
||||
static sht1x_dev_t *get_dev(int argc, char **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;
|
||||
}
|
||||
|
||||
static void error_msg(const char *msg)
|
||||
{
|
||||
printf("[sht1x] Operation failed: %s\n", msg);
|
||||
}
|
||||
|
||||
static int read_sensor(int16_t *temp, int16_t *hum, int argc, char **argv)
|
||||
{
|
||||
const sht1x_dev_t *dev = get_dev(argc, argv);
|
||||
|
||||
if (!dev) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
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_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, HUMIDITY | TEMPERATURE);
|
||||
|
||||
if (!success) {
|
||||
printf("Error reading SHT11\n");
|
||||
|
||||
return 1;
|
||||
if (read_sensor(NULL, &hum, argc, argv)) {
|
||||
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;
|
||||
}
|
||||
printf("Relative humidity: %i.%02i%%\n", (int)hum / 100, (int)hum % 100);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _get_temperature_handler(int argc, char **argv)
|
||||
{
|
||||
(void) argc;
|
||||
(void) argv;
|
||||
int16_t temp;
|
||||
|
||||
uint8_t success;
|
||||
sht1x_val_t sht1x_val;
|
||||
success = sht1x_read_sensor(&sht1x_val, TEMPERATURE);
|
||||
|
||||
if (!success) {
|
||||
printf("Error reading SHT11\n");
|
||||
|
||||
return 1;
|
||||
if (read_sensor(&temp, NULL, argc, argv)) {
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
printf("Temperature: %-6.2f°C\n", (double) sht1x_val.temperature);
|
||||
|
||||
return 0;
|
||||
}
|
||||
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;
|
||||
|
||||
uint8_t success;
|
||||
sht1x_val_t sht1x_val;
|
||||
success = sht1x_read_sensor(&sht1x_val, HUMIDITY | TEMPERATURE);
|
||||
|
||||
if (!success) {
|
||||
printf("Error reading SHT11\n");
|
||||
|
||||
return 1;
|
||||
if (read_sensor(&temp, &hum, argc, argv)) {
|
||||
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);
|
||||
|
||||
return 0;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
int _set_offset_handler(int argc, char **argv)
|
||||
static void print_config(const sht1x_dev_t *dev)
|
||||
{
|
||||
if (argc != 2) {
|
||||
printf("Usage: %s <OFFSET>\n", argv[0]);
|
||||
const char *vdds[] = { "5.0", "4.0", "3.5", "3.0", "2.5" };
|
||||
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
sht1x_temperature_offset = atoi(argv[1]);
|
||||
printf("Temperature offset set to %f\n", (double) sht1x_temperature_offset);
|
||||
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");
|
||||
}
|
||||
|
||||
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]);
|
||||
}
|
||||
|
||||
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]);
|
||||
}
|
||||
|
||||
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 _sht_config_handler(int argc, char **argv)
|
||||
{
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -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},
|
||||
|
Loading…
Reference in New Issue
Block a user