Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions components/modules/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,12 @@ config LUA_MODULE_GPIO
help
Includes the GPIO module (recommended).

config LUA_MODULE_HTU21
bool "HTU21D/STH21 module"
default "n"
help
Includes the htu21 module.

config LUA_MODULE_I2C
bool "I2C module"
default "y"
Expand Down
31 changes: 31 additions & 0 deletions components/modules/htu21.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#include "module.h"
#include "lauxlib.h"
#include <stdint.h>

#include "platform.h"


static int htu21_read(lua_State *L)
{
uint32_t i2c_id = (uint32_t) luaL_optinteger( L, 1, 0 );

uint16_t rawT = platform_htu21_read(i2c_id, PLATFORM_HTU21_T_MEASUREMENT_HM);
uint16_t rawRH = platform_htu21_read(i2c_id, PLATFORM_HTU21_RH_MEASUREMENT_HM);

if (rawT == PLATFORM_HTU21_ERROR || rawRH == PLATFORM_HTU21_ERROR) {
luaL_error(L, "htu21 invalid CRC or i2c_id");
}

lua_pushinteger(L, platform_htu21_temp_ticks_to_millicelsius(rawT));
lua_pushinteger(L, platform_htu21_rh_ticks_to_per_cent_mille(rawRH));

return 2;
}


static const LUA_REG_TYPE htu21_map[] = {
{LSTRKEY("read"), LFUNCVAL(htu21_read)},
{LNILKEY, LNILVAL}
};

NODEMCU_MODULE(HTU21, "htu21", htu21_map, NULL);
77 changes: 77 additions & 0 deletions components/platform/htu21.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
* Driver for HTU21D/SHT21 humidity/temperature sensor.
*
*/
#include "platform.h"
#include "lua.h"

#define HTU21_ADDRESS 0x40

//Give this function the 2 byte message (measurement) and the check_value byte from the HTU21D
//If it returns 0, then the transmission was good
//If it returns something other than 0, then the communication was corrupted
//From: http://www.nongnu.org/avr-libc/user-manual/group__util__crc.html
//POLYNOMIAL = 0x0131 = x^8 + x^5 + x^4 + 1 : http://en.wikipedia.org/wiki/Computation_of_cyclic_redundancy_checks
#define SHIFTED_DIVISOR 0x988000 //This is the 0x0131 polynomial shifted to farthest left of three bytes

inline int32_t platform_htu21_temp_ticks_to_millicelsius(uint32_t ticks)
{
ticks &= ~0x0003; /* clear status bits */
/*
* Formula T = -46.85 + 175.72 * ST / 2^16 from datasheet p14,
* optimized for integer fixed point (3 digits) arithmetic
*/
return ((21965 * ticks) >> 13) - 46850;
}

inline int32_t platform_htu21_rh_ticks_to_per_cent_mille(uint32_t ticks)
{
ticks &= ~0x0003; /* clear status bits */
/*
* Formula RH = -6 + 125 * SRH / 2^16 from datasheet p14,
* optimized for integer fixed point (3 digits) arithmetic
*/
return ((15625 * ticks) >> 13) - 6000;
}

static uint8_t checkCRC(uint16_t ravValue, uint8_t checksum)
{
uint32_t remainder = (uint32_t) ravValue << 8; //Pad with 8 bits because we have to add in the check value
remainder |= checksum; //Add on the check value

uint32_t divsor = (uint32_t) SHIFTED_DIVISOR;

//Operate on only 16 positions of max 24. The remaining 8 are our remainder and should be zero when we're done.
for (int i = 0; i < 16; i++)
{
if (remainder & (uint32_t) 1 << (23 - i)) //Check if there is a one in the left position
remainder ^= divsor;

divsor >>= 1; //Rotate the divsor max 16 times so that we have 8 bits left of a remainder
}

return (uint8_t) remainder;
}

uint16_t platform_htu21_read(uint32_t i2c_id, uint8_t reg)
{
uint16_t rawValue;
uint8_t checksum;

if (platform_i2c_exists(i2c_id) == PLATFORM_ERR)
return PLATFORM_HTU21_ERROR;

platform_i2c_send_start(i2c_id);
platform_i2c_send_address(i2c_id, HTU21_ADDRESS, PLATFORM_I2C_DIRECTION_TRANSMITTER, 0);
platform_i2c_send_byte(i2c_id, reg, 0);
platform_i2c_send_start(i2c_id);
platform_i2c_send_address(i2c_id, HTU21_ADDRESS, PLATFORM_I2C_DIRECTION_RECEIVER, 0);

rawValue = (uint16_t) platform_i2c_recv_byte(i2c_id, 1) << 8;
rawValue |= platform_i2c_recv_byte(i2c_id, 1);
checksum = (uint8_t) platform_i2c_recv_byte(i2c_id, 0);

platform_i2c_send_stop(0);

return checkCRC(rawValue, checksum) != 0 ? PLATFORM_HTU21_ERROR : rawValue;
}
9 changes: 9 additions & 0 deletions components/platform/include/platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,15 @@ uint16_t platform_onewire_crc16( const uint8_t* input, uint16_t len, uint16_t cr

int platform_dht_read( uint8_t gpio_num, uint8_t wakeup_ms, uint8_t *data );

// *****************************************************************************
// HTU21 platform interface
#define PLATFORM_HTU21_ERROR (uint16_t) 1
#define PLATFORM_HTU21_T_MEASUREMENT_HM 0xE3
#define PLATFORM_HTU21_RH_MEASUREMENT_HM 0xE5

uint16_t platform_htu21_read( uint32_t i2c_id, uint8_t reg );
int32_t platform_htu21_temp_ticks_to_millicelsius( uint32_t ticks );
int32_t platform_htu21_rh_ticks_to_per_cent_mille( uint32_t ticks );

// *****************************************************************************
// WS2812 platform interface
Expand Down
28 changes: 28 additions & 0 deletions docs/en/modules/htu21.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# HDC1080 Module
| Since | Origin / Contributor | Maintainer | Source |
| :----- | :-------------------- | :---------- | :------ |
| 2017-02-03 | [Pawel Switalski](https://github.com/s-pw) | [Pawel Switalski](https://github.com/s-pw) | [htu21.c](../../../components/modules/htu21.c)|


This module provides access to the [HTU21D](https://www.sparkfun.com/products/13763) temperature and humidity sensor. The module also works with SHT21.

## htu21.read()
Samples the sensor then returns temperature and humidity value.

#### Syntax
`htu21.read([i2c_id])`

#### Parameters
- `i2c_id` i2c interface id, defaults to i2c.SW if omitted

#### Returns
Temperature data in millidegree Celsius and humidity data in per cent mille

#### Example
```lua
local sda, scl = 1, 2
i2c.setup(i2c.SW, sda, scl, i2c.SLOW) -- call i2c.setup() only once
local temperature, humidity = htu21.read(i2c.SW)
print(temperature / 1000 .. '°C')
print(humidity / 1000 .. '%')
```
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ pages:
- 'dht': 'en/modules/dht.md'
- 'file': 'en/modules/file.md'
- 'gpio': 'en/modules/gpio.md'
- 'htu21': 'en/modules/htu21.md'
- 'i2c': 'en/modules/i2c.md'
- 'ledc': 'en/modules/ledc.md'
- 'net': 'en/modules/net.md'
Expand Down