sensors: dht: move dht to own directory under drivers/sensor/
Change-Id: Id19b4ea414347caa23730e3ccd4f79761878af01 Signed-off-by: Anas Nashif <anas.nashif@intel.com>
This commit is contained in:
parent
49a6d13849
commit
9078ad7982
6 changed files with 5 additions and 4 deletions
72
drivers/sensor/dht/Kconfig
Normal file
72
drivers/sensor/dht/Kconfig
Normal file
|
@ -0,0 +1,72 @@
|
|||
# Kconfig - DHT Temperature and Himidity Sensor configuration options
|
||||
|
||||
#
|
||||
# Copyright (c) 2016 Intel Corporation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
menuconfig DHT
|
||||
bool
|
||||
prompt "DHT Temperature and Humidity Sensor"
|
||||
depends on SENSOR && GPIO
|
||||
default n
|
||||
help
|
||||
Enable driver for the DHT temperature and humidity sensor family.
|
||||
|
||||
choice
|
||||
prompt "Chip type"
|
||||
depends on DHT
|
||||
default DHT_CHIP_DHT11
|
||||
help
|
||||
Choose desired chip type from the DHT family.
|
||||
|
||||
config DHT_CHIP_DHT11
|
||||
bool
|
||||
prompt "DHT11"
|
||||
help
|
||||
Choose this option to enable the DHT11 chip.
|
||||
|
||||
config DHT_CHIP_DHT22
|
||||
bool
|
||||
prompt "DHT22"
|
||||
help
|
||||
Choose this option to enable the DHT22 chip.
|
||||
|
||||
endchoice
|
||||
|
||||
config DHT_NAME
|
||||
string
|
||||
prompt "Driver name"
|
||||
default "DHT11" if DHT_CHIP_DHT11
|
||||
default "DHT22" if DHT_CHIP_DHT22
|
||||
depends on DHT
|
||||
help
|
||||
Device name with which the sensor is identified.
|
||||
|
||||
config DHT_GPIO_DEV_NAME
|
||||
string
|
||||
prompt "GPIO device"
|
||||
default "GPIO_0"
|
||||
depends on DHT
|
||||
help
|
||||
The device name of the GPIO device to which the chip's data pin
|
||||
is connected.
|
||||
|
||||
config DHT_GPIO_PIN_NUM
|
||||
int
|
||||
prompt "Interrupt GPIO pin number"
|
||||
default 0
|
||||
depends on DHT
|
||||
help
|
||||
The number of the GPIO on which the chip's data pin is connected.
|
1
drivers/sensor/dht/Makefile
Normal file
1
drivers/sensor/dht/Makefile
Normal file
|
@ -0,0 +1 @@
|
|||
obj-$(CONFIG_DHT) += dht.o
|
248
drivers/sensor/dht/dht.c
Normal file
248
drivers/sensor/dht/dht.c
Normal file
|
@ -0,0 +1,248 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Intel Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <device.h>
|
||||
#include <gpio.h>
|
||||
#include <misc/byteorder.h>
|
||||
#include <misc/util.h>
|
||||
#include <sensor.h>
|
||||
#include <string.h>
|
||||
#include <zephyr.h>
|
||||
|
||||
#include "dht.h"
|
||||
|
||||
/**
|
||||
* @brief Measure duration of signal send by sensor
|
||||
*
|
||||
* @param drv_data Pointer to the driver data structure
|
||||
* @param singnal_val Value of signal being measured
|
||||
*
|
||||
* @return duration in usec of signal being measured,
|
||||
* -1 if duration exceeds DHT_SIGNAL_MAX_WAIT_DURATION
|
||||
*/
|
||||
static int8_t dht_measure_signal_duration(struct dht_data *drv_data,
|
||||
uint32_t signal_val)
|
||||
{
|
||||
uint32_t val;
|
||||
uint32_t elapsed_cycles;
|
||||
uint32_t max_wait_cycles = (uint32_t)(
|
||||
(uint64_t)DHT_SIGNAL_MAX_WAIT_DURATION *
|
||||
(uint64_t)sys_clock_hw_cycles_per_sec /
|
||||
(uint64_t)USEC_PER_SEC
|
||||
);
|
||||
uint32_t start_cycles = sys_cycle_get_32();
|
||||
|
||||
do {
|
||||
gpio_pin_read(drv_data->gpio, CONFIG_DHT_GPIO_PIN_NUM, &val);
|
||||
elapsed_cycles = sys_cycle_get_32() - start_cycles;
|
||||
|
||||
if (elapsed_cycles >= max_wait_cycles) {
|
||||
return -1;
|
||||
}
|
||||
} while (val == signal_val);
|
||||
|
||||
return (uint64_t)elapsed_cycles *
|
||||
(uint64_t)USEC_PER_SEC /
|
||||
(uint64_t)sys_clock_hw_cycles_per_sec;
|
||||
}
|
||||
|
||||
static int dht_sample_fetch(struct device *dev, enum sensor_channel chan)
|
||||
{
|
||||
struct dht_data *drv_data = dev->driver_data;
|
||||
int ret = 0;
|
||||
int8_t signal_duration[DHT_DATA_BITS_NUM];
|
||||
int8_t max_duration, min_duration, avg_duration;
|
||||
uint8_t buf[5];
|
||||
unsigned int i, j;
|
||||
|
||||
__ASSERT_NO_MSG(chan == SENSOR_CHAN_ALL);
|
||||
|
||||
/* send start signal */
|
||||
gpio_pin_write(drv_data->gpio, CONFIG_DHT_GPIO_PIN_NUM, 0);
|
||||
|
||||
sys_thread_busy_wait(DHT_START_SIGNAL_DURATION);
|
||||
|
||||
gpio_pin_write(drv_data->gpio, CONFIG_DHT_GPIO_PIN_NUM, 1);
|
||||
|
||||
/* switch to DIR_IN to read sensor signals */
|
||||
gpio_pin_configure(drv_data->gpio, CONFIG_DHT_GPIO_PIN_NUM,
|
||||
GPIO_DIR_IN);
|
||||
|
||||
/* wait for sensor response */
|
||||
if (dht_measure_signal_duration(drv_data, 1) == -1) {
|
||||
ret = -EIO;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* read sensor response */
|
||||
if (dht_measure_signal_duration(drv_data, 0) == -1) {
|
||||
ret = -EIO;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* wait for sensor data */
|
||||
if (dht_measure_signal_duration(drv_data, 1) == -1) {
|
||||
ret = -EIO;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* read sensor data */
|
||||
for (i = 0; i < DHT_DATA_BITS_NUM; i++) {
|
||||
/* LOW signal to indicate a new bit */
|
||||
if (dht_measure_signal_duration(drv_data, 0) == -1) {
|
||||
ret = -EIO;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* HIGH signal duration indicates bit value */
|
||||
signal_duration[i] = dht_measure_signal_duration(drv_data, 1);
|
||||
if (signal_duration[i] == -1) {
|
||||
ret = -EIO;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* the datasheet says 20-40us HIGH signal duration for a 0 bit and
|
||||
* 80us for a 1 bit; however, since dht_measure_signal_duration is
|
||||
* not very precise, compute the threshold for deciding between a
|
||||
* 0 bit and a 1 bit as the average between the minimum and maximum
|
||||
* if the durations stored in signal_duration
|
||||
*/
|
||||
min_duration = signal_duration[0];
|
||||
max_duration = signal_duration[0];
|
||||
for (i = 1; i < DHT_DATA_BITS_NUM; i++) {
|
||||
if (min_duration > signal_duration[i]) {
|
||||
min_duration = signal_duration[i];
|
||||
}
|
||||
if (max_duration < signal_duration[i]) {
|
||||
max_duration = signal_duration[i];
|
||||
}
|
||||
}
|
||||
avg_duration = ((int16_t)min_duration + (int16_t)max_duration) / 2;
|
||||
|
||||
/* store bits in buf */
|
||||
j = 0;
|
||||
memset(buf, 0, sizeof(buf));
|
||||
for (i = 0; i < DHT_DATA_BITS_NUM; i++) {
|
||||
if (signal_duration[i] >= avg_duration) {
|
||||
buf[j] = (buf[j] << 1) | 1;
|
||||
} else {
|
||||
buf[j] = buf[j] << 1;
|
||||
}
|
||||
|
||||
if (i % 8 == 7) {
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
/* verify checksum */
|
||||
if (((buf[0] + buf[1] + buf[2] + buf[3]) & 0xFF) != buf[4]) {
|
||||
SYS_LOG_DBG("Invalid checksum in fetched sample");
|
||||
ret = -EIO;
|
||||
} else {
|
||||
memcpy(drv_data->sample, buf, 4);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
/* switch to DIR_OUT and leave pin to HIGH until next fetch */
|
||||
gpio_pin_configure(drv_data->gpio, CONFIG_DHT_GPIO_PIN_NUM,
|
||||
GPIO_DIR_OUT);
|
||||
gpio_pin_write(drv_data->gpio, CONFIG_DHT_GPIO_PIN_NUM, 1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dht_channel_get(struct device *dev,
|
||||
enum sensor_channel chan,
|
||||
struct sensor_value *val)
|
||||
{
|
||||
struct dht_data *drv_data = dev->driver_data;
|
||||
|
||||
__ASSERT_NO_MSG(chan == SENSOR_CHAN_TEMP || chan == SENSOR_CHAN_HUMIDITY);
|
||||
|
||||
val->type = SENSOR_VALUE_TYPE_INT_PLUS_MICRO;
|
||||
|
||||
/* see data calculation example from datasheet */
|
||||
#if defined(CONFIG_DHT_CHIP_DHT11)
|
||||
/* use only integral data byte */
|
||||
if (chan == SENSOR_CHAN_HUMIDITY) {
|
||||
val->val1 = drv_data->sample[0] * 1000;
|
||||
val->val2 = 0;
|
||||
} else { /* chan == SENSOR_CHAN_TEMP */
|
||||
val->val1 = drv_data->sample[2];
|
||||
val->val2 = 0;
|
||||
}
|
||||
#elif defined(CONFIG_DHT_CHIP_DHT22)
|
||||
/*
|
||||
* use both integral and decimal data bytes; resulted 16bit data has
|
||||
* a resolution of 0.1 units
|
||||
*/
|
||||
int16_t raw_val, sign;
|
||||
|
||||
if (chan == SENSOR_CHAN_HUMIDITY) {
|
||||
raw_val = (drv_data->sample[0] << 8) | drv_data->sample[1];
|
||||
val->val1 = raw_val * 100;
|
||||
val->val2 = 0;
|
||||
} else { /* chan == SENSOR_CHAN_TEMP */
|
||||
raw_val = (drv_data->sample[2] << 8) | drv_data->sample[3];
|
||||
|
||||
sign = raw_val & 0x8000;
|
||||
raw_val = raw_val & ~0x8000;
|
||||
|
||||
val->val1 = raw_val / 10;
|
||||
val->val2 = (raw_val % 10) * 100000;
|
||||
|
||||
/* handle negative value */
|
||||
if (sign) {
|
||||
val->val1 = -val->val1;
|
||||
val->val2 = -val->val2;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct sensor_driver_api dht_api = {
|
||||
.sample_fetch = &dht_sample_fetch,
|
||||
.channel_get = &dht_channel_get,
|
||||
};
|
||||
|
||||
static int dht_init(struct device *dev)
|
||||
{
|
||||
struct dht_data *drv_data = dev->driver_data;
|
||||
|
||||
drv_data->gpio = device_get_binding(CONFIG_DHT_GPIO_DEV_NAME);
|
||||
if (drv_data->gpio == NULL) {
|
||||
SYS_LOG_ERR("Failed to get GPIO device.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
gpio_pin_configure(drv_data->gpio, CONFIG_DHT_GPIO_PIN_NUM,
|
||||
GPIO_DIR_OUT);
|
||||
|
||||
gpio_pin_write(drv_data->gpio, CONFIG_DHT_GPIO_PIN_NUM, 1);
|
||||
|
||||
dev->driver_api = &dht_api;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct dht_data dht_data;
|
||||
|
||||
DEVICE_INIT(dht_dev, CONFIG_DHT_NAME, &dht_init, &dht_data,
|
||||
NULL, SECONDARY, CONFIG_SENSOR_INIT_PRIORITY);
|
35
drivers/sensor/dht/dht.h
Normal file
35
drivers/sensor/dht/dht.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Intel Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _SENSOR_DHT
|
||||
#define _SENSOR_DHT
|
||||
|
||||
#include <device.h>
|
||||
|
||||
#define SYS_LOG_DOMAIN "DHT"
|
||||
#define SYS_LOG_LEVEL CONFIG_SYS_LOG_SENSOR_LEVEL
|
||||
#include <misc/sys_log.h>
|
||||
|
||||
#define DHT_START_SIGNAL_DURATION 18000
|
||||
#define DHT_SIGNAL_MAX_WAIT_DURATION 100
|
||||
#define DHT_DATA_BITS_NUM 40
|
||||
|
||||
struct dht_data {
|
||||
struct device *gpio;
|
||||
uint8_t sample[4];
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue