From 515a7bf1ab829e3246582c69eab06d39ef3ed939 Mon Sep 17 00:00:00 2001 From: vowstar Date: Wed, 17 Jun 2015 16:30:12 +0800 Subject: [PATCH] Add dhtlib for DHT11/21/22/33/44, port from Arduino. --- app/Makefile | 148 +++++++++++++++---------------- app/dhtlib/Makefile | 48 +++++++++++ app/dhtlib/dht.c | 206 ++++++++++++++++++++++++++++++++++++++++++++ app/dhtlib/dht.h | 63 ++++++++++++++ 4 files changed, 392 insertions(+), 73 deletions(-) create mode 100644 app/dhtlib/Makefile create mode 100644 app/dhtlib/dht.c create mode 100644 app/dhtlib/dht.h diff --git a/app/Makefile b/app/Makefile index f52b890b..fbc69d78 100644 --- a/app/Makefile +++ b/app/Makefile @@ -21,24 +21,25 @@ ifndef PDIR # { GEN_IMAGES= eagle.app.v6.out GEN_BINS= eagle.app.v6.bin SPECIAL_MKTARGETS=$(APP_MKTARGETS) -SUBDIRS= \ - user \ - driver \ - lwip \ - json \ - upgrade \ - platform \ - libc \ - lua \ - coap \ - mqtt \ - u8glib \ - smart \ - wofs \ - modules \ - spiffs \ - cjson \ - crypto \ +SUBDIRS= \ + user \ + driver \ + lwip \ + json \ + upgrade \ + platform \ + libc \ + lua \ + coap \ + mqtt \ + u8glib \ + smart \ + wofs \ + modules \ + spiffs \ + cjson \ + crypto \ + dhtlib endif # } PDIR @@ -47,10 +48,10 @@ LDDIR = ../ld CCFLAGS += -Os -TARGET_LDFLAGS = \ - -nostdlib \ - -Wl,-EL \ - --longcalls \ +TARGET_LDFLAGS = \ + -nostdlib \ + -Wl,-EL \ + --longcalls \ --text-section-literals ifeq ($(FLAVOR),debug) @@ -71,52 +72,53 @@ ifeq ($(APP), 2) LD_FILE = $(LDDIR)/eagle.app.v6.app2.ld endif -COMPONENTS_eagle.app.v6 = \ - user/libuser.a \ - driver/libdriver.a \ - lwip/liblwip.a \ - json/libjson.a \ - upgrade/libupgrade.a \ - platform/libplatform.a \ - libc/liblibc.a \ - lua/liblua.a \ - coap/coap.a \ - mqtt/mqtt.a \ - u8glib/u8glib.a \ - smart/smart.a \ - wofs/wofs.a \ - spiffs/spiffs.a \ - cjson/libcjson.a \ - crypto/libcrypto.a \ +COMPONENTS_eagle.app.v6 = \ + user/libuser.a \ + driver/libdriver.a \ + lwip/liblwip.a \ + json/libjson.a \ + upgrade/libupgrade.a \ + platform/libplatform.a \ + libc/liblibc.a \ + lua/liblua.a \ + coap/coap.a \ + mqtt/mqtt.a \ + u8glib/u8glib.a \ + smart/smart.a \ + wofs/wofs.a \ + spiffs/spiffs.a \ + cjson/libcjson.a \ + crypto/libcrypto.a \ + dhtlib/libdhtlib.a \ modules/libmodules.a -LINKFLAGS_eagle.app.v6 = \ - -L../lib \ - -Wl,--gc-sections \ - -Xlinker -Map=mapfile \ - -nostdlib \ - -T$(LD_FILE) \ - -Wl,--no-check-sections \ - -u call_user_start \ - -Wl,-static \ - -Wl,--start-group \ - -lc \ - -lgcc \ - -lhal \ - -lphy \ - -lpp \ - -lnet80211 \ - -lwpa \ - -lmain \ - -ljson \ - -lsmartconfig \ - -lssl \ - $(DEP_LIBS_eagle.app.v6) \ - -Wl,--end-group \ +LINKFLAGS_eagle.app.v6 = \ + -L../lib \ + -Wl,--gc-sections \ + -Xlinker -Map=mapfile \ + -nostdlib \ + -T$(LD_FILE) \ + -Wl,--no-check-sections \ + -u call_user_start \ + -Wl,-static \ + -Wl,--start-group \ + -lc \ + -lgcc \ + -lhal \ + -lphy \ + -lpp \ + -lnet80211 \ + -lwpa \ + -lmain \ + -ljson \ + -lsmartconfig \ + -lssl \ + $(DEP_LIBS_eagle.app.v6) \ + -Wl,--end-group \ -lm -DEPENDS_eagle.app.v6 = \ - $(LD_FILE) \ +DEPENDS_eagle.app.v6 = \ + $(LD_FILE) \ $(LDDIR)/eagle.rom.addr.v6.ld ############################################################# @@ -127,24 +129,24 @@ DEPENDS_eagle.app.v6 = \ # for a subtree within the makefile rooted therein # -#UNIVERSAL_TARGET_DEFINES = \ +#UNIVERSAL_TARGET_DEFINES = \ # Other potential configuration flags include: # -DTXRX_TXBUF_DEBUG # -DTXRX_RXBUF_DEBUG # -DWLAN_CONFIG_CCX -CONFIGURATION_DEFINES = -D__ets__ \ - -DICACHE_FLASH \ - -DLWIP_OPEN_SRC \ - -DPBUF_RSV_FOR_WLAN \ +CONFIGURATION_DEFINES = -D__ets__ \ + -DICACHE_FLASH \ + -DLWIP_OPEN_SRC \ + -DPBUF_RSV_FOR_WLAN \ -DEBUF_LWIP -DEFINES += \ - $(UNIVERSAL_TARGET_DEFINES) \ +DEFINES += \ + $(UNIVERSAL_TARGET_DEFINES) \ $(CONFIGURATION_DEFINES) -DDEFINES += \ - $(UNIVERSAL_TARGET_DEFINES) \ +DDEFINES += \ + $(UNIVERSAL_TARGET_DEFINES) \ $(CONFIGURATION_DEFINES) diff --git a/app/dhtlib/Makefile b/app/dhtlib/Makefile new file mode 100644 index 00000000..838d3b80 --- /dev/null +++ b/app/dhtlib/Makefile @@ -0,0 +1,48 @@ + +############################################################# +# Required variables for each makefile +# Discard this section from all parent makefiles +# Expected variables (with automatic defaults): +# CSRCS (all "C" files in the dir) +# SUBDIRS (all subdirs with a Makefile) +# GEN_LIBS - list of libs to be generated () +# GEN_IMAGES - list of images to be generated () +# COMPONENTS_xxx - a list of libs/objs in the form +# subdir/lib to be extracted and rolled up into +# a generated lib/image xxx.a () +# +ifndef PDIR +GEN_LIBS = libdhtlib.a +endif + + +############################################################# +# Configuration i.e. compile options etc. +# Target specific stuff (defines etc.) goes in here! +# Generally values applying to a tree are captured in the +# makefile at its root level - these are then overridden +# for a subtree within the makefile rooted therein +# +#DEFINES += + +############################################################# +# Recursion Magic - Don't touch this!! +# +# Each subtree potentially has an include directory +# corresponding to the common APIs applicable to modules +# rooted at that subtree. Accordingly, the INCLUDE PATH +# of a module can only contain the include directories up +# its parent path, and not its siblings +# +# Required for each makefile to inherit from the parent +# + +INCLUDES := $(INCLUDES) -I $(PDIR)include +INCLUDES += -I ./ +INCLUDES += -I ./include +INCLUDES += -I ../include +INCLUDES += -I ../../include +INCLUDES += -I ../platform +PDIR := ../$(PDIR) +sinclude $(PDIR)Makefile + diff --git a/app/dhtlib/dht.c b/app/dhtlib/dht.c new file mode 100644 index 00000000..f1f59784 --- /dev/null +++ b/app/dhtlib/dht.c @@ -0,0 +1,206 @@ +// +// FILE: dht.cpp +// AUTHOR: Rob Tillaart +// VERSION: 0.1.14 +// PURPOSE: DHT Temperature & Humidity Sensor library for Arduino +// URL: http://arduino.cc/playground/Main/DHTLib +// +// HISTORY: +// 0.1.14 replace digital read with faster (~3x) code => more robust low MHz machines. +// 0.1.13 fix negative dht_temperature +// 0.1.12 support DHT33 and DHT44 initial version +// 0.1.11 renamed DHTLIB_TIMEOUT +// 0.1.10 optimized faster WAKEUP + TIMEOUT +// 0.1.09 optimize size: timeout check + use of mask +// 0.1.08 added formula for timeout based upon clockspeed +// 0.1.07 added support for DHT21 +// 0.1.06 minimize footprint (2012-12-27) +// 0.1.05 fixed negative dht_temperature bug (thanks to Roseman) +// 0.1.04 improved readability of code using DHTLIB_OK in code +// 0.1.03 added error values for temp and dht_humidity when read failed +// 0.1.02 added error codes +// 0.1.01 added support for Arduino 1.0, fixed typos (31/12/2011) +// 0.1.00 by Rob Tillaart (01/04/2011) +// +// inspired by DHT11 library +// +// Released to the public domain +// + +#include "platform.h" +#include "dht.h" + +#ifndef LOW +#define LOW 0 +#endif /* ifndef LOW */ + +#ifndef HIGH +#define HIGH 1 +#endif /* ifndef HIGH */ + +#define COMBINE_HIGH_AND_LOW_BYTE(byte_high, byte_low) ((byte_high << 8) | (byte_low)) + +static double dht_humidity; +static double dht_temperature; + +static uint8_t dht_bits[5]; // buffer to receive data +static int dht_readSensor(uint8_t pin, uint8_t wakeupDelay); + +///////////////////////////////////////////////////// +// +// PUBLIC +// + +// return values: +// DHTLIB_OK +// DHTLIB_ERROR_CHECKSUM +// DHTLIB_ERROR_TIMEOUT +int dht_read11(uint8_t pin) +{ + // READ VALUES + int rv = dht_readSensor(pin, DHTLIB_DHT11_WAKEUP); + if (rv != DHTLIB_OK) + { + dht_humidity = DHTLIB_INVALID_VALUE; // invalid value, or is NaN prefered? + dht_temperature = DHTLIB_INVALID_VALUE; // invalid value + return rv; + } + + // CONVERT AND STORE + dht_humidity = dht_bits[0]; // dht_bits[1] == 0; + dht_temperature = dht_bits[2]; // dht_bits[3] == 0; + + // TEST CHECKSUM + // dht_bits[1] && dht_bits[3] both 0 + uint8_t sum = dht_bits[0] + dht_bits[2]; + if (dht_bits[4] != sum) return DHTLIB_ERROR_CHECKSUM; + + return DHTLIB_OK; +} + + +// return values: +// DHTLIB_OK +// DHTLIB_ERROR_CHECKSUM +// DHTLIB_ERROR_TIMEOUT +int dht_read(uint8_t pin) +{ + // READ VALUES + int rv = dht_readSensor(pin, DHTLIB_DHT_WAKEUP); + if (rv != DHTLIB_OK) + { + dht_humidity = DHTLIB_INVALID_VALUE; // invalid value, or is NaN prefered? + dht_temperature = DHTLIB_INVALID_VALUE; // invalid value + return rv; // propagate error value + } + + // CONVERT AND STORE + dht_humidity = COMBINE_HIGH_AND_LOW_BYTE(dht_bits[0], dht_bits[1]) * 0.1; + dht_temperature = COMBINE_HIGH_AND_LOW_BYTE(dht_bits[2] & 0x7F, dht_bits[3]) * 0.1; + if (dht_bits[2] & 0x80) // negative dht_temperature + { + dht_temperature = -dht_temperature; + } + + // TEST CHECKSUM + uint8_t sum = dht_bits[0] + dht_bits[1] + dht_bits[2] + dht_bits[3]; + if (dht_bits[4] != sum) + { + return DHTLIB_ERROR_CHECKSUM; + } + return DHTLIB_OK; +} + +///////////////////////////////////////////////////// +// +// PRIVATE +// + +// return values: +// DHTLIB_OK +// DHTLIB_ERROR_TIMEOUT +int dht_readSensor(uint8_t pin, uint8_t wakeupDelay) +{ + // INIT BUFFERVAR TO RECEIVE DATA + uint8_t mask = 128; + uint8_t idx = 0; + uint8_t i = 0; + + // replace digitalRead() with Direct Port Reads. + // reduces footprint ~100 bytes => portability issue? + // direct port read is about 3x faster + // uint8_t bit = digitalPinToBitMask(pin); + // uint8_t port = digitalPinToPort(pin); + // volatile uint8_t *PIR = portInputRegister(port); + + // EMPTY BUFFER + for (i = 0; i < 5; i++) dht_bits[i] = 0; + + // REQUEST SAMPLE + // pinMode(pin, OUTPUT); + DIRECT_MODE_OUTPUT(pin); + // digitalWrite(pin, LOW); // T-be + DIRECT_WRITE_LOW(pin); + // delay(wakeupDelay); + for (i = 0; i < wakeupDelay; i++) os_delay_us(1000); + // digitalWrite(pin, HIGH); // T-go + DIRECT_WRITE_HIGH(pin); + os_delay_us(40); + // pinMode(pin, INPUT); + DIRECT_MODE_INPUT(pin); + + // GET ACKNOWLEDGE or TIMEOUT + uint16_t loopCntLOW = DHTLIB_TIMEOUT; + while (DIRECT_READ(pin) == LOW ) // T-rel + { + os_delay_us(1); + if (--loopCntLOW == 0) return DHTLIB_ERROR_TIMEOUT; + } + + uint16_t loopCntHIGH = DHTLIB_TIMEOUT; + while (DIRECT_READ(pin) != LOW ) // T-reh + { + os_delay_us(1); + if (--loopCntHIGH == 0) return DHTLIB_ERROR_TIMEOUT; + } + + // READ THE OUTPUT - 40 BITS => 5 BYTES + for (i = 40; i != 0; i--) + { + loopCntLOW = DHTLIB_TIMEOUT; + while (DIRECT_READ(pin) == LOW ) + { + os_delay_us(1); + if (--loopCntLOW == 0) return DHTLIB_ERROR_TIMEOUT; + } + + uint32_t t = system_get_time(); + + loopCntHIGH = DHTLIB_TIMEOUT; + while (DIRECT_READ(pin) != LOW ) + { + os_delay_us(1); + if (--loopCntHIGH == 0) return DHTLIB_ERROR_TIMEOUT; + } + + if ((system_get_time() - t) > 40) + { + dht_bits[idx] |= mask; + } + mask >>= 1; + if (mask == 0) // next byte? + { + mask = 128; + idx++; + } + } + // pinMode(pin, OUTPUT); + DIRECT_MODE_OUTPUT(pin); + // digitalWrite(pin, HIGH); + DIRECT_WRITE_HIGH(pin); + + return DHTLIB_OK; +} +// +// END OF FILE +// \ No newline at end of file diff --git a/app/dhtlib/dht.h b/app/dhtlib/dht.h new file mode 100644 index 00000000..de31bd69 --- /dev/null +++ b/app/dhtlib/dht.h @@ -0,0 +1,63 @@ +// +// FILE: dht.h +// AUTHOR: Rob Tillaart +// VERSION: 0.1.14 +// PURPOSE: DHT Temperature & Humidity Sensor library for Arduino +// URL: http://arduino.cc/playground/Main/DHTLib +// +// HISTORY: +// see dht.cpp file +// + +#ifndef dht_h +#define dht_h + +// #if ARDUINO < 100 +// #include +// #else +// #include +// #endif +#include "c_types.h" + +#define DHT_LIB_VERSION "0.1.14" + +#define DHTLIB_OK 0 +#define DHTLIB_ERROR_CHECKSUM -1 +#define DHTLIB_ERROR_TIMEOUT -2 +#define DHTLIB_INVALID_VALUE -999 + +#define DHTLIB_DHT11_WAKEUP 18 +#define DHTLIB_DHT_WAKEUP 1 + +// max timeout is 100 usec. +// For a 16 Mhz proc 100 usec is 1600 clock cycles +// loops using DHTLIB_TIMEOUT use at least 4 clock cycli +// so 100 us takes max 400 loops +// so by dividing F_CPU by 40000 we "fail" as fast as possible +// ESP8266 uses delay_us get 1us time +#define DHTLIB_TIMEOUT (100) + +// Platform specific I/O definitions + +#define DIRECT_READ(pin) (0x1 & GPIO_INPUT_GET(GPIO_ID_PIN(pin_num[pin]))) +#define DIRECT_MODE_INPUT(pin) GPIO_DIS_OUTPUT(pin_num[pin]) +#define DIRECT_MODE_OUTPUT(pin) +#define DIRECT_WRITE_LOW(pin) (GPIO_OUTPUT_SET(GPIO_ID_PIN(pin_num[pin]), 0)) +#define DIRECT_WRITE_HIGH(pin) (GPIO_OUTPUT_SET(GPIO_ID_PIN(pin_num[pin]), 1)) + +// return values: +// DHTLIB_OK +// DHTLIB_ERROR_CHECKSUM +// DHTLIB_ERROR_TIMEOUT +int dht_read11(uint8_t pin); +int dht_read(uint8_t pin); + +inline int dht_read21(uint8_t pin) { return dht_read(pin); }; +inline int dht_read22(uint8_t pin) { return dht_read(pin); }; +inline int dht_read33(uint8_t pin) { return dht_read(pin); }; +inline int dht_read44(uint8_t pin) { return dht_read(pin); }; + +#endif +// +// END OF FILE +// \ No newline at end of file